Visitar URL original
GitHub - grafana/otel-checker: Otel Me If It's Right project · GitHub
Skip to content

About

Otel Me If It's Right project

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

39 stars

Watchers

7 watching

Forks

OTel Me If It's Right

Checker for if the implementation of OpenTelemetry instrumentation is correct by scanning the code in your repository, checking environment variables, validating your Grafana token and more.

Usage

For source installs, you need Go 1.26 or higher. Prebuilt binaries are also available from the GitHub Releases page.

Installation

Prebuilt binaries

Download the archive for your operating system and CPU architecture from the latest release, extract it, and put the otel-checker binary on your PATH. Release archives are provided for Linux, macOS, and Windows on amd64 and arm64. The statically linked Linux archives work on both glibc- and musl-based distributions, such as Alpine Linux. checksums.txt contains SHA-256 checksums for verification.

Go install

  1. Install the otel-checker binary

    go install github.com/grafana/otel-checker/cmd/otel-checker@latest
    
  2. You can confirm it was installed with:

    ❯ ls $GOPATH/bin
    otel-checker
    

Commands

otel-checker check                  # all components
otel-checker check sdk              # SDK only
otel-checker check collector        # Collector config only
otel-checker check beyla            # Beyla only
otel-checker check alloy            # Grafana Alloy only
otel-checker check grafana-cloud    # Grafana Cloud connectivity only
otel-checker check config           # OpenTelemetry declarative config file only
otel-checker serve                  # web UI for a previously-saved JSON result
otel-checker explain                    # show explanations for every finding from a saved results file
otel-checker explain <id>               # show the explanation for a single ID
otel-checker explain list               # list every available explain ID
otel-checker version                    # print the binary version
otel-checker completion <shell>         # generate shell completion script

The check command takes an optional comma-separated list of components (check sdk,collector,beyla). With no argument, every component is checked.

Run otel-checker check --help or otel-checker check sdk --help for the full flag set on each subcommand.

Examples

# Single-component checks
otel-checker check sdk --language=js
otel-checker check sdk --language=java --manual-instrumentation
otel-checker check collector --collector-config-path=./otel/config.yaml
otel-checker check config --config-path=./otel-config.yaml
otel-checker check grafana-cloud --language=python

# Multi-component (positional, comma-separated, no spaces)
otel-checker check sdk,collector,beyla --language=js

# Every component at once
otel-checker check --language=js

Still missing telemetry?

Static checks do not prove runtime export or ingestion. Whether a finding needs runtime investigation or checks passed but data is absent, follow Runtime debugging with gcx. The guide includes the setup path if you do not yet have gcx or a telemetry backend.

Explanations

Each actionable finding (errors and warnings) is tagged with a stable explain ID. In the default table output the ID appears in the EXPLAIN_ID column:

 STATUS  COMPONENT  MESSAGE                              EXPLAIN_ID
 FAIL    SDK        package.json missing on path /src/inst  js.package-json.unreadable

Look up the guidance for any finding with:

otel-checker explain js.package-json.unreadable

Or enumerate every available explain ID:

otel-checker explain list

To see explanations for every finding from a previous run, save the JSON output once and call explain with no ID:

otel-checker check --language=js --format=json > results.json
otel-checker explain

With no ID, explain reads ./results.json by default (also ./results.yaml / ./results.yml) — the same file serve watches — and prints each explain doc in turn, deduplicating repeated IDs and skipping findings that have none. Pass --data=<path> to point at a different file.

The same IDs also appear as a explain_id field on every entry when using --format=json or --format=yaml, so downstream tooling can match findings against the explain catalog programmatically.

Output formats

By default results are printed as colored text. Use --format=json or --format=yaml for machine-readable output suitable for CI pipelines:

otel-checker check sdk --language=go --format=json

Web UI

Pass --web-server to any check invocation to also serve the results at http://127.0.0.1:8080. Override the bind address with --listen=host:port; the default binds to loopback only. Press Ctrl-C to shut the server down cleanly.

Serving a results file

otel-checker serve watches a JSON or YAML results file on disk and renders it in the web UI. The page polls every few seconds, so the moment the file is created or rewritten the browser picks up the new content automatically.

By default, serve looks for ./results.json, then ./results.yaml, then ./results.yml in the current directory. If none exist yet, the server still starts and shows a placeholder pointing at the expected path — useful for keeping the UI open while a long-running pipeline writes results.

# Start the server (looks for ./results.json by default)
otel-checker serve

# In another terminal, write the file; the UI updates on the next poll
otel-checker check sdk --language=go --format=json > results.json

# Point at a specific file or a different format
otel-checker serve --data=./out/results.yaml

Kubernetes

To validate an application deployed to a Kubernetes pod, see the Kubernetes runbook.

Checks

Common Environment Variables

These checks are automatically performed for all languages and components.

  • Signal exporters (OTEL_TRACES_EXPORTER, OTEL_METRICS_EXPORTER, OTEL_LOGS_EXPORTER): must be otlp, console, or unset; none is rejected.
  • Service name: OTEL_SERVICE_NAME (or service.name in OTEL_RESOURCE_ATTRIBUTES).
  • Resource attributes checks:
    • Validates the presence of recommended OpenTelemetry resource attributes
    • Checks for the following attributes:
      • service.name (via OTEL_SERVICE_NAME or in OTEL_RESOURCE_ATTRIBUTES)
      • service.namespace (e.g., shop)
      • deployment.environment.name (e.g., production)
      • service.instance.id (e.g., checkout-123)
      • service.version (e.g., 1.2)
    • For missing attributes, provides specific recommendations with example values
    • Follows the OpenTelemetry specification for precedence (e.g., OTEL_SERVICE_NAME takes precedence over service.name in OTEL_RESOURCE_ATTRIBUTES)
    • Example warning: Set OTEL_RESOURCE_ATTRIBUTES="service.namespace=shop": An optional namespace for service.name

When a declarative config file is present (see the Config section below), resource attribute checks source from the file's resource.attributes and resource.attributes_list blocks instead of OTEL_RESOURCE_ATTRIBUTES, with env-var substitutions (${VAR}, ${VAR:-default}) resolved against the process environment. Warnings then point at the config file (config.resource-attributes.missing, config.service-name.unset) instead of the env-var equivalents.

Grafana Cloud

Run otel-checker check grafana-cloud (add --language=python if the customer uses Python — that variant expects the URL-encoded Authorization=Basic%20<token> form; every other language uses the literal-space form, which is also the default when --language is omitted):

  • OTEL_EXPORTER_OTLP_ENDPOINT matches https://otlp-gateway-<zone>.grafana.net/otlp.
  • OTEL_EXPORTER_OTLP_PROTOCOL is http/protobuf.
  • OTEL_EXPORTER_OTLP_HEADERS contains an Authorization=Basic <token> entry.
  • Credential validation: tests the endpoint with the provided token.

When a declarative config file is present, endpoint validation reads from the file's otlp_http blocks (with env-var substitution) instead of the env vars, and the auth-header / credential-HTTP checks are skipped. See the Config section.

SDK

JavaScript

Run otel-checker check sdk --language=js:

  • Node version — must be an Active LTS release (even-major, currently 22, 24, or 26). Odd-major Current releases (23, 25) are flagged as well.
  • @opentelemetry/api dependency in package.json.
  • Auto-instrumentation mode (default):
    • @opentelemetry/auto-instrumentations-node dependency.
    • NODE_OPTIONS includes --require @opentelemetry/auto-instrumentations-node/register.
    • OTEL_NODE_RESOURCE_DETECTORS set to all or covers env,host,os,serviceinstance.
  • Manual-instrumentation mode (--manual-instrumentation):
    • No concurrent auto-instrumentation via NODE_OPTIONS.
    • Uses @opentelemetry/exporter-trace-otlp-http (not -otlp-proto).
    • Warns when ConsoleSpanExporter / ConsoleMetricExporter is used outside debugging.
  • Supported libraries: package.json dependencies are matched against the OpenTelemetry JS contrib registry.

Python

Run otel-checker check sdk --language=python:

  • Supported libraries: requirements.txt dependencies are matched against the OpenTelemetry Python contrib registry.

.NET

Run otel-checker check sdk --language=dotnet:

  • .NET version (>= 8.0).
  • Auto-instrumentation environment variables:
    • CORECLR_ENABLE_PROFILING = 1
    • CORECLR_PROFILER = {918728DD-259F-4A6A-AC2B-B85E1B658318}
    • CORECLR_PROFILER_PATH is set
    • OTEL_DOTNET_AUTO_HOME is set
  • Supported instrumentations: .csproj NuGet dependencies are matched against the OpenTelemetry .NET auto-instrumentation library list.

Note

Only .NET 8.0 and higher are supported

Java

Run otel-checker check sdk --language=java:

  • Java version (>= 8).
  • Supported libraries (discovered from a locally running Maven or Gradle, including a wrapper if found in the current directory or a parent):
    • Without --manual-instrumentation: libraries supported by the Java Agent.
    • With --manual-instrumentation: libraries with manual instrumentation support.

Go

Run otel-checker check sdk --language=go:

  • Supported libraries for manual instrumentation, based on go.mod in the current directory.

Ruby

Run otel-checker check sdk --language=ruby:

  • Ruby version (CRuby >= 3.3, JRuby >= 9.4, or TruffleRuby >= 22.1).
  • Bundler installed.
  • Gemfile and Gemfile.lock exist.
  • Required gems: opentelemetry-api, opentelemetry-sdk, opentelemetry-exporter-otlp.
  • Auto-instrumentation (default): opentelemetry-instrumentation-all or at least one specific instrumentation gem (e.g. -rack, -rails).

PHP

Run otel-checker check sdk --language=php:

  • PHP version (>= 8.0).
  • Composer installed.
  • composer.json and composer.lock exist.
  • Required packages: open-telemetry/api, open-telemetry/sem-conv, open-telemetry/sdk, open-telemetry/exporter-otlp.
  • Auto-instrumentation (default): at least one instrumentation package (e.g. symfony, pdo, laravel, wordpress, guzzle).

Collector

Run otel-checker check collector:

  • config.yaml exists and is readable, and parses as valid YAML.
  • At least one otlp receiver has the http protocol configured.
  • At least one otlphttp / otlp_http exporter has an endpoint matching the Grafana Cloud format (https://*.grafana.net/otlp); warns when set to localhost.
  • For each of the traces, metrics, and logs pipelines: the exporter list contains an otlphttp / otlp_http exporter, and the receiver list contains an otlp receiver.

Named components (e.g. otlphttp/grafana_cloud, otlp/app) are supported.

Config (declarative configuration)

Run otel-checker check config:

  • otel-config.yaml (or otel-config.yml) exists and parses as valid YAML matching the OpenTelemetry declarative configuration schema. Override the path with --config-path=<file>.
  • file_format is declared at the top level.
  • Each of the three signals (traces, metrics, logs) declares at least one otlp_http endpoint under its provider (endpoint format validated by the Grafana Cloud check):
    • Traces: tracer_provider.processors[].batch|simple.exporter.otlp_http.endpoint
    • Metrics: meter_provider.readers[].periodic|pull.exporter.otlp_http.endpoint
    • Logs: logger_provider.processors[].batch|simple.exporter.otlp_http.endpoint
  • Recommended resource attributes are declared under resource.attributes or resource.attributes_list. Both blocks contribute; per spec, attributes entries have higher priority than attributes_list when both declare the same key. Reported IDs: config.service-name.unset, config.resource-attributes.missing.
  • Every key in the file is checked against the generated schema model. Fields the schema doesn't know about (typos, deprecated fields, or a checker schema that's out of date) surface as config.unknown-field warnings. Schema-level extension slots like custom sampler / processor variants are silently accepted per spec. The warning fires only for keys inside strict (additionalProperties: false) containers.

Environment-variable substitution is applied to every string value the checker consumes (endpoints, resource attribute values, attributes_list). Supported forms:

  • ${VAR} and ${env:VAR} — resolves to the process env; unresolved reference fires config.env-var.unresolved.
  • ${VAR:-default} — uses default verbatim when VAR is unset or empty.
  • $$ — escape sequence for a literal $; $${VAR} produces the literal string ${VAR} (unexpanded).

Substitution is single-pass per spec — if a resolved value itself contains ${...}, the placeholder is left literal, NOT re-expanded.

The declarative config and OpenTelemetry environment variables are mutually exclusive per the OTel spec. When --config-path is passed (or a default otel-config.yaml is present):

  • The Grafana Cloud check reads OTLP endpoints from the config file and skips the env-var, auth-header, and credential-HTTP checks.
  • The Common Environment Variables resource-attribute checks read from resource: in the config file instead of OTEL_RESOURCE_ATTRIBUTES / OTEL_SERVICE_NAME.
  • When running check config alone (without also selecting grafana-cloud), the endpoint check is driven from the config component so check config produces a complete report; when both components are selected, endpoint findings are reported once under Grafana Cloud.

Without a config file, all env-var-based behavior is unchanged.

Beyla

Note

TBD

Alloy

Note

TBD

About

Otel Me If It's Right project

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

39 stars

Watchers

7 watching

Forks

Releases

Used by

Contributors

Languages