Skip to content
Novus Examples
3 min readNovus ExamplesGuideAdvancedv2026.09

Observability Fixtures for Log and Trace Parsers

Clock skew across hosts, timestamps out of order, a stack trace spanning twelve lines, and NaN in a Prometheus gauge. The telemetry shapes that break ingest.

Telemetry arrives from machines that disagree with each other

Not about facts, about time. Two hosts whose clocks differ by a few seconds will produce a trace where a child span starts before its parent, and a log pipeline fed by several producers will see timestamps go backwards. Both are normal. Code that assumes otherwise produces negative durations, dropped events and dashboards that are quietly wrong.

The observability catalogue is 120 fixtures covering traces, metrics, logs, profiles and alerting config.

Time, which is the whole category

Three log fixtures exist for exactly this:

  • json-lines-out-of-order-timestamps - events arriving late, which every real pipeline sees.
  • json-lines-clock-skew-across-hosts - the same logical sequence recorded by hosts whose clocks disagree.
  • json-lines-trace-correlated-logs - logs carrying trace and span ids, so they can be joined to a trace.

The questions these answer: does your ingest sort, or assume arrival order is event order? Does a negative computed duration get clamped, dropped, or stored as negative? Does a late event land in the right window or in the current one? None of those raise errors, and all of them change what a dashboard says.

Traces, in four serialisations of one journey

otlp-json-trace-checkout, otlp-trace-proto3-json-encoding, jaeger-json-trace-checkout, zipkin-v2-trace-checkout, and trace-span-table-csv-export.

The same checkout journey in OTLP JSON, OTLP's proto3-JSON encoding, Jaeger's format, Zipkin v2, and flattened to CSV. That makes them a conversion test set: a converter's output can be compared against a sibling representing the same truth.

The proto3-JSON encoding deserves its own mention. It is not ordinary JSON: 64-bit integers are strings, enums may appear as names or numbers, and field names are camelCase where the proto is snake_case. A parser written against hand-written OTLP JSON meets all three the first time it sees real exporter output.

Prometheus exposition, and the values that are not numbers

  • prometheus-exposition-counters-gauges - the baseline.
  • prometheus-exposition-histogram and -summary - the two aggregate types, which are frequently conflated. A histogram carries cumulative buckets; a summary carries precomputed quantiles that cannot be aggregated across instances. Averaging summary quantiles across three replicas is a common and completely invalid operation.
  • prometheus-label-value-escaping - quotes, backslashes and newlines inside label values.
  • prometheus-special-numeric-values - NaN, +Inf, -Inf, which are legal in the exposition format. A parser using a naive float conversion either throws or silently produces zero, and zero is much worse: a gauge that should read "no data" reads "nothing is happening".

Logs that are not one line

json-lines-with-multiline-stack-traces.

JSON Lines promises one object per line, and a stack trace embedded in a message field contains newlines that must be escaped. Producers get this wrong constantly. The fixture lets you decide what your reader does with a line that is not valid JSON: skip and count, or abort the file. Both are defensible; silently skipping without counting is not, because the loss is invisible.

Profiles, as before-and-after pairs

cpu-folded-stacks-before and cpu-folded-stacks-after are the same program profiled either side of a change, which is the shape a flame-graph differ needs. allocation-folded-stacks-bytes profiles bytes rather than time, wall-clock-folded-stacks-per-thread splits by thread, and folded-stacks-deep-recursion is the one that breaks renderers: a stack deep enough that naive recursive layout hits a limit.

Configuration, including one that is deliberately wrong

prometheus-alerting-rules, prometheus-recording-rules, prometheus-scrape-configuration, alertmanager-routing-configuration, and prometheus-alerting-rules-invalid.

The invalid one is the point. Alerting config is the code that tells you when everything else is broken, so a validator that accepts a malformed rule file is a silent single point of failure. Test that yours rejects it, and read the message it gives.

Where to start

  1. prometheus-special-numeric-values, because NaN becoming zero inverts a dashboard's meaning.
  2. json-lines-clock-skew-across-hosts, and check for negative durations.
  3. otlp-trace-proto3-json-encoding, if you parse OTLP at all.
  4. json-lines-with-multiline-stack-traces, and make sure skipped lines are counted.
  5. prometheus-alerting-rules-invalid, to confirm your validator is not a no-op.

Continue this workflow

Try the workflow

Documentation and troubleshooting

Was this article helpful?

Found an error? Send a correction.