Enforce using specific parameters in Serilog (or generally in an external function)

Viewed 299

I'd like to create a contract enforcing the use of specific template of parameters on the Serilog logging function.

Is there a way to do this without encapsulating the function with my own (which would need to be done for each logging level)?

I have a namespace called EventLog which holds event types, facilities, ect. I'd like to enforce using an event type and facility from that namespace when logging.

Rather than:

void _LogLevel_<T0, T1, T2>(string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2);

I'd like to enforce this:

void _LogLevel_<EventLog.EventItem, EventLog.Facility, T0, T1>(string messageTemplate, EventLog.EventItem EventType, EventLog.Facility Facility, T0 propertyValue0, T1 propertyValue1, ...);

Assuming code would not compile if the two parameters are not specified, and that the first two objects would be serialized as any generic T0, T1, ... would be in Serilog.

This is to assure that when the logging function is called, the given parameters will always be added.

Another problem with this is that Serilog has it's own DSL, and I cannot enforce adding {@Event}, {@Facility} to the messageTemplate, which is a string.

1 Answers

Doing this through the message template seems like it will be laborious; you could achieve what you're after by piggy-backing on Serilog's ForContext() with an additional method:

public static ILogger ForEvent(EventItem item, EventFacility facility)
{
    return Log.ForContext("Event", item, true).ForContext("Facility", facility, true);
}

Which you'd call like MyLog.ForEvent(e, f).Information("Hello!").

If you're using ILogger, rather than the static Log class that the above example uses, you might try an extension method:

public static ILogger ForEvent(this ILogger log, EventItem item, EventFacility facility)
{
    return log.ForContext("Event", item, true).ForContext("Facility", facility, true);
}
Related