What can you learn from production.log?

Published on

Many developers fail to realize that using the basic Unix tools, you can find on any server, you can find and collect valuable data from your logs. Often the data you need can be found without using any external services, including but not limited to service measurements.

This is a start of a series of posts that will try to show some of the nice things you can achieve with the Rails log from the command line.

The basics

Let’s star with the simplest one — following the incoming logs:

tail -f log/production.log

We could of course show the complete log with cat, but often it is far longer than we would expect and following the logs tends to be much nicer. On the other hand cat can be handy when combined with grep and tail.

Filtering

The first thing we want to learn is to filter the log from the information we don’t need for the current measurement. Filtering is all about recognizing the patterns in the text and cutting out everything that doesn’t match it. A common thing is to display only the CRUD request logs, or to filter everything out except database actions.

A nice scheme for creating complex filters (and the one we will be using in the examples) is the following:

cat log/production.log | <filters> | tail

In the above command the cat command pushes the logs into the filters, and the tail command shows a portion of the result. An alternative for the tail - that shows the end of the results - can be the head command that shows the start. By default, both commands display only 10 results, but can be tweaked to show more with the -n option. For example to list the last 20 lines we can use the following scheme:

cat log/production.log | <filters> | tail -n 20

But enough with the boring details, let’s define a filter. The following example shows only incoming POST requests.

cat log/production.log | grep 'method=POST' | tail -n 20

In the above example we used the grep command that returns only the lines that have the provided string or regular expression in them. We can also combine multiple grep commands, where the second grep will only work on the lines that the first grep returned.

For example, the following command shows only the POST requests that had a HTTP status 200 as their answer:

cat log/production.log | grep 'method=POST'
                       | grep 'status=200'
                       | tail -n 20

Similarly to the previous ones, we can easily show only the logs that were created yesterday:

cat log/production.log | grep 'method=POST'
                       | grep 'status=200'
                       | grep 'time=2015-02-10'
                       | tail -n 20

As the final example I will demonstrate something more complicated. We will list only the POST requests that had a duration longer than 10 milliseconds. Unfortunately, we can’t use the previous technique anymore because the string that we are matching are different on each line (somewhere the duration is 13 milliseconds, somewhere it is 114 milliseconds…).

Fortunately, we can use regular expressions with the grep command. What we need is actually more than one digit in the duration that will give us a number larger or equal to 10. To match a digit we will use the [0-9] notation, and to match 0 or more of them we will write [0-9]*.

cat log/production.log | grep 'method=POST'
                       | grep 'duration=[0-9]*[0-9][0-9]'
                       | tail -n 20

In the above example we used [0-9][0-9] to match two digits and [0-9]* to match the remaining.

Final words

I hope you enjoyed this tutorial, I will give my best to finish the next one soon, where I will be talking about counting.

Happy hacking!