Skip to content

Adding support for enrichers that use dependency injection. Ready to open PR. #458

@Banner-Keith

Description

@Banner-Keith

Hello,

I have a scenario where I want to add an enricher that needs to get a service from the IoC container.

Like this:

public class ExampleEnricher : ILogEventEnricher
{
	private readonly IHttpContextAccessor _httpContextAccessor;
	private readonly IMySingletonService _mySingletonService;

	public ClientAppNameEnricher(IHttpContextAccessor httpContextAccessor, IMySingletonService mySingletonService)
	{
		_httpContextAccessor = httpContextAccessor;
		_mySingletonService = mySingletonService;
	}
	// ...
}

public static class ExampleEnricherLoggerConfigurationExtensions
{
	public static LoggerConfiguration WithExampleValue(this LoggerEnrichmentConfiguration enrichmentConfiguration, IServiceProvider services)
	{
		ClientAppNameEnricher clientAppNameEnricher = services.GetRequiredService<ClientAppNameEnricher>();
		return enrichmentConfiguration.With(clientAppNameEnricher);
	}
}

This allows for the potential of more powerful enrichers that rely on other services and would allow for enrichers that need the HttpContext in .net core to use IHttpContextAccessor instead of creating a new HttpContextAccessor inline.

The code changes needed are not too invasive.

ConfigurationLoggerConfigurationExtensions gets a new overload of Configuration that takes IServiceProvider from the UseSerilog callback. e.g. .ReadFrom.Configuration(context.Configuration, services)

ConfigurationReader gets a new nullable optional constructor parameter for the service provider. It gets added as a field.

SelectConfigurationMethod is modified slightly to allow it to return methods with an IServiceProvider parameter.

The two ApplyEnrichment methods both call CallConfigurationMethodsWithServiceProvider instead of CallConfigurationMethods The new method wires up the field of the service provider to the parameter in the extension method.

In my testing so far it works great. Everything is backward compatible.

Example of the error you'll see if you don't have the service provider passed in and you add an extension the needs it.

Missing service provider. The WithExampleValue method requires that IServiceProvider be registered.
Either remove WithExampleValue or use .UseSerilog with the (context, services, configuration) callback
and pass the service provider in.
Example:
hostBuilder.Host.UseSerilog((context, services, configuration) =>
{
	LoggerConfiguration loggerConfiguration = configuration.ReadFrom
		.Services(services)
		.ReadFrom.Configuration(context.Configuration, services);

	// ...
});

If you are open to this type of change, I will work on some tests and readme changes to support this feature. If this isn't something you are interested in that's okay too. I would add a note in the readme that you should be very cautious about how you use this feature, so you don't end up with performance problems using it.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions