dragonfly/internal/dflog/logger.go

356 lines
8.4 KiB
Go

/*
* Copyright 2020 The Dragonfly Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package logger
import (
"fmt"
"os"
"path"
"strconv"
"time"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
"golang.org/x/sys/unix"
"google.golang.org/grpc/grpclog"
)
var (
CoreLogger *zap.SugaredLogger
GrpcLogger *zap.SugaredLogger
GinLogger *zap.SugaredLogger
GCLogger *zap.SugaredLogger
StorageGCLogger *zap.SugaredLogger
JobLogger *zap.SugaredLogger
KeepAliveLogger *zap.SugaredLogger
StatSeedLogger *zap.Logger
DownloaderLogger *zap.Logger
coreLogLevelEnabler zapcore.LevelEnabler
)
func init() {
config := zap.NewDevelopmentConfig()
config.Level = zap.NewAtomicLevelAt(zap.InfoLevel)
log, err := config.Build(zap.AddCaller(), zap.AddStacktrace(zap.WarnLevel), zap.AddCallerSkip(1))
if err == nil {
sugar := log.Sugar()
SetCoreLogger(sugar)
SetGrpcLogger(sugar)
SetGinLogger(sugar)
SetGCLogger(sugar)
SetStorageGCLogger(sugar)
SetKeepAliveLogger(sugar)
SetStatSeedLogger(log)
SetDownloadLogger(log)
SetJobLogger(sugar)
}
levels = append(levels, config.Level)
}
// SetLevel updates all log level
func SetLevel(level zapcore.Level) {
Infof("change log level to %s", level.String())
for _, l := range levels {
l.SetLevel(level)
}
}
func SetCoreLogger(log *zap.SugaredLogger) {
CoreLogger = log
coreLogLevelEnabler = log.Desugar().Core()
}
func SetGCLogger(log *zap.SugaredLogger) {
GCLogger = log
}
func SetStorageGCLogger(log *zap.SugaredLogger) {
StorageGCLogger = log
}
func SetKeepAliveLogger(log *zap.SugaredLogger) {
KeepAliveLogger = log
}
func SetStatSeedLogger(log *zap.Logger) {
StatSeedLogger = log
}
func SetDownloadLogger(log *zap.Logger) {
DownloaderLogger = log
}
func SetGrpcLogger(log *zap.SugaredLogger) {
GrpcLogger = log
var v int
vLevel := os.Getenv("GRPC_GO_LOG_VERBOSITY_LEVEL")
if vl, err := strconv.Atoi(vLevel); err == nil {
v = vl
}
grpclog.SetLoggerV2(&zapGrpc{GrpcLogger, v})
}
func SetGinLogger(log *zap.SugaredLogger) {
GinLogger = log
}
func SetJobLogger(log *zap.SugaredLogger) {
JobLogger = log
}
type SugaredLoggerOnWith struct {
withArgs []any
}
func With(args ...any) *SugaredLoggerOnWith {
return &SugaredLoggerOnWith{
withArgs: args,
}
}
func WithPeer(hostID, taskID, peerID string) *SugaredLoggerOnWith {
return &SugaredLoggerOnWith{
withArgs: []any{"hostID", hostID, "taskID", taskID, "peerID", peerID},
}
}
func WithTask(taskID, url string) *SugaredLoggerOnWith {
return &SugaredLoggerOnWith{
withArgs: []any{"taskID", taskID, "url", url},
}
}
func WithHost(hostID, hostname, ip string) *SugaredLoggerOnWith {
return &SugaredLoggerOnWith{
withArgs: []any{"hostID", hostID, "hostname", hostname, "ip", ip},
}
}
func WithTaskID(taskID string) *SugaredLoggerOnWith {
return &SugaredLoggerOnWith{
withArgs: []any{"taskID", taskID},
}
}
func WithHostID(hostID string) *SugaredLoggerOnWith {
return &SugaredLoggerOnWith{
withArgs: []any{"hostID", hostID},
}
}
func WithKeepAlive(hostname, ip, sourceType string, clusterID uint64) *SugaredLoggerOnWith {
return &SugaredLoggerOnWith{
withArgs: []any{"hostname", hostname, "ip", ip, "sourceType", sourceType, "clusterID", clusterID},
}
}
func WithTaskAndPeerID(taskID, peerID string) *SugaredLoggerOnWith {
return &SugaredLoggerOnWith{
withArgs: []any{"taskID", taskID, "peerID", peerID},
}
}
func WithHostnameAndIP(hostname, ip string) *SugaredLoggerOnWith {
return &SugaredLoggerOnWith{
withArgs: []any{"hostname", hostname, "ip", ip},
}
}
func WithGroupAndJobID(taskID, jobID string) *SugaredLoggerOnWith {
return &SugaredLoggerOnWith{
withArgs: []any{"groupID", taskID, "jobID", jobID},
}
}
func WithGroupAndTaskID(groupID, taskID string) *SugaredLoggerOnWith {
return &SugaredLoggerOnWith{
withArgs: []any{"groupID", groupID, "taskID", taskID},
}
}
func (log *SugaredLoggerOnWith) With(args ...any) *SugaredLoggerOnWith {
args = append(args, log.withArgs...)
return &SugaredLoggerOnWith{
withArgs: args,
}
}
func (log *SugaredLoggerOnWith) Infof(template string, args ...any) {
if !coreLogLevelEnabler.Enabled(zap.InfoLevel) {
return
}
CoreLogger.Infow(fmt.Sprintf(template, args...), log.withArgs...)
}
func (log *SugaredLoggerOnWith) Info(args ...any) {
if !coreLogLevelEnabler.Enabled(zap.InfoLevel) {
return
}
CoreLogger.Infow(fmt.Sprint(args...), log.withArgs...)
}
func (log *SugaredLoggerOnWith) Warnf(template string, args ...any) {
if !coreLogLevelEnabler.Enabled(zap.WarnLevel) {
return
}
CoreLogger.Warnw(fmt.Sprintf(template, args...), log.withArgs...)
}
func (log *SugaredLoggerOnWith) Warn(args ...any) {
if !coreLogLevelEnabler.Enabled(zap.WarnLevel) {
return
}
CoreLogger.Warnw(fmt.Sprint(args...), log.withArgs...)
}
func (log *SugaredLoggerOnWith) Errorf(template string, args ...any) {
if !coreLogLevelEnabler.Enabled(zap.ErrorLevel) {
return
}
CoreLogger.Errorw(fmt.Sprintf(template, args...), log.withArgs...)
}
func (log *SugaredLoggerOnWith) Error(args ...any) {
if !coreLogLevelEnabler.Enabled(zap.ErrorLevel) {
return
}
CoreLogger.Errorw(fmt.Sprint(args...), log.withArgs...)
}
func (log *SugaredLoggerOnWith) Debugf(template string, args ...any) {
if !coreLogLevelEnabler.Enabled(zap.DebugLevel) {
return
}
CoreLogger.Debugw(fmt.Sprintf(template, args...), log.withArgs...)
}
func (log *SugaredLoggerOnWith) Debug(args ...any) {
if !coreLogLevelEnabler.Enabled(zap.DebugLevel) {
return
}
CoreLogger.Debugw(fmt.Sprint(args...), log.withArgs...)
}
func (log *SugaredLoggerOnWith) IsDebug() bool {
return coreLogLevelEnabler.Enabled(zap.DebugLevel)
}
func Infof(template string, args ...any) {
CoreLogger.Infof(template, args...)
}
func Info(args ...any) {
CoreLogger.Info(args...)
}
func Warnf(template string, args ...any) {
CoreLogger.Warnf(template, args...)
}
func Warn(args ...any) {
CoreLogger.Warn(args...)
}
func Errorf(template string, args ...any) {
CoreLogger.Errorf(template, args...)
}
func Error(args ...any) {
CoreLogger.Error(args...)
}
func Debugf(template string, args ...any) {
CoreLogger.Debugf(template, args...)
}
func Debug(args ...any) {
CoreLogger.Debug(args...)
}
func IsDebug() bool {
return coreLogLevelEnabler.Enabled(zap.DebugLevel)
}
func Fatalf(template string, args ...any) {
CoreLogger.Fatalf(template, args...)
}
func Fatal(args ...any) {
CoreLogger.Fatal(args...)
}
type zapGrpc struct {
*zap.SugaredLogger
verbose int
}
func (z *zapGrpc) Infoln(args ...any) {
z.SugaredLogger.Info(args...)
}
func (z *zapGrpc) Warning(args ...any) {
z.SugaredLogger.Warn(args...)
}
func (z *zapGrpc) Warningln(args ...any) {
z.SugaredLogger.Warn(args...)
}
func (z *zapGrpc) Warningf(format string, args ...any) {
z.SugaredLogger.Warnf(format, args...)
}
func (z *zapGrpc) Errorln(args ...any) {
z.SugaredLogger.Error(args...)
}
func (z *zapGrpc) Fatalln(args ...any) {
z.SugaredLogger.Fatal(args...)
}
func (z *zapGrpc) V(level int) bool {
return level <= z.verbose
}
// Redirect stdout and stderr to file for debugging.
func RedirectStdoutAndStderr(console bool, logDir string) {
// When console log is enabled, skip redirect.
if console {
return
}
// Redirect stdout to stdout.log file.
stdoutPath := path.Join(logDir, "stdout.log")
if stdout, err := os.OpenFile(stdoutPath, os.O_WRONLY|os.O_CREATE|os.O_APPEND|os.O_SYNC, 0644); err != nil {
Warnf("open %s error: %s", stdoutPath, err)
} else if err := unix.Dup2(int(stdout.Fd()), int(os.Stdout.Fd())); err != nil {
Warnf("redirect stdout error: %s", err)
}
fmt.Fprintf(os.Stdout, "stdout redirect at %v\n", time.Now())
// Redirect stderr to stderr.log file.
stderrPath := path.Join(logDir, "stderr.log")
if stderr, err := os.OpenFile(stderrPath, os.O_WRONLY|os.O_CREATE|os.O_APPEND|os.O_SYNC, 0644); err != nil {
Warnf("open %s error: %s", stderrPath, err)
} else if err := unix.Dup2(int(stderr.Fd()), int(os.Stderr.Fd())); err != nil {
Warnf("redirect stderr error: %s", err)
}
fmt.Fprintf(os.Stderr, "stderr redirect at %v\n", time.Now())
}