meta-tracing
A small companion to the tracing crate
that collects structured metadata as you go and hands you a single
JSON-serializable record at the end.
Why
tracing is great at producing a stream of events for humans, log
aggregators, and OTel pipelines. But sometimes you also want a single
structured object describing what a unit of work did — sizes, timings,
named summary sections, warnings — to return alongside an API response,
attach to a job record, or write to S3.
meta-tracing runs alongside tracing. Every call also emits a span or
event, so your logs stay consistent; and at the end you call .build()
and get a CollectedMeta value you can serialize.
At a glance
MetaCollector ──► (sections + issues + timings) ──► CollectedMeta { JSON }
Quick start
# Cargo.toml
[]
= "0.1"
= { = "1", = ["derive"] }
= "1"
use MetaCollector;
use Serialize;
let mut meta = new;
meta.set_input_rows;
// Timed section — opens a tracing span, captures elapsed_ms when finished.
// Free-form warnings; prefix with [WARN] / [ERROR] to drive log levels.
meta.add_issue;
meta.set_output_rows;
let result = meta.build;
println!;
The output is a CollectedMeta with sections, issues, input_rows,
output_rows, and processing_time_ms — all skip-serialize-if-empty so
the JSON stays tight.
What's in the box
MetaCollector— the builder you hand around in your processing code.- Sections (
add_section,merge_section) — named JSON blobs from anySerializetype.merge_sectiondeep-merges into an existing object, which is useful when multiple stages contribute to the same section (e.g."validation"). - Issues (
add_issue,add_issues) — free-form strings;[WARN]/[ERROR]prefixes drive the correspondingtracinglevel, andCollectedMeta::warning_count()/error_count()count them. - Row tracking (
set_input_rows,set_output_rows,set_rows) — common enough to deserve dedicated fields. - Timed sections (
timed_sectionreturns aTimedSectionguard) — opens an INFOmeta_sectionspan and, onfinish*, writes{ elapsed_ms, data? }into the section under that name.
Convenience free functions (record_input_rows, record_section,
record_issue, …) take Option<&mut MetaCollector> so optional
collection sites can stay one-liner.
What this is not
- Not a tracing layer / subscriber. It calls into
tracingbut doesn't hook the dispatch — bring your own subscriber. - Not opinionated about transport.
CollectedMetaimplementsSerialize/Deserialize; do what you like with the JSON. - Not a metrics library. If you need counters, histograms, and an
exporter, look at
metricsoropentelemetry.
License
Dual-licensed under either of:
- Apache License, Version 2.0 (LICENSE-APACHE)
- MIT license (LICENSE-MIT)
at your option.
Contribution
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual-licensed as above, without any additional terms or conditions.