How to finally start writing logs?

I was at the same time terrified and feeling adventurous by the idea of writing about programming for a long time. It’s quite overwhelming, I have to say and it should be — there are so many talented and knowledgeable people around, it’s easy to get intimidated. And, of course, there is always someone who knows more than you do. So, what I decided to do is to write about what I don’t know and how I live with not knowing things. Because my favourite character or my life coach, if I may, says: “Dude, sucking at sumthin’ is the first step towards being sorta good at something.” © Jake the Dog

So, without further ado.

One of the things I didn’t know when I started programming and, by all means, I still don’t know, is how to write a perfect log in your application, or at least how to write considerably helpful logs.

I’m sure there are lots of useful articles (I’ve read some of them) about it and lots of people write uber effective logs. Their logs follow one precise style guideline, never get abandoned and also somehow make you application run at light speed with less recourses used. We all know those people. Those “I wrote some Haskel before lunch to solve some theoretical CS problem” people. And I’m happy for them, honestly. I’m sure it wasn’t easy and they’ve made some effort to make their logs a masterpiece, but personally I find myself sometimes in a position where I kind of really need to writhe THE CODE and I have no time to reflect “if my logging system is robust enough” — the fact that I have a logging system set up is a big plus already. It’s all about priorities, you know.

So, what I thought could be wise is it to sketch what people that have no time but a lot of ambition for improvements (like me, he-he) can do about their logging practices.

I guess the most important question that needs to be answered is — why to log?

For me the answer would be something like this:

  1. Debugging

It looks pretty simple and may be it is.

Spoiler: Examples are in javascript, but concepts apply to other languages as well and I’m going to talk about free form, old, simple string logs, not even json logs.

I. Debugging

Debugging logs are supposed to help you find and fix problems in the code. Cool. So, how to write them then?

First of all, important to mention, we all know that :

 console.log(“did it get here?”)

and other debugging logs that are important only to a developer and are not helpful in the context of a project should not be committed. We all know we do this but we don’t have to admit it publicly.

Second, one of the things that must be logged and committed — is error logs, but it’s probably a whole separate topic to cover, so I’ll talk about two things that bother me about logging errors.

  • You must indicate that a log is an error ether using your logger’s level or plain text inside logs that is searchable ( “ERROR” should do) or whatever else and serialise the error where possible, so you’d have stack trace for actual debugging
const takePaymentFromUser = (user) => {   if(!user){
throw new Error(“No user provided”)
}
//TODO take that sweet money
}
const main = () => {
try {
takePaymentFromUser()
}catch (e){
console.error(e.message)
}
}
main()

The output will be :

No user provided

This is great but not helping anyone. I think that there are two things that would make it better: 1. It should have stack trace, so you know where to look (arguable, apply judgement) 2. It should give more context on what is the consequence of this error.

There are at least 1538 ways of rewriting this example to fulfil both requirements, I’ll add one:

const takePaymentFromUser = (user) => {   if(!user){
throw new Error(“Unable to take payment. No user provided”)
}
//TODO take that sweet money
}
const main = () => {
try {
takePaymentFromUser()
}catch (e){
console.error(e)
}
}
main()

Output:

Error: Unable to take payment. No user providedat takePaymentFromUser (/home/runner/OurTameChapters/index.js:3:13)at main (/home/runner/OurTameChapters/index.js:10:5).... etc

Ok! Now we are talking! By looking at this log you’ll immediately know, that something important (money money money) is very wrong and will know where is it wrong, too. This brings me to the next section

II. Monitoring

Another thing you want your logs to do is to help to know your app is actually ok even you are not staring at the console and if it’s not ok you’ll know about it. This topic is also waaaay too big to cover in one go, so I won’t even attempt. There are couple things worth mentioning though, like, why to monitor at all? Here is why:

  1. Allows to make sure app is stable and predictable and if it’s not know it as soon as possible .

Couple things to look out for when you log information that you plan to monitor.

  • If it’s something that you plan to monitor through time, like amount of logins per day or error rate or other things, you probably wouldn’t want to change the monitored log after you set it up. So, it’s best to put some more thinking in phrasing this logs. It should have enough context for 3-month-later-you to still understand what it means and find elegant.

III. Archeology, I mean Information

This one is an odd combination of debugging and monitoring, mostly needed for providing context to other logs and generally make sense of them. It may seem silly at first but there are some important events in every application that should be logged even if this is boring. Most of this logs would need to reflect some lifecycle event, like “app started” or “app stopped” or “how many of something is available” you know, whatever is basically the fundament of your app and what in case of “sh*t went down” situation would be the remaining ruins of your app, so future archeologists would have some stones to turn.

It’s kind of hard to come up with a useful and not too of an obvious example but I will attempt anyway. I believe it goes without saying that when your app starts it should let the world know with something like “app started to listen on port *port*” and all that, but what’s more important is to pin point the most important yet fragile places of your app, like first connection to external resource, bringing up a database, refreshing access tokens, things that don’t happen too often, so you won’t flood your logs with them, but are important enough to know that they are ok.

Some might say here: “Well, I log my errors, so why log success?” — what I’d say to is this is — when it comes to investigation of a crime scene it’s much nicer to know what definitely has happened good or bad, then guess what may have happen with no evidence to it © Me.

Conclusion:

I don’t have any good conclusion here, it was indeed a very brief touch on what’s up with logs. Beside that I would like to wish everyone happy coding, more experiments and less anxiety about imperfect logs/code/world.

The end… for now.

PS

I almost forgot, if you are, my friend, a total nerd and you want to learn even more (!) on logs there are tons of materials! Of course, I’d recommend to get to know classic Uncle Bob’s “Clean code” chapter on logs. Also, I’d strongly recommend to look at JSON logs and logging platforms “best practices” recommendations. And come on! Comment what’s your favourite “ how-to” article on logs and I’ll get offended if it’s not this one!

Cheers!

#logs #begginersfriendly

Software engineer and a sociotechnologist.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store