Expand description
§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
[dependencies]
meta-tracing = "0.1"
serde = { version = "1", features = ["derive"] }
serde_json = "1"use meta_tracing::MetaCollector;
use serde::Serialize;
#[derive(Serialize)]
struct LoadStats { input_rows: usize, output_rows: usize }
let mut meta = MetaCollector::new();
meta.set_input_rows(1_000);
// Timed section — opens a tracing span, captures elapsed_ms when finished.
{
let section = meta.timed_section("load");
// ... do work ...
section.finish_with_data(&LoadStats { input_rows: 1_000, output_rows: 950 });
}
// Free-form warnings; prefix with [WARN] / [ERROR] to drive log levels.
meta.add_issue("[WARN] 50 rows dropped");
meta.set_output_rows(950);
let result = meta.build();
println!("{}", serde_json::to_string_pretty(&result).unwrap());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.
Structs§
- Collected
Meta - Accumulated metadata - the final serializable output
- Meta
Collector - Accumulates metadata during processing with automatic tracing.
- Timed
Section - A timed section that creates a tracing span and captures elapsed time.
- Timed
Section Meta - Timed section metadata with data
- Timing
Meta - Timing metadata for a section
Functions§
- record_
input_ rows - Record input rows if collector is present
- record_
issue - Add an issue if collector is present
- record_
issues - Add multiple issues if collector is present
- record_
output_ rows - Record output rows if collector is present
- record_
rows - Record both input and output rows if collector is present
- record_
section - Add a section if collector is present