xlogrus

package module
v1.1.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 11, 2025 License: MIT Imports: 12 Imported by: 0

README

xlogrus

Easy configuration with minor dependencies

Features

Support below logs
  • manual user log with default name trace.log
  • auto gin middleware log with default name access.log
  • auto gorm middleware log with default name db.log
Color enabled/disabled
  • enabled color for screen
  • disabled in log file
Loop log with customized log count
  • 7 files for trace.log/access.log/db.log by default
Multi-hook for different log-level and middleware
  • Centralized warn/error/fatal level to error.log
  • Seperated logs for user/gin/gorm to trace.log/access.log/db.log
  • link log point to alive log files, it's handy when using tail command

Install

go get -u github.com/justin-ren/xlogrus

Dependencies

//log engine
"github.com/sirupsen/logrus"
//loop log
"github.com/lestrrat-go/file-rotatelogs"
//hook for log file
"github.com/rifflock/lfshook"
//log format
"github.com/x-cray/logrus-prefixed-formatter"

Example

User Log
  • example code
import (
	"database/sql"
	"fmt"
	"net/http"
	"os"

	"github.com/gin-gonic/gin"
	xlog "github.com/justin-ren/xlogrus"
	"github.com/pkg/errors"
	"gorm.io/driver/sqlite"
	"gorm.io/gorm"
)


func main() {
	if len(os.Args) > 1 {
		if os.Args[1] == "user" {
			userLogTest()
		} else if os.Args[1] == "gin" {
			ginLogTest()
		} else if os.Args[1] == "gorm" {
			gormLogTest()
		}
	} else {
		userLogTest()
	}
}

func userLogTest() {
	var lg *xlog.TLogrus
	var err error
	if lg, _, err = xlog.NewUserLog(
		xlog.WithFileNamePrefix[xlog.UserOpt]("user.log"), // 自动继承方法
		xlog.WithLogLevel[xlog.UserOpt]("info"),
		xlog.WithLogPath[xlog.UserOpt]("/tmp/logs/"),
	); err != nil {
		fmt.Printf("%+v\n", errors.Cause(err))
		panic(err)
	}

	lg.Debugln("debug msg")
	lg.Infoln("info msg")
	//below log level would be saved in error.log with timestamp %Y%m and keep 7 files by default`
	//so automatically keep 7 months logs
	lg.Warnln("warn msg")
	lg.Errorln("error msg")
	lg.Fatalf("%+v", errors.New("error stack")) //save error stack to log filess
}

  • color is enabled in stdout user log
  • color is disabled in log file
vscode ➜ /workspaces/go/xlogrus-edit (master) $ cat /tmp/logs/user.log
[2025-03-04 08:25:14.153871]  INFO info msg
[2025-03-04 08:25:14.154505]  WARN warn msg
[2025-03-04 08:25:14.154887] ERROR error msg
[2025-03-04 08:25:14.155100] FATAL error stack
main.userLogTest
        /workspaces/go/xlogrus-edit/main.go:57
main.main
        /workspaces/go/xlogrus-edit/main.go:28
runtime.main
        /usr/local/go/src/runtime/proc.go:271
runtime.goexit
        /usr/local/go/src/runtime/asm_amd64.s:1695
Gin Log
  • example code
//visit http://localhost:8080/log/skip and http://localhost:8080/log/hello for test
func ginLogTest() {
	var gHandle gin.HandlerFunc
	var err error
	if _, gHandle, _, err = xlog.NewGinLog(
		xlog.WithFileNamePrefix[xlog.GinOpt]("access.log"), // 自动继承方法
		xlog.WithLogLevel[xlog.GinOpt]("info"),
		xlog.WithLogPath[xlog.GinOpt]("/tmp/logs/"),
		xlog.WithSkipRoute[xlog.GinOpt](map[string]struct{}{"/skip": {}}),
	); err != nil {
		fmt.Printf("%+v\n", errors.Cause(err))
		panic(err)
	}
	r := gin.New()
	r.Use(gHandle, gin.Recovery())
	rLog := r.Group("log")
	rLog.GET("/hello", func(ctx *gin.Context) {
		ctx.JSON(http.StatusOK, gin.H{"msg": "hello"})
	})
	rLog.GET("/skip", func(ctx *gin.Context) {
		ctx.JSON(http.StatusOK, gin.H{"msg": "ignored"})
	})
	err = r.Run(":8080")
	if err != nil {
		panic(errors.Cause(err))
	}

}

  • color is enabled in stdout gin log
  • color is disabled in log file
vscode ➜ /workspaces/go/xlogrus-edit (master) $ cat /tmp/logs/error.log
[2025-03-03 23:38:20.619887]  WARN  clientIP=127.0.0.1 dataLength=-1 latency=7.5µs method=GET path=/ statusCode=404
vscode ➜ /workspaces/go/xlogrus-edit (master) $ cat /tmp/logs/access.log
[2025-03-03 23:38:20.619887]  WARN  clientIP=127.0.0.1 dataLength=-1 latency=7.5µs method=GET path=/ statusCode=404
[2025-03-03 23:38:25.912537]  INFO  clientIP=127.0.0.1 dataLength=17 latency=45.2µs method=GET path=/log/skip statusCode=200
[2025-03-03 23:38:42.127364]  INFO  clientIP=127.0.0.1 dataLength=15 latency=20µs method=GET path=/log/hello statusCode=200
Gorm log
  • example code
func gormLogTest() {
	type notExistingTable struct{}
	connString := fmt.Sprintf("file:%s?mode=memory&cache=shared", "gormLogTest")
	var lg *xlog.GormLog
	var err error
	if lg, _, err = xlog.NewGormLog(
		xlog.WithErrLogPrefix[xlog.GormOpt]("db.log"),
		xlog.WithBKeywords[xlog.GormOpt]([]xlog.BannedKeyword{
			{
				Keyword:         "pass",
				IsCaseSensitive: false,
			},
		}),
		xlog.WithGormLogLevel[xlog.GormOpt]("warn"),
		xlog.WithLogPath[xlog.GormOpt]("/tmp/logs/"),
	); err != nil {
		fmt.Printf("%+v\n", errors.Cause(err))
		panic(err)
	}

	var db *gorm.DB
	if db, err = gorm.Open(sqlite.Open(
		connString),
		&gorm.Config{Logger: lg},
	); err != nil {
		fmt.Printf("%+v\n", errors.Cause(err))
		panic(err)
	}
	var sqlDB *sql.DB
	if sqlDB, err = db.DB(); err != nil {
		fmt.Printf("%+v\n", errors.Cause(err))
		panic(err)
	}

	defer func() {
		if err := sqlDB.Close(); err != nil {
			fmt.Printf("%+v\n", errors.Cause(err))
			panic(err)
		}
	}()

	if errCreate := db.Create(&notExistingTable{}).Error; errCreate != nil {
		fmt.Printf("failed to create table as expected: %+v\n", errCreate)
	}

}
  • color is enabled in stdout gorm
  • color is disabled in log file
vscode ➜ /workspaces/go/xlogrus-edit (master) $ cat /tmp/logs/db.log
[2025-03-04 08:16:22.290016] ERROR  elapsed=0.204776 err=no such table: not_existing_tables from=/workspaces/go/xlogrus-edit/main.go:129 rows=0 sql=INSERT INTO `not_existing_tables` DEFAULT VALUES

Documentation

Overview

* @Author: justin-ren * @Date: 2025-03-01 02:50:20 * @LastEditors: justin-ren * @LastEditTime: 2025-03-04 13:25:36 * @FilePath: /xlogrus/gin_log.go * @Description: gin event log *

* @Author: justin-ren * @Date: 2025-03-01 02:52:00 * @LastEditors: justin-ren * @LastEditTime: 2025-03-04 13:31:12 * @FilePath: /xlogrus/gorm_log.go * @Description: gorm event log *

* @Author: justin-ren * @Date: 2025-02-26 02:11:15 * @LastEditors: justin-ren * @LastEditTime: 2025-03-03 23:22:06 * @FilePath: /xlogrus-edit/xlogrus/xlogrus.go * @Description: *

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func NewGinLog

func NewGinLog(setFunc ...c.LogOption[GinOpt]) (*TLogrus, gin.HandlerFunc, *GinOpt, error)

func NewGormLog

func NewGormLog(setFunc ...c.LogOption[GormOpt]) (*GormLog, *GormOpt, error)

func NewUserLog

func NewUserLog(setFunc ...c.LogOption[UserOpt]) (*TLogrus, *UserOpt, error)

func WithBKeywords

func WithBKeywords[
	T any,
	PT interface {
		*T
		SetBKeywords([]BannedKeyword) error
	},
](keywords []BannedKeyword) c.LogOption[T]

WithBKeywords 设置禁用关键词列表

func WithErrLogPrefix

func WithErrLogPrefix[
	T any,
	PT interface {
		*T
		SetErrLogPrefix(string) error
	},
](prefix string) c.LogOption[T]

WithErrLogPrefix 设置错误日志前缀

func WithErrLogSuffix

func WithErrLogSuffix[
	T any,
	PT interface {
		*T
		SetErrLogSuffix(string) error
	},
](suffix string) c.LogOption[T]

WithErrLogSuffix 设置错误日志后缀

func WithFileNamePrefix

func WithFileNamePrefix[

	T any,
	PT interface {
		*T                              // 1. 必须是指向 T 的指针类型(比如 *UserOpt)
		SetFileNamePrefix(string) error // 2. 必须实现指定签名的方法
	},
](prefix string) c.LogOption[T]

WithFileNamePrefix sets the filename prefix. 定义泛型函数 WithFileNamePrefix,用于创建设置文件名前缀的选项

func WithFileNameSuffixTimeFormat

func WithFileNameSuffixTimeFormat[
	T any,
	PT interface {
		*T
		SetFileNameSuffixTimeFormat(string) error
	},
](format string) c.LogOption[T]

WithFileNameSuffixTimeFormat 设置文件名后缀时间格式

func WithGormLogLevel

func WithGormLogLevel[
	T any,
	PT interface {
		*T
		SetGormLoglevel(string) error
	},
](level string) c.LogOption[T]

WithGormLogLevel 设置 GORM 日志级别

func WithIsHelper

func WithIsHelper[
	T any,
	PT interface {
		*T
		SetIsHelper(bool) error
	},
](value bool) c.LogOption[T]

WithIsHelper 设置是否为帮助函数

func WithKeepCount

func WithKeepCount[
	T any,
	PT interface {
		*T
		SetKeepCount(int) error
	},
](count int) c.LogOption[T]

WithKeepCount 设置日志保留数量

func WithLogFileTimeFormat

func WithLogFileTimeFormat[
	T any,
	PT interface {
		*T
		SetLogFileTimeFormat(string) error
	},
](format string) c.LogOption[T]

WithLogFileTimeFormat 设置日志文件时间格式

func WithLogLatency

func WithLogLatency[
	T any,
	PT interface {
		*T
		SetLogLatency(bool) error
	},
](value bool) c.LogOption[T]

WithLogLatency 设置是否记录延迟

func WithLogLevel

func WithLogLevel[
	T any,
	PT interface {
		*T
		SetLogLevel(string) error
	},
](logLevel string) c.LogOption[T]

WithLogLevel 设置日志级别

func WithLogPath

func WithLogPath[
	T any,
	PT interface {
		*T
		SetLogPath(string) error
	},
](path string) c.LogOption[T]

WithLogPath 设置日志路径

func WithSetErrFileHook

func WithSetErrFileHook[
	T any,
	PT interface {
		*T
		SetSetErrFileHook(bool) error
	},
](enabled bool) c.LogOption[T]

WithSetErrFileHook 设置是否分离错误日志

func WithSkipErrRecordNotFound

func WithSkipErrRecordNotFound[
	T any,
	PT interface {
		*T
		SetSkipErrRecordNotFound(bool) error
	},
](value bool) c.LogOption[T]

为 GormOpt 的字段生成 With 函数 WithSkipErrRecordNotFound 设置是否忽略记录未找到错误

func WithSkipRoute

func WithSkipRoute[
	T any,
	PT interface {
		*T
		SetSkipRoute(map[string]struct{}) error
	},
](r map[string]struct{}) c.LogOption[T]

func WithSlowThreshold

func WithSlowThreshold[
	T any,
	PT interface {
		*T
		SetSlowThreshold(time.Duration) error
	},
](threshold time.Duration) c.LogOption[T]

WithSlowThreshold 设置慢查询阈值

func WithStdoutTimeFormat

func WithStdoutTimeFormat[
	T any,
	PT interface {
		*T
		SetStdoutTimeFormat(string) error
	},
](format string) c.LogOption[T]

WithStdoutTimeFormat 设置标准输出时间格式

Types

type BannedKeyword

type BannedKeyword struct {
	// Keyword represent the string watched, for example : "password"
	Keyword string
	// CaseMatters if set to false, the Keyword matching will occur depending on the case.
	// if set to true, Keyword will cd .strictly match input messages
	IsCaseSensitive bool
}

type GinOpt

type GinOpt struct {
	*c.OptLog
	SkipRoute map[string]struct{}
}

func GetGinOpt

func GetGinOpt() *GinOpt

func (*GinOpt) SetSkipRoute

func (opt *GinOpt) SetSkipRoute(r map[string]struct{}) error

type GormLog

type GormLog struct {
	Logger *logrus.Logger
	Opt    *GormOpt
}

func (*GormLog) Error

func (gormLog *GormLog) Error(ctx context.Context, msg string, args ...interface{})

func (*GormLog) Info

func (gormLog *GormLog) Info(ctx context.Context, msg string, args ...interface{})

func (*GormLog) LogMode

func (gormLog *GormLog) LogMode(level logger.LogLevel) logger.Interface

LogMode implementation log mode.

func (*GormLog) Trace

func (gormLog *GormLog) Trace(ctx context.Context, begin time.Time, fc func() (string, int64), err error)

func (*GormLog) Warn

func (gormLog *GormLog) Warn(ctx context.Context, msg string, args ...interface{})

type GormOpt

type GormOpt struct {
	//ignore if NotFound error happened
	SkipErrRecordNotFound bool
	//slow sql threshold
	SlowThreshold time.Duration
	//record line number and filename
	IsHelper bool
	//replace sensitive word, such as password
	BKeywords []BannedKeyword

	// if set to true, it will add latency information for your queries
	LogLatency bool
	//gorm log level for automatically triggering
	//logrus log level is debug and don't need to modify
	GormLogLevel logger.LogLevel
	*c.OptLog
}

func GetGormOpt

func GetGormOpt() *GormOpt

GetOpt

  • @msg get default values
  • @return: *GormOpt

func (*GormOpt) SetBKeywords

func (g *GormOpt) SetBKeywords(keywords []BannedKeyword) error

SetBKeywords 设置 BKeywords 字段

func (*GormOpt) SetGormLoglevel

func (g *GormOpt) SetGormLoglevel(level string) error

SetGormLoglevel 方法 level支持 silent, error, warn, warning,info

func (*GormOpt) SetIsHelper

func (g *GormOpt) SetIsHelper(value bool) error

SetIsHelper 设置 IsHelper 字段

func (*GormOpt) SetLogLatency

func (g *GormOpt) SetLogLatency(value bool) error

SetLogLatency 设置 LogLatency 字段

func (*GormOpt) SetSkipErrRecordNotFound

func (g *GormOpt) SetSkipErrRecordNotFound(value bool) error

SetSkipErrRecordNotFound 设置 SkipErrRecordNotFound 字段

func (*GormOpt) SetSlowThreshold

func (g *GormOpt) SetSlowThreshold(threshold time.Duration) error

SetSlowThreshold 设置 SlowThreshold 字段

type TGormLog

type TGormLog = logger.LogLevel

type TLogrus

type TLogrus = logrus.Logger

type UserOpt

type UserOpt struct {
	*c.OptLog //继承OptLog所有的方法
}

func GetUserOpt

func GetUserOpt() *UserOpt

Directories

Path Synopsis
gin module
gorm module
user module

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL