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

Akka.Logging: structured logging #5135

Closed
Aaronontheweb opened this issue Jul 7, 2021 · 2 comments
Closed

Akka.Logging: structured logging #5135

Aaronontheweb opened this issue Jul 7, 2021 · 2 comments

Comments

@Aaronontheweb
Copy link
Member

Is your feature request related to a problem? Please describe.
I've been doing some work in areas where a structured logging approach akin to Serilog's log enrichment and structured data system would be very useful.

Moreover, there are some other issues with our logging system that make it tricky:

1 - We decouple the production of LogEvents from their eventual formatting, which happens inside dedicated logging actors who are subscribed to the LogEvent topic in the EventStream.

This is done, primarily, for performance reasons as string formatting is:

  • expensive and
  • transmitting logs to things like HTTP / File System / Database sinks can accidentally turn the logging system into a global lock for all actors. Yes, this actually happens regularly when users don't use the ILoggingAdapter and it is extremely destructive when it happens - the fault there lies with both the end-users and the logging libraries themselves for not being clear about sync / async guarantees while logging.

So while this decoupling produces a lot of great results, it produces a couple of nasty ones too:

  • ILogEventEnrichers from Serilog and similar constructs from other libraries rely on extracting the value from the enrichment process at the time the LogEvent is produced, i.e. from the live actor that is doing the logging. This is a problem because our extensible logging system can only produce those outcomes during stage 2 - when the LogEvent is formatted into its target logging system. This means enrichment vehicles can't capture temporary, runtime context when the actor is processing a message - which impedes the ability for enrichment tools to produce value.
  • Akka.NET's built-in LogEvent and ILoggingAdapter types don't have any means to express properties (Dictionary<string, object>) in a way that can be consistently implemented across multiple logging packages.

2 - The Context.GetLogger() Method Fundamentally Lacks Extensibility
The hacks we have to do inside Akka.Logger.Serilog today, for instance, to introduce a modicum of contextual logging is quite hacky, in my opinion:

https://github.com/akkadotnet/Akka.Logger.Serilog#semantic-logging-syntax

var log = Context.GetLogger<SerilogLoggingAdapter>(); // correct
log.Info("My boss makes me use {semantic} logging", "semantic"); // serilog semantic logging format

Serilog's string formatter is, of course, different than the normal one we use inside Akka.NET, and making that switch is the primary reason why this code exists. However, I'm of the opinion that developers should be able to specify "use structured logging" or "don't use structured logging" generically, without having to call plugin-specific methods inside their actors.

The underlying ILoggingAdapter should support some more extensibility points, driven via an internal provider, that can help introduce third party implementations behind the scenes.

Describe the solution you'd like
I think it would be ideal if we could:

  1. Allow logging plugins to inject their own ILoggingAdapter implementations behind the scenes, which can automatically do things such as inject the SerilogMessageFormatter without end-users having to decorate their code.
  2. Support the capture of structured properties on ILoggingAdapter, or perhaps offer a second interface akin to the JVM's LogMarker for capturing structured data.
  3. Open extensibility points to allow for things like Serilog's LogContext to be used inside an Akka.NET actor, and to have those values captured into an Akka.NET LogEvent. This could, in theory, be done through the ILoggingAdapter extensibility I mentioned earlier.

Describe alternatives you've considered

In JVM Akka they solved this by introducing a LogMarker type that could accept a Dictionary<string,object> of additional properties along with the format string and / or Exception data: akka/akka#28209

Introducing something like that, a second set of interfaces and classes for doing structured logging specifically, might be a nice way to give developers the ability to swap between structured logging and simple logging.

@Aaronontheweb
Copy link
Member Author

I actually have a spike for this in a private branch - I'll make a PR soon once I get a chance to do more with it.

@Aaronontheweb
Copy link
Member Author

I think we can mark this as resolved for now - we'd need to add support for a "default" semantic logging ILogMessageFormatter for this to be implemented by default in Akka.NET, but all of the infrastructure to do that is now enabled.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
No open projects
Development

No branches or pull requests

1 participant