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

Google.Cloud.Logging.Console : getting / setting the traceId manually ? #11042

Closed
christopheblin opened this issue Sep 18, 2023 · 6 comments
Closed
Assignees
Labels
api: logging Issues related to the Cloud Logging API. needs more info This issue needs more information from the customer to proceed. type: question Request for information or clarification. Not an issue.

Comments

@christopheblin
Copy link

After #9948, the result is that using a simple stdout logger allows to correlate all logs of the same HTTP request because they have the same "trace"

Which allows a nice view like this where you can fold/unfold logs of the same trace

image

My question : is there a way to manually get / set the id of the trace ?

@jskeet
Copy link
Collaborator

jskeet commented Sep 18, 2023

I'll assign this to Amanda in case I've missed something, but I believe the trace ID is just Activity.Current.TraceId.ToHexString().
(I don't know enough about the Activity API to know whether you can set the trace ID yourself.)

@jskeet jskeet added type: question Request for information or clarification. Not an issue. api: logging Issues related to the Cloud Logging API. labels Sep 18, 2023
@amanda-tarafa
Copy link
Contributor

Getting the Trace ID is as @jskeet said, you just use Activity.Current.TraceId.

Setting the Trace ID and it having an effect in the exported data, depends.

This is briefly described in Google.Cloud.Loggin.Console documentation. In particular:

For initializing or modifying the Activity ID:

When writing a server application, the current .NET Activity needs to be initialized with the trace context included in the current request. ASP.NET Core does this for you automatically based on HTTP headers. Alternatively, if your application is starting traces itself (for example, if it's responding to Pub/Sub messages instead of HTTP requests), it needs to initialize the current Activity explicitly, as described in the Distributed Tracing guide.

But, you'd need to make sure that those "custom" traces are exported, i.e. you'd need to write explicit code to export them.

Your application needs to be exporting traces to Google Cloud Trace. This could be performed automatically by the runtime, or via explicit code or instrumentation. Google Cloud runtimes export some traces automatically. (For example, Cloud Run will export traces for received requests by default, but you would need to export traces for any additional information.) Please refer to the documentation for the runtime you're using for more details.

@jskeet jskeet added the needs more info This issue needs more information from the customer to proceed. label Sep 20, 2023
@jskeet
Copy link
Collaborator

jskeet commented Sep 20, 2023

@christopheblin: Does that answer everything you need?

@christopheblin
Copy link
Author

Hi ,

Thanks to the pointers given by Amanda, I found out that to set the traceId of the Activity.CUrrent, you need to do

var traceId = ...
var spanId = ...
Activity.Current.SetParentId(ActivityTraceId.CreateFromString(traceId), ActivitySpanId.CreateFromString(spanId));

To find traceId and spanId, I read https://cloud.google.com/run/docs/trace

So I am currently trying to make it work with "traceparent".
It works locally butit does not seem to work with cloud run which seems to override this header with its own :(

I think I can close this issue because my question is answered

@christopheblin
Copy link
Author

For the record, the problem is not that cloud run override the header on its own BUT you must start a new activity in order for it to work in Cloud run (no idea why, I do not see how it makes a difference...)

    var activity = new Activity(httpContext.Request.Method + " " + httpContext.Request.Path)
        .SetParentId(traceId, spanId)
        .Start();
    try
    {
        await _next(httpContext);
    }
    finally
    {
        activity.Stop();
    }

instead of the more simpler version that only works locally

    Activity.Current.SetParentId(traceId, spanId);
    await _next(httpContext);

@christopheblin
Copy link
Author

OK I now understand why we need to start a new activity in Cloud run : Activity.Current.Parent is already populated (I do not know by who or how) and so it is ignored

To see why it is ignored, look at https://github.com/dotnet/runtime/blob/main/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Activity.cs#L574

Basically,

        if (Parent != null)
        {
            NotifyError(new InvalidOperationException(SR.SetParentIdOnActivityWithParent));
        }

The NotifyError simply throws and immediately catches the exception, which mean that we never have a chance to see it ...

In .NET 7+, the restriction is even more hard because the SetParentId can only be called before .Start()

        if (_id != null || _spanId != null)
        {
            // Cannot set the parent on already started Activity.
            NotifyError(new InvalidOperationException(SR.ActivitySetParentAlreadyStarted));
        } 

so in the end, I'm glad to have the bug before .NET 8 :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
api: logging Issues related to the Cloud Logging API. needs more info This issue needs more information from the customer to proceed. type: question Request for information or clarification. Not an issue.
Projects
None yet
Development

No branches or pull requests

3 participants