核心引擎 · log日志

本篇是Go从零实现ORM框架MyGORM核心篇的第一篇。

目的

  • MyGorm核心日志的封装。

Log日志

MyGorm核心实现之log日志记录,一个好的架构,离不开详细日志,否则出现问题的时候抓眼瞎。因此在实现核心功能前,先实现一个简单的log日志记录。

为什么不直接使用原生的 log 库,log 标准库没有日志分级,不打印文件和行号,这就意味着我们很难快速知道是哪个地方发生了错误。

功能

  1. 支持日志分级。
  2. 不同层级日志显示时使用不同的颜色区分。
  3. 显示打印日志代码对应的文件名和行号。

首先使用命令mkdir mygorm创建一个名为 mygorm文件夹,然后执行 go mod init mygorm并新建文件 log.go,用于放置和日志相关的代码。

现在的代码结构为:

1
2
3
4
mygorm/
log/
|--log.go
|--go.mod

颜色

通常,我们会对不同等级的日志输出不同的颜色来区分。

1
2
fmt.Printf("\033[1;31;40m%s\033[0m\n","Red.")
fmt.Printf("\033[1;37;41m%s\033[0m\n","Red.")

第一行是红字黑底,第二行红底白字。
我们来解析\033[1;31;40m%s\033[0m\n 这个字符串中的字符分别代表了什么。

  • \033\ 表示转义,\033 表示设置颜色。
  • [1;31;40m:定义颜色,[ 表示开始颜色设置,m 为颜色设置结束,以 ; 号分隔。1 代码,表示显示方式,31 表示前景颜色(文字的 颜色),40 表示背景颜色。
  • \033[0m:表示恢复终端默认样式。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// 前景 背景 颜色
// ---------------------------------------
// 30 40 黑色
// 31 41 红色
// 32 42 绿色
// 33 43 黄色
// 34 44 蓝色
// 35 45 紫红色
// 36 46 青蓝色
// 37 47 白色

// 3 位前景色, 4 位背景色

// 代码 意义
// -------------------------
// 0 终端默认设置
// 1 高亮显示
// 4 使用下划线
// 5 闪烁
// 7 反白显示
// 8 不可见

根据上面的颜色,我设置了4种日志级别,代码我已经上传github,点击即可跳转。

log日志代码

my-gorm/log/log.go

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
package log

import (
"io"
"log"
"os"
"sync"
)

type LevelFlag uint

const (
DebugLevel LevelFlag = iota
InfoLevel
WarnLevel
ErrorLevel
DisableLevel
)

// 颜色设置
var debugLog = log.New(os.Stdout, "\033[1;37;40m[mygorm-debug]", log.Ldate|log.Lmicroseconds|log.Lshortfile)
var infoLog = log.New(os.Stdout, "\033[1;32;40m[mygorm-info]", log.Ldate|log.Lmicroseconds|log.Lshortfile)
var warnLog = log.New(os.Stdout, "\033[1;33;40m[mygorm-warn]", log.Ldate|log.Lmicroseconds|log.Lshortfile)
var errorLog = log.New(os.Stdout, "\033[1;31;40m[mygorm-error]", log.Ldate|log.Lmicroseconds|log.Lshortfile)

var loggers = []*log.Logger{debugLog, infoLog, warnLog, errorLog}
var mu sync.Mutex

// 日志方法
var (
Debug = debugLog.Println
DebugF = debugLog.Printf

Info = infoLog.Println
InfoF = infoLog.Printf

Warn = warnLog.Println
WarnF = warnLog.Printf

Error = errorLog.Println
ErrorF = errorLog.Printf
)

// SetLogLevel 设置日志级别
func SetLogLevel(level LevelFlag) {
//加锁
mu.Lock()
//释放锁
defer mu.Unlock()

//先把所有的日志级别允许输出
for _, logger := range loggers {
logger.SetOutput(os.Stdout)
}

//设置的level 大于err 说明err以下的都不输出
if level > ErrorLevel {
errorLog.SetOutput(io.Discard)
}

//只有 level 大于 warn才会输出,只有err 级别才会输出
if level > WarnLevel {
warnLog.SetOutput(io.Discard)
}

if level > InfoLevel {
infoLog.SetOutput(io.Discard)
}

if level > DebugLevel {
debugLog.SetOutput(io.Discard)
}

}

log日志测试代码

my-gorm/log/log_test.go

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package log

import (
"testing"
)

func TestSetLogLevel(t *testing.T) {
//设置级别为err
SetLogLevel(ErrorLevel)
Error("error TestSetLogLevel") //会输出
Info("info TestSetLogLevel") //不会输出
}

func TestSetLogLevel2(t *testing.T) {
//设置级别为info
SetLogLevel(InfoLevel)
Error("error TestSetLogLevel2") //会输出
Info("info TestSetLogLevel") //会输出
}

log日志测试输出

  • TestSetLogLevel方法输出

TestSetLogLevel.png

  • TestSetLogLevel2方法输出

TestSetLogLevel2.png

这样就实现了一个简单的日志级别输出。




本站由 [PengBin](/) 使用 [Stellar 1.26.3](https://github.com/xaoxuu/hexo-theme-stellar/tree/1.26.3) 主题创建。 本博客所有文章除特别声明外,均采用 [CC BY-NC-SA 4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/) 许可协议,转载请注明出处。