How to install and use GLog

GLog is the logging library from Google for C++. It makes it real easy for you to add logging to any C++ application.

  • Install: Installing GLog header files and library files is easy:
$ sudo apt install libgoogle-glog-dev
  • Header file: The header file to include in your source file is glog/logging.h

  • Initialization: You will need to call google::InitGoogleLogging method with the name of your program as the input parameter to start logging.

  • Levels: There are 4 levels for logging messages in increasing order of severity: INFO, WARNING, ERROR and FATAL. These severity levels have values 0, 1, 2 and 3 respectively.

  • Log function: To log a message, use the LOG macro, similar to how you use cout. For example, this example shows logging messages of different severity:

#include <glog/logging.h>

int main(int argc, char* argv[])
{
    google::InitGoogleLogging(argv[0]);

    LOG(INFO) << "This is an info  message";
    LOG(WARNING) << "This is a warning message";
    LOG(ERROR) << "This is an error message";
    LOG(FATAL) << "This is a fatal message";

    return 0;
}
  • Library: To compile a source file using GLog, you will need to link using -lglog.

  • Log files: By default, when you run your program, 3 new log files will be created in /tmp directory. The filenames are of this format:

foobar.home-machine.ashwin.log.ERROR.20171026-220607.21911
foobar.home-machine.ashwin.log.INFO.20171026-220607.21911
foobar.home-machine.ashwin.log.WARNING.20171026-220607.21911

Format:
program_name.hostname.user_name.log.level.date.time.pid

The file with INFO in its name has log messages of levels INFO and above. The file with WARNING int its name has log messages of levels WARNING and above. Similarly, for the file with ERROR in its name.

In addition, 3 symbolic links are created in the same logging directory pointing to the latest log files. These 3 filenames are of the format:

foobar.ERROR
foobar.INFO
foobar.WARNING
  • Log to display: By default, when you run your program, you will see log messages of ERROR and FATAL on the stderr, so they will appear on the console. Note that the first FATAL message will prompt the killing of your program.

  • If you want the program to log to stderr instead of writing to log files, set this environment variable GLOG_logtostderr=1

  • If you want to change the logging directory from /tmp to some other location, set this environment variable GLOG_log_dir=/some/path

Reference: GLog documentation

Could not create logging file error

Problem

I tried to train a model using Caffe on a remote computer. The training proceeded without any problems, but this error would show up in the console output occasionally:

Could not create logging file: No such file or directory
COULD NOT CREATE A LOGGINGFILE 20170221-111719.33617!I0221 11:17:19.399444 33617 solver.cpp:243] Iteration 86860, loss = 3.38734

Solution

This error turned out to be from GLog, the Google logging module. Caffe uses GLog for its logging. On this particular remote computer, the GLOG_log_dir environment variable had been set, but to a non-existent path! This was the reason GLog was complaining. Once I removed this environment variable and restarted the training, I no longer saw the error.

Tried with: Ubuntu 14.04

Log of sudo commands

I recently discovered that a user on a server had accidentally killed my program. Many users, including me, on this server have sudo permissions. So, I guess the kill was carried out by using sudo. How to find out who is the killer?

Thankfully, all actions taken under sudo are logged in the /var/log/auth.log file. You will find entries of this form:

Sep 26 08:31:26 foobar-machine sudo:   joe : TTY=pts/1 ; PWD=/home/joe/scripts ; USER=root ; COMMAND=/usr/sbin/openvpn --daemon --config foobar.ovpn
Sep 26 08:31:26 foobar-machine sudo: pam_unix(sudo:session): session opened for user root by joe(uid=0)
Sep 26 08:31:27 foobar-machine sudo: pam_unix(sudo:session): session closed for user root

You can see that all pertinent information is available in the log: who ran the command, what command and when.

Tried with: Ubuntu 16.04

GiTk

GiTk is a GUI tool written in Tcl/Tk for viewing the Git log as a directed acyclic graph (DAG) and has many features to browse and explore the DAG. This is a tool that ships along with Git, so it should be present wherever Git is there. It accepts many of the options that can be passed to git log.

  • By default, it shows only history of the current branch:
$ gitk
  • Colors: It is important to understand the various colors used in GiTk. Commit with yellow circle is the HEAD. When GiTk is opened, it always jumps to this commit. Commit with red circle is your uncommitted changes. All other commits are shown in blue circle. Local branche names are shown in green, while remote branch names are shown in combination of orange and green with the orange section being the remote name and the green section being the branch name.

  • Configuration file: Configuration settings of this tool can be changed or set in ~/.config/gitk/gitk

  • To view history of another branch:

$ gitk some_other_branch
  • To view the history of all branches:
$ gitk --all
  • To view the history of a certain file:
$ gitk /path/to/file
  • --date-order: Show commits in reverse chronological order of their dates. I use this when I want to get a sense of the progress of the team working on the repository. You might think this is very useful and may wonder why this is not turned on by default. Note that this makes the chain of development harder to visualize. The default view is --topo-order which tries to show as many commits of a branch together as possible. See the man page for an example scenario.

  • --merges: View only the pieces of the DAG with merges.

  • --no-merges: View the disconnected pieces of the DAG with the merge commits removed.

  • --first-parent: Show only the first parent in merges. This greatly simplifies the visual complexity of the DAG. This is especially useful when viewing the DAG of a repository that follows the GitFlow branching model. Note that the first parent of a merge is the branch to which the other branch was merged.

  • -n: Provide a number to this option to limit loading only that many commits. This is useful when viewing a repository with a large number of commits. For example: gitk -n 1000

  • To search and view all the commits with a certain string, type it in the Find box and press Enter. You will see that all the commits with that string are highlighted in bold. You can jump up and down between these commits using the Up and Down arrow buttons at the left.

  • To diff two commits: Click the first commit to highlight it. Next right-click on the second commit to get the context menu and in that menu choose Diff this and selected.

  • F2: To view all the branches and tags in a dialog. Clicking on one of them takes you to that tag or branch. This is useful to navigate a complex DAG.

  • Right-click on any line in the diff shown below and choose Show origin of this line to jump to the commit that added this line. You typically check this on line that are modified or removed in the current commit of course.

  • For complex DAGs, edges are broken into dangling arrowheads. Clicking on the arrow tip jumps you to the other end of the edge.

  • Click on any edge and all the edges that for that segment of the graph are shown in bold. The bottom pane changes to show the parents and children of that piece of the graph.

  • Mark: To bookmark a commit, right-click and choose Mark this commit. The commit will be shown in a box. Marking is useful to bookmark a commit and later return to it. For example, mark a commit, navigate to another part of the DAG and then right-click anywhere and choose Return to mark to go back to the marked commit. It is also useful for diff of two commits. For example, after marking a commit, right-click on another commit and you can choose to diff the two. Only one mark can be set. Setting a new mark, removes the previous one.

  • External Diff: No matter what you are doing in GitK, viewing a commit or comparing two commits, the lower-left box always shows the diffs and the lower-right box the files which are different. However, you may prefer to see diffs side-by-side or using a different external diff viewer, like Meld. This can be done easily. Just right-click any of the filepaths shown in the lower-right box and choose External Diff to view in your favorite diff viewer. The diff program it will use is the one you have set using the diff.tool configuration option in Git.

Tried with: Git 2.4.1 and Ubuntu 14.04

How to wrap git log

I display the log of Git in my own custom format. When the display text for a commit is longer than the width of the terminal, it is just truncated!

I could not find any way to make Git wrap the display of log message in the terminal. What I instead do is to pipe the git log through the classic Unix fold command:

$ git log | fold

By default, fold wraps to a width of 80 columns. You can specify the width of your terminal to it using the -w or --width option.

Tried with: Git 1.9.1 and Ubuntu 14.04

How to log in OpenNI 2

I use OpenNI 2 to read depth and color (RGB) images from a Primesense camera. Sometimes when my program does not work as expected, I like to enable the logging that is built into OpenNI 2.

  • To change the logging settings, the file that needs to be edited is Redist/OpenNI.ini.

  • Log messages can be printed to the console by setting LogToConsole to 1. If you run your program after this is enabled, it prints log messages on the console.

  • Log messages can be written to a log file by setting LogToFile to 1. If you run your program after this is enabled, it prints log messages to files in a Log subdirectory. One log file is created for every invocation of your program. The log filename is a timestamp, for example: 2015_08_18__20_27_53_16182.log

  • Four levels of verbosity is available for log messages. In increasing verbosity these are: error (3), warning (2), info (1) and verbose (0).

Tried with: OpenNI 2.2, Primesense RD1.09 and Ubuntu 14.04

Log levels in OGRE

There are 3 logging levels that can be specified in OGRE. These can be seen in the OgreMain/include/OgreLog.h file:

/** The level of detail to which the log will go into.
*/
enum LoggingLevel
{
    LL_LOW = 1,
    LL_NORMAL = 2,
    LL_BOREME = 3
};

There are 3 types of log messages that can be asked to be logged. These are also seen in OgreMain/include/OgreLog.h file:

/** The importance of a logged message.
*/
enum LogMessageLevel
{
    LML_TRIVIAL = 1,
    LML_NORMAL = 2,
    LML_CRITICAL = 3
};

How to output with timestamp using ts

You might sometimes want to create a log of the output from a program. Going into the program and adding a timestamp for each print command might seem cumbersome or not possible. It is here that the tiny ts utility makes itself useful. Pipe any output through it and it prefixes a timestamp to each line. Pipe the output of a long-running program through it and then save it to a file and you have a log!

To get this program, install the moreutils package:

$ sudo apt install moreutils

To use it:

$ ./my-program | ts > log.txt

Tried with: MoreUtils 0.5 and Ubuntu 14.04