Beispiel
tracing 0.1.44: Record late span fields and scoped events while proving target filters, nested subscriber restoration, thread-local isolation, and teardown behavior
Verifiziertes Beispiel für cargo tracing 0.1.44: Record late span fields and scoped events while proving target filters, nested subscriber restoration…
sha256:f62f98bbd367198898e5a347730e84d546ee4fbc75f3b19e6ee3664c61af4d0e
Dieses Netzwerk bietet eine Sache: ein Sample, das baut. Es hat es in einer Sandbox ausgeführt und die signierte Quittung behalten. Es bewertet nichts und garantiert nichts — ob derselbe Code bei Ihnen baut, hat es nicht gemessen.
Wie viele verschiedene Signaturschlüssel eine bestandene Vertragsquittung eingereicht haben. Einer ist der Autor allein; mehr als einer heißt, jemand anderes hat es auch gebaut. Ein Schlüssel wird selbst erzeugt und hat keine registrierte Identität dahinter — gezählt werden Schlüssel, nicht Personen.
MIT-0
Ausführungsbelege
Die deklarierte Umgebung und die signierten Läufe stehen getrennt, damit Sie genau sehen, was dieses Sample ausgeführt hat und wo.
- Beleggrundlage
- Signierter Vertrag bestanden
- Verifizierungsbelege
- 3
- Signaturschlüssel, die es gebaut haben
- 3
Deklarierte Umgebung
rust linux x64 rust rust cargo
Umgebungen der Verifizierungsläufe
| Umgebung | Contract | Stufen | Lauf |
|---|---|---|---|
| rust 1 · linux alpine/x64 · docker ed25519:d91480838ac982c9 | PASS | compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS CONTAINER_RUN · cargo@1 |
2026-08-17 |
| rust 1 · linux alpine/x64 · docker ed25519:2175b912ea1c23b1 | PASS | compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS CONTAINER_RUN · cargo@1 |
2026-08-18 |
| rust 1 · linux alpine/x64 · docker ed25519:c1973797be207ac4 | PASS | compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS CONTAINER_RUN · cargo@1rust:1-alpine@sha256:a10e64dd139b… |
2026-09-08 |
Fall
HOW- Ziel
- Record late span fields and scoped events while proving target filters, nested subscriber restoration, thread-local isolation, and teardown behavior
- Symbole
-
- tracing::span!
- tracing::event!
- tracing::Span::record
- tracing::subscriber::with_default
- tracing_subscriber::filter::Targets
- tracing_subscriber::Layer::with_filter
- tracing_subscriber::layer::Context::event_scope
- Umgebung
- rust
- Erstellt
- 2026-08-17T01:09:31Z
Contract
- assert Span::record updates a field declared with tracing::field::Empty and the event observes the entered span scope
- assert a per-layer Targets filter captures the allowed target while excluding a higher-severity event from an unlisted target
- assert a nested with_default replaces rather than composes with the outer dispatcher, then restores the outer dispatcher when its closure returns
- assert a with_default dispatcher is thread-local and is not inherited by a thread spawned inside the scoped closure
- assert events emitted after the outer with_default closure returns are not delivered to either scoped capture
Dateien
- Cargo.lock
- Cargo.toml
- csx.json
- src/lib.rs
Quelltext
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 4
[[package]]
name = "cargo-tracing-api"
version = "0.1.0"
dependencies = [
"tracing",
"tracing-subscriber",
]
[[package]]
name = "cfg-if"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
[[package]]
name = "lazy_static"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
[[package]]
name = "once_cell"
version = "1.21.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50"
[[package]]
name = "pin-project-lite"
version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd"
[[package]]
name = "proc-macro2"
version = "1.0.107"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "985e7ec9bb745e6ce6535b544d84d6cd6f7ad8bd711c398938ae983b91a766d9"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.47"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fbf4db142a473a8d80c26bbf18454ed458bf8d26c8219c331daecfdbd079001"
dependencies = [
"proc-macro2",
]
[[package]]
name = "sharded-slab"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6"
dependencies = [
"lazy_static",
]
[[package]]
name = "syn"
version = "2.0.119"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "872831b642d1a07999a962a351ed35b955ea2cfc8f3862091e2a240a84f17297"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "thread_local"
version = "1.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ad99c4c6d32803332c548b1af0540b357b3f5fc0be8f6c6bfe8b2e6ae784070"
dependencies = [
"cfg-if",
]
[[package]]
name = "tracing"
version = "0.1.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100"
dependencies = [
"pin-project-lite",
"tracing-attributes",
"tracing-core",
]
[[package]]
name = "tracing-attributes"
version = "0.1.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "tracing-core"
version = "0.1.36"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a"
dependencies = [
"once_cell",
]
[[package]]
name = "tracing-subscriber"
version = "0.3.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cb7f578e5945fb242538965c2d0b04418d38ec25c79d160cd279bf0731c8d319"
dependencies = [
"sharded-slab",
"thread_local",
"tracing-core",
]
[[package]]
name = "unicode-ident"
version = "1.0.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
[package]
name = "cargo-tracing-api"
version = "0.1.0"
edition = "2021"
[dependencies]
tracing = "=0.1.44"
tracing-subscriber = { version = "=0.3.23", default-features = false, features = ["registry"] }
{"case":{"believed":"A subscriber installed with with_default is often assumed to compose with an existing default and propagate to threads spawned inside its closure.","caseId":"case:sha256:7cc6a428fa2a0b7782dbab1a2f523fa8dbd4f78620b782d8dde18bd640f8c159","contract":["assert Span::record updates a field declared with tracing::field::Empty and the event observes the entered span scope","assert a per-layer Targets filter captures the allowed target while excluding a higher-severity event from an unlisted target","assert a nested with_default replaces rather than composes with the outer dispatcher, then restores the outer dispatcher when its closure returns","assert a with_default dispatcher is thread-local and is not inherited by a thread spawned inside the scoped closure","assert events emitted after the outer with_default closure returns are not delivered to either scoped capture"],"goal":"Record late span fields and scoped events while proving target filters, nested subscriber restoration, thread-local isolation, and teardown behavior","kind":"HOW","packages":["pkg:cargo/tracing@0.1.44","pkg:cargo/tracing-subscriber@0.3.23"],"schemaVersion":1,"symbols":["tracing::span!","tracing::event!","tracing::Span::record","tracing::subscriber::with_default","tracing_subscriber::filter::Targets","tracing_subscriber::Layer::with_filter","tracing_subscriber::layer::Context::event_scope"]},"contractCommand":["cargo","test","--locked","--offline"],"environment":{"arch":"x64","ecosystem":"cargo","executionContext":"rust","language":"rust","os":"linux","packageManager":"cargo","runtime":"rust","schemaVersion":1},"license":"MIT-0","packages":["pkg:cargo/tracing@0.1.44","pkg:cargo/tracing-subscriber@0.3.23"],"schemaVersion":1,"symbols":["tracing::span!","tracing::event!","tracing::Span::record","tracing::subscriber::with_default","tracing_subscriber::filter::Targets","tracing_subscriber::Layer::with_filter","tracing_subscriber::layer::Context::event_scope"],"verifierAdapter":"cargo@1"}
//! A deterministic contract for scoped `tracing` subscribers.
#[cfg(test)]
mod tests {
use std::collections::{BTreeMap, HashMap};
use std::fmt;
use std::sync::{Arc, Mutex};
use tracing::field::{Field, Visit};
use tracing::span::{Attributes, Id, Record};
use tracing::{Event, Level, Subscriber};
use tracing_subscriber::filter::{LevelFilter, Targets};
use tracing_subscriber::layer::{Context, SubscriberExt};
use tracing_subscriber::registry::LookupSpan;
use tracing_subscriber::{Layer, Registry};
#[derive(Debug, Default)]
struct Capture {
spans: HashMap<u64, SpanSnapshot>,
events: Vec<EventSnapshot>,
}
#[derive(Debug, PartialEq, Eq)]
struct SpanSnapshot {
name: &'static str,
target: &'static str,
fields: BTreeMap<String, String>,
}
#[derive(Debug, PartialEq, Eq)]
struct EventSnapshot {
target: &'static str,
level: &'static str,
fields: BTreeMap<String, String>,
scope: Vec<&'static str>,
}
#[derive(Clone)]
struct CaptureLayer {
capture: Arc<Mutex<Capture>>,
}
impl CaptureLayer {
fn new(capture: Arc<Mutex<Capture>>) -> Self {
Self { capture }
}
}
impl<S> Layer<S> for CaptureLayer
where
S: Subscriber + for<'lookup> LookupSpan<'lookup>,
{
fn on_new_span(&self, attributes: &Attributes<'_>, id: &Id, _ctx: Context<'_, S>) {
let metadata = attributes.metadata();
let mut fields = BTreeMap::new();
attributes.record(&mut FieldVisitor(&mut fields));
self.capture.lock().unwrap().spans.insert(
id.clone().into_u64(),
SpanSnapshot {
name: metadata.name(),
target: metadata.target(),
fields,
},
);
}
fn on_record(&self, id: &Id, values: &Record<'_>, _ctx: Context<'_, S>) {
let mut capture = self.capture.lock().unwrap();
let span = capture
.spans
.get_mut(&id.clone().into_u64())
.expect("recorded span was created by this subscriber");
values.record(&mut FieldVisitor(&mut span.fields));
}
fn on_event(&self, event: &Event<'_>, ctx: Context<'_, S>) {
let metadata = event.metadata();
let mut fields = BTreeMap::new();
event.record(&mut FieldVisitor(&mut fields));
let scope = ctx
.event_scope(event)
.map(|scope| {
scope
.from_root()
.map(|span| span.metadata().name())
.collect()
})
.unwrap_or_default();
self.capture.lock().unwrap().events.push(EventSnapshot {
target: metadata.target(),
level: metadata.level().as_str(),
fields,
scope,
});
}
}
struct FieldVisitor<'a>(&'a mut BTreeMap<String, String>);
impl Visit for FieldVisitor<'_> {
fn record_str(&mut self, field: &Field, value: &str) {
self.0.insert(field.name().into(), value.into());
}
fn record_u64(&mut self, field: &Field, value: u64) {
self.0.insert(field.name().into(), value.to_string());
}
fn record_bool(&mut self, field: &Field, value: bool) {
self.0.insert(field.name().into(), value.to_string());
}
fn record_debug(&mut self, field: &Field, value: &dyn fmt::Debug) {
self.0.insert(field.name().into(), format!("{value:?}"));
}
}
#[test]
fn scoped_subscribers_replace_restore_filter_and_do_not_cross_threads() {
let outer_capture = Arc::new(Mutex::new(Capture::default()));
let inner_capture = Arc::new(Mutex::new(Capture::default()));
let outer = Registry::default().with(CaptureLayer::new(outer_capture.clone()));
let targets = Targets::new()
.with_default(LevelFilter::OFF)
.with_target("sample::allowed", LevelFilter::INFO);
let inner =
Registry::default().with(CaptureLayer::new(inner_capture.clone()).with_filter(targets));
tracing::subscriber::with_default(outer, || {
tracing::event!(target: "sample::outer", Level::INFO, phase = "before");
tracing::subscriber::with_default(inner, || {
let request = tracing::span!(
target: "sample::allowed",
Level::INFO,
"request",
request_id = tracing::field::Empty,
status = "started"
);
request.record("request_id", &"req-42");
let _entered = request.enter();
tracing::event!(
target: "sample::allowed",
Level::INFO,
user_id = 7_u64,
action = "accepted"
);
tracing::event!(
target: "sample::blocked",
Level::ERROR,
secret = true,
action = "must-not-escape"
);
// `with_default` installs a thread-local default. A child thread does
// not inherit it, even while the scoped closure is still running.
std::thread::spawn(|| {
tracing::event!(
target: "sample::allowed",
Level::INFO,
worker = true
);
})
.join()
.unwrap();
});
// Dropping the inner scope restores the previous (outer) dispatcher.
tracing::event!(target: "sample::outer", Level::INFO, phase = "after");
});
// Dropping the outer scope restores the process default; neither capture
// receives events emitted after teardown.
tracing::event!(target: "sample::outer", Level::INFO, phase = "outside");
let inner = inner_capture.lock().unwrap();
assert_eq!(
inner.events.len(),
1,
"blocked and child-thread events stay out"
);
assert_eq!(inner.events[0].target, "sample::allowed");
assert_eq!(inner.events[0].level, "INFO");
assert_eq!(inner.events[0].fields.get("user_id"), Some(&"7".into()));
assert_eq!(
inner.events[0].fields.get("action"),
Some(&"accepted".into())
);
assert_eq!(inner.events[0].scope, vec!["request"]);
assert_eq!(inner.spans.len(), 1);
let span = inner.spans.values().next().unwrap();
assert_eq!(span.name, "request");
assert_eq!(span.target, "sample::allowed");
assert_eq!(span.fields.get("status"), Some(&"started".into()));
assert_eq!(span.fields.get("request_id"), Some(&"req-42".into()));
drop(inner);
let outer = outer_capture.lock().unwrap();
assert_eq!(
outer.events.len(),
2,
"inner scope replaces, then restores outer"
);
assert_eq!(outer.events[0].fields.get("phase"), Some(&"before".into()));
assert_eq!(outer.events[1].fields.get("phase"), Some(&"after".into()));
assert!(outer.spans.is_empty());
}
}