Bounded GenAI metrics and keyed summaries from OpenTelemetry traces
2
stars
12
commits
Go
primary language
Sep 8, 2026
updated
An OpenTelemetry Collector distribution for continuous, bounded answers about high-cardinality agent traffic without exporting or indexing every underlying value. It turns GenAI traces into bounded Prometheus metrics and keyed top-k summaries.
Use it alongside an existing trace backend to find where reported token volume is accumulating, measure missing usage, and keep high-cardinality identities out of metric labels.
| Question | Required span data | Result | Boundary |
|---|---|---|---|
| Where is reported token or request volume accumulating? | A matched model operation, optional token fields, and bounded attributes such as team, model, provider, or route | Request and token rates by bounded slice, plus token-weighted prompt signatures with lower and upper bounds | Volume does not establish task value, waste, or root cause |
| Could an identity create unsafe Prometheus cardinality? | A supported user, prompt, document, or MCP field configured as a hashed field | Distinct estimates remain metrics; keyed identities remain outside labels | The connector does not scan every arbitrary attribute for cardinality |
| Are agent or tool spans inflating model-request accounting? | gen_ai.operation.name, or the documented model fallback | Only configured model operations count as requests; root agent runs have a separate counter | The connector does not provide a count for every possible span kind |
| How much reported token usage is missing? | gen_ai.usage.input_tokens and/or gen_ai.usage.output_tokens when available | Missing usage is counted separately from real zero-token values | The collector never infers unreported tokens |
These are fleet-level measurement signals. Trace explorers and evaluation systems remain the right tools for understanding one agent run or judging its output.
Requirements: Docker with Compose, Go 1.26.6 or newer, and openssl.
git clone https://github.com/llm-measurement/otelcol-genai-sketches.git
cd otelcol-genai-sketches
export GENAI_SKETCH_SECRET="$(openssl rand -hex 32)"
make example-up
This starts a sample application, the collector, a Prometheus metrics server, and a provisioned Grafana dashboard.
The sample emits model, agent, tool, and retrieval spans. It also includes missing token fields and enough prompt variety to exercise bounded estimates.
Let the example run for at least one minute, then use the dashboard in this order:
Then inspect the high-cardinality surface:
docker compose -f examples/compose.yaml logs collector \
| grep 'genaisketch topk snapshot'
The snapshot contains keyed hashes, estimates, and lower and upper bounds. It does not contain prompt text, and its hashes never become Prometheus labels.
Stop the example with:
make example-down
The token-consumption playbook contains the PromQL queries and an interpretation table for the same workflow.
You can add the connector without replacing Datadog, Langfuse, Alloy, or another OTLP destination:
applications -> Collector fan-out -> current trace backend
-> bounded sketch metrics
The distribution includes OTLP gRPC and HTTP exporters. CI verifies that one trace batch can be forwarded while the connector derives metrics from it. You can also let an existing Collector or Alloy deployment own the fan-out and run this distribution as a sidecar.
See Keep Your Existing Telemetry Backend for tested generic OTLP configurations and coexistence paths for an ordinary Collector, Datadog, Langfuse, and Grafana Alloy.
Use this collector when you need to:
This is not a prompt logger, billing ledger, arbitrary attribute-to-label converter, anomaly detector, loop stopper, budget enforcer, or differential-privacy system.
If exact traces are safe to retain and remain fast and affordable to query, use them. The connector is an always-on bounded evidence surface, not a replacement for raw records needed for diagnosis, audit, or replay.
| Signal | Meaning |
|---|---|
gen_ai_sketch_requests_total | Model request spans matched by the operation filter |
gen_ai_sketch_agent_runs_total | Root invoke_agent spans |
gen_ai_sketch_input_tokens_total | Reported input tokens |
gen_ai_sketch_output_tokens_total | Reported output tokens |
gen_ai_sketch_total_tokens_total | Reported input plus output tokens |
gen_ai_sketch_missing_token_usage_total | Matched requests with neither token field |
gen_ai_sketch_active_slices | Currently retained slice states |
gen_ai_sketch_distinct_users | Estimated distinct keyed user values |
gen_ai_sketch_distinct_prompt_signatures | Estimated distinct keyed prompt values |
gen_ai_sketch_distinct_retrieval_docs | Estimated distinct keyed document values |
Optional MCP metrics estimate distinct sessions, methods, and resources. Weighted top-k prompt signatures are emitted as structured logs with estimates and lower and upper bounds. They never become Prometheus labels.
See Metrics for exact signal semantics.
GenAI applications -> OTLP traces -> this collector -> Prometheus metrics
| -> bounded structured logs
+--------------> optional existing OTLP backend
Use this distribution when source spans already flow through OpenTelemetry. If you own a custom streaming, batch, or warehouse pipeline and do not need OTLP-to-metrics conversion, use llm-sketchkit directly.
The connector uses llm-sketchkit for canonicalization, keyed hashing, distinct
counting, frequent-item estimates, and deduplication. Raw prompt text, user IDs,
document IDs, and request IDs do not enter connector aggregate state or its derived
metrics and snapshots.
An optional forwarded trace remains the original trace. If instrumentation captured raw content, the existing trace backend still receives it. See the shadow-mode guide before enabling fan-out.
The connector is also published as a standalone Go module for the OpenTelemetry Collector Builder. Add it to a builder manifest:
connectors:
- gomod: github.com/llm-measurement/otelcol-genai-sketches/connector/genaisketchconnector v0.1.0-alpha.1
Configure genaisketch as an exporter from the traces pipeline and a receiver in the
metrics pipeline. The path: override in this repository's builder manifest exists
only for a local checkout.
Start with the example configuration. The connector
requires a secret of at least 16 bytes from GENAI_SKETCH_SECRET by default.
connectors:
genaisketch:
window_duration: 1m
retention_windows: 10
max_slices: 2000
topk: 20
slices:
- name: model
keys: [gen_ai.request.model]
from_resource_attributes: [gen_ai.request.model]
Slice values are exported in cleartext as Prometheus labels. Use only bounded,
low-cardinality, non-sensitive attributes such as model, team, route, or provider.
Configured slice capacity uses deterministic inactive-slice eviction and one
__overflow__ value. Excess traffic is counted rather than silently dropped, and it
does not create new label values.
See Configuration for field mapping, operation filtering, resource fallback, MCP support, deduplication, and capacity limits.
Keyed hashes are pseudonymous, not anonymous. Values remain linkable while the same secret is in use, and anyone holding the secret can test candidate values. Rotating the secret breaks comparison with earlier windows.
The structured top-k surface contains keyed hashes and bounded estimates. Treat collector logs as sensitive operational data even though raw source values are not included. The connector rejects known high-cardinality MCP identifiers as slice keys and rejects overlap between plaintext slice keys and configured hashed fields.
Token attributes are optional. Missing usage is counted explicitly; the connector does not invent token weights. Bloom-filter deduplication is bounded and may undercount because false positives are possible.
See Security to report a vulnerability privately.
Recorded local measurements include:
These are measurements from one Apple M4 Max system, not universal capacity claims. Workload definitions, machine details, commands, and non-passing runs are in Benchmarks.
make tidy
make check
make dist
make test-integration
The integration suite covers OTLP-to-Prometheus behavior, gRPC and HTTP shadow-mode fan-out, bounded overflow, deterministic eviction, restart stability, tree locality, and sentinel scans across metric, label, and structured-log surfaces.
This project is alpha software. Interfaces and metric semantics may change between alpha releases. Pin an exact version and test it against your own traffic before production use. See the changelog for release notes.
Licensed under the Apache License 2.0.
12 commits
Go
96.6%
Makefile
2.3%
Shell
1.1%
Bounded GenAI metrics and keyed summaries from OpenTelemetry traces
2
stars
12
commits
Go
primary language
Sep 8, 2026
updated
An OpenTelemetry Collector distribution for continuous, bounded answers about high-cardinality agent traffic without exporting or indexing every underlying value. It turns GenAI traces into bounded Prometheus metrics and keyed top-k summaries.
Use it alongside an existing trace backend to find where reported token volume is accumulating, measure missing usage, and keep high-cardinality identities out of metric labels.
| Question | Required span data | Result | Boundary |
|---|---|---|---|
| Where is reported token or request volume accumulating? | A matched model operation, optional token fields, and bounded attributes such as team, model, provider, or route | Request and token rates by bounded slice, plus token-weighted prompt signatures with lower and upper bounds | Volume does not establish task value, waste, or root cause |
| Could an identity create unsafe Prometheus cardinality? | A supported user, prompt, document, or MCP field configured as a hashed field | Distinct estimates remain metrics; keyed identities remain outside labels | The connector does not scan every arbitrary attribute for cardinality |
| Are agent or tool spans inflating model-request accounting? | gen_ai.operation.name, or the documented model fallback | Only configured model operations count as requests; root agent runs have a separate counter | The connector does not provide a count for every possible span kind |
| How much reported token usage is missing? | gen_ai.usage.input_tokens and/or gen_ai.usage.output_tokens when available | Missing usage is counted separately from real zero-token values | The collector never infers unreported tokens |
These are fleet-level measurement signals. Trace explorers and evaluation systems remain the right tools for understanding one agent run or judging its output.
Requirements: Docker with Compose, Go 1.26.6 or newer, and openssl.
git clone https://github.com/llm-measurement/otelcol-genai-sketches.git
cd otelcol-genai-sketches
export GENAI_SKETCH_SECRET="$(openssl rand -hex 32)"
make example-up
This starts a sample application, the collector, a Prometheus metrics server, and a provisioned Grafana dashboard.
The sample emits model, agent, tool, and retrieval spans. It also includes missing token fields and enough prompt variety to exercise bounded estimates.
Let the example run for at least one minute, then use the dashboard in this order:
Then inspect the high-cardinality surface:
docker compose -f examples/compose.yaml logs collector \
| grep 'genaisketch topk snapshot'
The snapshot contains keyed hashes, estimates, and lower and upper bounds. It does not contain prompt text, and its hashes never become Prometheus labels.
Stop the example with:
make example-down
The token-consumption playbook contains the PromQL queries and an interpretation table for the same workflow.
You can add the connector without replacing Datadog, Langfuse, Alloy, or another OTLP destination:
applications -> Collector fan-out -> current trace backend
-> bounded sketch metrics
The distribution includes OTLP gRPC and HTTP exporters. CI verifies that one trace batch can be forwarded while the connector derives metrics from it. You can also let an existing Collector or Alloy deployment own the fan-out and run this distribution as a sidecar.
See Keep Your Existing Telemetry Backend for tested generic OTLP configurations and coexistence paths for an ordinary Collector, Datadog, Langfuse, and Grafana Alloy.
Use this collector when you need to:
This is not a prompt logger, billing ledger, arbitrary attribute-to-label converter, anomaly detector, loop stopper, budget enforcer, or differential-privacy system.
If exact traces are safe to retain and remain fast and affordable to query, use them. The connector is an always-on bounded evidence surface, not a replacement for raw records needed for diagnosis, audit, or replay.
| Signal | Meaning |
|---|---|
gen_ai_sketch_requests_total | Model request spans matched by the operation filter |
gen_ai_sketch_agent_runs_total | Root invoke_agent spans |
gen_ai_sketch_input_tokens_total | Reported input tokens |
gen_ai_sketch_output_tokens_total | Reported output tokens |
gen_ai_sketch_total_tokens_total | Reported input plus output tokens |
gen_ai_sketch_missing_token_usage_total | Matched requests with neither token field |
gen_ai_sketch_active_slices | Currently retained slice states |
gen_ai_sketch_distinct_users | Estimated distinct keyed user values |
gen_ai_sketch_distinct_prompt_signatures | Estimated distinct keyed prompt values |
gen_ai_sketch_distinct_retrieval_docs | Estimated distinct keyed document values |
Optional MCP metrics estimate distinct sessions, methods, and resources. Weighted top-k prompt signatures are emitted as structured logs with estimates and lower and upper bounds. They never become Prometheus labels.
See Metrics for exact signal semantics.
GenAI applications -> OTLP traces -> this collector -> Prometheus metrics
| -> bounded structured logs
+--------------> optional existing OTLP backend
Use this distribution when source spans already flow through OpenTelemetry. If you own a custom streaming, batch, or warehouse pipeline and do not need OTLP-to-metrics conversion, use llm-sketchkit directly.
The connector uses llm-sketchkit for canonicalization, keyed hashing, distinct
counting, frequent-item estimates, and deduplication. Raw prompt text, user IDs,
document IDs, and request IDs do not enter connector aggregate state or its derived
metrics and snapshots.
An optional forwarded trace remains the original trace. If instrumentation captured raw content, the existing trace backend still receives it. See the shadow-mode guide before enabling fan-out.
The connector is also published as a standalone Go module for the OpenTelemetry Collector Builder. Add it to a builder manifest:
connectors:
- gomod: github.com/llm-measurement/otelcol-genai-sketches/connector/genaisketchconnector v0.1.0-alpha.1
Configure genaisketch as an exporter from the traces pipeline and a receiver in the
metrics pipeline. The path: override in this repository's builder manifest exists
only for a local checkout.
Start with the example configuration. The connector
requires a secret of at least 16 bytes from GENAI_SKETCH_SECRET by default.
connectors:
genaisketch:
window_duration: 1m
retention_windows: 10
max_slices: 2000
topk: 20
slices:
- name: model
keys: [gen_ai.request.model]
from_resource_attributes: [gen_ai.request.model]
Slice values are exported in cleartext as Prometheus labels. Use only bounded,
low-cardinality, non-sensitive attributes such as model, team, route, or provider.
Configured slice capacity uses deterministic inactive-slice eviction and one
__overflow__ value. Excess traffic is counted rather than silently dropped, and it
does not create new label values.
See Configuration for field mapping, operation filtering, resource fallback, MCP support, deduplication, and capacity limits.
Keyed hashes are pseudonymous, not anonymous. Values remain linkable while the same secret is in use, and anyone holding the secret can test candidate values. Rotating the secret breaks comparison with earlier windows.
The structured top-k surface contains keyed hashes and bounded estimates. Treat collector logs as sensitive operational data even though raw source values are not included. The connector rejects known high-cardinality MCP identifiers as slice keys and rejects overlap between plaintext slice keys and configured hashed fields.
Token attributes are optional. Missing usage is counted explicitly; the connector does not invent token weights. Bloom-filter deduplication is bounded and may undercount because false positives are possible.
See Security to report a vulnerability privately.
Recorded local measurements include:
These are measurements from one Apple M4 Max system, not universal capacity claims. Workload definitions, machine details, commands, and non-passing runs are in Benchmarks.
make tidy
make check
make dist
make test-integration
The integration suite covers OTLP-to-Prometheus behavior, gRPC and HTTP shadow-mode fan-out, bounded overflow, deterministic eviction, restart stability, tree locality, and sentinel scans across metric, label, and structured-log surfaces.
This project is alpha software. Interfaces and metric semantics may change between alpha releases. Pin an exact version and test it against your own traffic before production use. See the changelog for release notes.
Licensed under the Apache License 2.0.
12 commits
Go
96.6%
Makefile
2.3%
Shell
1.1%