异常日志解析定位代码行提交人员

# 背景

监控系统可以统计异常日志,但是需要人去查看,然后根据代码报错信息分发给具体责任人,这个过程比较繁琐,可以通过脚本自动化处理。

# 解决方案

报错信息中包含代码文件路径和行号,可以通过git blame命令查看代码提交人员,然后根据提交人员分发。

# 实现

package gitAuthorAnalyze

import (
	"log"
	"os"
	"os/exec"
	"regexp"
	"strings"

	"github.com/tealeg/xlsx"
)

func getAuthor(content string) string {
	match := regexp.MustCompile(`(.*) Line:(\d+).*`).FindStringSubmatch(content)
	if len(match) != 3 {
		return ""
	}
	path := match[1]
	num := match[2]
	path = strings.ReplaceAll(path, ".", "/") + ".java"
	baseDir := "D:/code/projectName"
	projects := getDirs(baseDir)
	return getAuthorByProject(baseDir, projects, path, num)
}

func execGitAuthorCommand(projectPath string, file string, num string) string {
	cmd := exec.Command("git", "blame", "-L", num+","+num, file)
	cmd.Dir = projectPath
	output, err := cmd.Output()
	if err != nil {
		log.Fatal(err)
	}
	author := strings.Split(string(output), "(")[1]
	return strings.Split(author, " ")[0]
}

func getAuthorByProject(baseDir string, projects []string, path string, num string) string {
	for _, project := range projects {
		dirPath := baseDir + "/" + project
		childDirs := getDirs(dirPath)
		//如果childDirs包含src
		if contains(childDirs, "src") {
			//判断文件是否存在
			file := dirPath + "/src/main/java/" + path
			if _, err := os.Stat(file); err == nil {
				return execGitAuthorCommand(dirPath, file, num)
			} else {
				continue
			}

		} else {
			file := getAuthorByProject(dirPath, childDirs, path, num)
			if file != "" {
				return file
			}
		}
	}
	return ""
}

func contains(childDirs []string, s string) bool {
	for _, childDir := range childDirs {
		if childDir == s {
			return true
		}
	}
	return false
}

func getDirs(baseDir string) []string {
	dirs := []string{}
	files, err := os.ReadDir(baseDir)
	if err != nil {
		log.Fatal(err)
	}
	for _, file := range files {
		if file.IsDir() {
			dirs = append(dirs, file.Name())
		}
	}
	return dirs
}

func main() {
	excelFileName := "resource/24H内异常次数统计.xlsx"
	xlFile, err := xlsx.OpenFile(excelFileName)
	if err != nil {
		log.Fatal(err)
	}
	sheet := xlFile.Sheets[0]
	for i, row := range sheet.Rows {
		cell := row.Cells[0]
		if len(row.Cells) <= 2 {
			row.AddCell()
			//设置格式
			addCell := row.Cells[2]
			addCell.SetStyle(cell.GetStyle())
		}
		if i == 0 {
			row.Cells[2].SetString("git author")
			continue
		}
		cells := row.Cells
		msg := cells[0].String()
		row.Cells[2].SetString(getAuthor(msg))
	}
	err = xlFile.Save(excelFileName)
	if err != nil {
		log.Fatal(err)
	}
}

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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
上次更新: 2024/12/07, 12:00:34
最近更新
01
docker-compose笔记
01-12
02
MySQL数据迁移
11-27
03
Docker部署服务,避免PID=1
11-27
更多文章>