125 lines
3.7 KiB
Go
125 lines
3.7 KiB
Go
// Package logger define log struct of modelRT project
|
|
package logger
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"sync"
|
|
"time"
|
|
|
|
"modelRT/config"
|
|
"modelRT/constants"
|
|
|
|
"github.com/natefinch/lumberjack"
|
|
"go.uber.org/zap"
|
|
"go.uber.org/zap/zapcore"
|
|
)
|
|
|
|
var (
|
|
once sync.Once
|
|
_globalLoggerMu sync.RWMutex
|
|
_globalLogger *zap.Logger
|
|
)
|
|
|
|
// getEncoder returns a console encoder for development (human-readable, colored) and a JSON encoder
|
|
// for container modes (parseable by Promtail pipeline_stages).
|
|
func getEncoder(mode string) zapcore.Encoder {
|
|
cfg := zap.NewProductionEncoderConfig()
|
|
cfg.EncodeTime = zapcore.TimeEncoderOfLayout("2006-01-02 15:04:05")
|
|
cfg.TimeKey = "time"
|
|
cfg.EncodeCaller = zapcore.ShortCallerEncoder
|
|
if mode == constants.DevelopmentLogMode {
|
|
cfg.EncodeLevel = zapcore.CapitalColorLevelEncoder
|
|
return zapcore.NewConsoleEncoder(cfg)
|
|
}
|
|
cfg.EncodeLevel = zapcore.CapitalLevelEncoder
|
|
return zapcore.NewJSONEncoder(cfg)
|
|
}
|
|
|
|
// getWriteSyncer returns write targets based on mode:
|
|
// - development: stdout + optional Loki direct-push (when loki.endpoint is set)
|
|
// - container modes: stdout always (Promtail collects) + rotating file (when filepath is set)
|
|
func getWriteSyncer(lCfg config.LoggerConfig) zapcore.WriteSyncer {
|
|
stdout := zapcore.AddSync(os.Stdout)
|
|
|
|
if lCfg.Mode == constants.DevelopmentLogMode {
|
|
if lCfg.Loki.Endpoint == "" {
|
|
return stdout
|
|
}
|
|
return zapcore.NewMultiWriteSyncer(stdout, newLokiSyncer(lCfg.Loki))
|
|
}
|
|
|
|
syncers := []zapcore.WriteSyncer{stdout}
|
|
if lCfg.FilePath != "" {
|
|
dateStr := time.Now().Format("2006-01-02 15:04:05")
|
|
syncers = append(syncers, zapcore.AddSync(&lumberjack.Logger{
|
|
Filename: fmt.Sprintf(lCfg.FilePath, dateStr),
|
|
MaxSize: lCfg.MaxSize,
|
|
MaxAge: lCfg.MaxAge,
|
|
MaxBackups: lCfg.MaxBackups,
|
|
Compress: lCfg.Compress,
|
|
}))
|
|
}
|
|
return zapcore.NewMultiWriteSyncer(syncers...)
|
|
}
|
|
|
|
// containerFields reads K8s Downward API environment variables and returns them as global zap fields.
|
|
// These fields appear on every log line, allowing Loki/Grafana to filter by pod, namespace, and node.
|
|
// Inject them in the Deployment manifest:
|
|
//
|
|
// env:
|
|
// - name: K8S_NAMESPACE
|
|
// valueFrom: {fieldRef: {fieldPath: metadata.namespace}}
|
|
// - name: K8S_NODE_NAME
|
|
// valueFrom: {fieldRef: {fieldPath: spec.nodeName}}
|
|
func containerFields() []zap.Field {
|
|
var fields []zap.Field
|
|
// HOSTNAME is automatically set to the pod name by Kubernetes.
|
|
if pod := os.Getenv("HOSTNAME"); pod != "" {
|
|
fields = append(fields, zap.String("pod", pod))
|
|
}
|
|
if ns := os.Getenv("K8S_NAMESPACE"); ns != "" {
|
|
fields = append(fields, zap.String("namespace", ns))
|
|
}
|
|
if node := os.Getenv("K8S_NODE_NAME"); node != "" {
|
|
fields = append(fields, zap.String("node", node))
|
|
}
|
|
return fields
|
|
}
|
|
|
|
// initLogger return successfully initialized zap logger
|
|
func initLogger(lCfg config.LoggerConfig) *zap.Logger {
|
|
writeSyncer := getWriteSyncer(lCfg)
|
|
encoder := getEncoder(lCfg.Mode)
|
|
|
|
l := new(zapcore.Level)
|
|
if err := l.UnmarshalText([]byte(lCfg.Level)); err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
core := zapcore.NewCore(encoder, writeSyncer, l)
|
|
opts := []zap.Option{zap.AddCaller()}
|
|
if lCfg.Mode != constants.DevelopmentLogMode {
|
|
opts = append(opts, zap.Fields(containerFields()...))
|
|
}
|
|
logger := zap.New(core, opts...)
|
|
|
|
zap.ReplaceGlobals(logger)
|
|
return logger
|
|
}
|
|
|
|
// InitLoggerInstance define func of return instance of zap logger
|
|
func InitLoggerInstance(lCfg config.LoggerConfig) {
|
|
once.Do(func() {
|
|
_globalLogger = initLogger(lCfg)
|
|
})
|
|
}
|
|
|
|
// GetLoggerInstance define func of returns the global logger instance It's safe for concurrent use.
|
|
func GetLoggerInstance() *zap.Logger {
|
|
_globalLoggerMu.RLock()
|
|
logger := _globalLogger
|
|
_globalLoggerMu.RUnlock()
|
|
return logger
|
|
}
|