Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Global Attributes #65

Closed
ewrogers opened this issue Nov 1, 2023 · 1 comment
Closed

Global Attributes #65

ewrogers opened this issue Nov 1, 2023 · 1 comment

Comments

@ewrogers
Copy link

ewrogers commented Nov 1, 2023

Feature Request

I have the need to have an attribute, say environment that is attached to every event without the need to create a global span and pass that throughout the application.

Motivation

There are some attributes which are common to an application, usually known at app-initialization time. For example, environment which is taken from some environment variable say ENVIRONMENT which will have the value dev | stage | uat | prod.

It would be nice to just be able to define this at initialization time, for attributes that should be included with each event as "global" base attributes. I can see this for distributed systems with something like runner_id as well which is a run-time static variable.

Proposal

In these cases the values are likely known at startup, so they could be assigned as part of the tracing initialization. Expanding on the builder pattern with some kind of .with_base_attribute(k, v) that can be called numerous times to register each one.

This attribute could be attached to each event and logged without the need for juggling spans, especially in a highly asynchronous code-base.

Alternatives

I have tried using an info_span! that I create in the main of the application and .enter it, retaining the guard for the lifetime of the application. It does not seem to work if tokio::spawn is called to create tasks, even if they are marked as #[instrument].

I have tried manually attaching the span via .instrument(span.clone()) on the async fn spawned, which does seem to work. The problem is those tasks also spawn other tasks and it becomes quite messy attempting to "pass it all the way down".

Example:

// GOAL: I want `environment = dev` to be added to every `event!` logged


// This is run as a tokio::task
#[instrument(skip_all)]
async fn dispatcher(mut rx: tokio::mpsc::Receiver<Message>, ...) -> Result<()> {
    while let Some(msg) = rx.recv.await {
        match msg {
            Message::SpawnTask => {
                // We could call `.instrument` on run_bg_task() but what is the span?
                tokio::spawn(run_bg_task())
            }
        }
    }

    Ok(())
}

// This span does not capture `dispatcher` as the parent automatically
#[instrument]
async fn run_bg_task() -> Result<()> {
    // do some work...
    Ok(())
}
@jtescher
Copy link
Collaborator

jtescher commented Nov 7, 2023

You can configure kv attributes that appear on all spans and metrics via resources, e.g. https://github.com/open-telemetry/opentelemetry-rust/blob/4c3f8a04844ca702f38aa2ed4f3c6dbc0de0b138/examples/tracing-jaeger/src/main.rs#L20-L23

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants