GLog 使用方法与技巧

GLog:简单易用的c++日志库

Posted by YuCong on August 18, 2020

GLog提供了非常简单易用的c++日志解决方案。


Created 2020.08.18 by Cong Yu; Last modified: 2020.08.18-v1.0.2

Contact: windmillyucong@163.com

Copyleft! 2022 Cong Yu. Some rights reserved.


GLog

References

// todo(congyu) 待整理

使用

使用时非常简单:

1
2
3
4
5
6
7
8
9
10
#include <glog/logging.h>

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

  LOG(ERROR) << "HELLO!!!";
  LOG(INFO) << "HELLO!!!";
}
log格式

glog的输出格式为

1
Log line format: [IWEF]yyyymmdd hh:mm:ss.uuuuuu threadid file:line] msg

会输出时间,线程号,文件以及行号,非常方便debug!

CMake 中使用glog
################## add_third_party()  
#  
# CMake function to define a named third party library interface, with included  
# headers and linked libraries.  
#  
# Parameters:  
# NAME: name of target  
# INCLUDES: list of include directories for the library  
# LINKS: list of other libraries to be linked in to the library  
# DEFINES: list of compile definitions  
# COMPILE_OPTIONS: list of compile options  
#  
# Examples:  
# add_third_party(  
#   NAME  
#     foo  
#   INCLUDES  
#     "${CMAKE_INSTALL_INCLUDEDIR}/foo"  
#   LINKS  
#     another  
#   DEFINES  
#     -Dbar  
#   COMPILE_OPTIONS  
#     -Wall  
# )  
function(ADD_THIRD_PARTY)  
    cmake_parse_arguments(ADD_THIRD_PARTY  
            ""  
            "NAME"  
            "INCLUDES;LINKS;DEFINES;COMPILE_OPTIONS"  
            ${ARGN})  
  
    unset(${ADD_THIRD_PARTY_NAME}_LIB_DEPENDS CACHE)  
    add_library(${ADD_THIRD_PARTY_NAME} INTERFACE)  
    target_include_directories(${ADD_THIRD_PARTY_NAME} INTERFACE  
            ${ADD_THIRD_PARTY_INCLUDES})  
    target_link_libraries(${ADD_THIRD_PARTY_NAME} INTERFACE  
            ${ADD_THIRD_PARTY_LINKS})  
    target_compile_definitions(${ADD_THIRD_PARTY_NAME} INTERFACE  
            ${ADD_THIRD_PARTY_DEFINES})  
    target_compile_options(${ADD_THIRD_PARTY_NAME} INTERFACE  
            ${ADD_THIRD_PARTY_COMPILE_OPTIONS})  
endfunction()

  
# gflags: Google Commandline Flags  
find_package(gflags CONFIG HINTS ${CMAKE_INSTALL_PREFIX})  
if (gflags_FOUND)  
    add_third_party(NAME gflag LINKS gflags)  
else (gflags_FOUND)  
    MESSAGE(FATAL_ERROR "gflag not found")  
endif ()  
  
## glog: Google Logging Library  
find_package(glog CONFIG HINTS ${CMAKE_INSTALL_PREFIX} NO_CMAKE_PACKAGE_REGISTRY)  
if (glog_FOUND)  
    add_third_party(            NAME glog  
            LINKS glog::glog gflag    )  
else ()  
    MESSAGE(FATAL_ERROR "glog not found")  
endif ()

  
################ bin ####################  
add_executable(hello_glog src/hello_glog.cpp)  
target_link_libraries(hello_glog  
        glog
        gflags
        )

log 输出到文件

输出到文件
1
2
$ mkdir log
$ GLOG_log_dir=log ./bin/hello_glog

以上命令会将Log 分三个等级(error和warning以及info)输出到log文件夹下面的文件里面。

log文件备份

以上命令,每次运行都是将log写入到同一个文件夹里面,如果经常运行,log全部堆在一起不方便查看。所以可以使用一些log备份的小技巧,将历史log做成一个队列,只保存指定数量的历史log,每次都将历史log的编号加1,抛弃掉最古老的log。下一个shell脚本如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
while true;
do

LOG_BACKUP_PATH=log.backup
if [ -d $LOG_BACKUP_PATH ];then
  cd $LOG_BACKUP_PATH
  MAX_LOG_NUM=100
  [ -d log.$MAX_LOG_NUM ] && rm -r log.$MAX_LOG_NUM

  LOG_NUM=$(( $MAX_LOG_NUM - 1 ))
  while [ $LOG_NUM -gt 0 ];do
    if [ -d log.$LOG_NUM ];then
      mv log.$LOG_NUM log.$(( $LOG_NUM + 1 ))
    fi
    LOG_NUM=$(( $LOG_NUM - 1 ))
  done
  cd ..
else
  mkdir $LOG_BACKUP_PATH
fi

if [ -d log ];then
  mv log log.backup/log.1
fi

mkdir log/
# run user cmd
LD_LIBRARY_PATH=./lib GLOG_log_dir=log ./hello_glog_test

if [ $? -eq 0 ];then
  break;
fi 

ps aux| grep ffmpeg|grep -v grep|awk '{print $2}'|xargs kill -2
sleep 30
done

注意

在输出时,会出现需要某些数据类型需要转换的情况,如int8_t uint8_t等类型的数据是无法直接正常输出的。

1
2
3
int8_t priority;
LOG(ERROR) << priority;
LOG(ERROR) << static_cast<int>(priority);

此时的输出为, 只有第二行是正常输出:

1
2
E20201010 01:10:39.901511 217686 hello_glog.cpp:95] 
E20201010 01:10:39.901536 217686 hello_glog.cpp:96] 1

日志分析脚本

项目中经常会有对日志中的数据进行处理分析的需求,可以写一些自动化的脚本,方便快捷得完成这些任务。

时间分析

如:使用re正则表达式分析时间

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# %%  
import re  
import datetime  
import time  

def GlogTimestampAnalysis(line):  
    data_time_pattern = r'\d{8} \d{2}:\d{2}:\d{2}.\d{6}'  
    data_time_format = '%Y%m%d %H:%M:%S.%f'  
    time_str = None  
    time_info = None  
    try:        
        time_str = re.findall(data_time_pattern, line)  
        time_info = datetime.datetime.strptime(time_str[0], data_time_format)  
    except Exception as e:  
        print('{!r}'.format(e))  
    print(time_str, time_info)  
    pass
1
GlogTimestampAnalysis('E20201010 23:13:54.477016 121482 test.cpp:115]')

Q

todo(congyu) 几个小问题:

  • glog的多线程输出是如何做到线程安全的?

Contact

Feel free to contact me windmillyucong@163.com anytime for anything.

License

Creative Commons BY-SA 4.0

CC0