A:添加日志控件
This commit is contained in:
1 parent
52057a1750
commit
2177d6a545
5 files changed
+595
No files matched your search
+10
@@ -0,0 +1,10 @@
|
||||
module rear
|
||||
|
||||
go 1.24
|
||||
|
||||
require (
|
||||
go.uber.org/zap v1.27.0
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.2.1
|
||||
)
|
||||
|
||||
require go.uber.org/multierr v1.10.0 // indirect
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
|
||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
||||
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
||||
go.uber.org/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ=
|
||||
go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
|
||||
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
|
||||
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc=
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
@@ -0,0 +1,21 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
//TIP <p>To run your code, right-click the code and select <b>Run</b>.</p> <p>Alternatively, click
|
||||
// the <icon src="AllIcons.Actions.Execute"/> icon in the gutter and select the <b>Run</b> menu item from here.</p>
|
||||
|
||||
func main() {
|
||||
//TIP <p>Press <shortcut actionId="ShowIntentionActions"/> when your caret is at the underlined text
|
||||
// to see how GoLand suggests fixing the warning.</p><p>Alternatively, if available, click the lightbulb to view possible fixes.</p>
|
||||
s := "gopher"
|
||||
fmt.Printf("Hello and welcome, %s!\n", s)
|
||||
|
||||
for i := 1; i <= 5; i++ {
|
||||
//TIP <p>To start your debugging session, right-click your code in the editor and select the Debug option.</p> <p>We have set one <icon src="AllIcons.Debugger.Db_set_breakpoint"/> breakpoint
|
||||
// for you, but you can always add more by pressing <shortcut actionId="ToggleLineBreakpoint"/>.</p>
|
||||
fmt.Println("i =", 100/i)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,352 @@
|
||||
package logger
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"go.uber.org/zap"
|
||||
"go.uber.org/zap/zapcore"
|
||||
"gopkg.in/natefinch/lumberjack.v2"
|
||||
)
|
||||
|
||||
// LogLevel 日志级别
|
||||
type LogLevel int
|
||||
|
||||
const (
|
||||
DebugLevel LogLevel = iota
|
||||
InfoLevel
|
||||
WarnLevel
|
||||
ErrorLevel
|
||||
FatalLevel
|
||||
)
|
||||
|
||||
// Config 日志配置
|
||||
type Config struct {
|
||||
Level LogLevel `json:"level"` // 日志级别
|
||||
LogPath string `json:"log_path"` // 日志文件路径
|
||||
MaxSize int `json:"max_size"` // 单个日志文件最大大小(MB)
|
||||
MaxBackups int `json:"max_backups"` // 保留的旧日志文件个数
|
||||
MaxAge int `json:"max_age"` // 保留旧日志文件的最大天数
|
||||
Compress bool `json:"compress"` // 是否压缩旧日志文件
|
||||
EnableConsole bool `json:"enable_console"` // 是否同时输出到控制台
|
||||
EnableCaller bool `json:"enable_caller"` // 是否显示调用者信息(文件名和行号)
|
||||
TimeFormat string `json:"time_format"` // 时间格式
|
||||
AsyncBufferSize int `json:"async_buffer_size"` // 异步缓冲区大小
|
||||
}
|
||||
|
||||
// Logger 日志器结构体
|
||||
type Logger struct {
|
||||
zap *zap.Logger
|
||||
sugar *zap.SugaredLogger
|
||||
config *Config
|
||||
}
|
||||
|
||||
// defaultConfig 默认配置
|
||||
func defaultConfig() *Config {
|
||||
return &Config{
|
||||
Level: InfoLevel,
|
||||
LogPath: "./logs/app.log",
|
||||
MaxSize: 1, // 1MB
|
||||
MaxBackups: 30, // 保留30个备份
|
||||
MaxAge: 7, // 保留7天
|
||||
Compress: true, // 压缩旧文件
|
||||
EnableConsole: true,
|
||||
EnableCaller: true,
|
||||
TimeFormat: "2006-01-02 15:04:05.000",
|
||||
AsyncBufferSize: 1000,
|
||||
}
|
||||
}
|
||||
|
||||
// NewLogger 创建新的日志器
|
||||
func NewLogger(skipCaller int, config ...*Config) (*Logger, error) {
|
||||
var cfg *Config
|
||||
if len(config) > 0 && config[0] != nil {
|
||||
cfg = config[0]
|
||||
} else {
|
||||
cfg = defaultConfig()
|
||||
}
|
||||
|
||||
// 确保日志目录存在
|
||||
logDir := filepath.Dir(cfg.LogPath)
|
||||
if err := os.MkdirAll(logDir, 0755); err != nil {
|
||||
return nil, fmt.Errorf("failed to create log directory: %w", err)
|
||||
}
|
||||
|
||||
// 配置日志轮转
|
||||
hook := &lumberjack.Logger{
|
||||
Filename: cfg.LogPath,
|
||||
MaxSize: cfg.MaxSize,
|
||||
MaxBackups: cfg.MaxBackups,
|
||||
MaxAge: cfg.MaxAge,
|
||||
Compress: cfg.Compress,
|
||||
LocalTime: true,
|
||||
}
|
||||
|
||||
// 创建编码器配置
|
||||
encoderConfig := zapcore.EncoderConfig{
|
||||
TimeKey: "time",
|
||||
LevelKey: "level",
|
||||
NameKey: "logger",
|
||||
CallerKey: "caller",
|
||||
MessageKey: "msg",
|
||||
StacktraceKey: "stacktrace",
|
||||
LineEnding: zapcore.DefaultLineEnding,
|
||||
EncodeLevel: zapcore.LowercaseLevelEncoder,
|
||||
EncodeTime: getTimeEncoder(cfg.TimeFormat),
|
||||
EncodeDuration: zapcore.SecondsDurationEncoder,
|
||||
EncodeCaller: zapcore.ShortCallerEncoder,
|
||||
}
|
||||
|
||||
// 创建文件写入器
|
||||
var fileWriter zapcore.WriteSyncer
|
||||
if cfg.AsyncBufferSize > 0 {
|
||||
// 使用异步缓冲写入器
|
||||
fileWriter = &zapcore.BufferedWriteSyncer{
|
||||
WS: zapcore.AddSync(hook),
|
||||
Size: cfg.AsyncBufferSize,
|
||||
FlushInterval: time.Second,
|
||||
}
|
||||
} else {
|
||||
fileWriter = zapcore.AddSync(hook)
|
||||
}
|
||||
|
||||
// 创建控制台写入器
|
||||
consoleWriter := zapcore.AddSync(os.Stdout)
|
||||
|
||||
// 设置日志级别
|
||||
var level zapcore.Level
|
||||
switch cfg.Level {
|
||||
case DebugLevel:
|
||||
level = zapcore.DebugLevel
|
||||
case InfoLevel:
|
||||
level = zapcore.InfoLevel
|
||||
case WarnLevel:
|
||||
level = zapcore.WarnLevel
|
||||
case ErrorLevel:
|
||||
level = zapcore.ErrorLevel
|
||||
case FatalLevel:
|
||||
level = zapcore.FatalLevel
|
||||
default:
|
||||
level = zapcore.InfoLevel
|
||||
}
|
||||
|
||||
// 创建核心组件
|
||||
var cores []zapcore.Core
|
||||
|
||||
// 文件输出核心
|
||||
fileCore := zapcore.NewCore(
|
||||
zapcore.NewJSONEncoder(encoderConfig),
|
||||
fileWriter,
|
||||
level,
|
||||
)
|
||||
cores = append(cores, fileCore)
|
||||
|
||||
// 控制台输出核心
|
||||
if cfg.EnableConsole {
|
||||
consoleEncoderConfig := encoderConfig
|
||||
consoleEncoderConfig.EncodeLevel = zapcore.CapitalColorLevelEncoder
|
||||
// zapcore.NewJSONEncoder(...) → 输出 JSON 格式日志(机器友好、可解析)
|
||||
// zapcore.NewConsoleEncoder(...) → 输出彩色文本日志(人类友好)
|
||||
consoleCore := zapcore.NewCore(
|
||||
zapcore.NewConsoleEncoder(consoleEncoderConfig),
|
||||
consoleWriter,
|
||||
level,
|
||||
)
|
||||
cores = append(cores, consoleCore)
|
||||
}
|
||||
|
||||
// 创建tee核心(同时写入多个目标)
|
||||
core := zapcore.NewTee(cores...)
|
||||
|
||||
// 配置选项
|
||||
var options []zap.Option
|
||||
if cfg.EnableCaller {
|
||||
// 向上寻找调用者【1 或 2 即可】
|
||||
options = append(options, zap.AddCaller(), zap.AddCallerSkip(skipCaller))
|
||||
}
|
||||
options = append(options, zap.AddStacktrace(zapcore.ErrorLevel))
|
||||
|
||||
// 创建zap logger
|
||||
zapLogger := zap.New(core, options...)
|
||||
|
||||
logger := &Logger{
|
||||
zap: zapLogger,
|
||||
sugar: zapLogger.Sugar(),
|
||||
config: cfg,
|
||||
}
|
||||
|
||||
return logger, nil
|
||||
}
|
||||
|
||||
// getTimeEncoder 获取时间编码器
|
||||
func getTimeEncoder(format string) zapcore.TimeEncoder {
|
||||
return func(t time.Time, enc zapcore.PrimitiveArrayEncoder) {
|
||||
enc.AppendString(t.Format(format))
|
||||
}
|
||||
}
|
||||
|
||||
// Debug 调试级别日志
|
||||
func (l *Logger) Debug(msg string, fields ...zap.Field) {
|
||||
l.zap.Debug(msg, fields...)
|
||||
}
|
||||
|
||||
// Debugf 格式化调试日志
|
||||
func (l *Logger) Debugf(template string, args ...interface{}) {
|
||||
l.sugar.Debugf(template, args...)
|
||||
}
|
||||
|
||||
// Info 信息级别日志
|
||||
func (l *Logger) Info(msg string, fields ...zap.Field) {
|
||||
l.zap.Info(msg, fields...)
|
||||
}
|
||||
|
||||
// Infof 格式化信息日志
|
||||
func (l *Logger) Infof(template string, args ...interface{}) {
|
||||
l.sugar.Infof(template, args...)
|
||||
}
|
||||
|
||||
// Warn 警告级别日志
|
||||
func (l *Logger) Warn(msg string, fields ...zap.Field) {
|
||||
l.zap.Warn(msg, fields...)
|
||||
}
|
||||
|
||||
// Warnf 格式化警告日志
|
||||
func (l *Logger) Warnf(template string, args ...interface{}) {
|
||||
l.sugar.Warnf(template, args...)
|
||||
}
|
||||
|
||||
// Error 错误级别日志
|
||||
func (l *Logger) Error(msg string, fields ...zap.Field) {
|
||||
l.zap.Error(msg, fields...)
|
||||
}
|
||||
|
||||
// Errorf 格式化错误日志
|
||||
func (l *Logger) Errorf(template string, args ...interface{}) {
|
||||
l.sugar.Errorf(template, args...)
|
||||
}
|
||||
|
||||
// Fatal 致命错误日志(会调用os.Exit(1))
|
||||
func (l *Logger) Fatal(msg string, fields ...zap.Field) {
|
||||
l.zap.Fatal(msg, fields...)
|
||||
}
|
||||
|
||||
// Fatalf 格式化致命错误日志
|
||||
func (l *Logger) Fatalf(template string, args ...interface{}) {
|
||||
l.sugar.Fatalf(template, args...)
|
||||
}
|
||||
|
||||
// With 添加字段到日志上下文
|
||||
func (l *Logger) With(fields ...zap.Field) *Logger {
|
||||
return &Logger{
|
||||
zap: l.zap.With(fields...),
|
||||
sugar: l.zap.With(fields...).Sugar(),
|
||||
config: l.config,
|
||||
}
|
||||
}
|
||||
|
||||
// WithFields 使用映射添加字段
|
||||
func (l *Logger) WithFields(fields map[string]interface{}) *Logger {
|
||||
var zapFields []zap.Field
|
||||
for k, v := range fields {
|
||||
zapFields = append(zapFields, zap.Any(k, v))
|
||||
}
|
||||
return l.With(zapFields...)
|
||||
}
|
||||
|
||||
// Sync 同步缓冲区(确保所有日志都被写入)
|
||||
func (l *Logger) Sync() error {
|
||||
return l.zap.Sync()
|
||||
}
|
||||
|
||||
// Close 关闭日志器
|
||||
func (l *Logger) Close() error {
|
||||
return l.Sync()
|
||||
}
|
||||
|
||||
// GetZapLogger 获取原始的zap logger(用于高级用法)
|
||||
func (l *Logger) GetZapLogger() *zap.Logger {
|
||||
return l.zap
|
||||
}
|
||||
|
||||
// GetSugarLogger 获取sugar logger(用于更简单的API)
|
||||
func (l *Logger) GetSugarLogger() *zap.SugaredLogger {
|
||||
return l.sugar
|
||||
}
|
||||
|
||||
// 全局默认日志器
|
||||
var defaultLogger *Logger
|
||||
|
||||
// InitDefaultLogger 初始化默认日志器
|
||||
func InitDefaultLogger(config ...*Config) error {
|
||||
var err error
|
||||
defaultLogger, err = NewLogger(2, config...)
|
||||
return err
|
||||
}
|
||||
|
||||
// 自动初始化
|
||||
func ensureDefaultLogger() {
|
||||
if defaultLogger == nil {
|
||||
_ = InitDefaultLogger() // 忽略错误或打印到stderr
|
||||
}
|
||||
}
|
||||
|
||||
// Debug 全局日志函数
|
||||
func Debug(msg string, fields ...zap.Field) {
|
||||
ensureDefaultLogger()
|
||||
defaultLogger.Debug(msg, fields...)
|
||||
}
|
||||
|
||||
func Debugf(template string, args ...interface{}) {
|
||||
ensureDefaultLogger()
|
||||
defaultLogger.Debugf(template, args...)
|
||||
}
|
||||
|
||||
func Info(msg string, fields ...zap.Field) {
|
||||
ensureDefaultLogger()
|
||||
defaultLogger.Info(msg, fields...)
|
||||
}
|
||||
|
||||
func Infof(template string, args ...interface{}) {
|
||||
ensureDefaultLogger()
|
||||
defaultLogger.Infof(template, args...)
|
||||
}
|
||||
|
||||
func Warn(msg string, fields ...zap.Field) {
|
||||
ensureDefaultLogger()
|
||||
defaultLogger.Warn(msg, fields...)
|
||||
}
|
||||
|
||||
func Warnf(template string, args ...interface{}) {
|
||||
ensureDefaultLogger()
|
||||
defaultLogger.Warnf(template, args...)
|
||||
}
|
||||
|
||||
func Error(msg string, fields ...zap.Field) {
|
||||
ensureDefaultLogger()
|
||||
defaultLogger.Error(msg, fields...)
|
||||
}
|
||||
|
||||
func Errorf(template string, args ...interface{}) {
|
||||
ensureDefaultLogger()
|
||||
defaultLogger.Errorf(template, args...)
|
||||
}
|
||||
|
||||
func Fatal(msg string, fields ...zap.Field) {
|
||||
ensureDefaultLogger()
|
||||
defaultLogger.Fatal(msg, fields...)
|
||||
}
|
||||
|
||||
func Fatalf(template string, args ...interface{}) {
|
||||
ensureDefaultLogger()
|
||||
defaultLogger.Fatalf(template, args...)
|
||||
}
|
||||
|
||||
// Sync 确保所有日志都被写入
|
||||
func Sync() error {
|
||||
if defaultLogger != nil {
|
||||
return defaultLogger.Sync()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,196 @@
|
||||
package logger
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"go.uber.org/zap"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestLog(t *testing.T) {
|
||||
//err := InitDefaultLogger()
|
||||
//if err != nil {
|
||||
// panic(err)
|
||||
//}
|
||||
Infof("App started with default logger")
|
||||
Sync()
|
||||
}
|
||||
|
||||
func main() {
|
||||
// 示例1: 使用默认配置
|
||||
defaultLogger, err := NewLogger(1)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer defaultLogger.Close()
|
||||
|
||||
defaultLogger.Info("Application started with default config")
|
||||
|
||||
// 示例2: 使用自定义配置
|
||||
customConfig := &Config{
|
||||
Level: InfoLevel,
|
||||
LogPath: "./logs/custom.log",
|
||||
MaxSize: 2, // 2MB
|
||||
MaxBackups: 10, // 保留10个备份
|
||||
MaxAge: 3, // 保留3天
|
||||
Compress: true, // 压缩旧文件
|
||||
EnableConsole: true, // 同时输出到控制台
|
||||
EnableCaller: true, // 显示文件名和行号
|
||||
TimeFormat: "2006-01-02 15:04:05",
|
||||
AsyncBufferSize: 500, // 异步缓冲区大小
|
||||
}
|
||||
|
||||
customLogger, err := NewLogger(1, customConfig)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer customLogger.Close()
|
||||
|
||||
// 示例3: 各种日志级别的使用
|
||||
customLogger.Debug("This is a debug message")
|
||||
customLogger.Info("This is an info message")
|
||||
customLogger.Warn("This is a warning message")
|
||||
customLogger.Error("This is an error message")
|
||||
|
||||
// 示例4: 格式化日志
|
||||
customLogger.Infof("User %s logged in at %s", "john_doe", time.Now().Format("15:04:05"))
|
||||
customLogger.Warnf("Failed to process %d items", 5)
|
||||
|
||||
// 示例5: 结构化日志(带字段)
|
||||
customLogger.Info("User operation",
|
||||
zap.String("user_id", "12345"),
|
||||
zap.String("action", "login"),
|
||||
zap.Duration("duration", time.Millisecond*150),
|
||||
zap.Bool("success", true),
|
||||
)
|
||||
|
||||
customLogger.Error("Database connection failed",
|
||||
zap.String("database", "mysql"),
|
||||
zap.String("host", "localhost:3306"),
|
||||
zap.Error(errors.New("connection timeout")),
|
||||
)
|
||||
|
||||
// 示例6: 使用With添加上下文字段
|
||||
userLogger := customLogger.With(
|
||||
zap.String("user_id", "67890"),
|
||||
zap.String("session_id", "abc123"),
|
||||
)
|
||||
|
||||
userLogger.Info("User action performed")
|
||||
userLogger.Warn("Rate limit approached")
|
||||
|
||||
// 示例7: 使用WithFields添加多个字段
|
||||
requestLogger := customLogger.WithFields(map[string]interface{}{
|
||||
"request_id": "req_001",
|
||||
"method": "POST",
|
||||
"path": "/api/users",
|
||||
"ip": "192.168.1.1",
|
||||
})
|
||||
|
||||
requestLogger.Info("Request started")
|
||||
requestLogger.Infof("Request completed in %dms", 250)
|
||||
|
||||
// 示例8: 初始化全局默认日志器
|
||||
err = InitDefaultLogger(&Config{
|
||||
Level: DebugLevel,
|
||||
LogPath: "./logs/global.log",
|
||||
MaxSize: 1,
|
||||
EnableConsole: true,
|
||||
EnableCaller: true,
|
||||
})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// 使用全局日志函数
|
||||
Info("Using global logger")
|
||||
Debugf("Debug message with value: %d", 42)
|
||||
Error("Global error", zap.String("component", "main"))
|
||||
|
||||
// 示例9: 模拟不同场景的日志
|
||||
simulateApplicationFlow(customLogger)
|
||||
|
||||
// 示例10: 性能测试(异步日志的好处)
|
||||
performanceTest(customLogger)
|
||||
|
||||
// 确保所有日志都被写入
|
||||
Sync()
|
||||
}
|
||||
|
||||
// simulateApplicationFlow 模拟应用程序流程
|
||||
func simulateApplicationFlow(l *Logger) {
|
||||
l.Info("Starting application flow simulation")
|
||||
|
||||
// 模拟用户注册
|
||||
userID := "user_12345"
|
||||
userLogger := l.With(zap.String("user_id", userID))
|
||||
|
||||
userLogger.Info("User registration started")
|
||||
userLogger.Debug("Validating user input")
|
||||
|
||||
// 模拟数据库操作
|
||||
dbLogger := userLogger.With(zap.String("component", "database"))
|
||||
dbLogger.Info("Inserting user into database")
|
||||
|
||||
// 模拟成功
|
||||
dbLogger.Info("User created successfully",
|
||||
zap.Duration("db_time", time.Millisecond*45),
|
||||
zap.String("table", "users"),
|
||||
)
|
||||
|
||||
userLogger.Info("User registration completed successfully")
|
||||
|
||||
// 模拟错误场景
|
||||
errorLogger := l.With(zap.String("component", "payment"))
|
||||
errorLogger.Error("Payment processing failed",
|
||||
zap.String("payment_id", "pay_67890"),
|
||||
zap.String("gateway", "stripe"),
|
||||
zap.Error(errors.New("insufficient funds")),
|
||||
zap.Float64("amount", 99.99),
|
||||
)
|
||||
|
||||
l.Info("Application flow simulation completed")
|
||||
}
|
||||
|
||||
// performanceTest 性能测试
|
||||
func performanceTest(l *Logger) {
|
||||
l.Info("Starting performance test")
|
||||
|
||||
start := time.Now()
|
||||
count := 1000
|
||||
|
||||
for i := 0; i < count; i++ {
|
||||
l.Infof("Performance test log entry %d", i)
|
||||
}
|
||||
|
||||
duration := time.Since(start)
|
||||
l.Info("Performance test completed",
|
||||
zap.Int("log_count", count),
|
||||
zap.Duration("total_time", duration),
|
||||
zap.Float64("logs_per_second", float64(count)/duration.Seconds()),
|
||||
)
|
||||
}
|
||||
|
||||
// 业务函数示例
|
||||
func processUserRequest(userID string, l *Logger) error {
|
||||
requestLogger := l.With(
|
||||
zap.String("function", "processUserRequest"),
|
||||
zap.String("user_id", userID),
|
||||
)
|
||||
|
||||
requestLogger.Info("Processing user request")
|
||||
|
||||
// 模拟一些处理逻辑
|
||||
time.Sleep(time.Millisecond * 10)
|
||||
|
||||
if userID == "invalid" {
|
||||
err := errors.New("invalid user ID")
|
||||
requestLogger.Error("Request processing failed",
|
||||
zap.Error(err),
|
||||
)
|
||||
return err
|
||||
}
|
||||
|
||||
requestLogger.Info("Request processed successfully")
|
||||
return nil
|
||||
}
|
||||
Reference in new issue
Block a user