Go语言标准库提供了基础的日志功能,通过log
包可以快速实现日志记录。标准库log
包的主要特点:
Print
、Fatal
、Panic
然而,标准库日志包存在一些局限性:
logger会打印每条日志信息的日期、时间,默认输出到系统的标准错误。
Fatal
系列函数会在写入日志信息后调用os.Exit(1)
。
Panic
系列函数会在写入日志信息后panic
。
package main
import "log"
func main() {
log.Println("this is a simple log")
log.Fatalln("this is a fatal log")
log.Panicln("this is a panic log")
}
默认情况下的logger只会提供日志的时间信息,但是很多情况下我们希望得到更多信息,比如记录该日志的文件名和行号等。log标准库中为我们提供了定制这些设置的方法。
log标准库中的Flags函数会返回标准logger的输出配置,而SetFlags函数用来设置标准logger的输出配置。
func Flags() int
func SetFlags(flag int)
控制输出日志信息的细节,不能控制输出的顺序和格式。
const (
Ldate = 1 << iota // 日期:2009/01/23
Ltime // 时间:01:23:23
Lmicroseconds // 微秒级别的时间:01:23:23.123123(用于增强Ltime位)
Llongfile // 文件全路径名+行号: /a/b/c/d.go:23
Lshortfile // 文件名+行号:d.go:23(会覆盖掉Llongfile)
LUTC // 使用UTC时间
LstdFlags = Ldate | Ltime // 标准logger的初始值
)
package main
import "log"
func main() {
log.SetFlags(log.Llongfile | log.Lmicroseconds | log.Ldate)
log.Println("this is a simple log")
log.Fatalln("this is a fatal log")
log.Panicln("this is a panic log")
}
//2022/12/02 11:15:17.686667 E:/go-project/nginx-log-parse/cmd/main.go:7: this is a simple log
//2022/12/02 11:15:17.695173 E:/go-project/nginx-log-parse/cmd/main.go:8: this is a fatal log
func Prefix() string
func SetPrefix(prefix string)
package main
import "log"
func main() {
log.SetFlags(log.Llongfile | log.Lmicroseconds | log.Ldate)
log.SetPrefix("[SIMPLE]")
log.Println("this is a simple log")
log.SetPrefix("[FATAL]")
log.Fatalln("this is a fatal log")
log.SetPrefix("[PANIC]")
log.Panicln("this is a panic log")
}
//[SIMPLE]2022/12/02 11:17:05.758862 E:/go-project/nginx-log-parse/cmd/main.go:8: this is a simple log
//[FATAL]2022/12/02 11:17:05.767646 E:/go-project/nginx-log-parse/cmd/main.go:10: this is a fatal log
func SetOutput(w io.Writer)
func New(out io.Writer, prefix string, flag int) *Logger
package main
import (
"log"
"os"
)
func main() {
// 默认日志输出到标准错误
log.Println("这是一条标准日志消息")
// 创建日志文件
f, err := os.OpenFile("app.log", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
log.Fatal(err)
}
defer f.Close()
// 配置日志输出到文件
logger := log.New(f, "APP: ", log.Ldate|log.Ltime|log.Lshortfile)
// 使用配置好的logger记录日志
logger.Println("应用启动成功")
logger.Printf("配置加载完成: %s", "config.json")
// 记录致命错误并终止程序
if err != nil {
logger.Fatalf("无法连接数据库: %v", err)
}
}
package main
import (
"fmt"
"log"
"os"
"runtime"
"strings"
"time"
)
// CustomLogger 自定义日志格式
type CustomLogger struct {
logger *log.Logger
}
const (
LevelDebug = "DEBUG"
LevelInfo = "INFO"
LevelWarning = "WARNING"
LevelError = "ERROR"
LevelFatal = "FATAL"
)
// NewCustomLogger 初始化自定义日志
func NewCustomLogger() *CustomLogger {
return &CustomLogger{
logger: log.New(os.Stdout, "", 0), // 输出到标准输出,不带前缀
}
}
// 自定义日志格式
func (l *CustomLogger) formatLog(level, message string) string {
// 获取当前时间
now := time.Now().Format("2006-01-02 15:04:05.000")
// 获取调用栈信息
pc, file, line, ok := runtime.Caller(3) // 跳过三层调用栈
caller := "unknown"
if ok {
funcName := runtime.FuncForPC(pc).Name()
caller = fmt.Sprintf("%s:%d", file, line)
if index := strings.LastIndex(funcName, "."); index != -1 {
caller = fmt.Sprintf("%s.%s:%d", funcName[:index], funcName[index+1:], line)
}
}
// 构建日志格式
return fmt.Sprintf("%s [%s] %s - %s",
now, level, caller, message)
}
// Log 日志输出函数
func (l *CustomLogger) Log(level, message string) {
logLine := l.formatLog(level, message)
l.logger.Println(logLine)
}
func (l *CustomLogger) Debug(message string) {
l.Log(LevelDebug, message)
}
func (l *CustomLogger) Debugf(format string, v ...any) {
message := fmt.Sprintf(format, v...)
l.Log(LevelDebug, message)
}
func (l *CustomLogger) Info(message string) {
l.Log(LevelInfo, message)
}
func (l *CustomLogger) Infof(format string, v ...any) {
message := fmt.Sprintf(format, v...)
l.Log(LevelInfo, message)
}
func (l *CustomLogger) Warning(message string) {
l.Log(LevelWarning, message)
}
func (l *CustomLogger) Warningf(format string, v ...any) {
message := fmt.Sprintf(format, v...)
l.Log(LevelWarning, message)
}
func (l *CustomLogger) Error(message string) {
l.Log(LevelError, message)
}
func (l *CustomLogger) Errorf(format string, v ...any) {
message := fmt.Sprintf(format, v...)
l.Log(LevelError, message)
}
func (l *CustomLogger) Fatal(message string) {
l.Log(LevelFatal, message)
}
func (l *CustomLogger) Fatalf(format string, v ...any) {
message := fmt.Sprintf(format, v...)
l.Log(LevelFatal, message)
}