美文网首页
go 的标准日志库 Log

go 的标准日志库 Log

作者: wayyyy | 来源:发表于2022-05-15 04:26 被阅读0次

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

  • Print/Printf/Println : 打印日志信息
  • Panic/Panicf/Panicln : 打印日志信息后,以拼装好的字符串为参数调用 Panic
  • Fatal/Fatalf/Fatalln : 打印日志信息后,os.Exit(1) 退出程序
var std = New(os.Stderr, "", LstdFlags)

func New(out io.Writer, prefix string, flag int) *Logger {
    return &Logger{out: out, prefix: prefix, flag: flag}
}

type Logger struct {
    mu     sync.Mutex // ensures atomic writes; protects the following fields
    prefix string     // prefix on each line to identify the logger (but see Lmsgprefix)
    flag   int        // properties
    out    io.Writer  // destination for output
    buf    []byte     // for accumulating text to write
}

func Println(v ...interface{}) {
   std.Output(2, fmt.Sprintln(v...))
}

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

  • io.Writer : 任何实现了 Writer 接口的结构,日志会写到这个里面, std 的输出位置是 os.Stderr
  • prefix : 自定义前缀字符串,std 传入的是空字符串
  • flag : 一些标志位,定制化 prefix,std 的是 LstdFlags, 默认日志格式中的时间就从这个标志位而来

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

func main() {
   var buf bytes.Buffer
   log.SetOutput(&buf)
   log.SetPrefix("[info: ]")
   log.SetFlags(log.LstdFlags | log.Lshortfile)
   log.Println("自定义日志格式")
   //fmt.Print(&buf)
}

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

package main

import (
    "fmt"
    "io"
    "log"
    "os"
    "runtime"
    "strings"
)

type Level int

const (
    ErrorLevel Level = 0
    WarnLevel  Level = 1
    InfoLevel  Level = 2
    DebugLevel Level = 3
)

func levelToString(level Level) string {
    switch level {
    case InfoLevel:
        return "info"
    case WarnLevel:
        return "warn"
    case ErrorLevel:
        return "error"
    case DebugLevel:
        return "debug"
    }
    return ""
}

func levelToFormatString(level Level) string {
    switch level {
    case InfoLevel:
        return "[" + levelToString(level) + "]"
    case WarnLevel:
        return "[" + levelToString(level) + "]"
    case ErrorLevel:
        return "[" + levelToString(level) + "]"
    case DebugLevel:
        return "[" + levelToString(level) + "]"
    }
    return ""
}

type Logger struct {
    out       io.WriteCloser
    level     Level
    logger    *log.Logger
    requestID string
}

var logFlags = log.Ldate | log.Ltime | log.Lmicroseconds

func NewLogger(path string, logLevel Level) Logger {
    file, err := os.OpenFile(path, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
    if err != nil {
        panic("failed to open log file" + path)
    }

    l := Logger{
        out:    file,
        level:  logLevel,
        logger: log.New(file, "", logFlags),
    }

    return l
}

func (l *Logger) SetRequestID(requestID string) {
    l.requestID = requestID
}

func (l Logger) Close() error {
    return l.out.Close()
}

func (l Logger) Debug(args ...interface{}) {
    if l.level < DebugLevel {
        return
    }

    preFixArray := make([]interface{}, 0, 10)
    preFixArray = append(preFixArray, getCaller())
    preFixArray = append(preFixArray, l.requestID)
    preFixArray = append(preFixArray, levelToFormatString(DebugLevel))

    args = append(preFixArray, args...)
    l.logger.Println(args...)
}

func (l Logger) INFO(args ...interface{}) {
    if l.level < InfoLevel {
        return
    }

    preFixArray := make([]interface{}, 0, 10)
    preFixArray = append(preFixArray, getCaller())
    preFixArray = append(preFixArray, l.requestID)
    preFixArray = append(preFixArray, levelToFormatString(InfoLevel))

    args = append(preFixArray, args...)
    l.logger.Println(args...)
}

func (l Logger) Warn(args ...interface{}) {
    if l.level < WarnLevel {
        return
    }

    preFixArray := make([]interface{}, 0, 10)
    preFixArray = append(preFixArray, getCaller())
    preFixArray = append(preFixArray, l.requestID)
    preFixArray = append(preFixArray, levelToFormatString(WarnLevel))

    args = append(preFixArray, args...)
    l.logger.Println(args...)
}

func (l Logger) Error(args ...interface{}) {
    if l.level < ErrorLevel {
        return
    }

    preFixArray := make([]interface{}, 0, 10)
    preFixArray = append(preFixArray, getCaller())
    preFixArray = append(preFixArray, l.requestID)
    preFixArray = append(preFixArray, levelToFormatString(ErrorLevel))

    args = append(preFixArray, args...)
    l.logger.Println(args...)
}

func getCaller() string {
    pc, fullPath, line, ok := runtime.Caller(2)
    if !ok {
        return ""
    }

    pcName := runtime.FuncForPC(pc).Name()
    file := fullPath

    pcNameParts := strings.Split(pcName, "/")
    pcName = pcNameParts[len(pcNameParts)-1]
    pcNameParts = strings.Split(pcName, ".")
    pcName = pcNameParts[len(pcNameParts)-1]

    return fmt.Sprintf("%s:%s:%d", file, pcName, line)
}

var GLog Logger

测试:

func main() {
    GLog := NewLogger("./core.log", InfoLevel)
    GLog.SetRequestID("wyauix1qu")
    defer GLog.Close()

    GLog.Debug("hello world")
    GLog.INFO("hello world")
    GLog.Warn("hello world")
    GLog.Error("hello world")
}

输出日志格式:

2022/05/15 05:29:42.186008 D:/Code/go_workspace/project/gotour/gotour/loger/main.go:main:9 wyauix1qu [info] hello world
2022/05/15 05:29:42.212080 D:/Code/go_workspace/project/gotour/gotour/loger/main.go:main:10 wyauix1qu [warn] hello world
2022/05/15 05:29:42.212080 D:/Code/go_workspace/project/gotour/gotour/loger/main.go:main:11 wyauix1qu [error] hello world

相关文章

  • Go 标准库介绍六: log

    Go 标准库介绍六: log 原文链接 http://ironxu.com/775 本文介绍Go 标准库 log ...

  • go 的标准日志库 Log

    我们常使用 Go log 以下三组函数: Print/Printf/Println : 打印日志信息 Panic/...

  • Go语言 日志组件编写

    在使用Go语言的时候,发现标准库的日志log功能很初级。 基本也就围绕上面几个方法来做日志处理。于是我上Githu...

  • golang特殊编译

    兼容不同平台的跨平台编译 说明:因为go的log/sys_log库只能在unix系统编译通过,所以用这个日志库作为...

  • Go how to use the 'zap' log plu

    简介 为什么我们今天要使用这个库Becousego 标准日志库log[https://darjun.github....

  • go标准库源码-log模块

    前言 log模块的源码比较简单,适合作为学习go标准库源码的开端。 Logger类型结构 out log输出的目的...

  • golang学习资源

    教程类 Go 标准库中文文档 Go 标准库文档 Go 实例学标准库 Go入门指南The-way-to-go Go语...

  • 日志

    日志门面接口 slf4jlogback 本身就是在这个标准下的log4j log4j2默认没实现标准基础库升级到s...

  • 22 Go 常用标准库简析

    Go 常用标准库 Go官方以包的形式提供功能丰富的标准库,了解这些包会让你在项目开发中如鱼得水。Go标准库很容易理...

  • Go常用库-日志Logrus

    写在前面: Logrus版本: v1.4.2 logrus相当于标准库log包的加强版,是目前最流行的日志库.它在...

网友评论

      本文标题:go 的标准日志库 Log

      本文链接:https://www.haomeiwen.com/subject/cyzrurtx.html