98 lines
2.4 KiB
Go
98 lines
2.4 KiB
Go
package hlog
|
|
|
|
import (
|
|
"io"
|
|
"os"
|
|
|
|
"github.com/pkg/errors"
|
|
"github.com/rs/zerolog"
|
|
"github.com/rs/zerolog/pkgerrors"
|
|
)
|
|
|
|
// Logger wraps a zerolog.Logger and manages an optional log file.
|
|
// It embeds *zerolog.Logger, so all zerolog methods are available directly.
|
|
type Logger struct {
|
|
*zerolog.Logger
|
|
logFile *os.File
|
|
}
|
|
|
|
// NewLogger creates a new Logger instance based on the provided configuration.
|
|
//
|
|
// The logger output depends on cfg.LogOutput:
|
|
// - "console": Logs to the provided io.Writer w
|
|
// - "file": Logs to a file in cfg.LogDir (w can be nil)
|
|
// - "both": Logs to both the io.Writer and a file
|
|
//
|
|
// When file logging is enabled, cfg.LogDir must be set to a valid directory path.
|
|
// The log file will be named "server.log" and placed in that directory.
|
|
//
|
|
// The logger is configured with:
|
|
// - Unix timestamp format
|
|
// - Error stack trace marshaling
|
|
// - Log level from cfg.LogLevel
|
|
//
|
|
// Returns an error if:
|
|
// - cfg is nil
|
|
// - w is nil when cfg.LogOutput is not "file"
|
|
// - cfg.LogDir is empty when file logging is enabled
|
|
// - cfg.LogFileName is empty when file logging is enabled
|
|
// - The log file cannot be created
|
|
func NewLogger(
|
|
cfg *Config,
|
|
w io.Writer,
|
|
) (*Logger, error) {
|
|
if cfg == nil {
|
|
return nil, errors.New("No config provided")
|
|
}
|
|
if w == nil && cfg.LogOutput != "file" {
|
|
return nil, errors.New("No Writer provided for log output.")
|
|
}
|
|
|
|
zerolog.TimeFieldFormat = zerolog.TimeFormatUnix
|
|
zerolog.ErrorStackMarshaler = pkgerrors.MarshalStack
|
|
|
|
var consoleWriter zerolog.ConsoleWriter
|
|
if w != nil {
|
|
consoleWriter = zerolog.ConsoleWriter{Out: w}
|
|
}
|
|
|
|
var logFile *os.File
|
|
var err error
|
|
if cfg.LogOutput == "file" || cfg.LogOutput == "both" {
|
|
if cfg.LogDir == "" {
|
|
return nil, errors.New("LOG_DIR must be set when LOG_OUTPUT is 'file' or 'both'")
|
|
}
|
|
if cfg.LogFileName == "" {
|
|
return nil, errors.New("LOG_FILE_NAME must be set when LOG_OUTPUT is 'file' or 'both'")
|
|
}
|
|
logFile, err = newLogFile(cfg.LogDir, cfg.LogFileName, cfg.LogAppend)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "newLogFile")
|
|
}
|
|
}
|
|
|
|
var output io.Writer
|
|
if logFile != nil {
|
|
if w != nil {
|
|
output = zerolog.MultiLevelWriter(logFile, consoleWriter)
|
|
} else {
|
|
output = logFile
|
|
}
|
|
} else {
|
|
output = consoleWriter
|
|
}
|
|
|
|
logger := zerolog.New(output).
|
|
With().
|
|
Timestamp().
|
|
Logger().
|
|
Level(cfg.LogLevel)
|
|
|
|
hlog := &Logger{
|
|
Logger: &logger,
|
|
logFile: logFile,
|
|
}
|
|
|
|
return hlog, nil
|
|
}
|