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

[Question] Why does AspNetCore instrumentation documentation suggests adding custom attributes through Enrich hook instead of directly updating activity in middleware? #2306

Open
jundayin opened this issue Nov 7, 2024 · 0 comments

Comments

@jundayin
Copy link

jundayin commented Nov 7, 2024

Component

OpenTelemetry.Instrumentation.AspNetCore

Question details

In the documentation we were told to add custom attributes through enrich hook in the following format

services.AddOpenTelemetry()
    .WithTracing(builder => builder
        .AddAspNetCoreInstrumentation(o =>
        {
            o.EnrichWithHttpRequest = (activity, httpRequest) =>
            {
                activity.SetTag("requestProtocol", httpRequest.Protocol);
            };
            o.EnrichWithHttpResponse = (activity, httpResponse) =>
            {
                activity.SetTag("responseLength", httpResponse.ContentLength);
            };
            o.EnrichWithException = (activity, exception) =>
            {
                if (exception.Source != null)
                {
                    activity.SetTag("exception.source", exception.Source);
                }
            };
        }));

In my code I need to read the request body and set one of the fields as part of the custom attributes. Basically I do something like

o.EnrichWithHttpRequest = (activity, httpRequest) =>
{
    httpRequest.EnableBuffering();
    try
    {
        var buffer = new byte[Convert.ToInt32(httpRequest.ContentLength)];
        httpRequest.Body.ReadAsync(buffer, 0, buffer.Length);
        var requestContent = Encoding.UTF8.GetString(buffer);
        var policyRequest = JsonConvert.DeserializeObject<PolicyRequest>(requestContent);
        string policyNamespace = policyRequest.Namespace;
        activity.SetTag(TelemetryConstants.PolicyNamespaceKey, policyNamespace);
    }
    catch (Exception e)
    {
        Console.WriteLine($"Failed to process policy namespace. Exception: {e.Message}");
    }
    finally
    {
        httpRequest.Body.Position = 0;
    }
};

This is not a thread-safe approach and apparently it breaks a lot of inbound requests. Later I realize since we only need to update the acitivity tag directly, maybe I can get the Acitivity directly in the middleware

public class TestMiddleware
{
    public async Task InvokeAsync(HttpContext httpContext) 
    {
        --- get the namespace from request body ---
        Activity.Current?.AddTag(TelemetryConstants.PolicyNamespaceKey, policyNamespace);
}

Although it works, I don't know if this has any issue that I'm not aware. That makes me curious why the documentation only mentions the hook approach

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

1 participant