Ambient context
emit
supports enriching events automatically with properties from the ambient environment.
Using the #[span]
macro
The most straightforward way to add ambient context is using the #[span]
macro. Any properties captured by the span will also be added to events emitted during its execution:
#![allow(unused)] fn main() { extern crate emit; #[emit::span("greet {user}", lang)] fn greet(user: &str, lang: &str) { match lang { "el" => emit::emit!("Γεια σου, {user}"), "en" => emit::emit!("Hello, {user}"), "eo" => emit::emit!("Saluton, {user}"), /* .. */ _ => (), } } greet("Rust", "eo"); }
Event {
mdl: "my_app",
tpl: "Saluton, {user}",
extent: Some(
"2024-10-02T20:53:29.580999000Z",
),
props: {
"user": "Rust",
"span_id": b26bfe938b77eb19,
"lang": "eo",
"user": "Rust",
"trace_id": 7fc2efc824915dc180c29a79af358e78,
},
}
Note the presence of the lang
property on the events produced by emit!
. They appear because they're added to the ambient context by the #[span]
attribute on greet()
.
See Tracing for more details.
Manually
Ambient context can be worked with directly. emit
stores its ambient context in an implementation of the Ctxt
trait. Properties in the ambient context can be added or removed using Frame
s. You may want to work with context directly when you're not trying to produce spans in a distributed trace, or when your application doesn't have a single point where attributes could be applied to manipulate ambient context.
When converted to use ambient context manually, the previous example looks like this:
#![allow(unused)] fn main() { extern crate emit; fn greet(user: &str, lang: &str) { // Get a frame over the amient context that pushes the `lang` property let mut frame = emit::Frame::push( emit::ctxt(), emit::props! { lang, }, ); // Make the frame active // While this guard is in scope the `lang` property will be present // When this guard is dropped the `lang` property will be removed // Frames may be entered and exited multiple times let _guard = frame.enter(); // The rest of the function proceeds as normal match lang { "el" => emit::emit!("Γεια σου, {user}"), "en" => emit::emit!("Hello, {user}"), "eo" => emit::emit!("Saluton, {user}"), /* .. */ _ => (), } } greet("Rust", "eo"); }
Event {
mdl: "my_app",
tpl: "Saluton, {user}",
extent: Some(
"2024-10-02T21:01:50.534810000Z",
),
props: {
"user": "Rust",
"lang": "eo",
},
}
When using ambient context manually, it's important that frames are treated like a stack. They need to be exited in the opposite order they were entered in.