question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Support dependency injection into sinks, enrichers, filters, etc.

See original GitHub issue

Assuming, we’d like to initialize Serilog in the first few lines of Program.Main(), and independently of ASP.NET Core/other hosting code, how can we support sinks and other pipeline elements that depend on the framework and components that are initialized later?

For example, in #84 there’s a discussion regarding the use of Application Insights configuration from dependency injection in a Serilog sink.

LateInitSink in this gist demonstrates a possible approach:

        var signalRSink = new LateInitSink();

        Log.Logger = new LoggerConfiguration()
            .WriteTo.Sink(signalRSink)
            .CreateLogger();

        Log.Information("Sadly, nobody will get this");

        // ... resolve that hub ...
        signalRSink.Init(wt => wt.Console());

        Log.Information("Ah so nice to be loggin' again");

@khellang suggested using a name like DependencyInjectedSink instead of LateInitSink, so make the API more searchable/discoverable.

We could, finalize/ship an implementation of this approach.

The need to also support enrichers, filters, and so-on, could be met by including a range of similar types for those cases.

As an alternative, or extension of this idea, we could create a wrapper API that mimics LoggerConfiguration and sets up the full range of extension points for DI (rough sketch):

// Initialize what we can, early on. The `deferred` variable
// will hold a `DeferredLoggerConfiguration` that's hooked
// into late-init sinks, enrichers, etc. by a new `CreateLogger()`
// extension-based overload.
Log.Logger = new LoggerConfiguration()
    .WriteTo.Console()
    .CreateLogger(out var deferred);

// Later, post-DI-setup, or elsewhere in the app:
deferred
    .AddSink(writeTo => writeTo.File(...))
    .AddEnricher(enrich => enrich.WithProperty(...))
    .UpdateLogger();

This API should be possible using some extension points already in 2.9.0; it would be nicer to support deferred.WriteTo.File() etc. but we’d need new APIs to enable it.

Thoughts?

See also #130.

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Reactions:7
  • Comments:17 (11 by maintainers)

github_iconTop GitHub Comments

8reactions
davidfowlcommented, Feb 17, 2020
                    var provider = builder.Services.BuildServiceProvider();

That line will create a different DI container than the one the application uses. You’ll end up with 2 sets of singletons and nobody is disposing the container here either so your disposable objects don’t get disposed.

7reactions
ralphhendrikscommented, Jan 24, 2020

Over the last days I have been struggling to figure out the current most correct way of configuring the Application Insights sink in an ASP.NET Core 3.1 application, preferrably without deprecation warnings. Reading serilog/serilog-sinks-applicationinsights#121 and related brought me to this issue.

I am all for a DI-friendly API design. However, I would be very reluctant to develop serilog’s API design to contain any explicit notion of DI, and MS.DI in particular. Several third party DI containers are non-conforming to the MS.DI interfaces, such as https://github.com/simpleinjector/SimpleInjector, whose main author @dotnetjunkie is actively involved in many discussion around this topic. With that in mind, I am not a fan of the proposed .AddAspNetCoreDIEnricher() API suggestions.

The main problem is quite well summarized by @cmeeren:

  • The Application Insights telemetry config is set up and registered with DI in ConfigureServices (so that it picks up all telemetry initializers and processors that are also registered), and therefore only available after it has ConfigureServices has run
  • The telemetry config is needed when configuring Serilog
  • UseSerilog is configured before ConfigureServices is called

Given Microsoft’s design philosophy, where the composition root of the application is on the level of the IHost, there is now a timing problem in setting up the Serilog logging pipeline. Ideally configuring logging would be about the first thing to do after application startup, which is before building and running the host. However, some logging pipeline components might have dependencies first set up in the composition root.

IMHO a good approach would be to do all fail-safe/isolated logger setup directly after application startup (e.g. configuring a console sink for logging to stdout), and then being able to either add configuration to that same logger, or to derive from it (and update the static instance) in the composition root. A clean API for this might be to add an overload of LoggerConfiguration that would take an existing, already configured Logger. However, I am not sufficiently familiar with the internals of serilog to know whether this can safely be implemented.

It would be great if we can take this discussion forward. (@nblumhardt pardon the indirect nudge 😉)

Read more comments on GitHub >

github_iconTop Results From Across the Web

Injecting services into Serilog filters, enrichers, and sinks
It's now a lot easier to inject services from your dependency injection (DI) container into your Serilog pipeline. What was the problem? ASP.NET ......
Read more >
Setting up Serilog in ASP.NET Core - Detailed Beginner ...
How to use Serilog Enrichers; Log Message Output Templates; Log Filtering; Summary ... Here is the list of some common Sinks supported by...
Read more >
How do I get a serilog enricher to work with dependency ...
It can be used to dynamically inject an object, that would take IServiceProvider in ctor and use GetService to find a context it...
Read more >
How to use dependency injection in action filters in ASP. ...
Filters enable you to execute code at certain stages of the request processing pipeline. An action filter is a filter that is executed ......
Read more >
Structured logging in ASP.NET Core using Serilog and Seq
Serilog uses several nouns, like: sinks, enrichers, properties, destructuring policies and others, at the same time offering the means to ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found