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 | shInstalls otel-test to ~/.local/bin. On Windows, download the .zip.
test “passwords are removed from spans”
tracesinject
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)
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 initotel-test v0.1.0created ./otel-test.yamlcreated ./collector.yamlcreated ./fixtures/login-span.jsoncreated ./fixtures/login-log.jsoncreated ./fixtures/healthz-span.json$ otel-test testotel-test v0.1.0Collector: v0.164.0Config: collector.yamlTests: 3✓ passwords are removed from spans✓ passwords are removed from logs✓ health checks are dropped3 passed, 0 failedTime: 8.50s
otel-test init, then otel-test test on the generated project.
Features
Policy you can run in CI.
- 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
- DocumentationRead how every assertion works.Open the docs
How it works
Only the edges change.
Inputs
Your project
collector.yaml
fixtures/*.json
otel-test.yaml
Tracelet
otel-test
analyze
rewrite
validate
Real process
otelcol-contrib
dashed: replaced
solid: copied verbatim
Capture
Exporter boundary
otlp_http/backend
datadog
kafka/shared
Results
Assertions
✓ passed
✗ failed
exit code
01
Analyze
Parse otel-test.yaml, the Collector config and every fixture. Report every problem at once, with its location.
02
Rewrite
Replace each receiver with a local OTLP/HTTP endpoint and each exporter with a capture exporter that keeps its ID.
03
Validate
Run otelcol validate on the rewritten config before anything starts.
04
Run
Start a fresh Collector for each test and wait until it reports ready.
05
Inject
POST the fixture to the chosen receiver. The Collector must accept it.
06
Capture
Record what reaches each exporter during the observation window and the graceful shutdown.
07
Report
Evaluate assertions and print expected vs. actual for every failure.
Use cases
Five production-style configs, tested.
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 limitationsTested
- 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 | shSet 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