代码拉取完成,页面将自动刷新
package log
import (
"context"
"fmt"
"os"
"path/filepath"
"time"
rotatelogs "github.com/openimsdk/tools/log/file-rotatelogs"
"github.com/openimsdk/tools/utils/stringutil"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
"github.com/openimsdk/protocol/constant"
"github.com/openimsdk/tools/mcontext"
)
type LogFormatter interface {
Format() any
}
const (
LevelFatal = iota
LevelPanic
LevelError
LevelWarn
LevelInfo
LevelDebug
LevelDebugWithSQL
)
var (
pkgLogger Logger
osStdout Logger
sp = string(filepath.Separator)
logLevelMap = map[int]zapcore.Level{
LevelDebugWithSQL: zapcore.DebugLevel,
LevelDebug: zapcore.DebugLevel,
LevelInfo: zapcore.InfoLevel,
LevelWarn: zapcore.WarnLevel,
LevelError: zapcore.ErrorLevel,
LevelPanic: zapcore.PanicLevel,
LevelFatal: zapcore.FatalLevel,
}
)
const callDepth = 2
const hoursPerDay = 24
// InitFromConfig initializes a Zap-based logger.
func InitLoggerFromConfig(
loggerPrefixName, moduleName string,
sdkType, platformName string,
logLevel int,
isStdout bool,
isJson bool,
logLocation string,
rotateCount uint,
rotationTime uint,
moduleVersion string,
isSimplify bool,
) error {
l, err := NewZapLogger(loggerPrefixName, moduleName, sdkType, platformName, logLevel, isStdout, isJson, logLocation, rotateCount, rotationTime, moduleVersion, isSimplify)
if err != nil {
return err
}
pkgLogger = l.WithCallDepth(callDepth)
if isJson {
pkgLogger = pkgLogger.WithName(moduleName)
}
return nil
}
// InitConsoleLogger init osStdout and osStderr.
func InitConsoleLogger(moduleName string,
logLevel int,
isJson bool, moduleVersion string) error {
l, err := NewConsoleZapLogger(moduleName, logLevel, isJson, moduleVersion, os.Stdout)
if err != nil {
return err
}
osStdout = l.WithCallDepth(callDepth)
if isJson {
osStdout = osStdout.WithName(moduleName)
}
return nil
}
func ZDebug(ctx context.Context, msg string, keysAndValues ...any) {
if pkgLogger == nil {
return
}
pkgLogger.Debug(ctx, msg, keysAndValues...)
}
func ZInfo(ctx context.Context, msg string, keysAndValues ...any) {
if pkgLogger == nil {
return
}
pkgLogger.Info(ctx, msg, keysAndValues...)
}
func ZWarn(ctx context.Context, msg string, err error, keysAndValues ...any) {
if pkgLogger == nil {
return
}
pkgLogger.Warn(ctx, msg, err, keysAndValues...)
}
func ZError(ctx context.Context, msg string, err error, keysAndValues ...any) {
if pkgLogger == nil {
return
}
pkgLogger.Error(ctx, msg, err, keysAndValues...)
}
func CInfo(ctx context.Context, msg string, keysAndValues ...any) {
if osStdout == nil {
return
}
osStdout.Info(ctx, msg, keysAndValues...)
}
type ZapLogger struct {
zap *zap.SugaredLogger
level zapcore.Level
moduleName string
moduleVersion string
loggerPrefixName string
rotationTime time.Duration
sdkType string
platformName string
isSimplify bool
}
func NewZapLogger(
loggerPrefixName, moduleName string, sdkType, platformName string,
logLevel int,
isStdout bool,
isJson bool,
logLocation string,
rotateCount uint,
rotationTime uint,
moduleVersion string,
isSimplify bool,
) (*ZapLogger, error) {
zapConfig := zap.Config{
Level: zap.NewAtomicLevelAt(logLevelMap[logLevel]),
DisableStacktrace: true,
}
if isJson {
zapConfig.Encoding = "json"
} else {
zapConfig.Encoding = "console"
}
zl := &ZapLogger{level: logLevelMap[logLevel],
moduleName: moduleName,
loggerPrefixName: loggerPrefixName,
rotationTime: time.Duration(rotationTime) * time.Hour,
moduleVersion: moduleVersion,
sdkType: sdkType,
platformName: platformName,
isSimplify: isSimplify,
}
opts, err := zl.cores(isStdout, isJson, logLocation, rotateCount)
if err != nil {
return nil, err
}
l, err := zapConfig.Build(opts)
if err != nil {
return nil, err
}
zl.zap = l.Sugar()
return zl, nil
}
func NewConsoleZapLogger(
moduleName string,
logLevel int,
isJson bool,
moduleVersion string,
outPut *os.File) (*ZapLogger, error) {
zapConfig := zap.Config{
Level: zap.NewAtomicLevelAt(logLevelMap[logLevel]),
DisableStacktrace: true,
}
if isJson {
zapConfig.Encoding = "json"
} else {
zapConfig.Encoding = "console"
}
zl := &ZapLogger{level: logLevelMap[logLevel], moduleName: moduleName, moduleVersion: moduleVersion}
opts, err := zl.consoleCores(outPut, isJson)
if err != nil {
return nil, err
}
l, err := zapConfig.Build(opts)
if err != nil {
return nil, err
}
zl.zap = l.Sugar()
return zl, nil
}
func (l *ZapLogger) cores(isStdout bool, isJson bool, logLocation string, rotateCount uint) (zap.Option, error) {
c := zap.NewProductionEncoderConfig()
c.EncodeTime = l.timeEncoder
c.EncodeDuration = zapcore.SecondsDurationEncoder
c.MessageKey = "msg"
c.LevelKey = "level"
c.TimeKey = "time"
c.CallerKey = "caller"
c.NameKey = "logger"
var fileEncoder zapcore.Encoder
if isJson {
c.EncodeLevel = zapcore.CapitalLevelEncoder
fileEncoder = zapcore.NewJSONEncoder(c)
fileEncoder.AddInt("PID", os.Getpid())
fileEncoder.AddString("version", l.moduleVersion)
} else {
c.EncodeLevel = l.capitalColorLevelEncoder
c.EncodeCaller = l.customCallerEncoder
fileEncoder = zapcore.NewConsoleEncoder(c)
}
fileEncoder = &alignEncoder{Encoder: fileEncoder}
writer, err := l.getWriter(logLocation, rotateCount)
if err != nil {
return nil, err
}
var cores []zapcore.Core
if logLocation != "" {
cores = []zapcore.Core{
zapcore.NewCore(fileEncoder, writer, zap.NewAtomicLevelAt(l.level)),
}
}
if isStdout {
cores = append(cores, zapcore.NewCore(fileEncoder, zapcore.Lock(os.Stdout), zap.NewAtomicLevelAt(l.level)))
// cores = append(cores, zapcore.NewCore(fileEncoder, zapcore.Lock(os.Stderr), zap.NewAtomicLevelAt(l.level)))
}
return zap.WrapCore(func(c zapcore.Core) zapcore.Core {
return zapcore.NewTee(cores...)
}), nil
}
func (l *ZapLogger) consoleCores(outPut *os.File, isJson bool) (zap.Option, error) {
c := zap.NewProductionEncoderConfig()
c.EncodeTime = l.timeEncoder
c.EncodeDuration = zapcore.SecondsDurationEncoder
c.MessageKey = "msg"
c.LevelKey = "level"
c.TimeKey = "time"
c.CallerKey = "caller"
c.NameKey = "logger"
var fileEncoder zapcore.Encoder
if isJson {
c.EncodeLevel = zapcore.CapitalLevelEncoder
fileEncoder = zapcore.NewJSONEncoder(c)
fileEncoder.AddInt("PID", os.Getpid())
fileEncoder.AddString("version", l.moduleVersion)
} else {
c.EncodeLevel = l.capitalColorLevelEncoder
c.EncodeCaller = l.customCallerEncoder
fileEncoder = zapcore.NewConsoleEncoder(c)
}
var cores []zapcore.Core
cores = append(cores, zapcore.NewCore(fileEncoder, zapcore.Lock(outPut), zap.NewAtomicLevelAt(l.level)))
return zap.WrapCore(func(c zapcore.Core) zapcore.Core {
return zapcore.NewTee(cores...)
}), nil
}
func (l *ZapLogger) customCallerEncoder(caller zapcore.EntryCaller, enc zapcore.PrimitiveArrayEncoder) {
if l.sdkType != "" && l.platformName != "" {
fixedLength := 50
sdkPlatform := fmt.Sprintf("[%s/%s]", l.sdkType, l.platformName)
sdkPlatformFormatted := stringutil.FormatString(sdkPlatform, fixedLength, true)
enc.AppendString(sdkPlatformFormatted)
trimmedPath := caller.TrimmedPath()
trimmedPath = "[" + trimmedPath + "]"
s := stringutil.FormatString(trimmedPath, fixedLength, true)
enc.AppendString(s)
} else {
fixedLength := 50
trimmedPath := caller.TrimmedPath()
trimmedPath = "[" + trimmedPath + "]"
s := stringutil.FormatString(trimmedPath, fixedLength, true)
enc.AppendString(s)
}
}
func SDKLog(ctx context.Context, logLevel int, file string, line int, msg string, err error, keysAndValues []any) {
nativeCallerKey := "native_caller"
nativeCaller := fmt.Sprintf("[%s:%d]", file, line)
kv := []any{nativeCallerKey, nativeCaller}
kv = append(kv, keysAndValues...)
switch logLevel {
case LevelDebugWithSQL:
ZDebug(ctx, msg, kv...)
case LevelInfo:
ZInfo(ctx, msg, kv...)
case LevelWarn:
ZWarn(ctx, msg, err, kv...)
case LevelError:
ZError(ctx, msg, err, kv...)
}
}
func (l *ZapLogger) timeEncoder(t time.Time, enc zapcore.PrimitiveArrayEncoder) {
layout := "2006-01-02 15:04:05.000"
type appendTimeEncoder interface {
AppendTimeLayout(time.Time, string)
}
if enc, ok := enc.(appendTimeEncoder); ok {
enc.AppendTimeLayout(t, layout)
return
}
enc.AppendString(t.Format(layout))
}
func (l *ZapLogger) getWriter(logLocation string, rorateCount uint) (zapcore.WriteSyncer, error) {
var path string
if l.rotationTime%(time.Hour*time.Duration(hoursPerDay)) == 0 {
path = logLocation + sp + l.loggerPrefixName + ".%Y-%m-%d"
} else if l.rotationTime%time.Hour == 0 {
path = logLocation + sp + l.loggerPrefixName + ".%Y-%m-%d_%H"
} else {
path = logLocation + sp + l.loggerPrefixName + ".%Y-%m-%d_%H_%M_%S"
}
logf, err := rotatelogs.New(path,
rotatelogs.WithRotationCount(rorateCount),
rotatelogs.WithRotationTime(l.rotationTime),
)
if err != nil {
return nil, err
}
return zapcore.AddSync(logf), nil
}
func (l *ZapLogger) capitalColorLevelEncoder(level zapcore.Level, enc zapcore.PrimitiveArrayEncoder) {
s, ok := _levelToCapitalColorString[level]
if !ok {
s = _unknownLevelColor[zapcore.ErrorLevel]
}
pid := stringutil.FormatString(fmt.Sprintf("[PID:%d]", os.Getpid()), 15, true)
color := _levelToColor[level]
enc.AppendString(s)
enc.AppendString(color.Add(pid))
if l.moduleName != "" {
moduleName := stringutil.FormatString(l.moduleName, 25, true)
enc.AppendString(color.Add(moduleName))
}
if l.moduleVersion != "" {
moduleVersion := stringutil.FormatString(fmt.Sprintf("[%s]", l.moduleVersion), 30, true)
enc.AppendString(moduleVersion)
}
}
func (l *ZapLogger) ToZap() *zap.SugaredLogger {
return l.zap
}
func (l *ZapLogger) Debug(ctx context.Context, msg string, keysAndValues ...any) {
if l.level > zapcore.DebugLevel {
return
}
keysAndValues = l.kvAppend(ctx, keysAndValues)
l.zap.Debugw(msg, keysAndValues...)
}
func (l *ZapLogger) Info(ctx context.Context, msg string, keysAndValues ...any) {
if l.level > zapcore.InfoLevel {
return
}
keysAndValues = l.kvAppend(ctx, keysAndValues)
l.zap.Infow(msg, keysAndValues...)
}
func (l *ZapLogger) Warn(ctx context.Context, msg string, err error, keysAndValues ...any) {
if l.level > zapcore.WarnLevel {
return
}
if err != nil {
keysAndValues = append(keysAndValues, "error", err.Error())
}
keysAndValues = l.kvAppend(ctx, keysAndValues)
l.zap.Warnw(msg, keysAndValues...)
}
func (l *ZapLogger) Error(ctx context.Context, msg string, err error, keysAndValues ...any) {
if l.level > zapcore.ErrorLevel {
return
}
if err != nil {
keysAndValues = append(keysAndValues, "error", err.Error())
}
keysAndValues = l.kvAppend(ctx, keysAndValues)
l.zap.Errorw(msg, keysAndValues...)
}
func (l *ZapLogger) kvAppend(ctx context.Context, keysAndValues []any) []any {
if ctx == nil {
return keysAndValues
}
operationID := mcontext.GetOperationID(ctx)
opUserID := mcontext.GetOpUserID(ctx)
connID := mcontext.GetConnID(ctx)
triggerID := mcontext.GetTriggerID(ctx)
opUserPlatform := mcontext.GetOpUserPlatform(ctx)
remoteAddr := mcontext.GetRemoteAddr(ctx)
if l.isSimplify {
if len(keysAndValues)%2 == 0 {
for i := 1; i < len(keysAndValues); i += 2 {
if val, ok := keysAndValues[i].(LogFormatter); ok && val != nil {
keysAndValues[i] = val.Format()
}
}
} else {
ZError(ctx, "keysAndValues length is not even", nil)
}
}
if opUserID != "" {
keysAndValues = append([]any{constant.OpUserID, opUserID}, keysAndValues...)
}
if operationID != "" {
keysAndValues = append([]any{constant.OperationID, operationID}, keysAndValues...)
}
if connID != "" {
keysAndValues = append([]any{constant.ConnID, connID}, keysAndValues...)
}
if triggerID != "" {
keysAndValues = append([]any{constant.TriggerID, triggerID}, keysAndValues...)
}
if opUserPlatform != "" {
keysAndValues = append([]any{constant.OpUserPlatform, opUserPlatform}, keysAndValues...)
}
if remoteAddr != "" {
keysAndValues = append([]any{constant.RemoteAddr, remoteAddr}, keysAndValues...)
}
return keysAndValues
}
func (l *ZapLogger) WithValues(keysAndValues ...any) Logger {
dup := *l
dup.zap = l.zap.With(keysAndValues...)
return &dup
}
func (l *ZapLogger) WithName(name string) Logger {
dup := *l
dup.zap = l.zap.Named(name)
return &dup
}
func (l *ZapLogger) WithCallDepth(depth int) Logger {
dup := *l
dup.zap = l.zap.WithOptions(zap.AddCallerSkip(depth))
return &dup
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。