feat: Implement logging module with zap
This commit is contained in:
		
							
								
								
									
										157
									
								
								internal/pkg/log/log.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										157
									
								
								internal/pkg/log/log.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,157 @@
 | 
			
		||||
// MIT License
 | 
			
		||||
//
 | 
			
		||||
// Copyright (c) 2024 vinchent <vinchent@vinchent.xyz>
 | 
			
		||||
//
 | 
			
		||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
			
		||||
// of this software and associated documentation files (the "Software"), to deal
 | 
			
		||||
// in the Software without restriction, including without limitation the rights
 | 
			
		||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
			
		||||
// copies of the Software, and to permit persons to whom the Software is
 | 
			
		||||
// furnished to do so, subject to the following conditions:
 | 
			
		||||
//
 | 
			
		||||
// The above copyright notice and this permission notice shall be included in all
 | 
			
		||||
// copies or substantial portions of the Software.
 | 
			
		||||
//
 | 
			
		||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
			
		||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | 
			
		||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
			
		||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
			
		||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 | 
			
		||||
// SOFTWARE.
 | 
			
		||||
 | 
			
		||||
package log
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"os"
 | 
			
		||||
	"sync"
 | 
			
		||||
 | 
			
		||||
	"go.uber.org/zap"
 | 
			
		||||
	"go.uber.org/zap/zapcore"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type Logger interface {
 | 
			
		||||
	FatalLog(msg string, keyValues ...interface{})
 | 
			
		||||
	PanicLog(msg string, keyValues ...interface{})
 | 
			
		||||
	ErrorLog(msg string, keyValues ...interface{})
 | 
			
		||||
	WarnLog(msg string, keyValues ...interface{})
 | 
			
		||||
	InfoLog(msg string, keyValues ...interface{})
 | 
			
		||||
	DebugLog(msg string, keyValues ...interface{})
 | 
			
		||||
	Sync()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// zapLogger is an implementation of Logger interface
 | 
			
		||||
type zapLogger struct {
 | 
			
		||||
	z *zap.Logger
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	mu sync.Mutex
 | 
			
		||||
 | 
			
		||||
	// default global logger
 | 
			
		||||
	std = NewLogger(NewOptions())
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Init initializes global logger with options
 | 
			
		||||
func Init(opts *Options) {
 | 
			
		||||
	mu.Lock()
 | 
			
		||||
	defer mu.Unlock()
 | 
			
		||||
 | 
			
		||||
	std = NewLogger(opts)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewLogger(opts *Options) *zapLogger {
 | 
			
		||||
	if opts == nil {
 | 
			
		||||
		opts = NewOptions()
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var zapLevel zapcore.Level
 | 
			
		||||
	// If unknown level, use info
 | 
			
		||||
	if err := zapLevel.UnmarshalText([]byte(opts.Level)); err != nil {
 | 
			
		||||
		zapLevel = zap.InfoLevel
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	encoderCfg := zap.NewProductionEncoderConfig()
 | 
			
		||||
	encoderCfg.TimeKey = "timestamp"
 | 
			
		||||
	encoderCfg.MessageKey = "message"
 | 
			
		||||
	encoderCfg.EncodeTime = zapcore.ISO8601TimeEncoder
 | 
			
		||||
 | 
			
		||||
	config := zap.Config{
 | 
			
		||||
		Level:             zap.NewAtomicLevelAt(zapLevel),
 | 
			
		||||
		Development:       opts.Development,
 | 
			
		||||
		DisableCaller:     opts.DisableCaller,
 | 
			
		||||
		DisableStacktrace: opts.DisableStacktrace,
 | 
			
		||||
		Sampling:          nil,
 | 
			
		||||
		Encoding:          opts.Format,
 | 
			
		||||
		EncoderConfig:     encoderCfg,
 | 
			
		||||
		OutputPaths:       opts.OutputPaths,
 | 
			
		||||
		ErrorOutputPaths: []string{
 | 
			
		||||
			"stderr",
 | 
			
		||||
		},
 | 
			
		||||
		InitialFields: map[string]interface{}{
 | 
			
		||||
			"pid": os.Getpid(),
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	z := zap.Must(config.Build(zap.AddStacktrace(zapcore.PanicLevel), zap.AddCallerSkip(1)))
 | 
			
		||||
 | 
			
		||||
	zap.RedirectStdLog(z)
 | 
			
		||||
 | 
			
		||||
	return &zapLogger{z: z}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (z *zapLogger) FatalLog(msg string, keyValues ...interface{}) {
 | 
			
		||||
	z.z.Sugar().Fatalw(msg, keyValues...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (z *zapLogger) PanicLog(msg string, keyValues ...interface{}) {
 | 
			
		||||
	z.z.Sugar().Panicw(msg, keyValues...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (z *zapLogger) ErrorLog(msg string, keyValues ...interface{}) {
 | 
			
		||||
	z.z.Sugar().Errorw(msg, keyValues...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (z *zapLogger) WarnLog(msg string, keyValues ...interface{}) {
 | 
			
		||||
	z.z.Sugar().Warnw(msg, keyValues...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (z *zapLogger) InfoLog(msg string, keyValues ...interface{}) {
 | 
			
		||||
	z.z.Sugar().Infow(msg, keyValues...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (z *zapLogger) DebugLog(msg string, keyValues ...interface{}) {
 | 
			
		||||
	z.z.Sugar().Debugw(msg, keyValues...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (z *zapLogger) Sync() {
 | 
			
		||||
	_ = z.z.Sync()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func FatalLog(msg string, keyValues ...interface{}) {
 | 
			
		||||
	std.z.Sugar().Fatalw(msg, keyValues...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func PanicLog(msg string, keyValues ...interface{}) {
 | 
			
		||||
	std.z.Sugar().Panicw(msg, keyValues...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func ErrorLog(msg string, keyValues ...interface{}) {
 | 
			
		||||
	std.z.Sugar().Errorw(msg, keyValues...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func WarnLog(msg string, keyValues ...interface{}) {
 | 
			
		||||
	std.z.Sugar().Warnw(msg, keyValues...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func InfoLog(msg string, keyValues ...interface{}) {
 | 
			
		||||
	std.z.Sugar().Infow(msg, keyValues...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func DebugLog(msg string, keyValues ...interface{}) {
 | 
			
		||||
	std.z.Sugar().Debugw(msg, keyValues...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func Sync() {
 | 
			
		||||
	_ = std.z.Sync()
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										46
									
								
								internal/pkg/log/options.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								internal/pkg/log/options.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,46 @@
 | 
			
		||||
// MIT License
 | 
			
		||||
//
 | 
			
		||||
// Copyright (c) 2024 vinchent <vinchent@vinchent.xyz>
 | 
			
		||||
//
 | 
			
		||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
			
		||||
// of this software and associated documentation files (the "Software"), to deal
 | 
			
		||||
// in the Software without restriction, including without limitation the rights
 | 
			
		||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
			
		||||
// copies of the Software, and to permit persons to whom the Software is
 | 
			
		||||
// furnished to do so, subject to the following conditions:
 | 
			
		||||
//
 | 
			
		||||
// The above copyright notice and this permission notice shall be included in all
 | 
			
		||||
// copies or substantial portions of the Software.
 | 
			
		||||
//
 | 
			
		||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
			
		||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | 
			
		||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
			
		||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
			
		||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 | 
			
		||||
// SOFTWARE.
 | 
			
		||||
 | 
			
		||||
package log
 | 
			
		||||
 | 
			
		||||
// Options define the logger options
 | 
			
		||||
type Options struct {
 | 
			
		||||
	Level             string
 | 
			
		||||
	Development       bool
 | 
			
		||||
	DisableCaller     bool
 | 
			
		||||
	DisableStacktrace bool
 | 
			
		||||
	Format            string
 | 
			
		||||
	OutputPaths       []string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewOptions() *Options {
 | 
			
		||||
	return &Options{
 | 
			
		||||
		Level:             "debug",
 | 
			
		||||
		Development:       true,
 | 
			
		||||
		DisableCaller:     false,
 | 
			
		||||
		DisableStacktrace: false,
 | 
			
		||||
		Format:            "console",
 | 
			
		||||
		OutputPaths: []string{
 | 
			
		||||
			"stderr",
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user