Closed nblumhardt closed 9 years ago
Thanks @nblumhardt and @jvrdev! Agree with all those TODOs ;)
How about the public API? Do you have any thoughts on how/if it should change when moved from serilog to a stand-alone library?
I'd need to tinker a bit to bed down an opinion, but trying to orient the nuts and bolts around the basic scenarios of serialization and formatting, with some static helpers on top, seems interesting.
var template = MessageTemplate.Parse("Hello, {Name}");
// Args-to-string; produces "Hello, nblumhardt"
var formatted = template.Format(Environment.UserName);
// 'Serialization'; produces a dictionary with { "Name": "nblumhardt" }
var properties = template.Capture(Environment.Username);
Some static helpers:
var formatted = MessageTemplate.Format("Hello, {Name}", Environment.UserName);
var properties = MessageTemplate.Capture("Hello, {Name}", Environment.Username);
This setup gets us away from having to support some kind of LogEvent
-like class - anyone wanting to construct that kind of thing can use the nuts-and-bolts API from the first snippet and do this efficiently. We can also leave caching (Serilog does this only semi-effectively) in the hands of the caller.
Some thought needs to be given to @
:-)
Thanks! This sounds like the kind of API I was thinking of, too.
Some thought needs to be given to @ :-)
Do you mean because of the new C# string interpolation features?
No, sorry - thinking more of how much flexibility/Serilog infrastructure would be brought across (if any) to support it.
For most property types, e.g. Name
above, representing them as a simple scalar "nblumhardt"
, 42
, or array-of-scalars, is fine and doesn't require any special types. It's less clear what an @
-destructured value should be Capture()
d as. Serilog has StructureValue
and friends to snapshot object state in a way that makes concurrent access safe (and caches the reflection/allocation done in that process).
I don't think it would necessarily hurt to follow the Serilog design, but on the other hand, the custom structure types are a pain sometimes and would feel like a burden outside of the context of the thread-safety-net they provide Serilog.
Which is the right choice probably comes down to the scenarios, might be good to start collecting a few. Arguably, if this lib had existed a while back, it might form the basis of newer loggers like ASP.NET's one. This: https://github.com/akkadotnet/akka.net/issues/1045 - is a really interesting discussion that might spark some ideas (and perhaps be a good candidate use-case?)
FTR, the scenario that drove this originally for me, seems very similar to akkadotnet/akka.net#1045. I wanted to allow structured logging to exposed from Suave, and I wanted the internal message templates to resemble those from Serilog.
However, that left me with the trouble of supporting existing logging adapters for Suave. They would continue to need unstructured (flat strings) for log messages, and they wouldn't know how to render the internal Suave templates.
Right now, I lean heavily towards keeping the custom structure types (like StructureValue
), as I expect that they are "battle hardened" by being in use with Serilog.
The other adapters to Suave is Logary as far as I know, and I've created a corresponding issue to track this feature.
The way logary currently does it is through pretty-printing, like this:
https://twitter.com/logarylib/status/606854678266187776
I picture this feature as a simple switch in the console output that prettifies the actual log line.
I also think a library like this should be centered around a consensus-spec with an implementation in each of F# and C# that you can copy-paste into basically any-licensed code-base. As such it will be for everyone to add this feature.
I think it would be better not to make this repo about "serilog message templates" as that will lose you my participation, but rather about a specification-by-code and unit-tests of how they behave.
I would consider first-class F# support to be a requirement on top of the C# support you got very nicely done already.
I think @haf raises an important issue. Projects are likely to want to avoid the dependency on a library like is, and it might be far more valuable to create a suite of tests than an implementation could adhere to.
Another option that might be the best of both worlds-
This would greatly reduce the barrier to entry for new projects to support the format, which a spec alone won't do.
Shipping it as source avoids the annoying universal dependency, and provides anyone who wants to customise their implementation a starting point to go from.
Finally, the tests are there for anyone who'd like to validate a completely new implementation. (Most likely, they'd serve as de-facto spec rather than an executable suite in this case.)
I've attempted spec-only work like this in the past and found it very hard to get started: "Hey, project X! How about implementing our spec?" is a really tough sell :-)
Thoughts?
Agree @nblumhardt.
It's clear to me now that I will need to do a single-file F# implementation too (in the F# world, this could be referenced via paket GitHub dependencies).
I think the goal should be something that can be copy-pasted (or GitHub paket referenced) into other projects. The tests should be executable on different implementations.
This is quite similar to http://haacked.com/archive/2009/01/14/named-formats-redux.aspx/ , however I think those "named string formats" have less features (e.g. No ability to capture properties).
@nblumhardt @adamchester +1 to both of your reasoning :)
I think the TODOs are done.
Hey Adam! Good on you for kicking this off :-)
I'm keen to chip in where I can. So we don't duplicate effort, it'd be good to have a quick TODO list while the project gets set up (and probably a list of outstanding questions among them).
Some that come to mind:
HTH!