218 lines
8.1 KiB
Go
218 lines
8.1 KiB
Go
// Package logger ...
|
|
//
|
|
// Description : logger ...
|
|
//
|
|
// Author : go_developer@163.com<白茶清欢>
|
|
//
|
|
// Date : 2022-06-12 18:39
|
|
package logger
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"os"
|
|
"strings"
|
|
|
|
"git.zhangdeman.cn/zhangdeman/consts"
|
|
"git.zhangdeman.cn/zhangdeman/network/util"
|
|
"git.zhangdeman.cn/zhangdeman/serialize"
|
|
"git.zhangdeman.cn/zhangdeman/wrapper/op_any"
|
|
|
|
"git.zhangdeman.cn/zhangdeman/websocket/storage"
|
|
"go.uber.org/zap"
|
|
"go.uber.org/zap/zapcore"
|
|
)
|
|
|
|
var (
|
|
wsLoggerConnect storage.IConnection // ws 日志连接管理实例
|
|
)
|
|
|
|
// SetWsLoggerConnect 设置ws connect
|
|
//
|
|
// Author : go_developer@163.com<白茶清欢>
|
|
//
|
|
// Date : 15:20 2024/7/23
|
|
func SetWsLoggerConnect(connect storage.IConnection) {
|
|
wsLoggerConnect = connect
|
|
}
|
|
|
|
// GetWsLoggConnect 获取ws连接
|
|
//
|
|
// Author : go_developer@163.com<白茶清欢>
|
|
//
|
|
// Date : 15:34 2024/7/23
|
|
func GetWsLoggConnect() storage.IConnection {
|
|
return wsLoggerConnect
|
|
}
|
|
|
|
// LogData 记录日志数据
|
|
type LogData struct {
|
|
Env string `json:"env"` // 运行环境
|
|
Uri string `json:"uri"` // 请求的接口
|
|
TraceID string `json:"trace_id"` // 请求的trace_id
|
|
UserID string `json:"user_id"` // 用户ID
|
|
OperateMode string `json:"operate_mode"` // 操作模式(PC/APP/PAD等)
|
|
LogType string `json:"log_type"` // 日志类型
|
|
CodeVersion string `json:"code_version"` // 代码版本(可以设置为git commit id)
|
|
ServiceVersion string `json:"service_version"` // 服务本身的版本
|
|
ClientIp string `json:"client_ip"` // 客户端IP
|
|
ServerIp string `json:"server_ip"` // 服务器IP
|
|
Hostname string `json:"hostname"` // 服务器主机名
|
|
Code string `json:"code"` // 日志分类标记码
|
|
Data map[string]any `json:"data"` // 扩展记录的数据, 会展开一层进行记录
|
|
}
|
|
|
|
// ToFieldList 转换为 zap.Field 列表
|
|
func (ld *LogData) ToFieldList() []zap.Field {
|
|
var (
|
|
fieldList []zap.Field
|
|
mapLogData map[string]any
|
|
)
|
|
serialize.JSON.TransitionIgnoreError(ld, &mapLogData)
|
|
for k, v := range mapLogData {
|
|
fieldList = append(fieldList, zap.Any(k, v))
|
|
}
|
|
return fieldList
|
|
}
|
|
|
|
// InputLogConfig 输入的日志配置
|
|
type InputLogConfig struct {
|
|
Name string `json:"name" yaml:"name"` // 日志文件名
|
|
Path string `json:"path" yaml:"path"` // 日志文件路径
|
|
TimeIntervalType LogSplit `json:"time_interval_type" yaml:"time_interval_type"` // 日志切割规则
|
|
DivisionChar string `json:"division_char" yaml:"division_char"` // 文件名分隔符
|
|
LogLevel LogLevel `json:"log_level" yaml:"log_level"` // 日志等级
|
|
Console bool `json:"console" yaml:"console"` // 是否进行控制台日志输出
|
|
UseJson bool `json:"use_json" yaml:"use_json"` // 日志是否使用JSON格式
|
|
FileLine bool `json:"file_line" yaml:"file_line"` // 日志是否打印行号
|
|
MessageKey string `json:"message_key" yaml:"message_key"` // message 字段
|
|
LevelKey string `json:"level_key" yaml:"level_key"` // level 字段
|
|
TimeKey string `json:"time_key" yaml:"time_key"` // 时间字段
|
|
CallerKey string `json:"caller_key" yaml:"caller_key"` // 记录日志的文件的代码行数
|
|
UseShortFile bool `json:"use_short_file" yaml:"use_short_file"` // 是否使用短文件格式
|
|
CallerSkip int `json:"caller_skip" yaml:"caller_skip"` // 日志记录的文件跳过多少层
|
|
MaxAge int64 `json:"max_age" yaml:"max_age"` // 日志最长保存时间, 单位 : 秒
|
|
ZincSyncConfig *ZincConfig `json:"zinc_sync_config" yaml:"zinc_sync_config"` // 日志同步至zinc的配置
|
|
}
|
|
|
|
// NewLogData ...
|
|
func NewLogData(ctx context.Context, logType string, code string, logData map[string]any) *LogData {
|
|
hostname, _ := os.Hostname()
|
|
if nil == ctx {
|
|
ctx = context.Background()
|
|
}
|
|
commonLogData := &LogData{
|
|
Env: getStrVal(ctx, consts.GinEnvField),
|
|
Uri: getStrVal(ctx, consts.GinRequestURIField),
|
|
TraceID: getStrVal(ctx, consts.GinTraceIDField),
|
|
UserID: getStrVal(ctx, consts.GinUserIDField),
|
|
OperateMode: getStrVal(ctx, consts.GinOperateModeField),
|
|
LogType: logType,
|
|
CodeVersion: getStrVal(ctx, consts.GinCodeVersionField),
|
|
ServiceVersion: getStrVal(ctx, consts.GinServiceVersionField),
|
|
ClientIp: getStrVal(ctx, consts.GinClientIpField),
|
|
ServerIp: util.IP.GetHostIP(),
|
|
Hostname: hostname,
|
|
Code: code,
|
|
Data: logData,
|
|
}
|
|
return commonLogData
|
|
}
|
|
|
|
func getStrVal(ctx context.Context, key string) string {
|
|
val := ctx.Value(key)
|
|
if nil != val {
|
|
return op_any.AnyDataType(val).ToString()
|
|
}
|
|
if v := ctx.Value(consts.GinContextDataField); nil != v {
|
|
if data, ok := v.(map[string]any); ok {
|
|
if searchVal, exist := data[key]; exist && nil != searchVal {
|
|
return fmt.Sprintf("%v", searchVal)
|
|
}
|
|
}
|
|
}
|
|
return ""
|
|
}
|
|
|
|
// GetLogInstanceFromInputConfig 从输入配置获取日志实例
|
|
func GetLogInstanceFromInputConfig(logConf *InputLogConfig) (*zap.Logger, error) {
|
|
if nil == logConf {
|
|
return nil, nil
|
|
}
|
|
logConfList := []SetLoggerOptionFunc{
|
|
WithCallerSkip(logConf.CallerSkip),
|
|
WithCaller(),
|
|
WithUseJsonFormat(logConf.UseJson),
|
|
WithShortCaller(logConf.UseShortFile),
|
|
}
|
|
if logConf.Console {
|
|
logConfList = append(logConfList, WithConsoleOutput())
|
|
}
|
|
// 配置zinc日志同步
|
|
logConfList = append(logConfList, WithZincLogCollect(logConf.ZincSyncConfig))
|
|
|
|
var (
|
|
err error
|
|
loggerInstance *zap.Logger
|
|
splitConfig *RotateLogConfig
|
|
)
|
|
if splitConfig, err = NewRotateLogConfig(
|
|
logConf.Path,
|
|
logConf.Name,
|
|
WithDivisionChar(logConf.DivisionChar),
|
|
WithTimeIntervalType(logConf.TimeIntervalType),
|
|
WithMaxAge(logConf.MaxAge)); nil != err {
|
|
return nil, err
|
|
}
|
|
if loggerInstance, err = NewLogger(logConf.LogLevel, splitConfig, logConfList...); nil != err {
|
|
return nil, err
|
|
}
|
|
return loggerInstance, nil
|
|
}
|
|
|
|
// inputLevel2ZapLevel 输入日志等级转化为zap日志等级
|
|
func inputLevel2ZapLevel(inputLoggerLevel LogLevel) zapcore.Level {
|
|
inputLoggerLevel = LogLevel(strings.ToUpper(inputLoggerLevel.String()))
|
|
if !inputLoggerLevel.IsValid() {
|
|
// 非法的日志等级, 自动重定向为 info 级别
|
|
inputLoggerLevel = LogLevelInfo
|
|
}
|
|
loggerLevel := zapcore.DebugLevel
|
|
switch inputLoggerLevel {
|
|
case LogLevelDebug:
|
|
loggerLevel = zapcore.DebugLevel
|
|
case LogLevelInfo:
|
|
loggerLevel = zapcore.InfoLevel
|
|
case LogLevelWarn:
|
|
loggerLevel = zapcore.WarnLevel
|
|
case LogLevelError:
|
|
loggerLevel = zapcore.ErrorLevel
|
|
case LogLevelPanic:
|
|
loggerLevel = zapcore.PanicLevel
|
|
}
|
|
return loggerLevel
|
|
}
|
|
|
|
// ZincConfig zinc服务配置
|
|
type ZincConfig struct {
|
|
Authorization string `json:"authorization" dc:"授权secret,生成方式base64(user:password)"`
|
|
Domain string `json:"domain" dc:"zinc服务域名"`
|
|
Timeout int `json:"timeout" dc:"超时时间,单位毫秒,默认5000"`
|
|
Async bool `json:"async" dc:"数据异步写入"`
|
|
Index string `json:"index" dc:"日志使用的索引"`
|
|
CreateType string `json:"create_type" dc:"日志同步的类型: single - 单个同步 batch - 批量创建"`
|
|
BufferSize int `json:"buffer_size" dc:"批量创建时, 数据缓存buffer大小, 默认1000"`
|
|
ForceSyncTime int `json:"force_sync_time" dc:"批量同步日志时,强制同步的时间间隔,buffer没满也会强制同步, 单位: 秒"`
|
|
}
|
|
|
|
const (
|
|
DefaultTimeout = 5000 // 默认超时时间
|
|
DefaultBufferSize = 1000 // 默认buffer大小
|
|
DefaultForceFlushLogTime = 1000 // 强制刷新日志的时间间隔, 单位毫秒
|
|
)
|
|
|
|
const (
|
|
CreateTypeSingle = "single" // 逐条日志同步
|
|
CreateTypeBatch = "batch" // 批量日志同步
|
|
)
|