golang之log
标准库log
golang实现了简单易用的log,可以满足基本需求。虽然标准库实现了syslog,但已冻结不增加新功能。
Package log implements a simple logging package. It defines a type, Logger, with methods for formatting output. It also has a predefined 'standard' Logger accessible through helper functions Print[f|ln], Fatal[f|ln], and Panic[f|ln], which are easier to use than creating a Logger manually. That logger writes to standard error and prints the date and time of each logged message. Every log message is output on a separate line: if the message being printed does not end in a newline, the logger will add one.
The Fatal functions call os.Exit(1) after writing the log message. The Panic functions call panic after writing the log message.
log常用的函数是Print[f|ln],Fatal[f|ln]和Panic[f|ln]
func Flags() int获取flag,func Prefix() string获取前缀,SefFlags(flag int)和SetPrefix(prefix string)用于设置。
These flags define which text to prefix to each log entry generated by the Logger. flags常量如下:
const ( Ldate = 1 << iota // the date in the local time zone: 2009/01/23 Ltime // the time in the local time zone: 01:23:23 Lmicroseconds // microsecond resolution: 01:23:23.123123. assumes Ltime. Llongfile // full file name and line number: /a/b/c/d.go:23 Lshortfile // final file name element and line number: d.go:23. overrides Llongfile LUTC // if Ldate or Ltime is set, use UTC rather than the local time zone Lmsgprefix // move the "prefix" from the beginning of the line to before the message LstdFlags = Ldate | Ltime // initial values for the standard logger )
标准logger接口
type Logger func New(out io.Writer, prefix string, flag int) *Logger
type Logger func New(out io.Writer, prefix string, flag int) *Logger func (l *Logger) Fatal(v ...interface{}) func (l *Logger) Fatalf(format string, v ...interface{}) func (l *Logger) Fatalln(v ...interface{}) func (l *Logger) Flags() int func (l *Logger) Output(calldepth int, s string) error func (l *Logger) Panic(v ...interface{}) func (l *Logger) Panicf(format string, v ...interface{}) func (l *Logger) Panicln(v ...interface{}) func (l *Logger) Prefix() string func (l *Logger) Print(v ...interface{}) func (l *Logger) Printf(format string, v ...interface{}) func (l *Logger) Println(v ...interface{}) func (l *Logger) SetFlags(flag int) func (l *Logger) SetOutput(w io.Writer) func (l *Logger) SetPrefix(prefix string) func (l *Logger) Writer() io.Writer
标准库log/syslog
syslog实现了基本的linux级别级日志输出,可作为实现更多功能的syslog库的参考。
Package syslog provides a simple interface to the system log service. It can send messages to the syslog daemon using UNIX domain sockets, UDP or TCP.
Only one call to Dial is necessary. On write failures, the syslog client will attempt to reconnect to the server and write again.
func NewLogger(p Priority, logFlag int) (*log.Logger, error)
func Dial(network, raddr string, priority Priority, tag string) (*Writer, error)
The Priority is a combination of the syslog facility and severity. For example, LOG_ALERT | LOG_FTP sends an alert severity message from the FTP facility.
The default severity is LOG_EMERG; the default facility is LOG_KERN.
type Priority int const ( // From /usr/include/sys/syslog.h. // These are the same on Linux, BSD, and OS X. LOG_EMERG Priority = iota LOG_ALERT LOG_CRIT LOG_ERR LOG_WARNING LOG_NOTICE LOG_INFO LOG_DEBUG ) const ( // From /usr/include/sys/syslog.h. // These are the same up to LOG_FTP on Linux, BSD, and OS X. LOG_KERN Priority = iota << 3 LOG_USER LOG_MAIL LOG_DAEMON LOG_AUTH LOG_SYSLOG LOG_LPR LOG_NEWS LOG_UUCP LOG_CRON LOG_AUTHPRIV LOG_FTP LOG_LOCAL0 LOG_LOCAL1 LOG_LOCAL2 LOG_LOCAL3 LOG_LOCAL4 LOG_LOCAL5 LOG_LOCAL6 LOG_LOCAL7 )
openness log
https://github.com/open-ness/common.git
接口说明:https://godoc.org/github.com/open-ness/common/log
import “github.com/open-ness/common/log”
不仅提供基础的level[f|ln]函数,还提供GrpcLogger、Logger、Printer接口。
const ( // DefaultLevel is the initial logging verbosity DefaultLevel = syslog.LOG_INFO // DefaultFacility is the default facility portion of the syslog priority. DefaultFacility = syslog.LOG_LOCAL0 ) var ( // DefaultLogger is the package-level logger that is used for all package // funcs. DefaultLogger = &Logger{} )
import "github.com/open-ness/common/log/syslog"
func NewLogger(p syslog.Priority, logFlag int) (*log.Logger, error)
func ParseLevel(prio string) (syslog.Priority, error)
ParseLevel parses provided syslog severity name into its integer(syslog.Priority) representation. Supported input values: emerg, emergency, alert, crit, critical, err, error, warn, warning, notice, info, information, debug. Input is parsed without case sensitivity.
- type Logger
- func (l *Logger) ConnectSyslog(addr string) error
- func (l *Logger) ConnectSyslogTLS(addr string, conf *tls.Config) error
- func (l *Logger) DisconnectSyslog() error
- func (l *Logger) GetFacility() syslog.Priority
- func (l *Logger) GetLevel() syslog.Priority
- func (l *Logger) SetFacility(p syslog.Priority)
- func (l *Logger) SetLevel(p syslog.Priority)
- func (l *Logger) SetOutput(w io.Writer)
- func (l *Logger) WithField(key string, value interface{}) Printer
- func (l *Logger) WithFields(kvs map[string]interface{}) Printer
package api import "github.com/open-ness/common/log"
// 设置log tag或前缀,一般以模块为单位设置 var log = log.DefaultLogger.WithField("component", "api") func Hello(name string) { log.Infof("Hello %s!", name) // Output: "[component=api] Hello <name>!" }
// ------------------------------------------------------------
import "github.com/open-ness/common/log"
import "api"
func main(){
// 设置总日志级别, 一般仅在main中设置
lvl, err := log.ParseLevel("info")
if err != nil {
log.Errf("Failed to parse log level: %s", err.Error())
os.Exit(1)
}
log.SetLevel(lvl)
Hello("Golang")
}
Minimal support for structured tagging exists via (*Logger).WithField(s)
. Key-value pairs can be set before printing in order to automatically prepend data to each log. As an edge case, if the value is nil
, then the prepended data will look like [key]
rather than [key=<nil>]
.
结构化的log可通过在每个模块中设置(*Logger).WithField(s)来定位各个模块的输出,s一般为key-value,若value为nil,则输出数据格式为[key]。
zap
Zap是非常快的、结构化的,分日志级别的Go日志库。它同时提供了结构化日志记录和printf风格的日志记录;它非常的快。
go.uber.org/zap
const ( // DebugLevel logs are typically voluminous, and are usually disabled in // production. DebugLevel = zapcore.DebugLevel // InfoLevel is the default logging priority. InfoLevel = zapcore.InfoLevel // WarnLevel logs are more important than Info, but don't need individual // human review. WarnLevel = zapcore.WarnLevel // ErrorLevel logs are high-priority. If an application is running smoothly, // it shouldn't generate any error-level logs. ErrorLevel = zapcore.ErrorLevel // DPanicLevel logs are particularly important errors. In development the // logger panics after writing the message. DPanicLevel = zapcore.DPanicLevel // PanicLevel logs a message, then panics. PanicLevel = zapcore.PanicLevel // FatalLevel logs a message, then calls os.Exit(1). FatalLevel = zapcore.FatalLevel )
Zap提供了两种类型的日志记录器—Sugared Logger和Logger。在性能很好但不是很关键的上下文中,使用SugaredLogger。它比其他结构化日志记录包快4-10倍,并且支持结构化和printf风格的日志记录。在每一微秒和每一次内存分配都很重要的上下文中,使用Logger。它甚至比SugaredLogger更快,内存分配次数也更少,但它只支持强类型的结构化日志记录。
日志记录器方法的语法是这样的:
func (log *Logger) MethodXXX(msg string, fields ...Field)
其中MethodXXX是一个可变参数函数,可以是Info / Error/ Debug / Panic等。每个方法都接受一个消息字符串和任意数量的zapcore.Field场参数。每个zapcore.Field其实就是一组键值对参数。
package main import ( "net/http" "go.uber.org/zap" ) var logger *zap.Logger func main() { InitLogger() defer logger.Sync() simpleHttpGet("www.511.com") simpleHttpGet("http://www.baidu.com") } func InitLogger() { logger, _ = zap.NewProduction() } func simpleHttpGet(url string) { resp, err := http.Get(url) if err != nil { logger.Error("Error fetching url...", zap.String("url", url), zap.Error(err), ) } else { logger.Info("Success...", zap.String("statusCode", resp.Status), zap.String("url", url), ) resp.Body.Close() } }
{"level":"error","ts":1645532180.347498,"caller":"hello/hello.go:25","msg":"Error fetching url...","url":"www.511.com","error":"Get \"www.511.com\": unsupported protocol scheme \"\"","stacktrace":"main.simpleHttpGet\n\t/home/wang/repogo/hello/hello.go:25\nmain.main\n\t/home/wang/repogo/hello/hello.go:14\nruntime.main\n\t/usr/local/go/src/runtime/proc.go:255"} {"level":"info","ts":1645532185.5290735,"caller":"hello/hello.go:30","msg":"Success...","statusCode":"200 OK","url":"http://www.baidu.com"}
参考:
1. https://godoc.org/log/syslog
2. Go Web编程 12.1 应用日志 beego