理解底层— —Golang的log库,二开实现自定义Logger

news2024/9/27 9:19:07

理解底层— —Golang的log库,实现自定义Logger

1 分析实现思路

基于golang中自带的log库实现:对日志实现设置日志级别,每天生成一个文件,同时添加上前缀以及展示文件名等

  • 日志级别,通过添加prefix:[INFO]、[DEBUG]等来实现
  • 每天生成一个日志文件:写日志之前判断当前时间是否为新的一天
  • 日志文件命名:获取每天的时间来实现命名,同时添加读写锁保证并发安全
  • 获取调用日志文件代码行数及文件名:runtime.Caller获取函数调用栈

2 实战

2.1 server.go

package main

import "myTest/inter/log_pro/logger"

func main() {
	logger.SetFile("/Users/xsky/GolandProjects/MyTest/inter/log_pro/log/demo.log")
	logger.SetLevel(0)

	logger.Debug("hello %s", "ziyi")
	logger.Info("hello %s", "ziyi")
}

2.2 logger.go

package logger

import (
	"log"
	"os"
	"runtime"
	"strconv"
	"strings"
	"sync"
	"time"
)

//基于log库自定义实现logger
var (
	infoLogger  *log.Logger
	debugLogger *log.Logger

	logOut     *os.File
	logLevel   int
	currentDay int //每天生成一个日志文件
	logFile    string
	fileLock   sync.RWMutex //读写锁,保证同一时间只有一个协程重命名文件
)

const (
	DebugLevel = iota //0
	InfoLevel         //1
)

func SetLevel(level int) {
	logLevel = level
}

func init() {
	fileLock = sync.RWMutex{}
}

func SetFile(file string) {
	var err error
	logOut, err = os.OpenFile(file, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0664)
	if err != nil {
		panic(err)
	} else {
		//初始化自定义的Logger(基于golang中的log库)
		//log.LstdFlags表示时间格式等
		//log.Llongfile表示文件名及调用代码的位置,log.Llongfile=》改为通过getCallTrace获取前缀
		currentDay = time.Now().YearDay()
		infoLogger = log.New(logOut, "[INFO] ", log.LstdFlags)
		debugLogger = log.New(logOut, "[DEBUG] ", log.LstdFlags)
		logFile = file
	}
}

func checkIfDayChange() {
	fileLock.Lock()
	defer fileLock.Unlock()
	day := time.Now().YearDay()
	if day == currentDay {
		return
	} else {
		//关闭之前的文件,重命名,并生成新的文件
		logOut.Close()
		postFix := time.Now().Add(-24 * time.Hour).Format("20060102")
		err := os.Rename(logFile, logFile+"."+postFix)
		if err != nil {
			//TODO 重命名日志文件失败,根据自身情况做处理
		}
		logOut, err = os.OpenFile(logFile, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0664)
		if err != nil {
			//TODO 打开新的日志文件失败,根据自己业务需求做处理
		}
		infoLogger = log.New(logOut, "[INFO] ", log.LstdFlags)
		debugLogger = log.New(logOut, "[DEBUG] ", log.LstdFlags)
		currentDay = day
	}
}

//golang中的any相当于interface{}空接口
func Debug(format string, v ...any) {
	if logLevel <= DebugLevel {
		checkIfDayChange()
		debugLogger.Printf(getPrefix()+format, v)
	}
}

func Info(format string, v ...any) {
	if logLevel <= InfoLevel {
		checkIfDayChange()
		infoLogger.Printf(getPrefix()+format, v)
	}
}

//获取函数调用栈关系:拿到调用Info或者Debug所在的文件名及代码行数(runtime包)
func getCallTrace() (string, int) {
	_, file, lineNo, ok := runtime.Caller(3)
	if ok {
		return file, lineNo
	} else {
		return "", 0
	}
}

//获取调用Info、Debug代码所在行数,文件名只获取最后三级
func getPrefix() string {
	file, lineNo := getCallTrace()
	path := strings.Split(file, "/")
	if len(path) > 3 {
		file = strings.Join(path[len(path)-3:], "/")
	}
	return file + ":" + strconv.Itoa(lineNo) + " "
}

3 效果

运行server.go查看效果:

在这里插入图片描述

目录结构:
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/934637.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C 字符串处理

字符数组 输入输出 输入函数 scanf(%s, s)读入字符串&#xff0c;在第一个空白符( 、\n 、\t )处停止&#xff0c;不读入空白符&#xff0c;在串尾自动添加\0’ 。gets(s)读入一行字符&#xff0c;直到遇到\n &#xff0c;读入换行符并将其舍弃&#xff0c;在串尾自动添加\…

H5如何做性能测试?

说起H5性能测试&#xff0c;可能许多同学有所耳闻&#xff0c;但是不知道该如何去做性能测试&#xff0c;或者不知道H5应该关注哪些性能指标。今天我们就来看下。希望阅读本文后&#xff0c;能够有所了解。 常用指标 1、H5性能相关参数介绍 白屏时间&#xff1a;用户首次看到…

[LitCTF 2023]PHP是世界上最好的语言!!

进入环境看起来还是挺牛逼的&#xff0c;但是在右边输入框下有一个执行代码&#xff0c;有点牛 真的可以直接执行&#xff0c;那么 根据题目提示&#xff0c;我们得知flag&#xff0c;在根目录&#xff0c;所以我们可以直接利用 查看到flag位置 得到flag

IDEA插件反编译jar包

安装插件Java Decompiler 安装插件Java Decompiler成功之后重启idea 找到已安装插件的jar包 执行反编译 反编译 在已安装插件Java Decompiler的jar包位置下cmd命令执行反编译 java -cp "插件路径" org.jetbrains.java.decompiler.main.decompiler.ConsoleDec…

在线SM4(国密)加密解密工具

在线SM4(国密)加密解密工具

基于安卓的考研助手系统app 微信小程序

&#xff0c;设计并开发实用、方便的应用程序具有重要的意义和良好的市场前景。HBuilder技术作为当前最流行的操作平台&#xff0c;自然也存在着大量的应用服务需求。 本课题研究的是基于HBuilder技术平台的安卓的考研助手APP&#xff0c;开发这款安卓的考研助手APP主要是为了…

【管理运筹学】第 6 章 | 运输问题(2,表上作业法 | 初始可行解的确定)

文章目录 引言二、表上作业法2.1 初始基可行解的确定2.1.1 最小元素法2.1.2 伏格尔法 写在最后 引言 承接前文&#xff0c;在对运输问题有了基本的了解后&#xff0c;我们开始深入学习表上作业的具体内容。 二、表上作业法 2.1 初始基可行解的确定 2.1.1 最小元素法 基本思…

攻防世界-倒立屋

原题 解题思路 用StegSolve打开文件&#xff0c;调通道没用&#xff0c;wp说用RGB信道打开可以找到&#xff0c;但说实话用大括号也没找到在哪&#xff0c;得是预先知道答案才找得到。

Linux常用命令_文件处理命令:su root

文章目录 1. 命令格式与目录处理命令ls1.1 命令格式1.2 目录处理命令&#xff1a;ls 2. 目录处理命令2.1 目录处理命令&#xff1a;mkdir2.2 目录处理命令&#xff1a;cd2.3 目录处理命令&#xff1a;pwd2.4 目录处理命令&#xff1a;rmdir2.5 目录处理命令&#xff1a;cp2.6 目…

C语言文件操作收尾【随机读写 + 结束判定 + 文件缓冲区】

全文目录 前言fseek 重定位位置指示器函数ftell 获取当前文件指示器的位置rewind 重置位置指示器文本文件和二进制文件文件读取结束的判定feof 和 ferror 文件缓冲区总结 前言 有了文件的顺序读写基础&#xff0c;那么肯定会好奇文件的随机读写&#xff0c;毕竟顺序读写对于有…

构建与应用大数据环境:从搭建到开发与组件使用的全面指南

文章目录 环境搭建开发与组件使用性能优化与监控安全与隐私总结 &#x1f388;个人主页&#xff1a;程序员 小侯 &#x1f390;CSDN新晋作者 &#x1f389;欢迎 &#x1f44d;点赞✍评论⭐收藏 ✨收录专栏&#xff1a;大数据系列 ✨文章内容&#xff1a; &#x1f91d;希望作者…

基于 kernel 4.0 初始kmalloc

kmalloc 系列函数是驱动者常用来向内核大管家申请内存的API&#xff0c;今天抽空扒一扒它是怎么工作的&#xff1b;首先看看它的原型 1. kmalloc () 函数 static __always_inline void *kmalloc(size_t size, gfp_t flags) {if (__builtin_constant_p(size)) {if (size > …

性能测试工具分享推荐

性能测试工具 常用性能测试工具性能测试工具又分为软件性能测试工具和系统性能测试工具&#xff0c;以下主要从开源免费工具和商用工具两方面进行整理&#xff0c;开源工具是免费的但通常功能有限&#xff0c;商业工具价格也不便宜&#xff0c;具体还是要结合自己的需求来选择…

AI图片鉴黄检测合规图片API

AI图片鉴黄检测合规图片API 一、AI图片鉴黄检测合规二、使用步骤1、接口2、请求参数3、请求参数示例4、接口 返回示例 三、 报错说明1、返回以下报错说明你没有正确传入检测是图片的参数(file参数), 且请求参数是**multipart/form-data**格式⚠️ 一、AI图片鉴黄检测合规 人工…

JUC——多线程补充

前置可看 Java——多线程和锁_java多线程锁_北岭山脚鼠鼠的博客-CSDN博客 线程创建的三种方式 Thread、Runnable、Callable Thread类 Runable接口 Callable接口 Lamda表达式 Lamda表达式_北岭山脚鼠鼠的博客-CSDN博客 静态代理模式(Thread类的原理) 如下代码中 真实对象…

前端vue2、vue3去掉url路由“ # ”号——nginx配置

文章目录 ⭐前言⭐vue2中router默认出现#号&#x1f496;在vue2项目中去掉&#x1f496;在vue3项目中去掉 ⭐vue打包 assetsPublicPath base 为绝对路径 /&#x1f496;vue2 配置 assetsPublicPath&#x1f496;vue3 配置 base&#x1f496;验证 ⭐nginx 配置&#x1f496; 使用…

ROS-3.ros创建工作空间和工作包

工作空间 工作空间(workspace)是存放工程开发相关文件的目录&#xff0c;目录里面包括 src &#xff1a;代码空间&#xff0c;ROS的catkin软件包&#xff08;源代码包&#xff09;build&#xff1a;编译空间&#xff0c;catkin&#xff08;CMake&#xff09;的缓存信息和中间…

关于事件回调机制

OVERVIEW 关于事件回调机制1.事件回调编程模式2.C中的事件回调编程模式函数指针回调函数对象回调 3.简单回调实例 关于事件回调机制 1.事件回调编程模式 当涉及到编程和软件开发时&#xff0c;事件回调是一种常见的编程模式。它用于处理异步事件和消息传递系统中的事件通知。 …

map set

✅<1>主页&#xff1a;我的代码爱吃辣&#x1f4c3;<2>知识讲解&#xff1a;C STL map&&set☂️<3>开发环境&#xff1a;Visual Studio 2022&#x1f4ac;<4>前言&#xff1a;map和set是C98就已经支持的两个搜索效率极高的容器&#xff0c;其底…

无涯教程-分类算法 - 随机森林

随机森林是一种监督学习算法&#xff0c;可用于分类和回归&#xff0c;但是&#xff0c;它主要用于分类问题&#xff0c;众所周知&#xff0c;森林由树木组成&#xff0c;更多树木意味着更坚固的森林。同样&#xff0c;随机森林算法在数据样本上创建决策树&#xff0c;然后从每…