189 8069 5689

go+语言日志库 go语言日志库

Go语言之log(如何将日志写到指定文件里面)

对于Go语言的日志来说,如何将log写到指定的文件里面,下面是一个例子。

创新互联公司专业为企业提供尤溪网站建设、尤溪做网站、尤溪网站设计、尤溪网站制作等企业网站建设、网页设计与制作、尤溪企业网站模板建站服务,十余年尤溪做网站经验,不只是建网站,更提供有价值的思路和整体网络服务。

output:

output:

go 的标准日志库 Log

我们常使用 Go log 以下三组函数:

std 使用 log.New 构造出来,三个参数:

而日志输出位置,自定义前缀字符串,flag 这三者都能够自定义:

基本的 log 至少还需要输出不同的日志级别,所以可以基于标准库的 Log库 简单封装一个支持不同日志级别输出的日志。

测试:

输出日志格式:

GO Log统一接口

go日志库有很多:zap、 Logrus等,它们没有统一的接口。作为中间件提供方,中间件的日志怎么输出到业务的日志文件中?

解决方式:统一日志接口,类似于java中的slf4j。

1)统一接口层面

2)日志实现桥接到接口

sofa-mons有个pkg/log/proxylog.go文件,定义了log的代理。

1)接口

在接口层面,统一增加context参数,方便日志打印时获取通用参数(比如:trace信息)。

如何使用Google日志库

如何使用Google日志库 (glog)

介绍

Google glog是一个应用层的库. 它提供基于C++风格的流和多种宏接口.例如:

#include glog/logging.h

int main(int argc, char* argv[]) {

// Initialize Google's logging library.

google::InitGoogleLogging(argv[0]);

// ...

LOG(INFO) "Found " num_cookies " cookies";

}

Google glog定义了一系列的宏处理普通的日志工作. 你可以分级记录, control loggingbehavior from the command line, 按条件记录, abort theprogram when expected conditions are not met, introduce your ownverbose logging levels, 及其它. 文本只是简单的介绍了常用的glog功能而不是所有的细节.没介绍到的,自己读代码去吧.

严重等级

严重等级包括(按严重程度排序): INFO, WARNING,ERROR,和FATAL.记录一个FATAL级的错误后会自动终止程序执行(其实就是_asm int 3).一个严重等级高的记录不但记录在它自己的文件,也记录在比它低等的文件里.例如, 一个FATAL级的记录将会记在FATAL, ERROR,WARNING, 和INFO等级的日志里.

在debug状态下FATAL级记录也可以用DFATAL(当没定义NDEBUG宏的时候),发给客户的程序最好不要用FATAL小心客户对你使用_asm int 3,这时ERROR是个不错的选择.

glog默认把日志文件命名为"/tmp/...log...."(例如, "/tmp/hello_world.example.com.hamaji.log.INFO.20080709-222411.10474").glog默认把ERROR 和 FATAL 级的记录发送一份到stderr.

设置标志

标志可以改变glog的输出行为.如果你安装了Googlegflags library, configure 脚本 (具体请参考它的INSTALL文件)会自动检测并使用标志,这时你可以通过命令行使用标志.例如, 若你想发送 --logtostderr 标志,像下面这样:

./your_application --logtostderr=1

如果你没装Google gflags library,你就只能用带GLOG_的环境变量实现,例如.

GLOG_logtostderr=1 ./your_application (貌似在Windows里不能这样用吧?)

常用的标志有:

logtostderr (bool, default=false)

写日志到stderr而不是日志文件.

Note: you can set binary flags to true by specifying1, true, or yes (caseinsensitive).Also, you can set binary flags to false by specifying0, false, or no (again, caseinsensitive).

stderrthreshold (int, default=2, whichis ERROR)

将某级及以上级别的记录同时发送到stderr和日志文件. 严重等级INFO, WARNING, ERROR, FATAL 分别对应 0, 1, 2, 3.

minloglevel (int, default=0, whichis INFO)

只记录某级及以上级别的记录.

log_dir (string, default="")

指定日志保存的目录.

v (int, default=0)

Show all VLOG(m) messages for m less orequal the value of this flag. Overridable by --vmodule.See the section about verbose logging for moredetail.

vmodule (string, default="")

Per-module verbose level. The argument has to contain acomma-separated list of =.is a glob pattern (e.g., gfs* for all modules whose namestarts with "gfs"), matched against the filename base(that is, name ignoring .cc/.h./-inl.h). overrides any value given by --v.See also the section about verbose logging.

还有一些其它的标志,自己去logging.cc里面搜索"DEFINE_",爷就不多说了.

你也可以在程序里修改FLAGS_* 开头的全局变量. 通常设置FLAGS_*开头的变量会立即生效,和日志文件名或路径相关的变量例外.例如FLAGS_log_dir就不能放在google::InitGoogleLogging后面.例子代码:

LOG(INFO) "file";

// Most flags work immediately after updating values.

FLAGS_logtostderr = 1;

LOG(INFO) "stderr";

FLAGS_logtostderr = 0;

// This won't change the log destination. If you want to set this

// value, you should do this before google::InitGoogleLogging .

FLAGS_log_dir = "/some/log/directory";

LOG(INFO) "the same file";

条件/ Occasional Logging

下面的宏用于根据条件写日志:

LOG_IF(INFO, num_cookies 10) "Got lots of cookies";

只有当num_cookies 10的时候才会记录"Got lots of cookies"

如果有的代码执行非常频繁,你肯定不会希望每次都写入日志.这时,你可以使用下面的方法:

LOG_EVERY_N(INFO, 10) Got the googleCOUNTER th cookiepre

上面的代码只有当第1次,第11次,第21次....执行时才写入日志.Note that the specialgoogle::COUNTER value is used to identify which repetition ishappening.

条件和计次可以混合使用,例如:

LOG_IF_EVERY_N(INFO, (size 1024), 10) "Got the " google::COUNTER

"th big cookie";

除了间隔N次输出,还可以只输出前M次,例如:

LOG_FIRST_N(INFO, 20) Got the googleCOUNTER th cookiepre

只输出前20次.

Debug mode支持

"debug mode"的宏只在调试模式有效,其他模式不生效.上栗子:

DLOG(INFO) "Found cookies";

DLOG_IF(INFO, num_cookies 10) "Got lots of cookies";

DLOG_EVERY_N(INFO, 10) "Got the " google::COUNTER "th cookie";

CHECK宏

经常检查是否会出错而不是等着程序执行出错是个不错的习惯.CHECK宏就是干这个滴,它的功能和assert一样,条件不符合时终止程序.

与assert不同的是它*不*受NDEBUG的限制,无论是不是debug编译它都执行.所以下面的fp-Write(x)会被执行:

CHECK(fp-Write(x) == 4) "Write failed!";

有各种各样的宏用于CHECK相等/不相等,包括: CHECK_EQ,CHECK_NE, CHECK_LE, CHECK_LT,CHECK_GE,和CHECK_GT.它们会记录一个FATAL级的记录到日志,牛X的是他们还会把对比的两个值也一起记录.(那两个值必须定义了 operator ostreamcode ).例如:

CHECK_NE(1, 2) ": The world must be ending!";

We are very careful to ensure that each argument is evaluated exactlyonce, and that anything which is legal to pass as a function argument islegal here. In particular, the arguments may be temporary expressionswhich will end up being destroyed at the end of the apparent statement,for example:

CHECK_EQ(string("abc")[1], 'b');

The compiler reports an error if one of the arguments is apointer and the other is NULL. To work around this, simply static_castNULL to the type of the desired pointer.

CHECK_EQ(some_ptr, static_cast(NULL));

还有个好办法:用CHECK_NOTNULL宏:

CHECK_NOTNULL(some_ptr); some_ptr-DoSomething();

这宏也常用于构造函数中.

struct S {

S(Something* ptr) : ptr_(CHECK_NOTNULL(ptr)) {}

Something* ptr_;

};

这宏的缺点是不能跟C++流一起用.这时就得用CHECK_EQ了.

如果你要对比一个C字符串(char *)可以用:CHECK_STREQ, CHECK_STRNE,CHECK_STRCASEEQ,和CHECK_STRCASENE.带CASE的区分大小写. 这个宏参数可以用NULL指针.NULL与non-NULL比不等.两个NULL是相等的.

Note that both arguments may be temporary strings which aredestructed at the end of the current "full expression"(e.g., CHECK_STREQ(Foo().c_str(), Bar().c_str()) whereFoo and Bar return C++'sstd::string).

CHECK_DOUBLE_EQ 用于对比浮点数,会有小小的误差.CHECK_NEAR 可以接受一个浮点数作为误差.

详细日志

用VLOG宏,你还可以定义自己的严重等级. The --v command line option controlswhich verbose messages are logged:

VLOG(1) "I'm printed when you run the program with --v=1 or higher";

VLOG(2) "I'm printed when you run the program with --v=2 or higher";

With VLOG, the lower the verbose level, the morelikely messages are to be logged. For example, if--v==1, VLOG(1) will log, butVLOG(2) will not log. This is opposite of the severitylevel, where INFO is 0, and ERROR is 2.--minloglevel of 1 will log WARNING andabove. Though you can specify any integers for both VLOGmacro and --v flag, the common values for them are smallpositive integers. For example, if you write VLOG(0),you should specify --v=-1 or lower to silence it. Thisis less useful since we may not want verbose logs by default in mostcases. The VLOG macros always log at theINFO log level (when they log at all).

Verbose logging can be controlled from the command line on aper-module basis:

--vmodule=mapreduce=2,file=1,gfs*=3 --v=0

will:

a. Print VLOG(2) and lower messages from mapreduce.{h,cc}

b. Print VLOG(1) and lower messages from file.{h,cc}

c. Print VLOG(3) and lower messages from files prefixed with "gfs"

d. Print VLOG(0) and lower messages from elsewhere

The wildcarding functionality shown by (c) supports both '*'(matches 0 or more characters) and '?' (matches any single character)wildcards. Please also check the section about command line flags.

There's also VLOG_IS_ON(n) "verbose level" conditionmacro. This macro returns true when the --v is equal orgreater than n. To be used as

if (VLOG_IS_ON(2)) {

// do some logging preparation and logging

// that can't be accomplished with just VLOG(2) ...;

}

Verbose level condition macros VLOG_IF,VLOG_EVERY_N and VLOG_IF_EVERY_N behaveanalogous to LOG_IF, LOG_EVERY_N,LOF_IF_EVERY, but accept a numeric verbosity level asopposed to a severity level.

VLOG_IF(1, (size 1024))

"I'm printed when size is more than 1024 and when you run the "

"program with --v=1 or more";

VLOG_EVERY_N(1, 10)

"I'm printed every 10th occurrence, and when you run the program "

"with --v=1 or more. Present occurence is " google::COUNTER;

VLOG_IF_EVERY_N(1, (size 1024), 10)

"I'm printed on every 10th occurence of case when size is more "

" than 1024, when you run the program with --v=1 or more. ";

"Present occurence is " google::COUNTER;

Failure Signal Handler

The library provides a convenient signal handler that will dump usefulinformation when the program crashes on certain signals such as SIGSEGV.The signal handler can be installed bygoogle::InstallFailureSignalHandler(). The following is an example of outputfrom the signal handler.

*** Aborted at 1225095260 (unix time) try "date -d @1225095260" if you are using GNU date ***

*** SIGSEGV (@0x0) received by PID 17711 (TID 0x7f893090a6f0) from PID 0; stack trace: ***

PC: @ 0x412eb1 TestWaitingLogSink::send()

@ 0x7f892fb417d0 (unknown)

@ 0x412eb1 TestWaitingLogSink::send()

@ 0x7f89304f7f06 google::LogMessage::SendToLog()

@ 0x7f89304f35af google::LogMessage::Flush()

@ 0x7f89304f3739 google::LogMessage::~LogMessage()

@ 0x408cf4 TestLogSinkWaitTillSent()

@ 0x4115de main

@ 0x7f892f7ef1c4 (unknown)

@ 0x4046f9 (unknown)

By default, the signal handler writes the failure dump to the standarderror. You can customize the destination by InstallFailureWriter().

Miscellaneous Notes

Performance of Messages

The conditional logging macros provided by glog (e.g.,CHECK, LOG_IF, VLOG, ...) arecarefully implemented and don't execute the right hand sideexpressions when the conditions are false. So, the following checkmay not sacrifice the performance of your application.

CHECK(obj.ok) obj.CreatePrettyFormattedStringButVerySlow();

User-defined Failure Function

FATAL severity level messages or unsatisfiedCHECK condition terminate your program. You can changethe behavior of the termination byInstallFailureFunction.

void YourFailureFunction() {

// Reports something...

exit(1);

}

int main(int argc, char* argv[]) {

google::InstallFailureFunction(YourFailureFunction);

}

By default, glog tries to dump stacktrace and makes the programexit with status 1. The stacktrace is produced only when you run theprogram on an architecture for which glog supports stack tracing (asof September 2008, glog supports stack tracing for x86 and x86_64).

Raw Logging

The header file can beused for thread-safe logging, which does not allocate any memory oracquire any locks. Therefore, the macros defined in thisheader file can be used by low-level memory allocation andsynchronization code.Please check src/glog/raw_logging.h.in for detail.

Google Style perror()

PLOG() and PLOG_IF() andPCHECK() behave exactly like their LOG* andCHECK equivalents with the addition that they append adescription of the current state of errno to their output lines.E.g.

PCHECK(write(1, NULL, 2) = 0) Write NULL failedpre

This check fails with the following error message.

F0825 185142 test.cc:22] Check failed: write(1, NULL, 2) = 0 Write NULL failed: Bad address [14]

Syslog

SYSLOG, SYSLOG_IF, andSYSLOG_EVERY_N macros are available.These log to syslog in addition to the normal logs. Be aware thatlogging to syslog can drastically impact performance, especially ifsyslog is configured for remote logging! Make sure you understand theimplications of outputting to syslog before you use these macros. Ingeneral, it's wise to use these macros sparingly.

Strip Logging Messages

Strings used in log messages can increase the size of your binaryand present a privacy concern. You can therefore instruct glog toremove all strings which fall below a certain severity level by usingthe GOOGLE_STRIP_LOG macro:

If your application has code like this:

#define GOOGLE_STRIP_LOG 1 // this must go before the #include!

#include glog/logging.h

The compiler will remove the log messages whose severities are lessthan the specified integer value. SinceVLOG logs at the severity level INFO(numeric value 0),setting GOOGLE_STRIP_LOG to 1 or greater removesall log messages associated with VLOGs as well asINFO log statements.

对于Windows用户

glog的ERROR级错误与windows.h冲突. You can make glog not defineINFO, WARNING, ERROR,and FATAL by definingGLOG_NO_ABBREVIATED_SEVERITIES beforeincluding glog/logging.h . Even with this macro, you canstill use the iostream like logging facilities:

#define GLOG_NO_ABBREVIATED_SEVERITIES

#include windows.h

#include glog/logging.h

// ...

LOG(ERROR) "This should work";

LOG_IF(ERROR, x y) "This should be also OK";

However, you cannotuse INFO, WARNING, ERROR,and FATAL anymore for functions definedin glog/logging.h .

#define GLOG_NO_ABBREVIATED_SEVERITIES

#include windows.h

#include glog/logging.h

// ...

// This won't work.

// google::FlushLogFiles(google::ERROR);

// Use this instead.

google::FlushLogFiles(google::GLOG_ERROR);

If you don't need ERROR definedby windows.h, there are a couple of more workaroundswhich sometimes don't work:

#define WIN32_LEAN_AND_MEAN or NOGDIbefore you #include windows.h .

#undef ERRORafter you #include windows.h .

See this issue for more detail.


文章标题:go+语言日志库 go语言日志库
文章路径:http://cdxtjz.cn/article/dohjieh.html

其他资讯