Skip to content
Tracelet
v0.1.0First release, pinned to otelcol-contrib v0.164.0

Test your telemetry pipelines.

Catch broken OpenTelemetry Collector configurations before they reach production.

Tracelet runs the real otelcol-contrib binary with your processors and connectors, injects OTLP fixtures you write, captures what each exporter would have sent, and checks it against declarative assertions in YAML.

macOS and Linux

curl -fsSL https://github.com/SATVIKsynopsis/Tracelet/releases/latest/download/install.sh | sh

Installs otel-test to ~/.local/bin. On Windows, download the .zip.

test “passwords are removed from spans”

traces

inject

fixtures/login-span.json

processor

filter/healthz

processor

attributes/redact

processor

batch

exporter

otlp_http/backend

  • attribute password is absent
  • attribute http.route equals "/login"
  • exporter otlp_http/backend receives 1 item(s)
Illustration of one test: a span fixture is injected, passes through the filter, attributes and batch processors of the starter configuration, is captured at the otlp_http/backend exporter, and three assertions pass.

Demo

Two commands to a passing suite.

otel-test init writes a starter project: a Collector config that deletes passwords, hashes user names and drops health checks, with one test for each.

Break the config and the same suite tells you which item failed, at which exporter, and with what value.

Output from the published v0.1.0 release. The first run also downloads the pinned Collector (about 100 MB). Times depend on your machine and on each test's observation window.

$ otel-test init
otel-test v0.1.0
 
created ./otel-test.yaml
created ./collector.yaml
created ./fixtures/login-span.json
created ./fixtures/login-log.json
created ./fixtures/healthz-span.json
 
$ otel-test test
otel-test v0.1.0
 
Collector: v0.164.0
Config: collector.yaml
Tests: 3
 
✓ passwords are removed from spans
✓ passwords are removed from logs
✓ health checks are dropped
 
3 passed, 0 failed
 
Time: 8.50s

otel-test init, then otel-test test on the generated project.

Features

Policy you can run in CI.

Collector configs decide what is redacted, sampled, dropped and routed. Tracelet turns those decisions into tests that fail loudly when a config change breaks them.
  • 01

    Real Collector execution

    Your processors, connectors and pipeline order run unchanged in the real otelcol-contrib binary. Nothing is simulated.

    pinned v0.164.0 · SHA-256 verified

  • 02

    Custom telemetry fixtures

    Fixtures are standard OTLP/JSON request bodies for traces, logs or metrics, posted byte for byte to the Collector’s own receiver.

    resourceSpans · resourceLogs · resourceMetrics

  • 03

    Declarative assertions

    Check that attributes are present, absent, equal to a typed value or match a regex, that telemetry was dropped, or how many items reached an exporter.

    present · absent · equals · matches · dropped · count

  • 04

    Pipeline configuration analysis

    Specs, configs and fixtures are checked before anything runs. Every problem is reported at once with its location, and the rewritten config must pass otelcol validate.

    otel-test validate

  • 05

    Regression testing

    Each test runs in a fresh Collector. Attribute checks fail when nothing arrived, so a redaction test cannot pass because the data never came.

    17 deliberate regressions caught in the examples

  • 06

    CI-friendly CLI

    Distinct exit codes for failed assertions, invalid specs, invalid configs, Collector problems and execution errors. Color and downloads are controllable.

    --offline · --filter · NO_COLOR · exit 0–5

  • 07

    Rust-powered

    One self-contained binary with a built-in OTLP/HTTP and OTLP/gRPC capture server. Release builds for macOS, Linux and Windows.

    otel-test · ~5 MB archive

  • 08

    Traces, logs and metrics

    All three signals are tested end to end through the real Collector, including routing between them with connectors. Profiles pipelines are rejected.

    spans · log records · data points

How it works

Only the edges change.

Receivers and exporters are swapped for local endpoints. Processors, connectors, pipeline IDs and processor order are copied verbatim, so the code in the middle is exactly what runs in production.

Inputs

Your project

collector.yaml

fixtures/*.json

otel-test.yaml

Tracelet

otel-test

analyze

rewrite

validate

Real process

otelcol-contrib

receiverprocessors · connectorsexporter

dashed: replaced
solid: copied verbatim

Capture

Exporter boundary

otlp_http/backend

datadog

kafka/shared

Results

Assertions

✓ passed

✗ failed

exit code

Captured telemetry is reported under your original exporter IDs.
  1. 01

    Analyze

    Parse otel-test.yaml, the Collector config and every fixture. Report every problem at once, with its location.

  2. 02

    Rewrite

    Replace each receiver with a local OTLP/HTTP endpoint and each exporter with a capture exporter that keeps its ID.

  3. 03

    Validate

    Run otelcol validate on the rewritten config before anything starts.

  4. 04

    Run

    Start a fresh Collector for each test and wait until it reports ready.

  5. 05

    Inject

    POST the fixture to the chosen receiver. The Collector must accept it.

  6. 06

    Capture

    Record what reaches each exporter during the observation window and the graceful shutdown.

  7. 07

    Report

    Evaluate assertions and print expected vs. actual for every failure.

Use cases

Five production-style configs, tested.

Each example in the repository ships a realistic Collector config, its fixtures and tests, and a set of deliberate regressions that the suite must catch. They run against the pinned Collector with no mocks.
  • 01

    PII redaction

    A payment gateway applies an attribute allowlist and masks card numbers and e-mail addresses, even on allowed keys.

    • redaction
    • memory_limiter
    • batch
    Tests
    3
    Regressions caught
    2
    For example
    user.password added to allowed_keys "for debugging"
  • 02

    Tenant routing

    Each tenant's spans reach only that tenant's backend. Unknown tenants go to a shared topic. Errors are also copied to alerting.

    • routing
    • forward
    • filter
    Tests
    5
    Regressions caught
    3
    For example
    a copy-pasted routing rule sending globex spans to acme
  • 03

    Sampling and filtering

    Probe traffic is dropped first, then tail sampling keeps errors, slow requests and enterprise customers.

    • filter
    • tail_sampling
    Tests
    6
    Regressions caught
    4
    For example
    an always_sample policy quietly added as a baseline
  • 04

    Metrics transformation

    Legacy semantic conventions are renamed, user.id is aggregated away, runtime noise is dropped and the environment is stamped.

    • transform
    • metrics_transform
    • filter
    • resource
    Tests
    5
    Regressions caught
    4
    For example
    aggregation moved before the rename, which loses a series
  • 05

    Log redaction

    Secrets are removed from JSON log bodies and attributes, user IDs are hashed and client IPs truncated to /24.

    • transform (OTTL)
    • filter
    Tests
    6
    Regressions caught
    4
    For example
    secret deletion moved before JSON parsing

Scope

What runs, and what doesn't.

Tracelet tests what happens between your receivers and exporters. It is not an end-to-end test of your observability backends.

All known limitations

Tested

  • Processors and connectors, in your pipeline order
  • Routing between pipelines, including connectors
  • Which exporter receives what, and how many items
  • Attributes at item, scope and resource level
  • Telemetry that is dropped, filtered or sampled away

Not tested

  • Receiver behavior: filelog operators, Prometheus scraping
  • Exporter behavior, backends and their authentication
  • Span names and status, log bodies and severity, metric names and values
  • Routing on request headers or client metadata
  • Stateful processors that need a series of points over time

Install

One binary. One command.

The installer detects your OS and architecture, downloads the matching release archive, checks its SHA-256 and copies otel-test to ~/.local/bin.

On first use, otel-test downloads otelcol-contrib v0.164.0 for your platform (about 100 MB), verifies it against a checksum compiled into the binary, and caches it.

curl -fsSL https://github.com/SATVIKsynopsis/Tracelet/releases/latest/download/install.sh | sh

Set OTEL_TEST_INSTALL_DIR to install elsewhere, or OTEL_TEST_VERSION=v0.1.0 to pin a release. Needs curl or wget, and sha256sum or shasum.

Release targets

  • aarch64-apple-darwin (Apple Silicon)
  • x86_64-apple-darwin (Intel)

Then

otel-test init && otel-test test

Your next config change should come with a test.