如何为 Go 设计一个通用的日志包
需求
一个通用的日志包,应该满足以下几个需求:
兼容 log.Logger
,标准库大量使用了 log.Logger
作为其错误内容的输出通道,比如 net/http.Server.ErrorLog,所以兼容 log.Logger
是首要的需求;
自定义配置,不同的运行环境,往往需要不同的日志输出配置,在不重新编译源码的情况下,就能改变配置也应该成为一项标配;
不同的输出类型,根据目前市面上大部分的日志库,我们把日志分为以下六种类型:INFO
、WARN
、DEBUG
、TRACE
、ERROR
和 CRITICAL
;
对日志内容的自定义处理,比如将日志按时间段进行切割,或是重要内容发邮箱进行提醒等。
配置文件
根据以上的需求,我们可以拟定一个以下格式的 XML 配置文件:
<?xml version="1.0" encoding="utf-8"?>
<logs>
<info prefix="INFO" flag="log.lstdflag" >
<!-- 向控制台输出信息 -->
<console output="stderr" foreground="red" background="blue" />
</info>
<error prefix="ERROR" flag="log.lstdflag" />
<!-- 向控制台输出信息 -->
<console output="stderr" foreground="red" background="blue" />
<!-- 输出到 /var/logs/debug 目录下,如果大于 5M,则新建文件 -->
<rotate dir="/var/logs/debug/" size="5M" />
</error>
<critical prefix="CRITICAL" flag="log.lstdflag" >
<!-- 向指定的邮箱发送错误信息 -->
<smtp username="u"
password="p"
host="smtp.example.com"
subject="CRITICAL"
sendTo="u1@example.com;u2@example.com" />
</critical>
</logs>
顶级元素固定为 logs
;
二级元素为 INFO
和 WARN
等六种固定的类型,在加载时,将其初始为一个 *log.Logger
实例,初始化参数可以直接从 XML 的属性和子元素中获取;
二级以下的元素,统一初始化为 io.Writer
实例,当作 log.New()
的参数,用于初始化其父元素。用户可通过接口自定义这些元素,若有初始化参数,则从其 XML 属性值中获取。
这样就达到了一个自由度相对比较高的配置文件。
接口设计
根据以上要求,我们大致上可以确定下来接口的内容。
一个从配置文件进行初始化的接口:
func InitFromConfig(path string) error
以及各个输出类型的操作函数,最主要的就是获取 *log.Logger
的接口,以及一些常用的简化调用。以 INFO 类型为例,我们可以定义以下几个函数,其它类型也都相同,只是函数名不同。
func INFO() *log.Logger // 返回与 INFO 类型对应的 *log.Logger 实例
// 针对 INFO 类型日志的一些常用操作进行封装
func Info(v ...interface{}) // 相当于 INFO().Println()
func Infof(format string, v...interface{}) // 相当于 INFO().Printf()
我们还需要公开一个注册接口,用于注册用户自定义的元素:
type Init func(args map[string]string)(io.Writer, error)
func Register(name string, fn Init)
使用
只要在 main() 中正确定加载了配置文件,之后随处都可以调用:
// main.go
func main() {
err := logs.InitFromConfig("./config/logs.xml")
if err !=nil {
panic(err)
}
// do something
}
// file1.go
func h1(w http.ResponseWriter, r *http.Request) {
if !auth() {
logs.Infof("鉴权失败")
w.WriteHeader(http.StatusUnauthorized)
return
}
}
// file2.go
func getServer(port string, h http.Handler) *http.Server {
return &http.Server {
Addr: port,
Handler: h,
ErrorLog: logs.INFO(),
}
}
实现
完整的实现代码在:https://github.com/issue9/logs。
如何为 Go 设计一个通用的日志包的更多相关文章
- iOS开发:代码通用性以及其规范 第二篇(猜想iOS中实现TableView内部设计思路(附代码),以类似的思想实现一个通用的进度条)
在iOS开发中,经常是要用到UITableView的,我曾经思考过这样一个问题,为什么任何种类的model放到TableView和所需的cell里面,都可以正常显示?而我自己写的很多view却只是能放 ...
- 开源:通用的日志分析工具(LogViewer)
工具介绍 本工具最早是制作出来查看我的 FTL(Fast Trace Log) 二进制日志文件的, 后来因为去做Java后台,经常看 SpringBoot, Tomcat 等的日志, 就简单重构了一下 ...
- Linux下一个简单的日志系统的设计及其C代码实现
1.概述 在大型软件系统中,为了监测软件运行状况及排查软件故障,一般都会要求软件程序在运行的过程中产生日志文件.在日志文件中存放程序流程中的一些重要信息, 包括:变量名称及其值.消息结构定义.函数返回 ...
- 利用RBAC模型实现一个通用的权限管理系统
本文主要描述一个通用的权限系统实现思路与过程.也是对此次制作权限管理模块的总结. 制作此系统的初衷是为了让这个权限系统得以“通用”.就是生产一个web系统通过调用这个权限系统(生成的dll文件), 就 ...
- MySQL系列(十二)--如何设计一个关系型数据库(基本思路)
设计一个关系型数据库,也就是设计RDBMS(Relational Database Management System),这个问题考验的是对RDBMS各个模块的划分, 以及对数据库结构的了解.只要讲述 ...
- 如何从0到1设计一个MQ消息队列
消息队列作为系统解耦,流量控制的利器,成为分布式系统核心组件之一. 如果你对消息队列背后的实现原理关注不多,其实了解消息队列背后的实现非常重要. 不仅知其然还要知其所以然,这才是一个优秀的工程师需要具 ...
- 如何一步一步用DDD设计一个电商网站(十)—— 一个完整的购物车
阅读目录 前言 回顾 梳理 实现 结语 一.前言 之前的文章中已经涉及到了购买商品加入购物车,购物车内购物项的金额计算等功能.本篇准备把剩下的购物车的基本概念一次处理完. 二.回顾 在动手之前我对之 ...
- 如何一步一步用DDD设计一个电商网站(四)—— 把商品卖给用户
阅读目录 前言 怎么卖 领域服务的使用 回到现实 结语 一.前言 上篇中我们讲述了“把商品卖给用户”中的商品和用户的初步设计.现在把剩余的“卖”这个动作给做了.这里提醒一下,正常情况下,我们的每一步业 ...
- 如何一步一步用DDD设计一个电商网站(三)—— 初涉核心域
一.前言 结合我们本次系列的第一篇博文中提到的上下文映射图(传送门:如何一步一步用DDD设计一个电商网站(一)—— 先理解核心概念),得知我们这个电商网站的核心域就是销售子域.因为电子商务是以信息网络 ...
随机推荐
- PowerDesigner工具建表步骤
以商场VIP系统中的表为例 先建立管理员用户表 1.双击打开PowerDesigner工具,点File 选择 New Model 打开如下图,选择标红部分,点击OK 2点击选择标红部位Entity ...
- Leader/Follower多线程网络模型介绍
之前分享过<轻量级 web server Tornado代码分析>,介绍了目前我们采用nginx + tornado的方式搭建升级.配管.数据中心等各类服务组建客户端迭代体系.最近注意到, ...
- EBS R12 Vision Profile default value - IRC: Geocode Host
Profile Option Name Site Application Responsibility Server Server Org User IRC: Geocode Host http:// ...
- Angularjs 实现页面遮罩层功能
实现效果: 1.loading指令: "use strict" /** * Created by yw on 2015/9/27. * user defined loading d ...
- HTML 属性绑定
- Codeforces Gym 100513F F. Ilya Muromets 水题
F. Ilya Muromets Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/gym/100513/probl ...
- PHP设计日历类一 (38)
由两个文件组成: 第一个test.php <style> table { border:1px solid #; } .fontb { color:white; background:bl ...
- 从Oracle官网学习oracle数据库和java
网上搜索Oracle官网:oracle官网 进入Oracle官网 点击menu-Documentation-Java/Database,进入Oracle官网的文档网站 首先是Java,可以看到Java ...
- 【k8s】kubernetes(k8s)介绍
转自 http://blog.csdn.net/Real_Myth/article/details/78719244 一.Kubernetes系列之介绍篇 •Kubernetes介绍 1.背景介绍 ...
- python os用法详解
前言:在自动化测试中,经常需要查找操作文件,比如说查找配置文件(从而读取配置文件的信息),查找测试报告(从而发送测试报告邮件),经常要对大量文件和大量路径进行操作,这就依赖于os模块,所以今天整理下比 ...