github.com/lastbackend/toolkit@v0.0.0-20241020043710-cafa37b95aad/pkg/runtime/logger/zap/zap.go (about)

     1  /*
     2  Copyright [2014] - [2023] The Last.Backend authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package zap
    18  
    19  import (
    20  	"fmt"
    21  	"os"
    22  
    23  	"github.com/lastbackend/toolkit/pkg/runtime"
    24  	"github.com/lastbackend/toolkit/pkg/runtime/logger"
    25  	"github.com/lastbackend/toolkit/pkg/runtime/logger/empty"
    26  	"go.uber.org/fx/fxevent"
    27  	"go.uber.org/zap"
    28  	"go.uber.org/zap/zapcore"
    29  
    30  	"sync"
    31  )
    32  
    33  type zapLogger struct {
    34  	sync.RWMutex
    35  	logger *zap.SugaredLogger
    36  	opts   logger.Options
    37  	empty  logger.Logger
    38  }
    39  
    40  func NewLogger(runtime runtime.Runtime, fields logger.Fields) logger.Logger {
    41  
    42  	l := &zapLogger{
    43  		empty: empty.NewLogger(),
    44  	}
    45  
    46  	runtime.Config().Parse(&l.opts, "")
    47  	if l.opts.CallerSkipCount == 0 {
    48  		l.opts.CallerSkipCount = 1
    49  	}
    50  
    51  	// info level enabler
    52  	infoLevel := zap.LevelEnablerFunc(func(level zapcore.Level) bool {
    53  		return level == zapcore.InfoLevel
    54  	})
    55  
    56  	// error and fatal level enabler
    57  	errorFatalLevel := zap.LevelEnablerFunc(func(level zapcore.Level) bool {
    58  		return level == zapcore.ErrorLevel || level == zapcore.FatalLevel
    59  	})
    60  
    61  	// write syncers
    62  	stdoutSyncer := zapcore.Lock(os.Stdout)
    63  	stderrSyncer := zapcore.Lock(os.Stderr)
    64  
    65  	encoderConfig := zap.NewProductionEncoderConfig()
    66  	encoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder
    67  
    68  	encoder := zapcore.NewConsoleEncoder(encoderConfig)
    69  	if l.opts.JSONFormat {
    70  		encoder = zapcore.NewJSONEncoder(encoderConfig)
    71  	}
    72  
    73  	zapOptions := make([]zap.Option, 0)
    74  	zapOptions = append(zapOptions, zap.AddCallerSkip(l.opts.CallerSkipCount))
    75  	zapOptions = append(zapOptions, zap.AddCaller())
    76  
    77  	// tee core
    78  	core := zapcore.NewTee(
    79  		zapcore.NewCore(
    80  			encoder,
    81  			stdoutSyncer,
    82  			infoLevel,
    83  		),
    84  		zapcore.NewCore(
    85  			encoder,
    86  			stderrSyncer,
    87  			errorFatalLevel,
    88  		),
    89  	)
    90  
    91  	l.logger = zap.New(core, zapOptions...).Sugar().With()
    92  
    93  	return l
    94  }
    95  
    96  func (l *zapLogger) Debug(args ...interface{}) {
    97  	l.logger.Debug(args...)
    98  }
    99  
   100  func (l *zapLogger) Debugf(format string, args ...interface{}) {
   101  	l.logger.Debugf(format, args...)
   102  }
   103  
   104  func (l *zapLogger) Info(args ...interface{}) {
   105  	l.logger.Info(args...)
   106  }
   107  
   108  func (l *zapLogger) Infof(format string, args ...interface{}) {
   109  	l.logger.Infof(format, args...)
   110  }
   111  
   112  func (l *zapLogger) Warn(args ...interface{}) {
   113  	l.logger.Warn(args...)
   114  }
   115  
   116  func (l *zapLogger) Warnf(format string, args ...interface{}) {
   117  	l.logger.Warnf(format, args...)
   118  }
   119  
   120  func (l *zapLogger) Error(args ...interface{}) {
   121  	l.logger.Error(args...)
   122  }
   123  
   124  func (l *zapLogger) Errorf(format string, args ...interface{}) {
   125  	l.logger.Errorf(format, args...)
   126  }
   127  
   128  func (l *zapLogger) Panic(args ...interface{}) {
   129  	l.logger.Fatal(args...)
   130  }
   131  
   132  func (l *zapLogger) Panicf(format string, args ...interface{}) {
   133  	l.logger.Fatalf(format, args...)
   134  }
   135  
   136  func (l *zapLogger) Fatal(args ...interface{}) {
   137  	l.logger.Fatal(args...)
   138  }
   139  
   140  func (l *zapLogger) Fatalf(format string, args ...interface{}) {
   141  	l.logger.Fatalf(format, args...)
   142  }
   143  
   144  func (l *zapLogger) V(level logger.Level) logger.Logger {
   145  
   146  	if l.opts.Verbose < level {
   147  		return l.empty
   148  	}
   149  
   150  	return l
   151  }
   152  
   153  func (l *zapLogger) Inject(fn func(level logger.Level)) {
   154  	return
   155  }
   156  
   157  func (l *zapLogger) Fx() fxevent.Logger {
   158  
   159  	if l.opts.Verbose < 6 {
   160  		return l.empty.Fx()
   161  	}
   162  
   163  	return &fxevent.ZapLogger{
   164  		Logger: l.logger.Desugar(),
   165  	}
   166  }
   167  
   168  func getZapLevel(level logger.Level) zapcore.Level {
   169  	switch level {
   170  	case logger.DebugLevel:
   171  		return zapcore.DebugLevel
   172  	case logger.InfoLevel:
   173  		return zapcore.InfoLevel
   174  	case logger.WarnLevel:
   175  		return zapcore.WarnLevel
   176  	case logger.ErrorLevel:
   177  		return zapcore.ErrorLevel
   178  	case logger.FatalLevel:
   179  		return zapcore.FatalLevel
   180  	case logger.PanicLevel:
   181  		return zapcore.PanicLevel
   182  	default:
   183  		return zapcore.InfoLevel
   184  	}
   185  }
   186  
   187  func (l *zapLogger) getFields(fields logger.Fields) []zapcore.Field {
   188  	return l.fieldsMerge(l.opts.Fields, fields)
   189  }
   190  
   191  func (l *zapLogger) fieldsMerge(parent, src map[string]interface{}) []zapcore.Field {
   192  
   193  	var (
   194  		i   = 0
   195  		dst = make([]zapcore.Field, len(parent)+len(src))
   196  	)
   197  
   198  	for k, v := range parent {
   199  		switch v := v.(type) {
   200  		case int:
   201  			dst[i] = zap.Int(k, v)
   202  		case float64:
   203  			dst[i] = zap.Float64(k, v)
   204  		case string:
   205  			dst[i] = zap.String(k, v)
   206  		default:
   207  			dst[i] = zap.String(k, fmt.Sprintf("%s", v))
   208  		}
   209  		i++
   210  	}
   211  
   212  	for k, v := range src {
   213  		switch v := v.(type) {
   214  		case int:
   215  			dst[i] = zap.Int(k, v)
   216  		case float64:
   217  			dst[i] = zap.Float64(k, v)
   218  		case string:
   219  			dst[i] = zap.String(k, v)
   220  		default:
   221  			dst[i] = zap.String(k, fmt.Sprintf("%s", v))
   222  		}
   223  		i++
   224  	}
   225  	return dst
   226  }