opentelemetry-dotnet icon indicating copy to clipboard operation
opentelemetry-dotnet copied to clipboard

[feature request] Allow `ActivityContext` to be passed into `ILogger` explicitly, rather than relying solely on `Activity.Current`

Open Aaronontheweb opened this issue 11 months ago • 11 comments

Package

OpenTelemetry

Is your feature request related to a problem?

My scenario might be an edge-case but it also might not be - in the Akka.NET project we have our own logging infrastructure dating back to the beginning of the project (2013) designed to allow logs to be formatted and processed asynchronously using some of our actors. We capture the context from the live running actor and defer the expensive formatting until later - similar in spirit and execution to OpenTelemetry's own processing pipeline.

We capture a LogEvent, emit it via an in-memory topic broker to a LogActor who either renders it live (in batches) on the console or exports it to something like Serilog, NLog, or Microsoft.Extensions.Logging.

An issue I have: https://github.com/akkadotnet/akka.net/pull/7476 - we are trying to add support for capturing an ActivityContext when some of our built-in actors are doing message processing. The issue we have is this:

https://github.com/open-telemetry/opentelemetry-dotnet/blob/d9864b1e1d034e450e256f39d361857aad7edbe3/src/OpenTelemetry/Logs/ILogger/OpenTelemetryLogger.cs#L56

There's not any means to pass the ActivityContext as a state object to the OTEL ILogger implementation. The only real way to preserve our the ActivityContext is to forward the entire Activity to our LogActor, have it set that as the Activity.Current, and then clear it as soon as the ILogger is done.

What is the expected behavior?

I would love a means of being able to just pass in the ActivityContext explicitly from elsewhere to the Log method and use that as the provided context for the ILogger, so I can keep the processing of log events and the recording of traces temporally decoupled from each other.

Which alternative solutions or features have you considered?

As I mentioned in the first part of the post - we could just keep the entire Activity and temporarily restore it as Activity.Current in order to satisfy the current ILogger implementation. Not totally keen on doing this because it's kind of ugly.

Additional context

No response

Aaronontheweb avatar Jan 22 '25 20:01 Aaronontheweb

https://github.com/dotnet/runtime/issues/86966 This is related I believe.

This repo hasn't shipped a stable version of Logging appenders, but once it is there, I think it should allow setting LogRecord's traceid/spanid from any source. https://github.com/open-telemetry/opentelemetry-dotnet/blob/main/src/OpenTelemetry/Logs/LogRecord.cs#L123

cijothomas avatar Jan 22 '25 22:01 cijothomas

That looks very promising - how would I go about setting that field on the LogRecord ?

Aaronontheweb avatar Jan 22 '25 22:01 Aaronontheweb

https://github.com/open-telemetry/opentelemetry-dotnet/blob/main/docs/logs/extending-the-sdk/README.md#processor You can author a custom LogRecordProcessor, and override the traceid/spanids. Processors are run synchronously so they'll have access to the same context as logging statement....

If this does not work, https://github.com/open-telemetry/opentelemetry-dotnet/discussions/6047 is the solution, but unfortunately its not planned in short term due to lack of interest/manpower...

cijothomas avatar Jan 23 '25 01:01 cijothomas

Ah right, I could probably pass in my own formatting function with some custom state or whatever and have the LogRecordProcessor pick that up - that would work I think

Aaronontheweb avatar Jan 23 '25 02:01 Aaronontheweb

@cijothomas is there a nightly where I can test out the logging appenders?

Aaronontheweb avatar Jan 27 '25 14:01 Aaronontheweb

https://github.com/open-telemetry/opentelemetry-dotnet/discussions/6047#discussioncomment-11769008 Maybe only available in main-logs branch? @CodeBlanch can confirm is nightly is published from that branch.

cijothomas avatar Jan 27 '25 18:01 cijothomas

Given that the Activity.Current is stored in an AsyncLocal<Activity>, wouldn't just setting it before processing be enough? See https://github.com/dotnet/runtime/blob/main/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Activity.cs#L65

kzu avatar Jun 17 '25 17:06 kzu

@kzu not in our case - we're not using await-based propagation for our logging system. Log events are fed into a dedicated logging actor's mailbox and are processed in-bulk on the .NET ThreadPool asynchronously. AsyncLocal<T> doesn't propagate across that boundary.

Aaronontheweb avatar Jun 19 '25 13:06 Aaronontheweb

That's really what's at issue here - the current OTEL->MSFT.EXT.Logging integration is a tad too opinionated and it'd be great if we had some other means of correlating the trace / span ids with the logs.

Aaronontheweb avatar Jun 19 '25 13:06 Aaronontheweb

I assume doing ExecutionContext.Capture and restoring it later is also not an option, especially if things might not even land in the same process?

kzu avatar Jun 28 '25 01:06 kzu

I assume doing ExecutionContext.Capture and restoring it later is also not an option, especially if things might not even land in the same process?

It really should be as simple as just passing the ActivityContext to a logger overload

Aaronontheweb avatar Nov 18 '25 14:11 Aaronontheweb