首页 > 其他分享 >go语言log相关

go语言log相关

时间:2023-07-21 18:12:25浏览次数:31  
标签:输出 log zerolog go logger 级别 Logger 语言

log包

Go标准库中有log包,提供了简单的日志功能。

输出  格式输出 换行输出 解释
log.Print() log.Printf() log.Println() 类似fmt.Print*
log.Fatal() log.Fatalf() log.Fatalln() 相当于log.Print* + os.Exit(1)
log.Panic() log.Panicf() log.Panicln() 相当于log.Print* + panic()

日志输出需要使用日志记录器Logger。 log包提供了一个缺省的Logger即std。std是小写的,包外不可见,所以提供了Default()方法返回std给包外使用。

 上表列出的方法底层都使用std.Output输出日志内容。而std本质上是使用了标准错误输出、无前缀、 LstdFlags标准标记的记录器Logger实例。

// 使用缺省Logger
log.Print("abcde\n")
log.Printf("%s\n", "abcd")
log.Println("abc")
log.Fatal("xyz") // 等价于 log.Print("xyz");os.Exit(1)
log.Panicln("Failed") // 等价于 log.Println("Failed");panic()

自定义Logger

// 自定义Logger
infoLogger := log.New(os.Stdout, "Info: ", log.LstdFlags|log.Lmsgprefix)
infoLogger.Println("这是一个普通消息") // 使用stdout输出
errLogger := log.New(os.Stderr, "Error: ", log.LstdFlags)
errLogger.Fatal("这是一个错误消息")

写日志文件

New方法签名 New(out io.Writer, prefix string, flag int) *Logger 中out参数提供Writer接口即可,那么就可以提供一个可写文件对象。

package main

import (
    "log"
    "os"
)

func main() {
    f, err := os.OpenFile("log/test.log", // os.Open为只读打开,OpenFile按照指定方式打开文件
        os.O_CREATE|os.O_RDONLY|os.O_APPEND,
        0644) // Unix permission bits
    if err != nil {
        log.Panicf("%v %v", "文件打开失败:", err)
    }
    defer f.Close()
    logger := log.New(f, "[INFO]", log.Ldate|log.Ltime)
    logger.Println("开始初始化。。。。")
}

 zerolog

log模块太简陋了,实际使用并不方便。

  • logrus有日志级别、Hook机制、日志格式输出,很好用
  • zap是Uber的开源高性能日志库
  • zerolog更注重开发体验,高性能、有日志级别、链式API,json格式日志记录,号称0内存分配

安装: go get -u github.com/rs/zerolog/log

 级别

zerolog提供以下级别(从高到底)

  • panic (zerolog.PanicLevel, 5)
  • fatal (zerolog.FatalLevel, 4)
  • error (zerolog.ErrorLevel, 3)
  • warn (zerolog.WarnLevel, 2)
  • info (zerolog.InfoLevel, 1)
  • debug (zerolog.DebugLevel, 0)
  • trace (zerolog.TraceLevel, -1)

级别有

  • gLevel全局级别
  1. zerolog.SetGlobalLevel(级别数字或常量) 来设置全局级别
  2. zerolog.GlobalLevel() 获取当前全局级别
  • 每个Logger的级别
  • 消息的级别
package main
import (
 "fmt"
 "github.com/rs/zerolog"
 "github.com/rs/zerolog/log"
)
func main() {
 fmt.Println("全局级别gLevel为", zerolog.GlobalLevel())
 fmt.Println("缺省logger的级别为", log.Logger.GetLevel())
 log1 := log.Level(zerolog.WarnLevel) // 创建一个子logger
 fmt.Println("log1级别为", log1.GetLevel())
 fmt.Println("~~~~~~~~~~~~~~~~~~~~~~~~~~~")
 log.Trace().Msg("缺省logger输出trace级别消息") // 输出
 log.Info().Msg("缺省logger输出info级别消息")   // 输出
 log.Warn().Msg("缺省logger输出warn级别消息")   // 输出
 log.Error().Msg("缺省logger输出error级别消息") // 输出
 log1.Debug().Msg("log1的Debug级别消息")     // 不能输出
    log1.Warn().Msg("log1的Warn级别消息")       // 输出
 log1.Error().Msg("log1的Error级别消息")     // 输出
}

因为有消息级别和Logger级别,因此使用缺省logger,全部可以输出日志消息,而log1使22行、23行输出了日志

而缺省Logger的级别是trace,任何消息级别都大于等于log1的级别,因此都可以输出。

package main
import (
 "fmt"
 "github.com/rs/zerolog"
 "github.com/rs/zerolog/log"
)
func main() {
 zerolog.SetGlobalLevel(zerolog.ErrorLevel) // 调高全局级别
 fmt.Println("全局级别gLevel为", zerolog.GlobalLevel())
 fmt.Println("缺省logger的级别为", log.Logger.GetLevel())
 log1 := log.Level(zerolog.WarnLevel) // 创建一个子logger
 fmt.Println("log1级别为", log1.GetLevel())
 fmt.Println("~~~~~~~~~~~~~~~~~~~~~~~~~~~")
 log.Trace().Msg("缺省logger输出trace级别消息") // 不能输出
 log.Info().Msg("缺省logger输出info级别消息")   // 不能输出
 log.Warn().Msg("缺省logger输出warn级别消息")   // 不能输出
 log.Error().Msg("缺省logger输出error级别消息") // 输出
 log1.Debug().Msg("log1的Debug级别消息")     // 不能输出
 log1.Warn().Msg("log1的Warn级别消息")       // 不能输出
 log1.Error().Msg("log1的Error级别消息")     // 输出
}

缺省logger和log1都只有error级别的输出,说明将gLevel调整到error级别后,所有logger输出消息都必 须大于等于gLevel。

zerolog.SetGlobalLevel()设置的是全局变量gLevel,它影响所有Logger。

日志消息是否能够输出,应当满足下面的要求 消息级别 >= max(gLevel, 当前logger级别)

上下文

zerolog是以Json对象格式输出的,还可以自定义一些键值对字段增加到上下文中以输出。

zerolog.SetGlobalLevel(zerolog.InfoLevel)
log.Info().Bool("Success", false).Str("Reason", "File Not Found").Msg("文件没
找到")
log.Info().Str("Name", "Tom").Floats32("Scores", []float32{87.5, 90, 
59}).Send()
// Send is equivalent to calling Msg("")

错误日志

package main
import (
 "errors"
 "github.com/rs/zerolog"
 "github.com/rs/zerolog/log" // 全局logger
)
func main() {
 zerolog.TimeFieldFormat = zerolog.TimeFormatUnix // 自定义time字段时间的格
式,TimeFormatUnix时间戳
 // zerolog.ErrorFieldName = "err" // 修改日志Json中的缺省字段名error
 // 错误日志
 err := errors.New("自定义的错误")
 log.Error(). // 错误级别消息
 Err(err). // err字段,错误消息内容
 Send()    // 有错误消息了,message可以省略
 log.Fatal(). // fatal级别
 Err(err).
 Send()
}

全局Logger

// 全局Logger定义如下
var Logger = zerolog.New(os.Stderr).With().Timestamp().Logger()

可以覆盖全局Logger

// 全局日期格式
zerolog.TimeFieldFormat = zerolog.TimeFormatUnix
zerolog.TimeFieldFormat = "2006/01/02 15:04:05 -0700"
// With()创建一个全局Logger的子logger
log.Logger = log.With().Str("Name", "Cabel").Logger() // 覆盖了全局Logger
log.Info().Send() // {"level":"info","Name":"Cabel","time":1223947070}

自定义Logger

zerolog.TimeFieldFormat = zerolog.TimeFormatUnix
logger := log.With(). // With()返回基于全局Logger的子logger
 Str("School", "Mg").
 Caller(). // 增加日志调用的位置信息字段
 Logger()  // 返回Logger
logger.Info().Send() // {"level":"info","School":"Mg","time":1223947070}
log.Info().Send()    // {"level":"info","time":1223947070} 全局Logger
zerolog.TimeFieldFormat = zerolog.TimeFormatUnix
logger := zerolog.New(os.Stdout). // 不基于全局Logger,重新构造了一个Logger
 With().Str("School", "Mg").
 Caller().                 // 调用者信息:增加日志函数调用的位置信息字段
 Logger().                 // 返回Logger
 Level(zerolog.ErrorLevel) // 重新定义Logger级别为3 error,返回Logger
fmt.Println(logger.GetLevel())
logger.Info().Send() // {"level":"info","School":"Mg","time":1223947070} 
logger.Error().Send()
log.Info().Send() // {"level":"info","time":1223947070} 全局Logger

写日志文件

package main
import (
 "os"
 "github.com/rs/zerolog"
 "github.com/rs/zerolog/log" // 全局logger
)
func main() {
 zerolog.TimeFieldFormat = zerolog.TimeFormatUnix
 f, err := os.OpenFile("o:/my.log", os.O_CREATE|os.O_APPEND, os.ModePerm)
 if err != nil {
 log.Panic().Err(err).Send() // 内部调用panic
 }
 defer f.Close()
    
 multi := zerolog.MultiLevelWriter(f, os.Stdout) // 多分支写
    // Timestamp()为这个全新的Logger增加时间戳输出
 logger := zerolog.New(multi).With().Timestamp().Logger()
 logger.Info().Msg("日志兵分两路,去控制台stdout,还去日志文件")
}

如果只输出到文件可以使用 zerolog.New(f).With().Timestamp().Logger()

 

标签:输出,log,zerolog,go,logger,级别,Logger,语言
From: https://www.cnblogs.com/caibao666/p/17569369.html

相关文章

  • linux Vim配置Golang语言环境
    下载vim要配置Linux上的Vim,可以按照以下步骤进行操作:打开终端并运行以下命令安装Vim:sudoapt-getupdatesudoapt-getinstallvim12在主目录下创建.vimrc文件:cd~touch.vimrc12编辑.vimrc文件并添加您想要的配置选项。例如,您可以添加以下行以启用语法高亮和......
  • AT_abc251_g Intersection of Polygons Solution
    AT_abc251_gIntersectionofPolygonsSolutionPreface由于某些\(\LaTeX\)的原因,本文的公式无法正常查看,建议读者访问博客以获得正常阅读体验。Statement逆时针地给定一个有\(N\)个顶点,第\(i\)个顶点为\((x_i,y_i)\)的凸包\(P_0\)。再给出\(M\)个向量\((u_i,v......
  • 【补充】Django中路由分发的本质
    【补充】Django中路由分发的本质【一】路由分发机制在Django中,admin路由分发的本质是将管理员后台管理功能与应用程序正常的URL分发机制进行了分离。admin路由分发可以让开发者方便地创建、配置和管理应用程序的后台管理界面。【二】关键部分admin.site.register(mod......
  • mongodb表由未分片修改为分片
    环境:mongodb:4.4.22 1.范围分片:刚开始没有使用分片,后面写入数据了使用分片在路由服务器上执行:mongos>sh.shardCollection("db_pushmsg.app_message_nofenpian",{"user_id":1}){"ok":0,"errmsg":"Pleasecreateanindexthat......
  • apache 代码库的语言分布
    apache代码库的语言分布排行榜:htmljavaxmlc++jsonjavascriptcpython对这个排行多少有些意外。首先,php没有进入前八,javascript排行不高。xml/json排行之高在于大部分人还是喜欢用文件做数据存储?或者是因为项目数据比较小?html占据第一位,但html主要是描述性,而不是......
  • Intellij IDEA 显示 access.log 日志
    先配置  SpringBoot记录access.log日志,先让accesslog 显示出来  ......
  • Go:Missing type in composite literal
    在使用含字符串数组的结构体时,我出现了以下问题1packagemain23import"github.com/gin-gonic/gin"45typeMyJsonstruct{6Functions[]string`json:"functions"`7Descstring`json:"desc"`8}910funcmain(){11......
  • mongodb主从架构
    MongoDB主从架构实现简介在MongoDB中,主从架构又称为复制集(replset),是一种可用性和可靠性的解决方案。主从架构中,有一个主节点(Primary)和多个从节点(Secondary)。主节点负责处理所有的写操作和读操作,而从节点只负责读操作,通过复制主节点的数据保持与主节点的数据同步。流程下面是......
  • SLF4J: Class path contains multiple SLF4J bindings报错,logback-classic.jar与slf4j
    1.问题:控制台一直报错: 1SLF4J:ClasspathcontainsmultipleSLF4Jbindings.2SLF4J:Foundbindingin[jar:file:/logback-classic/1.1.11/logback-classic-1.1.11.jar!/org/slf4j/impl/StaticLoggerBinder.class]3SLF4J:Foundbindingin[jar:file:/slf4j/slf4j-log......
  • CF1155F Delivery Oligopoly 警告与思考--zhengjun
    警告:注意区分【强连通分量】,【边双联通分量】,【点双连通分量】。思考:之前没有做到过边双连通分量的拆解;一个边双联通分量可以看作一个基环上不断加一条链;注意,这里加的链首尾可以为同一个位置。到这步代码就好弄了。代码#include<bits/stdc++.h>usingnamespace......