Platform
One pipeline, three signals.
Metrics, traces and logs share a collector, a storage engine and a query language. That is the whole architecture, and it is why correlating them does not require exporting anything.
Collector
The boundary is yours, not ours.
The collector runs inside your network. Redaction, sampling and batching all happen before anything crosses the boundary, which means a sensitive field is never transmitted and then scrubbed — it is never transmitted.
- Standard OpenTelemetry Collector with one Northwind exporter
- Redaction rules are ordinary processor config, reviewable in your repo
- Buffers to disk if we are unreachable, so a Northwind outage is not yours
- No proprietary agent, no kernel module, no sidecar requirement
# The whole integration. Eleven lines.
processors:
redact:
# Never leaves the VPC unredacted
blocked_key_patterns: ["patient_.*", ".*_ssn"]
exporters:
northwind:
endpoint: "ingest.northwind.example"
api_key: "${NORTHWIND_API_KEY}"
compression: zstd
Signals
Three ways in, one way out.
Each signal has its own ingest path and its own trade-offs. They share a query language.
Time series
Metrics
Ten-second resolution, kept at full fidelity for as long as you pay to keep it.
| Resolution | 10 seconds |
|---|---|
| Ingest protocols | Prometheus remote-write, OTLP, StatsD |
Metrics in detail
Distributed tracing
Traces
Tail-based sampling that keeps the traces you actually needed.
| Sampling | Tail-based, policy-driven |
|---|---|
| Ingest protocols | OTLP gRPC and HTTP, Jaeger, Zipkin |
Traces in detail
Log management
Logs
Structured search over everything, without an index tax on every field.
| Storage | Columnar, compressed ~11:1 |
|---|---|
| Indexed fields | Metadata only |
Logs in detail
# p95 latency by endpoint, last hour
metric("http.server.duration")
| where service == "checkout-api"
| percentile(95) by endpoint
| over(1h)
# The traces behind the worst endpoint
trace()
| where service == "checkout-api"
and endpoint == "/v1/charge"
and duration > 800ms
# And the logs those traces emitted
log() | where trace_id in above()
NWQL
Stop translating between dialects.
During an incident nobody has the working memory to hold three query syntaxes at once. NWQL is one language across all three signals, and above() chains a result into the next query.
- PromQL runs unmodified, so existing dashboards and rules keep working
- Joins across signals on shared resource attributes
- Query results are addressable, so a chain is one expression rather than four tabs
See it against your own traffic.
A demo is a working account with your collector pointed at it, not a slide deck.