Manasvi Gupta bio photo

Manasvi Gupta

Apache Kafka, Spark, Scala

Twitter LinkedIn Github

Logs are not the only way we monitor our systems, but they play an important role, both for troubleshooting purposes and to check the general health of an application.


One of the problems we had was the readability of logs. When you know what you’re looking for in a log, it is easy to search for an exception. But when you don’t know what is wrong, going through gigabytes of logs in white text on a black background can be very time consuming and error-prone.


Essentially, solution is to add colors to our logs to facilitate the readability. Wouldn’t it be great if every level (i.e., info, warning, error) message had a different color? What if we could have different colors in our stack trace to highlight different exceptions?

How coloring works in Unix terminals

Before jumping into the details of the implementation, let’s first understand how the coloring works in Unix. An easy way to understand it is to type the following in a Unix terminal:

    echo -e "\033[31m   Exception log    \033[39m"


The result is:

    Exception log


What happened?


First, it’s important to know that every color has a corresponding ANSI color code:

Black = 30
Red = 31
Green = 32
Yellow = 33

Default = 39


For the color codes to take effect, they need to be preceded by the “start” escape character, \033[ and be followed by the “end” escape character m.


Therefore, to display a message in red, we would type the following:

\033[31m

How others solved this problem

One company solved this problem by enhancing their Logback logging to add colors while application logs are being generated.

My solution to coloring logs in Unix terminal

My solution was slightly different. I created an AWK script with pattern matching that can highlight logs when we “tail” application logs. Added benefit is that script can be customized by user.

tail -f application.log | awk '

# Initialize variables with color to be used in terminal
  BEGIN { RED="\033[0;31m"; 
          BLACK="\033[39m"; 
          YELLOW="\033[33m";
          LIGHT_GREEN="\033[1;32m"
  }

# Identify WARNings and show in Yellow
  /WARN/ {p=1} p && /INFO|ERROR|DEBUG/ {p=0};p {print YELLOW \$0 reset; next}
  
# Identify  INFOrmatin and show in Green
  /INFO/ {print LIGHT_GREEN $0; next}
  
# Identify ERRORs, including full stack traces and show in Red  
  /ERROR/ {p=1} p && /INFO|WARN|DEBUG/ {p=0};p {print RED \$0 reset; next}
  
# Anything not matching should be displayed with DEFAULT terminal settings
  // {print; next}
'


To avoid re-typing this script, you can add this AWK script in your bash profile as alias, like this:

alias colorlog="awk 'BEGIN { RED=\"\033[0;31m\"; BLACK=\"\033[39m\"; YELLOW=\"\033[33m\"; LIGHT_GREEN=\"\033[1;32m\"; GREEN=\"\033[0;32m\"; reset=\"$(tput sgr0)\" }

  /INFO/ {print GREEN \$0 reset; next}
  /ERROR/ {p=1} p && /INFO|WARN|DEBUG/ {p=0};p {print RED \$0 reset; next}
  /WARN/ {p=1} p && /INFO|ERROR|DEBUG/ {p=0};p {print YELLOW \$0 reset; next}
  // {print; next}'
"

and call it like this:

    tail -f application.log | colorlog


And Unix terminal looks like this after running above command