Skip to content

Clarify how Application Developers are supposed to set the Span status when using Instrumentation Libraries #4131

@fkoep

Description

@fkoep

What are you trying to achieve?

As an Application developer, I should be able to set the Span Status of Spans created by an Instrumentation Library.

In practice, a Spans lifetime is often tied to a library functions scope. It is not clear how you should gain access to the Span from the calling side or alternatively, how an Instrumentation Library should enable me to influence the Span Status.

Additional context.

In the Span::SetStatus operation (https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/api.md#set-status), the following line raises questions:

Application developers and Operators may set the status code to Ok.

When using an Instrumentation Library, how are Application developers supposed to do that?

It is stated that:

  • An Instrumentation library is supposed to leave the Span Status unset or set it to error.
  • The Span Status cannot be changed after the Span has ended.

This means the only way an Application Developer can set the Span Status is by the Instrumentation Library giving him the ability to modify the Span Status while the Span is still open.

However, most often Spans are tied to a functions scope and not accessible by the caller.

Example: When using an instrumented HTTP Client library, an Application can expect 404 errors in certain places. The Application might look up an resource and create it if it does not exist yet:

// Application code
fn get_or_create_picture(id):
    let picture; // a picture resource

    /* check if resource already exists */ 
    let response1 = http.get(url="https://myapi/picture/{id}");
    if response1.http_status == 404:
         /* resource does not exist, create it */
         let random_pic = generate_random_picture();
         let response2 = http.post(url="https://myapi/picture/create/{id}", data=random_pic);
         picture = response2.content;
    else:
         picture = response1.content;
        
    return picture;

If the first HTTP GET returns a 404, the resulting GET /picture/{id} Span would be marked with an error Span Status by the the HTTP Client library (as per Semantic Conventions for HTTP Spans). We handled that error, so we want to set the status to OK. However, the Span is hidden away in http.get() and cannot be modified by the outer Application logic.

In order for the Application Developer the overwrite this Span Status, the HTTP Client Library would need to accept a parameter for expected HTTP statusses, for which the Span Status should not be set to error:

/* ... */
let response1 = http.get(url="https://myapi/picture/{id}", expected_statusses=[404]);
/* ... */ 

Alternatively, the HTTP Client Library would need to return the still-open Span, so the Span Status can be overwritten by the Application code:

/* ... */
let response1 = http.get(url="https://myapi/picture/{id}");
if response1.http_status == 404:
    response1.tracing_span.setSpanStatus("OK");
/* ... */ 

Is that really how it is supposed to be done? That seems like a major imposition on Instrumention Libraries.

In my pseudocode example, the design of the REST API and Application code is debatable, but the Tracing specification clearly states that setting the Span Status like this is intended usage. Various Github Issues I found suggest the same. However, I cannot find any real-life examples.

Maybe I am overseeing something really simple which could be explained or recommended in 1-2 sentences in the Tracing API specification:

Application developers and Operators may set the status code to Ok. Instrumentation libraries must provide the ability to XYZ...

Metadata

Metadata

Assignees

No one assigned

    Labels

    spec:metricsRelated to the specification/metrics directoryspec:traceRelated to the specification/trace directorytriage:accepted:needs-sponsorReady to be implemented, but does not yet have a specification sponsor

    Type

    No type

    Projects

    Status

    Spec - Accepted

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions