diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..a063e66 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,30 @@ +# Changelog +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [Unreleased] +### Added +- Nothing + +### Changed +- Nothing + +### Deprecated +- Nothing + +### Removed +- Nothing + +### Fixed +- Nothing + +### Security +- Nothing + +## [1.3.0] - 2019-02-27 +### Added +- `ConfigureDefaultLogger` boilerplate for logger configuration +- `measuredLoggingHandler` to wrap loggers with metrics +- `CHANGELOG.md`: this file diff --git a/configure.go b/configure.go new file mode 100644 index 0000000..9571a59 --- /dev/null +++ b/configure.go @@ -0,0 +1,55 @@ +package log + +import ( + "os" +) + +// Config defines the logging configuration +type Config struct { + Level string `default:"info"` + Output string `default:"stdout"` +} + +// ConfigureDefaultLogger configures loggers for your service, optionally adding log message counters with your favorite +// metrics system +func ConfigureDefaultLogger(name string, cfg Config, logCounters ...CountLogMessage) { + if logLevel, ok := logLevelMap[cfg.Level]; ok { + SetLevel(logLevel) // This sets the default level for all future + DefaultLevel = logLevel + } else { + Warningf("Unknown log level configured: %s", cfg.Level) + } + + var handler Handler = NewFileHandler(getLoggerOutput(cfg.Output)) + + if len(logCounters) > 0 { + handler = &metricsAgentLoggingHandler{ + Handler: handler, + logCounters: logCounters, + } + } + handler.SetFormatter(DefaultFormatter) + + logger := NewLogger(name) + if cfg.Level != logLevelDebug { + logger = NoDebugLogger{ + Logger: logger, + } + } + logger.SetHandler(handler) + + DefaultLogger = logger + Infof("Configured default logger %s with log level %s", name, cfg.Level) +} + +func getLoggerOutput(outputName string) *os.File { + switch outputName { + case "stdout": + return os.Stdout + case "stderr": + return os.Stderr + default: + Warningf("Unknown logger output defined in the config: '%s'", outputName) + return os.Stderr + } +} diff --git a/log.go b/log.go index 665229f..3a19c85 100644 --- a/log.go +++ b/log.go @@ -58,3 +58,29 @@ func Infoln(args ...interface{}) { DefaultLogger.Infoln(args.. func Debug(args ...interface{}) { DefaultLogger.Debug(args...) } func Debugf(format string, args ...interface{}) { DefaultLogger.Debugf(format, args...) } func Debugln(args ...interface{}) { DefaultLogger.Debugln(args...) } + +const ( + logLevelCritical = "critical" + logLevelError = "error" + logLevelWarning = "warning" + logLevelNotice = "notice" + logLevelInfo = "info" + logLevelDebug = "debug" +) + +var logLevelMap = map[string]Level{ + logLevelCritical: CRITICAL, + logLevelError: ERROR, + logLevelWarning: WARNING, + logLevelNotice: NOTICE, + logLevelInfo: INFO, + logLevelDebug: DEBUG, +} + +var logLevelNameMap = make(map[Level]string) + +func init() { + for name, value := range logLevelMap { + logLevelNameMap[value] = name + } +} diff --git a/metrics_logging_handler.go b/metrics_logging_handler.go new file mode 100644 index 0000000..05dab9c --- /dev/null +++ b/metrics_logging_handler.go @@ -0,0 +1,21 @@ +package log + +// CountLogMessage offers a method to count log messages logged by the logger +type CountLogMessage func(level string) + +type metricsAgentLoggingHandler struct { + Handler + logCounters []CountLogMessage +} + +// Handle decorates Handler's Handle method counting the log messages +func (h *metricsAgentLoggingHandler) Handle(record *Record) { + level := "unknown" + if levelName, ok := logLevelNameMap[record.Level]; ok { + level = levelName + } + for _, countLogMessage := range h.logCounters { + countLogMessage(level) + } + h.Handler.Handle(record) +}