host_log_analyzer.go 2.0 KB
Newer Older
O
ob-robot 已提交
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
package log_analyzer

import (
	"os"
	"regexp"
	"time"

	"github.com/oceanbase/obagent/monitor/message"
)

// Nov 28 03:20:05
const hostLogAtLayout = "Jan _2 15:04:05"
const logTimeInHostFileNameLayout = "20060102"

// HostLogAnalyzer 主机日志
type HostLogAnalyzer struct {
	fileName string
}

var hostLogRegexp = regexp.MustCompile(`^(?P<time>[A-Z][a-z]{2,} [ |\d]\d \d\d:\d\d:\d\d) (?P<host>[^ ]+) (?P<content>.+)`)
var hostSubMatchIndex = make(map[string]int)

func init() {
	for i, name := range hostLogRegexp.SubexpNames() {
		hostSubMatchIndex[name] = i
	}
}

func NewHostLogAnalyzer(fileName string) LogAnalyzer {
	return &HostLogAnalyzer{
		fileName: fileName,
	}
}

func (o *HostLogAnalyzer) ParseLine(line string) (*message.Message, bool) {
	subMatch := hostLogRegexp.FindStringSubmatch(line)
	if subMatch == nil {
		return nil, false
	}
	contentIdx := hostSubMatchIndex["content"]
	if contentIdx >= len(subMatch) {
		return nil, false
	}
	t, err := parseHostLogTime(subMatch[hostSubMatchIndex["time"]], time.Now())
	if err != nil {
		return nil, false
	}
	msg := message.NewMessage(o.fileName, message.Log, t)
	msg.AddField("raw", line)
	msg.AddField("content", subMatch[contentIdx])
	msg.AddTag("level", "info")
	return msg, true
}

func parseHostLogTime(logStr string, now time.Time) (time.Time, error) {
	logAt, err := time.ParseInLocation(hostLogAtLayout, logStr, time.Local)
	if err != nil {
		return time.Time{}, err
	}
	// /var/log 日志默认保存 4 周
	// 由于日志行中没有年份,这里特殊处理下年份,对 12 月做特殊处理
	year := now.Year()
	if logAt.Month() == time.December &&
		now.Month() == time.January &&
		logAt.After(now) {
		year -= 1
	}
	logAt = time.Date(year, logAt.Month(), logAt.Day(), logAt.Hour(), logAt.Minute(), logAt.Second(), logAt.Nanosecond(), time.Local)
	return logAt, nil
}

// GetFileEndTime 获取文件最后写入时间
func (o *HostLogAnalyzer) GetFileEndTime(info os.FileInfo) (time.Time, error) {
	return ParseTimeFromFileName(info.Name(), "-", logTimeInHostFileNameLayout, info.ModTime()), nil
}