Skip to main content

Backends overview

hermes-otel exports plain OTLP (OpenTelemetry's wire protocol) over HTTP, or over gRPC with the generic otlp type, so any OTLP-compatible backend should work. The ones below ship with first-class support, docker-compose files, and (where relevant) smoke-test coverage.

Supported today​

BackendSignalsDeploymentAccount / cost
PhoenixTraces onlyLocal (single container) · Arize AX cloudOSS, no account · commercial cloud
LangfuseTracesLocal (docker compose) · CloudOSS, no account · free tier + paid
LangSmithTracesCloud only (self-host = enterprise)Free personal tier · paid tiers
SigNozTraces + metrics + logsLocal (docker compose) · CloudOSS, no account · free tier + paid cloud
JaegerTracesLocal (single container)OSS, no account needed
ZipkinTracesLocal (single container, the zipkin-otel image)OSS (Apache-2.0), no account
GreptimeDBTraces + metrics + logsLocal (single container) · Helm · GreptimeCloudOSS (Apache-2.0), no account
ClickStack (HyperDX)Traces + metrics + logsLocal (one all-in-one container) · upstream compose · Helm · ClickHouse CloudOSS (MIT), local account on first run
VictoriaMetrics familyTraces + metrics + logsLocal (three single-binary containers) · Helm · VictoriaMetrics CloudOSS (Apache-2.0), no account
Aspire DashboardTraces + metrics + logsLocal (single container)OSS (MIT), no account
Gigapipe (qryn)Traces + metrics + logsLocal (Gigapipe + ClickHouse) · Gigapipe CloudOSS (AGPL-3.0), no account
AgentaTracesLocal (docker compose, eleven containers) · Agenta Cloud (US / EU)OSS (MIT), local account · free cloud tier
Grafana TempoTracesLocal (docker compose) · Grafana CloudOSS, no account · free tier + paid cloud
Grafana LGTMTraces + metrics + logsLocal (single container)OSS, no account
UptraceTraces + metrics + logsLocal (docker compose) · Self-hostedOSS · premium license for HA features
OpenObserveTraces + metrics + logsLocal (single container) · Self-hosted HAOSS, no account
ParseableTraces + metrics + logsSelf-hosted · CloudOSS · paid cloud
HoneycombTraces + metrics + logsCloud (US / EU)Generous free tier · paid plans
W&B WeaveTracesW&B Cloud · Dedicated Cloud · Self-ManagedW&B account
ElasticTraces + metrics + logsElastic Cloud (mOTLP) · self-hosted EDOT CollectorElastic license / cloud plan
Azure Monitor (via the Collector, generic otlp)Traces + metrics + logsAzure subscription + the repo's Collector containerAzure pricing; documented, not verified
OpenLITTraces + metrics + logsLocal (docker compose, 2 containers) · HelmOSS (Apache-2.0), no account
MLflowTracesLocal (docker compose, 1 container) · Helm · DatabricksOSS (Apache-2.0), no account
Comet OpikTracesLocal (docker compose, 7 containers) · Helm · Comet cloudOSS (Apache-2.0) · free cloud tier
LaminarTraces + logsLocal (docker compose, 5 containers) · Helm · Laminar cloudOSS (Apache-2.0) · free cloud tier
LangWatchTraces + metrics + logsLocal (docker compose, 5 containers) · Helm · LangWatch cloudOSS (Apache-2.0) · free cloud tier
LatitudeTracesLocal (docker compose, 13 containers) · Helm · Latitude cloudOSS (MIT) · free cloud tier
telemetry.dev (via generic otlp)Traces + metrics + logsCloudFree tier + paid plans
Generic OTLPDepends on collectorAnywhere—

Quick picks​

"I just want to see a trace, right now, on my laptop" → Phoenix — one container, open the UI on port 6006, done. Or the Aspire Dashboard — one container, all three signals, a GenAI visualizer, and the plugin dashboard reads traces and logs back.

"I want pretty LLM-specific UI and I'm fine running a stack" → Langfuse — polished UI for LLM traces, free cloud tier, robust self-host.

"I want traces and the token/tool/cost metrics dashboard" → SigNoz, LGTM or OpenObserve — they accept OTLP metrics as well as traces (Phoenix does not).

"I want the Grafana APIs without running Grafana's stores" → Gigapipe — OTLP in, the Tempo, Prometheus and Loki APIs out of one port on ClickHouse; the plugin reads it with its LGTM adapters.

"I run VictoriaMetrics and want traces and logs in the same family" → VictoriaTraces + VictoriaMetrics + VictoriaLogs — one entry, three stores; the dashboard reads them through the Jaeger, Prometheus and LogsQL APIs.

"I want ClickHouse's own observability stack with a search UI" → ClickStack — HyperDX on ClickHouse in one container, traces + metrics + logs in the standard OTel tables; the dashboard adapter reads them straight from ClickHouse.

"I want all three signals in one open-source database I can query with SQL" → GreptimeDB — one container, OTLP in under /v1/otlp, SQL, PromQL and a Jaeger-compatible API out; the dashboard adapter reads all three signals.

"I want all three signals — traces, metrics, AND logs — in Grafana, in one container" → Grafana LGTM — grafana/otel-lgtm bundles Grafana + Tempo + Loki + Mimir + a collector. Turn on logs: {capture: true} and you get trace-id-correlated logs out of the box.

"I'm already on LangChain / LangSmith" → LangSmith — free personal tier, zero extra infra.

"Standard distributed tracing stack, no LLM-specific UI needed" → Jaeger, Zipkin or Grafana Tempo — all three are traces-only; pair with Prometheus if you need metrics. Zipkin is the lightest read API of the three and the dashboard adapter reads it.

"I want Claude Code, Cursor or Hermes itself to search the traces over MCP" → Jaeger (v1) or Grafana Tempo, read by Traceloop's opentelemetry-mcp server; verified setup and caveats in Query your traces over MCP.

"I want a cloud backend with a generous free tier and all three signals" → Honeycomb — OTLP-native; set OTEL_HONEYCOMB_API_KEY and a region.

"I want W&B's Agents and Traces UI for Hermes runs" → W&B Weave — direct OTLP trace ingest with OTEL_WEAVE_API_KEY, wandb.entity, and wandb.project.

"I want Hermes agent runs plus traces, metrics, and logs in Parseable" → Parseable — direct OTLP ingest into three datasets, with Agent Observability and a ready-made dashboard.

"I want a hosted backend purpose-built for LLM/agent telemetry, gen_ai.*-native" → telemetry.dev — OTLP ingest with a single Authorization: Bearer header, via the generic otlp type.

"I want an OTel-native LLM UI with all three signals, self-hosted and light" → OpenLIT — two containers, gen_ai.*-aware views, traces + metrics + logs on the standard /v1/* paths.

"We already run MLflow for experiments" → MLflow — traces land in an experiment next to your runs, with MLflow's own token and cost roll-ups.

"I want the richest LLM-trace view of the self-hosted batch: threads, span types, cost per call" → Comet Opik — maps both gen_ai.* and llm.* conventions; thread_id is the Hermes session.

"An agent-focused trace UI that also keeps the agent's log lines" → Laminar — span types, tokens and cost per call, plus log records next to the trace; metrics are off because Laminar drops them.

"An open-source LLMOps platform that reads both conventions and queries back" → Agenta — OTLP traces with a project key; span types, token roll-ups and sessions computed server-side; the dashboard adapter reads POST /api/spans/query.

"An LLM platform with all three signals and an evaluation workflow" → LangWatch — traces, metrics and logs under one /api/otel prefix; thread id = the Hermes session.

"Our observability is already Elastic (self-hosted or Elastic Cloud)" → Elastic — one type: elastic entry covers the managed OTLP endpoint (ApiKey auth) and a self-hosted EDOT Collector (no key needed).

"My company already has an OTel collector / New Relic / Datadog" → Generic OTLP — point at its ingest endpoint and it just works.

"We are on Azure / Application Insights" → Azure Monitor — no static-header OTLP endpoint exists, so the repo's Collector with COLLECTOR_TARGET=azuremonitor sends with the connection string; type: otlp at :4448.

"I want several of the above simultaneously" → Multi-backend fan-out — same spans, parallel, non-blocking.

Signal support​

Backends differ in which OTel signals they accept. Each backend type turns off, by default, the signals its backend can't take, so you don't need to configure anything. An explicit traces / metrics / logs on the entry still wins.

BackendTracesMetricsLogs
Phoenix✅❌ (rejects /v1/metrics; the plugin defaults metrics: false)❌
Langfuse✅❌❌
LangSmith✅❌❌
SigNoz✅✅✅
Jaeger✅❌❌
Zipkin✅❌ (/v1/metrics is 404)❌ (/v1/logs answers 202 but stores a record only as a span annotation; off by default)
GreptimeDB✅✅ (no exponential histograms)✅
ClickStack✅✅✅
VictoriaMetrics family✅✅ (when metrics_endpoint names VictoriaMetrics)✅ (when logs_endpoint names VictoriaLogs)
Aspire Dashboard✅✅ (no exponential histograms)✅
Gigapipe✅✅ (cumulative only)✅
Agenta✅❌❌
Grafana Tempo✅❌❌
Grafana LGTM✅✅✅
Uptrace✅✅✅
OpenObserve✅✅✅
Parseable✅✅✅
Honeycomb✅✅✅
W&B Weave✅❌❌
Elastic✅✅✅
Azure Monitor (via the Collector)✅✅ (converted to delta in the Collector)✅
OpenLIT✅✅✅
MLflow✅❌❌
Comet Opik✅❌❌
Laminar✅❌ (accepted and dropped; off by default)✅
LangWatch✅✅✅
Latitude✅❌❌
telemetry.dev✅✅✅
Generic OTLP✅✅ on by default; set metrics: false if the collector rejects it✅ on by default; set logs: false if the collector rejects it

If you care about token / tool / cost metrics on a traces-only backend, pair it with a Prometheus-compatible sink or fan out to SigNoz / LGTM / OpenObserve alongside. See OTel logs for the logs pipeline.

Metrics and your backend​

Two metric settings depend on the backend (since 1.15; details on the metrics reference):

BackendTemporality it wantsPresetExponential histograms
Grafana LGTM, Tempo-side Prometheus, Mimircumulative (delta is dropped unless otlp-deltatocumulative is on)cumulative (default)Prometheus 3.8+ native histograms; Mimir only with native-histogram ingestion enabled
OpenObservecumulative works; delta handling undocumentedcumulative (default)not documented
ClickStackeither: the ClickHouse exporter stores every point as sentcumulative (default)stored (otel_metrics_exponential_histogram)
VictoriaMetricscumulative natively; delta stored as-is since v1.132 (query with sum_over_time)cumulative (default)converted to VictoriaMetrics vmrange histograms
Gigapipecumulative only: delta points are rejected one by one (partial_success)cumulative (default)converted to _bucket / _sum / _count
Aspire Dashboardeither (stored as sent)cumulative (default)rejected ("is not supported"); keep metrics_histogram: explicit
GreptimeDBeither: stores cumulative and delta points as sentcumulative (default)rejected (ExponentialHistogram is not supported yet); keep metrics_histogram: explicit
SigNozrecommends delta; exponential histograms are delta-only and self-hosted-onlydeltaself-hosted only
Uptraceprefers delta, converts cumulativedeltarecommended
Honeycombeithercumulative (default)not verified
Parseable, generic otlpdepends on the collector behind itcumulative (default)depends
Elasticdelta required (ES does not handle cumulative histograms)deltaaccepted
Azure Monitor (via the Collector)delta required for the Application Insights experiences (Microsoft's statement); the azuremonitor target runs cumulative_to_deltacumulative (default; the Collector converts)required by the same statement; not converted by the target, metrics_histogram: exponential is global
OpenLITcumulative stored as-is (verified)cumulative (default)stored (exponential histogram type)
Datadog, New Relic, Logfire (via generic otlp today, explicit types tracked in #232)delta required (Datadog rejects cumulative sums; Logfire dashboards stay empty on cumulative; New Relic prefers delta)set metrics_temporality: delta on the entryDatadog and New Relic accept them

Override per entry with metrics_temporality: cumulative | delta, or for every backend with the top-level metrics_temporality. Backends that total a trace by summing every span's gen_ai.usage.* (Opik, LangWatch) are sent the agent root without its token roll-up (root_usage: false, the preset for those two types; true elsewhere), so their trace totals equal the sum of the api.* spans while Phoenix, Langfuse and the rest keep the roll-up on the root. metrics_histogram: exponential switches every backend to base-2 exponential histograms, so use it only when all of them accept those.

Short-lived runs. hermes -z exports metrics once, when it exits. A single cumulative point from a fresh process counts as zero on Datadog and New Relic (they treat the first point as a baseline) and goes stale after five minutes on Prometheus; the same run exported as delta counts in full on every delta-capable backend. Long-lived gateways are unaffected either way.

Selecting a single backend​

Single-backend selection is env-var-driven. First match wins:

  1. OTEL_LANGSMITH_API_KEY (or OTEL_LANGSMITH_ENDPOINT) set → LangSmith
  2. Langfuse credentials + at least one OTEL_LANGFUSE_* variable (OTEL_LANGFUSE_PUBLIC_API_KEY, OTEL_LANGFUSE_SECRET_API_KEY or OTEL_LANGFUSE_ENDPOINT) → Langfuse
  3. OTEL_SIGNOZ_ENDPOINT set → SigNoz
  4. OTEL_UPTRACE_ENDPOINT + DSN set → Uptrace
  5. OTEL_OPENOBSERVE_ENDPOINT + credentials set → OpenObserve
  6. OTEL_PARSEABLE_ENDPOINT + OTEL_PARSEABLE_API_KEY (or PARSEABLE_API_KEY) set → Parseable
  7. OTEL_WEAVE_API_KEY (or OTEL_WEAVE_ENDPOINT / OTEL_WEAVE_BASE_URL) + WANDB_ENTITY + WANDB_PROJECT set → W&B Weave
  8. OTEL_HONEYCOMB_API_KEY (or OTEL_HONEYCOMB_ENDPOINT) set → Honeycomb
  9. OTEL_ELASTIC_ENDPOINT set → Elastic (OTEL_ELASTIC_API_KEY optional: a local EDOT Collector needs none, and a key alone never opts in because Elastic has no default host)
  10. OTEL_OPENLIT_ENDPOINT set → OpenLIT (OTEL_OPENLIT_API_KEY optional, same rule)
  11. OTEL_MLFLOW_ENDPOINT set → MLflow (MLFLOW_EXPERIMENT_ID optional, default 0)
  12. OTEL_OPIK_API_KEY (cloud, with OPIK_WORKSPACE) or OTEL_OPIK_ENDPOINT set → Comet Opik
  13. OTEL_LAMINAR_API_KEY set (cloud, or with OTEL_LAMINAR_ENDPOINT) → Laminar
  14. OTEL_LANGWATCH_API_KEY set (cloud, or with OTEL_LANGWATCH_ENDPOINT) → LangWatch
  15. OTEL_LATITUDE_API_KEY + LATITUDE_PROJECT set (cloud, or with OTEL_LATITUDE_ENDPOINT) → Latitude
  16. OTEL_AGENTA_API_KEY set (cloud, or with OTEL_AGENTA_ENDPOINT) → Agenta
  17. OTEL_CLICKSTACK_ENDPOINT + OTEL_CLICKSTACK_API_KEY (or HYPERDX_API_KEY) set → ClickStack
  18. OTEL_GREPTIME_ENDPOINT set → GreptimeDB (OTEL_GREPTIME_DB, OTEL_GREPTIME_USER / OTEL_GREPTIME_PASSWORD optional)
  19. OTEL_VICTORIA_ENDPOINT set → VictoriaTraces (OTEL_VICTORIA_METRICS_ENDPOINT / OTEL_VICTORIA_LOGS_ENDPOINT switch metrics and logs on)
  20. OTEL_ASPIRE_ENDPOINT set → Aspire Dashboard (OTEL_ASPIRE_API_KEY optional)
  21. OTEL_GIGAPIPE_ENDPOINT set → Gigapipe (OTEL_GIGAPIPE_USER / OTEL_GIGAPIPE_PASSWORD optional)
  22. OTEL_JAEGER_ENDPOINT set → Jaeger
  23. OTEL_ZIPKIN_ENDPOINT set → Zipkin
  24. OTEL_TEMPO_ENDPOINT set → Tempo
  25. OTEL_PHOENIX_ENDPOINT set → Phoenix

Vendor SDK variables (LANGSMITH_API_KEY, LANGFUSE_PUBLIC_KEY / LANGFUSE_SECRET_KEY, WANDB_API_KEY, HONEYCOMB_API_KEY, ELASTIC_API_KEY, OPENLIT_API_KEY, MLFLOW_TRACKING_TOKEN, OPIK_API_KEY, LMNR_PROJECT_API_KEY, LANGWATCH_API_KEY, LATITUDE_API_KEY, HYPERDX_API_KEY, AGENTA_API_KEY) only fill in credentials. On their own they never switch export on, because they are often set for other tools and Hermes loads $HERMES_HOME/.env into the process; one plugin-namespaced OTEL_* variable is the explicit opt-in. When such credentials are present without the opt-in, the startup log says which OTEL_* variable would enable export, and the dashboard's OTel → Settings → Environment view shows the same notice.

Setting backends: in hermes_otel.yaml overrides the env-var flow entirely — see Multi-backend fan-out.

What each backend does differently​

Every one of these speaks OTLP, and every one of them differs in where it listens, which header carries the key, which signals it stores, which metric temporality it wants, how it totals tokens over a trace, what it truncates, and which API gives the data back. Backend quirks is the per-category comparison and lists, per backend, what the plugin does about each difference. In the repo the same catalog is docker-compose/QUIRKS.md.

Running one locally​

Every self-hostable backend above, plus the candidates tracked in #232, has its own folder under docker-compose/ in the repo: docker compose -f docker-compose/<name>/docker-compose.yaml up -d, and down -v to remove it with its data. Each folder has a README (why pick it, logins, the backends: snippet, verification query, caveats), and docker-compose/README.md is the manual: the comparison table, the port map, disk/memory budgets and the test loop.

Backends without an explicit type: yet are driven through the generic otlp type; each was verified end to end on 2026-10-05 with hermes-otel 1.19.0 (OpenLIT, MLflow, Opik, Laminar, LangWatch and Latitude have explicit types since 1.23):

BackendCompose fileStored from a Hermes turnPlugin config
OpenLIT (#222)openlit/traces + metrics + logstype: openlit, http://localhost:4338 (explicit type since 1.23)
MLflow (#221)mlflow/traces (with MLflow's own token and cost roll-ups)type: mlflow, http://localhost:5001 (explicit type since 1.23)
Comet Opik (#220)opik/traces (threads, span types, cost)type: opik, http://localhost:5173 (explicit type since 1.23)
Laminar (#223)laminar/traces + logs; metrics accepted and droppedtype: laminar, http://localhost:8100, api_key_env (explicit type since 1.23)
LangWatch (#229)langwatch/traces + metrics + logstype: langwatch, http://localhost:5560, api_key_env (explicit type since 1.23)
Langtrace (#224)langtrace/traces (string and int attributes only)type: otlp, http://localhost:3040/api/trace, header x-api-key, metrics: false, logs: false
Sigiro (#71)sigiro/traces + metrics + logstype: otlp, http://localhost:4378/v1/traces
OpenTelemetry Collector (#368)collector/traces + metrics + logs, printed (debug) or forwarded (otlphttp, verified into the viewer); Azure Monitor / AWS / Google Cloud targets documentedtype: otlp, http://localhost:4448/v1/traces; COLLECTOR_TARGET picks the destination
otel-desktop-viewer (#367)otel-desktop-viewer/traces + metrics + logs (5 spans, 27 log records, 13 metric names from one turn)type: otlp, http://localhost:4428/v1/traces; UI :3070, JSON-RPC POST /rpc. otel-tui is the terminal sibling: a docker run line in the same README, :4438
Maple Local (#49)maple/traces + metrics + logstype: otlp, http://localhost:4388/v1/traces
Parseable OSS (#238)parseable/traces + metrics + logs, through the bundled collectortype: otlp, http://localhost:4348/v1/traces
Zipkin (#364)zipkin/traces (7 spans from one turn; every attribute a string tag)type: zipkin, http://localhost:9411 (the zipkin-otel image; stock Zipkin has no OTLP)
Agenta (#371)agenta/traces (7 spans with Agenta's token roll-ups from one turn)type: agenta, http://localhost:3060, api_key_env (key from agenta/mint-api-key.sh)
Gigapipe (#370)gigapipe/traces + metrics + logs (7 spans, 28 log lines, 27 metric names from one turn)type: gigapipe, http://localhost:3110
Aspire Dashboard (#369)aspire/traces + metrics + logs (7 spans, 28 log rows from one turn; metrics in the UI only)type: aspire, http://localhost:4418, query_port: 18888
VictoriaTraces + VictoriaLogs + VictoriaMetrics (#366)victoria/traces + metrics + logs (7 spans, 28 log rows, 27 metric names from one turn)type: victoria, endpoint :10428 + metrics_endpoint :8428 + logs_endpoint :9428
ClickStack (#365)clickstack/traces + metrics + logs (7 spans, 28 log rows, 13 metric names from one turn)type: clickstack, http://localhost:4408, api_key_env (key from clickstack/mint-api-key.sh)
GreptimeDB (#363)greptime/traces + metrics + logs (7 spans, 28 log rows, 27 metric tables from one turn)type: greptime, http://localhost:4398 (the trace pipeline header on traces only)
Latitude (#230)latitude/traces (13 containers, ~15 GB of images)type: latitude, http://localhost:3002, api_key_env + project (explicit type since 1.23)

Elastic (elastic/: Elasticsearch + Kibana + EDOT Collector, type: elastic) was added on 2026-10-07 and verified with hermes-otel 1.21.0. Two of these are not open source: Sigiro publishes only a binary image, and Maple is source-available under FSL-1.1. Jaeger v2 (jaeger-v2/) and Langfuse v4 (LANGFUSE_VERSION=4) have their own stacks so the read-side issues #245 and #246 can be reproduced locally.

Planned​

These are OTLP-compatible and should work today with the generic OTLP backend — first-class docs, docker-compose files, and smoke tests are on the roadmap:

File an issue if you've tried one of these and hit friction — we'll prioritise.