Of those json is better if you want to be able to do more advanced stuff (nest dictionaries, use lists, ...) and logfmt is better if you want to have human-readable logs without external tools as well, an example line can look like
msg="Request finished" tag=request_finish status=200 [email protected] user_id=1234 app=mutelight app_id=1234
Some more info here https://www.brandur.org/logfmtFor logfmt, I seem to remember the spec not being very clear on quoting semantics (maybe I'm wrong). Anyhow, I would suggest using JSON since it has pretty broad support at this point.
You would know what is supported what with you being the author, just saying that the docs aren't super clear from a quick glance :).
And yes, I second the suggestion to focus on JSON. The main benefit of logfmt is that it's simpler for a human to parse directly but in general you probably shouldn't aim for that so..
Yes, I should mention it on the features page. It's currently only mentioned in the main docs:
But some other places describe this a bit more liberally. And [2] notes that I should include a time stamp in each log entry which makes sense.
[1]: https://stackoverflow.com/questions/10699953/format-for-writ... [2]: https://www.papertrail.com/solution/tips/8-essential-tips-fo...
It makes parsing and keeping track of the "state" of the file a lot easier. Say that your application crashes/gets killed halfway through writing a log message / json dict and then gets restarted and appends to the log file. How should the log reader handle that case if it suddenly becomes a valid nested object? And even if it doesn't, should it throw away the first new log message as well because that was embedded in the invalid json object? Much easier to just say "one line is one json object, if there are literal newlines that's the delimeter to start a new parse".
And yes in any case it's good to have a timestamp on your log message no matter the format, unless you're logging somewhere you know that it gets added immediately (like the systemd journal). Your log parser/forwarder can add a timestamp for when it reads your log message but that is not necessarily the same as when your application emits it.
This means that you shouldn't just write (to reuse the previous example):
msg="Request for user [email protected] finished with status 200"
you should do it like msg="Request finished" status=200 [email protected]
and not put any variables into the msg key (and not really do advanced formatting for any of the keys for that matter). This way once you get it put into a log system that understands your format you can do searches like "all log messages where user=foo" or "all statuses that are >=500 and <600" or search on specific messages, all without having to craft elaborate regular expressions and with better performance since the log search system can do indexing and various optimizations so that it doesn't have to be a full-text search every time.Probably the most common one (or at least was most common, maybe not anymore) would be "NCSA Common log format" (or just CLF) which looks something like this:
127.0.0.1 user-identifier frank [10/Oct/2000:13:55:36 -0700] "GET /apache_pb.gif HTTP/1.0" 200 2326
https://en.wikipedia.org/wiki/Common_Log_FormatMany tools for getting analytics out of server-side logs can work with CLF and the various variations. But probably today there are more "modern" formats as well.
[1]: https://serilog.net/
[2]: https://datalust.co/
I've always had trouble before figuring out what a good compromise between log format and flexibility looks like. Especially wrt newlines in the log message itself (eg if I want to log a stack trace)
Any thoughts for a format that would generally work ootb in lnav or other log viewers?