Let’s talk about logging
dave.cheney.net
dave.cheney.net
Let's look at error. If you're running a web server, or something like a web server, then when a request errors you don't want it to blow up the whole server. You just want to log that error. Yet you may not care about the many many other normal requests happening at the info level (and debug would be even more info underneath). Thus now error is actually useful both in terms of monitoring but also separating out from other requests that went through just fine.
People say exceptions should blow up the world -- that's great when you're debugging, but users don't typically want to keep reusing an app that crashes. There are more graceful ways to degrade.
For example, converting a user input to an integer. You can provide safe defaults if the value doesn't convert so it doesn't break the flow. As the developer however, if you see too many warnings with conversion errors then you may want to change the label of the form field, or provide some guidance to make it more clear to the user.
For a similar example: The D compiler gives very few warnings and some people want to remove those as well. The argument is that the compiler should not do the job of static analysis tools, just because it is convenient or easy. A compiler should either generate code or give an error.
If something is for developers only, make it debug-level.
However, in the server environment, there is also the IT/sysadmin role between user and developer. It makes sense to provide a level specifically for them. "warning" mostly fits that.
So say you're doing an hourly sync, and it falls over, you want to log a warning. It happens, no need to send out the fire engines.
If you're getting a warning every hour, that's "too many warnings".
postfix/postdrop[21416]: warning: mail_queue_enter: create file maildrop/465240.21416: No space left on device
My question is, if that is a warning, what's an error?
For example, the user has provided a config with two TCP ports to listen to, but the program only supports one.
You can either error out, and abort the action to listen to a port, or warn the user saying that you chose one of the ports, and proceed with listening to a port.
I suspect this isn't widely used because it relies on POSIX shared memory and support for keeping data structures in SHM isn't widely available.
Aren't you incurring a cost for logging for stuff that would end up being thrown out?
This also removes the rather heisenbergian issue of turning on and off debug logging. In a lot of application turning on debug logging is a surefire way of making sure any race conditions won't occur.
It also means that logging (to disk) will not occur in the performance critical bits of the code. The logging will be fully asynchronous as completely different process will be given the task of persisting the logs.
We don't [yet] use it as part of our logging framework, but recently I used it in a pretty interesting way. We had to make some changes to how we interact with SQL to handle transient faults on the cloud (specifically SQLAzure). Big risky change. In order to guarantee that we didn't mess anything up I sent events to ETW from our data access layer. A separate process would then listen for those ETW events and resolve the stack trace outside of the primary process (something that ETW will do for you). Each stack frame was then sent to a primary server. This allowed us to do very fast code coverage analysis on QA environments for additional guarantees beyond unit tests.
Without ETW this would have taken me a week instead of day - it's some really exciting tech. I'd love to see something analogous to ETW in Linux; it has made me realize that textual logging is, frankly, unacceptable.
As an aside, you're comment about textual logging points to a deficiency generally about how developers do logging - with text. ETW forces you to allocate Event IDs and structure to your log events so that logs can a) be consistent and b) can be easily (i.e without regex magic) monitored and alerted on, summarised and generally reasoned about.
If you are on a platform with ETW, you should use it. If not, you should still use some of its principles - i.e Event IDs and structured data.
I think that is a desirable property. When something broke, there's a good chance that those comparatively few lines tell me what and why, and if I'm really lucky give me enough info to reproduce the problem without diving into the more verbose logs (which might not even be generated/captured, if performance concerns preclude).
That's a rather bold assertion to make - I look at warnings in logs and approve of their inclusion. Sometimes you want a request to work even when some parts of it aren't quite as expected and in that case the right thing to do is log warnings that something is generating requests that are a bit off and it might be worth investigating that application to find out what is going on:
"be liberal in what you accept from others"
But log as warnings when you are being liberal... :-)
sprintf is lossy serialization.
My favorite example is ssh. Thousands of man hours have likely been wasted writing parsers for ssh logs that are generated from code like this:
authlog("%s %s%s%s for %s%.100s from %.200s port %d %s%s%s",
authmsg,
method,
submethod != NULL ? "/" : "", submethod == NULL ? "" : submethod,
authctxt->valid ? "" : "invalid user ",
authctxt->user,
get_remote_ipaddr(),
get_remote_port(),
compat20 ? "ssh2" : "ssh1",
authctxt->info != NULL ? ": " : "",
authctxt->info != NULL ? authctxt->info : "");
Which if the apis were better could have just looked like authlog({
"authmsg": authmsg,
"method": method,
"submethod": submethod,
"valid": authctxt->valid,
"user": authctxt->user,
"addr": get_remote_ipaddr(),
"port": get_remote_port(),
"ver": compat20 ? "ssh2" : "ssh1",
"info": authctxt->info});
(obviously C would need something a bit different)The updated(2009) syslog RFC supports structured data, but it's been 6 years and nothing uses it:
Use Structured Logging!
https://docs.google.com/presentation/d/1SnjZpcfJq9r6OpgsjsX9...
Unfortunately the blog posts stick around for a lot longer than they ought to, making it very hard for Googling newbies to decide whether they can trust the advice or not.
Reminds me of the old adage "the more you know, the less you know". Works in reverse!
I disagree with his post, too, but to brush it off as (or even relate it to) inexperience and junior devs is slightly out of place.