| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183 |
- package logs
- import (
- "fmt"
- "github.com/coroot/coroot-node-agent/utils/enums"
- "github.com/natefinch/lumberjack"
- "github.com/sirupsen/logrus"
- "log"
- "os"
- "path"
- "path/filepath"
- "strings"
- "time"
- )
- const (
- defaultTimestamp = "2006-01-02 15:04:05.999"
- defaultLogDelimeter = "|"
- defaultLogLevel = logrus.ErrorLevel
- defaultLogFileSize = 50
- // 日志保存天数
- defaultMaxAge = 3
- // 每天最多保存的日志数量
- defaultMaxBackups = 3
- )
- type LogConfig struct {
- Path string
- AppInfo string
- MaxSize int // 日志文件最大尺寸,单位MB
- MaxBackups int // 最多保留的旧日志文件数
- MaxAge int // 日志文件保留的最长时间,单位天
- // 控制台输出
- Console bool
- }
- // 定义Hook结构体
- type FileHook struct {
- level logrus.Level
- formatter logrus.Formatter
- logger *log.Logger
- }
- func InitLog(level string, config LogConfig) error {
- FormatterInit()
- if config.Console {
- logrus.SetOutput(os.Stdout)
- } else {
- logrus.SetOutput(&NoOut{})
- }
- //兜底容错
- if level == "" {
- level = enums.DefaultLogLevel
- }
- logrusLevel, err := logrus.ParseLevel(level)
- if err == nil {
- logrus.SetLevel(logrusLevel)
- } else {
- logrus.SetLevel(defaultLogLevel)
- logrus.WithError(err).Error("log level parse error, use default log level error")
- }
- logrus.SetFormatter(NewFormatter())
- logrus.SetReportCaller(true)
- if config.Path == "" {
- config.Path = log_config.Path
- }
- if config.Path == "" {
- return fmt.Errorf("config.Path is nil")
- }
- log_config = config
- RegisterLogHook(config)
- return nil
- }
- // 实现Hook接口
- func (hook *FileHook) Levels() []logrus.Level {
- return logrus.AllLevels[:hook.level+1]
- }
- func (hook *FileHook) Fire(entry *logrus.Entry) error {
- // 将日志消息格式化为字符串
- bytes, err := hook.formatter.Format(entry)
- hook.logger.Print(string(bytes))
- if err != nil {
- return fmt.Errorf("failed to format log entry: %v", err)
- }
- if err != nil {
- return fmt.Errorf("failed to write log entry: %v", err)
- }
- return nil
- }
- type NoOut struct {
- }
- func (no *NoOut) Write(p []byte) (n int, err error) {
- return 0, nil
- }
- func RegisterLogHook(logConf LogConfig) {
- hooks := make(logrus.LevelHooks)
- logrus.StandardLogger().ReplaceHooks(hooks)
- // 日志文件最大尺寸,不超过100MB
- if logConf.MaxSize > defaultLogFileSize || logConf.MaxSize < 1 {
- logConf.MaxSize = defaultLogFileSize
- }
- // 最多保留的旧日志文件数
- if logConf.MaxBackups > defaultMaxBackups || logConf.MaxBackups == 0 {
- logConf.MaxBackups = defaultMaxBackups
- }
- // 日志文件保留的最长时间,单位天
- if logConf.MaxAge > defaultMaxAge || logConf.MaxAge == 0 {
- logConf.MaxAge = defaultMaxAge
- }
- for _, val := range logrus.AllLevels {
- if val <= logrus.GetLevel() {
- fileName := filepath.Join(logConf.Path, logConf.AppInfo+"."+val.String()+".log")
- archive := &lumberjack.Logger{
- Filename: fileName,
- MaxSize: logConf.MaxSize, // 日志文件最大尺寸,单位MB
- MaxBackups: logConf.MaxBackups, // 最多保留的旧日志文件数
- MaxAge: logConf.MaxAge, // 日志文件保留的最长时间,单位天
- LocalTime: true, // 使用本地时间
- Compress: true,
- }
- sysLogger := &log.Logger{}
- sysLogger.SetOutput(archive)
- hooker := &FileHook{
- level: val,
- formatter: NewFormatter(),
- logger: sysLogger,
- }
- hooks.Add(hooker)
- }
- }
- }
- func FormatterInit() {
- logrus.SetFormatter(NewFormatter())
- logrus.SetReportCaller(true)
- }
- func NewFormatter() *MyFormatter {
- return &MyFormatter{
- Pid: os.Getpid(),
- TimestampFormat: defaultTimestamp,
- }
- }
- // Custom log format definition
- type MyFormatter struct {
- Pid int
- TimestampFormat string
- }
- func (s *MyFormatter) Format(entry *logrus.Entry) ([]byte, error) {
- //var callerFun string
- var fileInfo string
- var entryDataInfo string
- for key, val := range entry.Data {
- entryDataInfo += fmt.Sprintf(" %s=\"%v\"", key, val)
- }
- if entry.HasCaller() {
- //callerFun = entry.Caller.Function
- fileInfo = fmt.Sprintf("%s:%d", path.Base(entry.Caller.File), entry.Caller.Line)
- }
- timestamp := time.Now().Local().Format(s.TimestampFormat)
- msg := fmt.Sprintf("%s|%s|%d|%s] %s%s\n",
- timestamp, strings.ToUpper(entry.Level.String()), s.Pid, fileInfo, entry.Message, entryDataInfo)
- return []byte(msg), nil
- }
- var log_config LogConfig
- func GetLogConf() LogConfig {
- return log_config
- }
|