Writing Concise and Informative Logs

in software-development •  6 years ago 

Observability when working with lambdas is important, with so many getting spun up at different times and serving different requests it is good to have as much information as possible about what exactly is going on. When I wish to debug code my code or pull metrics I always use the json formatting. I do this because it is easily greppable by Cloudwatch and can hold some very valuable information, json is also an amazing format to work with. For anyone who doesn't know how to query Cloudwatch I would recommend checking this out. The most important thing is to put as much useful information into the log as possible, whilst preventing any unwanted information from slipping in.

Let us build up an informative log line

Here are the steps I follow when deciding what to add to a log line.

Let's say the following event has happened;

user has been updated

This is a vague statement but it is a good place to begin asking question and working out what information is needed. First question that springs to mind is which user has been updated?

Better add in a unique identifier for that user.

{
    msg: "a user has been updated",
    user_id: 1234,
}

What has been updated on the user? Some could argue that this information may be unnecessary but it all comes down to observability.

{
    level: "info"
    msg: "a user has been updated",
    user: {
        id: 1234,
        username: "JohnnMackk",
        email: "[email protected]"
    },
}

At what time did this happen? This is cheating since Logrus gives this to us for free but let us build it up.

{
    level: "info"
    msg: "a user has been updated",
    user: {
        id: 1234,
        username: "JohnnMackk",
        email: "[email protected]"
    },
    time: "05-11-2018 12:12:12",
}

Who actually updated this user? why not add their id? You could add the user as an object with their username ect but let's keep this log as small as possible

{
    level: "info"
    msg: "a user has been updated",
    logger_in_user: 1,
    user: {
        id: 1234,
        username: "JohnnMackk",
        email: "[email protected]"
    },
    time: "05-11-2018 12:12:12",
}

Finally let's say that something went wrong sometime during this request? How do we know what happened just before the error. Let us add a unique identifier into this log so that we can follow it as a stack trace;

{
    level: "info"
    run_id: "n70zqPXBaxA9RdJ4",
    msg: "a user has been updated",
    logger_in_user: 1,
    user: {
        id: 1234,
        username: "JohnnMackk",
        email: "[email protected]"
    },
    time: "05-11-2018 12:12:12",
}

Ok one last thing msg "a user has been updated" seems kind of redundant it was good for a starting point but now we have built up more of a picture around it, but we do need some kind of identifier to distinguish all logs of an "update" kind of nature.

Why don't we rename msg to type

{
    level: "info"
    run_id: "n70zqPXBaxA9RdJ4",
    type: "User Update",
    logger_in_user: 1,
    user: {
        id: 1234,
        username: "JohnnMackk",
        email: "[email protected]"
    },
    time: "05-11-2018 12:12:12",
}

And done, from a user has been updated we how have a clear descriptive log with no redundant data.

Observability

Now for the reason we did the above, to view our logs, and read exactly what our system is doing.

Querying these logs via cloudwatch

I have recently been working with Golang lambdas running on AWS so I was using Cloudwatch to view these logs. Fortunately Cloudwatch has a really cool query language for this very job. Using the above as an example.

I can now begin to query Cloudwatch and pull back all these events via;

{ $.type = "User Update" }"

If i wanted to get all the updated done by a certain user I can;

{ $.type = "User Update" && $.logger_in_user = 1 }

And if something went wrong during the request I can create myself a stack trace via;

{ $.run_id = "n70zqPXBaxA9RdJ4" }

Viewing on the commandline

When viewing from the command line I use jq. Essentially this tool is a grepper, and a json formatter all in one.

The simplest

tail -f some-json-log-file.log | |jq '.'
Authors get paid when people like you upvote their post.
If you enjoyed what you read here, create your account today and start earning FREE STEEM!
Sort Order:  

Congratulations @jmackenzie91! You have completed the following achievement on the Steem blockchain and have been rewarded with new badge(s) :

You published your First Post
You got a First Vote
You received more than 10 upvotes. Your next target is to reach 50 upvotes.

Click here to view your Board of Honor
If you no longer want to receive notifications, reply to this comment with the word STOP

Do not miss the last post from @steemitboard:

Meet the Steemians Contest - The results, the winners and the prizes
Meet the Steemians Contest - Special attendees revealed
Meet the Steemians Contest - Intermediate results

Support SteemitBoard's project! Vote for its witness and get one more award!