There are two fundamental advances with the structured approach that can't be emulated using text logs without (sometimes extreme levels of) additional effort.
Event Types
When you write two events with log4net like:
log.Debug("Disk quota {0} exceeded by user {1}", 100, "DTI-Matt");
log.Debug("Disk quota {0} exceeded by user {1}", 150, "nblumhardt");
These will produce similar text:
Disk quota 100 exceeded by user DTI-Matt
Disk quota 150 exceeded by user nblumhardt
But, as far as machine processing is concerned, they're just two lines of different text.
You may wish to find all "disk quota exceeded" events, but the simplistic case of looking for events like 'Disk quota%'
will fall down as soon as another event occurs looking like:
Disk quota 100 set for user DTI-Matt
Text logging throws away the information we initially have about the source of the event, and this has to be reconstructed when reading the logs usually with more and more elaborate match expressions.
By contrast, when you write the following two Serilog events:
log.Debug("Disk quota {Quota} exceeded by user {Username}", 100, "DTI-Matt");
log.Debug("Disk quota {Quota} exceeded by user {Username}", 150, "nblumhardt");
These produce similar text output to the log4net version, but behind the scenes, the "Disk quota {Quota} exceeded by user {Username}"
message template is carried by both events.
With an appropriate sink, you can later write queries where MessageTemplate = 'Disk quota {Quota} exceeded by user {Username}'
and get exactly the events where the disk quota was exceeded.
It's not always convenient to store the entire message template with every log event, so some sinks hash the message template into a numeric EventType
value (e.g. 0x1234abcd
), or, you can add an enricher to the logging pipeline to do this yourself.
It's more subtle than the next difference below, but a massively powerful one when dealing with large log volumes.
Structured Data
Again considering the two events about disk space usage, it may be easy enough using text logs to query for a particular user with like 'Disk quota' and like 'DTI-Matt'
.
But, production diagnostics aren't always so straightforward. Imagine it's necessary to find events where the disk quota exceeded was below 125 MB?
With Serilog, this is possible in most sinks using a variant of:
Quota < 125
Constructing this kind of query from a regular expression is possible, but it gets tiring fast and usually ends up being a measure of last resort.
Now add to this an event type:
Quota < 125 and EventType = 0x1234abcd
You start to see here how these capabilities combine in a straightforward way to make production debugging with logs feel like a first-class development activity.
One further benefit, perhaps not as easy to prevent up front, but once production debugging has been lifted out of the land of regex hackery, developers start to value logs a lot more and exercise more care and consideration when writing them. Better logs -> better quality applications -> more happiness all around.