This would allow implementations such as Serilog and recent versions of nlog (or any others I'm not aware of) to utilise some of their structured logging capabilities.

bonus points...

going further than type scoping LogManager.GetLogger(typeof(MyType)) (but more complex to implement no doubt) by adding a 'context' to the ILog interface would allow properties to be added outwith the message template, or just appended to log message strings for implementations that don't support structured logging either directly or scoped via a similar concept to serilog's enrichers.

I'm not sure what the method signature for this should be, is there an existing logging abstraction that supports multiple structured logging providers? If there is, lets use their method signature, if there isn't lets not create the IStructuredLog interface now and instead wrap the extension method over the concrete SerilogLogger, e.g:

We can create the interface later once we implement it on multiple Logging providers.

Mac
—
2017-03-18T17:29:59Z —
#3

I'm not aware of any existing abstractions for structured logging but I'll have a rummage about.

The second approach probably better for individual logging libs but more likely to fragment approaches without an interface contract to implement against.

Also without an interface, would be harder to promote discoverabllity/usage to gain adoption over time i.e. something like extending LogManager LogManager.GetStructuredLogger(typeof(MyType))

Mac
—
2017-03-19T14:39:55Z —
#4

ok after a wee rummage it appears that schema-less structured logging is pretty thin in the .net space outwith serilog.there is a project for nlog that uses anon classes to serialize json payloads into logs but it doesn't leverage the message template/hashing/destructuring directives and property storage that serilog uses so effectively. It's just a string + json payload appended.

I've hacked together an example using the IStructuredLog interface you suggested with the quick and dirty extension method for ILogFactory.GetStructuredLog() as I can't add to the LogManager static i.e. LogManager.GetStructuredLogger(typeof(T)) so using the Serilog.Log.Logger is just a cheat

Here's the interface where I've basically just copied the method signature of serilog using (exception, messageTemplate, properties)

The reason for the other method signatures which essentially duplicates the DebugFormat style is not really required, but for me, using the term 'format' is not really what structured logging (and in particular serilog) is doing

The ForContext methods allow me to scope the logger with additional enrichments,Either globally (things like machine names, thread id's etc) or locally, in particular the ability to add arbitrary props to logging events that aren't rendered as part of the message template (again I don't think exists outwith serilog). Message templates are not just strings but can control the destructuring of objects

If this is just for Serilog, we shouldn't create an interface. Just have extension methods on ILog that delegate to Serilog. These extensions can live in Serilog in the ServiceStack.Logging namespace. If we ever have multiple implementations we can extract out an interface then.