iis服务器助手广告
返回顶部
首页 > 资讯 > 后端开发 > GO >Go语言编程实现支持六种级别的日志库
  • 246
分享到

Go语言编程实现支持六种级别的日志库

GOgo语言 2022-06-07 20:06:09 246人浏览 薄情痞子
摘要

目录前言初始需求技术实现类型定义日志级别写到文件默认实现前言 golang标准日志库提供的日志输出方法有Print、Fatal、Panic等,没有常见的Debug、Info、E

目录

前言

初始需求

技术实现

类型定义

日志级别

写到文件

默认实现

前言

golang标准日志库提供的日志输出方法有Print、Fatal、Panic等,没有常见的Debug、Info、Error等日志级别,用起来不太顺手。这篇文章就来手撸一个自己的日志库,可以记录不同级别的日志。

其实对于追求简单来说,Golang标准日志库的三个输出方法也够用了,理解起来也很容易:

Print用于记录一个普通的程序日志,开发者想记点什么都可以。

Fatal用于记录一个导致程序崩溃的日志,并会退出程序。

Panic用于记录一个异常日志,并触发panic。

不过对于用惯了Debug、Info、Error的人来说,还是有点不习惯;对于想更细致的区分日志级别的需求,标准日志库还提供了一个通用的Output方法,开发者在要输出的字符串中加入级别也是可以的,但总是有点别扭,不够直接。

目前市面上也已经有很多优秀的三方日志库,比如uber开源的zap,常见的还有zerolog、logrus等。不过我这里还是想自己手撸一个,因为大多数开源产品都不会完全贴合自己的需求,有很多自己用不上的功能,这会增加系统的复杂性,有没有隐藏的坑也很难说,当然自己入坑的可能性也很大;再者看了官方日志库的实现之后,感觉可以简单封装下即可实现自己想要的功能,能够hold住。

初始需求

我这里的初始需求是:

将日志写入磁盘文件,每个月一个文件夹,每个小时一个文件。

支持常见日志级别:Trace、Debug、Info、Warn、Error、Fatal,并且程序能够设置日志级别。

我给这个日志库取名为ylog,预期的使用方法如下:

ylog.SetLevel(LevelInfo)
ylog.Debug("I am a debug log.")
ylog.Info("I am a Info log.")
技术实现 类型定义

需要定义一个结构体,保存日志级别、要写入的文件等信息。

type FileLogger struct {
lastHour int64
file     *os.File
Level    LogLevel
mu       sync.Mutex
iLogger  *log.Logger
Path     string
}

来看一下这几个参数:

lastHour 用来记录创建日志文件时的小时数,如果小时变了,就要创建新的日志文件。

file 当前使用的日志文件。

Level 当前使用的日志级别。

mu 因为可能在不同的go routine中写日志,需要一个互斥体保证日志文件不会重复创建。

iLogger 标准日志库实例,因为这里是封装了标准日志库。

Path 日志输出的最上层目录,比如程序根目录下的logs目录,这里就保存一个字符串:logs。

日志级别

先把日志级别定义出来,这里日志级别其实是int类型,从0到5,级别不断升高。

如果设置为ToInfo,则Info级别及比Info级别高的日志都能输出。

type LogLevel int
const (
LevelTrace LogLevel = iota
LevelDebug
LevelInfo
LevelWarn
LevelError
LevelFatal
)

上文提到可以在Output方法的参数中加入日志级别,这里就通过封装Output方法来实现不同级别的日志记录方法。这里贴出其中一个方法,封装的方式都一样,就不全都贴出来了:

func (l *FileLogger) CanInfo() bool {
return l.Level <= LevelInfo 
}
func (l *FileLogger) Info(v ...any) {
if l.CanInfo() {
l.ensureFile()
v = append([]any{"Info "}, v...)
l.iLogger.Output(2, fmt.Sprintln(v...))
}
}

输出日志前做了三件事:

判断日志级别,如果设置的日志级别小于等于当前输出级别,则可以输出。

确保日志文件已经创建好,后边会讲如何确保。

将日志级别前插到日志字符串中。

然后调用标准库的Output函数输出日志,这里第一个参数是为了获取到当前正在写日志的程序文件名,传入的是在程序调用栈中进行查找的深度值,这里用2就正好。

写到文件

标准库的log是支持输出到多种目标的,只要实现了io.Write接口:

type Writer interface {
Write(p []byte) (n int, err error)
}

因为文件对象也实现了这个接口,所以这里可以创建os.File的实例,并把它设置到内嵌的标准日志库实例,也就是设置到前边创建的FileLogger中的iLogger中。这个操作在ensureFile方法中,看一下这个文件的实现:

func (l *FileLogger) ensureFile() (err error) {
currentTime := time.Now()
if l.file == nil {
l.mu.Lock()
defer l.mu.Unlock()
if l.file == nil {
l.file, err = createFile(&l.Path, &currentTime)
l.iLogger.SetOutput(l.file)
l.iLogger.SetFlags(log.Lshortfile | log.Ldate | log.Ltime | log.Lmicroseconds)
l.lastHour = getTimeHour(&currentTime)
}
return
}
currentHour := getTimeHour(&currentTime)
if l.lastHour != currentHour {
l.mu.Lock()
defer l.mu.Unlock()
if l.lastHour != currentHour {
_ = l.file.Close()
l.file, err = createFile(&l.Path, &currentTime)
l.iLogger.SetOutput(l.file)
l.iLogger.SetFlags(log.Llongfile | log.Ldate | log.Ltime)
l.lastHour = getTimeHour(&currentTime)
}
}
return
}

这里稍微有点复杂,基本逻辑是:如果文件实例不存在,则创建;如果需要创建新的文件,则先关闭旧的文件再创建新的文件。

更改文件实例时需要加,否则可能多次操作,出现预期之外的情况。

设置输出到文件后,标准log库的Output方法就会将日志输出到这个文件了。

默认实现

经过上边一系列操作,这个FileLogger就可以使用了:

var logger = NewFileLogger(LevelInfo, "logs")
logger.Info("This is a info.")

不过和最初设想的用法有点差别:ylog.Info("xxxx")

这需要在ylog包中再定义一个名为Info的公开函数,可以在这个公开函数中调用一个默认创建的FileLogger实例,代码是这样的:

var stdPath = "logs"
var std = NewFileLogger(LevelInfo, stdPath)
func Trace(v ...any) {
if std.CanTrace() {
std.ensureFile()
v = append([]any{"Trace"}, v...)
std.iLogger.Output(2, fmt.Sprintln(v...))
}
}

注意这里没有调用std的Trace方法,这是因为Output中的第一个参数,如果嵌套调用std.Trace,则多了一层,这个参数就得设置为3,但是自己创建实例调用Trace时这个参数需要为2,这就产生冲突了。

经过以上这些操作,就可以实现预期的日志操作了:

ylog.SetLevel(LevelInfo)
ylog.Debug("I am a debug log.")
ylog.Info("I am a Info log.")

完整的程序代码:https://GitHub.com/bosima/ylog/tree/v1.0.1

下篇文章将继续改造这个日志库,支持输出JSON格式的日志,以及输出日志到kafka,更多关于Golan日志库的资料请关注编程网其它相关文章!


您可能感兴趣的文档:

--结束END--

本文标题: Go语言编程实现支持六种级别的日志库

本文链接: https://www.lsjlt.com/news/30707.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Go语言如何支持云上的实时日志处理?
    随着云计算的发展,云上的实时日志处理变得越来越重要。在现实生产环境中,应用程序的日志量非常大,如果日志处理不及时,会对系统性能造成很大影响。因此,如何在云上实时地处理日志变得非常重要。现在,越来越多的开发者开始选择使用Go语言来支持在云上实...
    99+
    2023-05-18
    Go语言 云上 实时日志处理
  • Go语言是否支持实时异步编程?
    随着计算机技术的不断发展,实时异步编程在开发中变得越来越重要。在这种编程模型中,程序需要在一个不断变化的环境中运行,同时需要快速响应事件。而Go语言作为一种高效的编程语言,能否支持实时异步编程呢?本文将对此进行探讨。 Go语言的并发模型 ...
    99+
    2023-06-25
    实时 异步编程 npm
  • Android编程实现动态支持多语言的方法
    本文实例讲述了Android编程实现动态支持多语言的方法。分享给大家供大家参考,具体如下:资源文件values/strings.xml中添加<string name="current_language">English</...
    99+
    2023-05-31
    android 多语言 roi
  • Go语言中有哪些支持异步编程的包?
    Go语言是一门非常流行的编程语言,它的高效性和简洁性使得越来越多的程序员选择使用它来开发应用程序。在Go语言中,异步编程是一种非常流行的编程方式。异步编程可以提高程序的性能和响应速度,使得程序能够更好地应对高并发的情况。本文将介绍一些Go语...
    99+
    2023-06-25
    实时 异步编程 npm
  • Go语言的泛型编程支持不足的深入分析
    缺乏泛型编程支持 泛型编程是一种允许开发人员编写可用于不同类型数据的代码的编程范式。这可以使代码更灵活、更可重用,并且更容易维护。然而,Go语言目前不支持泛型编程。 这使得在Go语言中编写某些类型的代码变得困...
    99+
    2024-02-01
    go语言 泛型编程 劣势
  • Nginx反向代理支持的编程语言分别有哪些
    Nginx反向代理支持的编程语言分别有哪些,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。说到Nginx反向代理,大家应该比较熟悉了吧,但是在使...
    99+
    2024-04-02
  • 使用GO语言接口实现日志记录:教程详解
    日志记录是每个应用程序都需要的一个重要功能。它可以帮助开发人员及时发现并解决应用程序中的问题,提高应用程序的稳定性。在GO语言中,我们可以通过实现一个接口来实现日志记录功能。 下面是一个简单的例子,演示如何使用GO语言接口实现日志记录。 ...
    99+
    2023-06-25
    教程 接口 日志
  • 如何通过GO语言实现高效的日志索引?
    日志是软件开发中非常重要的一个部分,它记录了应用程序运行时的各种信息,例如错误信息、警告信息、调试信息等。在开发和维护过程中,开发者需要不断地查看日志以了解应用程序的运行情况。因此,一个高效的日志索引系统对于软件开发者来说是非常重要的。 ...
    99+
    2023-07-02
    索引 日志 响应
  • 如何使用go语言编写高效的日志接口并实现存储?
    随着互联网的迅速发展,日志已经成为了一个不可或缺的组成部分。它可以帮助我们记录系统运行情况,以便我们更好地了解系统运行的状态,及时发现问题并进行处理。在这篇文章中,我将向您介绍如何使用Go语言编写高效的日志接口并实现存储。 首先,让我们来看...
    99+
    2023-08-22
    日志 接口 存储
  • GO 语言实现存储同步日志的最新技术趋势
    随着云计算、大数据和物联网等技术的发展,数据量不断增加,数据存储的需求也日益增加。而存储同步日志的需求也越来越高,因为存储同步日志可以保证数据的安全性和可靠性。在这篇文章中,我们将介绍 ,并演示一些相关的代码。 一、什么是存储同步日志? ...
    99+
    2023-08-10
    存储 同步 日志
  • 学习Go语言文档中的log.Println函数实现日志打印
    Go语言提供了一个log包,用于实现日志打印。其中,log.Println函数是一种常用的打印日志的方式,它可以输出日志信息,并且带有时间戳和文件名等基本信息,方便于后续的分析和处理。下面,我们将介绍如何使用log.Println函数打印日...
    99+
    2023-11-03
    文档 logPrintln 关键词:Go语言 日志打印
  • Go语言如何支持云计算中的虚拟现实和增强现实应用?
    虚拟现实(VR)和增强现实(AR)技术在近年来迅速发展,已经在游戏、医疗、教育、娱乐等领域中得到了广泛应用。与此同时,云计算作为一种新兴的计算方式,也正在对计算产生深远的影响。在云计算环境下,VR和AR应用需要处理大量的数据和复杂的计算,这...
    99+
    2023-05-18
    云计算 Go语言 虚拟现实/增强现实应用
  • GO语言怎么实现支持O(log(n))随机删除元素的堆
    今天小编给大家分享一下GO语言怎么实现支持O(log(n))随机删除元素的堆的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。背...
    99+
    2023-07-06
  • 如何在GO语言中实现高效的日志索引和响应?
    日志是任何应用程序中不可或缺的部分。它不仅可以帮助开发人员诊断和调试问题,还可以提供有关应用程序的重要统计信息。GO语言是一种非常适合编写高效程序的语言,因此在GO语言中实现高效的日志索引和响应是非常重要的。 本文将介绍如何在GO语言中实...
    99+
    2023-07-02
    索引 日志 响应
  • 怎么用go语言编程实现二维码生成及识别
    本文小编为大家详细介绍“怎么用go语言编程实现二维码生成及识别”,内容详细,步骤清晰,细节处理妥当,希望这篇“怎么用go语言编程实现二维码生成及识别”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。安装 go-qrc...
    99+
    2023-06-30
  • ASP MVC实现国际化功能的详细教程,让你的网站支持多种语言
    实现国际化的步骤: 创建资源文件: 在项目中创建一个名为“Resources”的文件夹。 在该文件夹下创建两个文件,分别命名为“en-US.resx”和“zh-CN.resx”。 在这些文件中,您可以添加键值对,其中键是您要翻译的...
    99+
    2024-02-24
    ASP MVC 国际化 资源文件 语言偏好 动态显示内容
  • 使用Go语言开发实现高性能的日志分析系统
    随着互联网的快速发展和智能化的推进,数据的生成和积累已经达到了一个空前的规模。在众多的业务系统中,日志数据是最为重要的一部分,它包含了系统运行的各个环节的信息,是进行故障排查、性能优化以及安全审计的重要依据。为了更有效地分析日志数据,提高系...
    99+
    2023-11-20
    - Go语言 - 高性能 - 日志分析
  • GO语言的异步编程模型:如何优雅地处理文件和日志?
    随着互联网的发展,异步编程模型在软件开发中变得越来越常见。GO语言作为一种高效的编程语言,也具备了异步编程的能力。在这篇文章中,我们将探讨GO语言的异步编程模型,并展示如何使用它来优雅地处理文件和日志。 一、GO语言的异步编程模型 在传统...
    99+
    2023-09-27
    异步编程 文件 日志
  • 异步编程和日志记录:GO语言有什么高效的解决方案?
    随着Web应用程序和云计算的快速发展,异步编程和日志记录成为了现代软件开发中不可或缺的部分。在异步编程中,程序不需要等待IO操作的完成,而是可以继续执行其他任务,从而提高程序的效率。而日志记录则是记录程序运行中的信息,以便开发人员在出现问...
    99+
    2023-09-27
    异步编程 文件 日志
  • Go语言网络编程:Go实现简单的内网穿透
    一、内网穿透 1. 内网穿透介绍 内网穿透是一种通过互联网建立远程连接到私有网络(内网)中设备的技术。通常情况下,内网设备由于位于一个受限制的网络环境中,无法直接从外部访问。内网穿透通过将内网设备的流...
    99+
    2023-09-02
    golang 服务器 计算机网络
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作