aboutsummaryrefslogtreecommitdiff
path: root/logger
diff options
context:
space:
mode:
Diffstat (limited to 'logger')
-rw-r--r--logger/log.go131
1 files changed, 131 insertions, 0 deletions
diff --git a/logger/log.go b/logger/log.go
new file mode 100644
index 0000000..a47d27d
--- /dev/null
+++ b/logger/log.go
@@ -0,0 +1,131 @@
+// SPDX-FileCopyrightText: 2020 Ethel Morgan
+//
+// SPDX-License-Identifier: MIT
+
+package logger
+
+import (
+ "context"
+ "fmt"
+ "sync"
+
+ log "github.com/sirupsen/logrus"
+)
+
+type (
+ // log, ctx := logger.FromContext(ctx)
+ // log.WithField("error", err).Warninging(...)
+ // log.AddField("transport", udn)
+ // log.Info(...)
+ Logger interface {
+ // AddField adds a field to the current logger.
+ AddField(name string, value interface{})
+
+ // WithField forks a logger, adding context.
+ WithField(name string, value interface{}) Logger
+
+ // WithError is a convenience method for one-off forks to log error messages under the key "error".
+ WithError(err error) Logger
+
+ // Fork returns a copy of the Logger and a fork of the context.Context to pass through.
+ Fork(context.Context) (Logger, context.Context)
+
+ Debug(string)
+ Info(string)
+ Warning(string)
+ Error(string)
+ Fatal(string)
+ }
+
+ logger struct {
+ mu sync.Mutex
+ values map[string]interface{}
+ }
+
+ // contextKey is a separate type to prevent collisions with other packages.
+ contextKey int
+)
+
+const (
+ loggerKey contextKey = iota
+)
+
+func FromContext(ctx context.Context) (Logger, context.Context) {
+ maybeLogger := ctx.Value(loggerKey)
+
+ if maybeLogger == nil {
+ l := Background()
+ return l, context.WithValue(ctx, loggerKey, l)
+ }
+
+ if l, ok := maybeLogger.(*logger); ok {
+ return l, ctx
+ }
+
+ panic(fmt.Sprintf("expected logger in context, found %+v", maybeLogger))
+}
+func Background() Logger {
+ return &logger{
+ values: map[string]interface{}{},
+ }
+}
+
+func (l *logger) AddField(name string, value interface{}) {
+ l.mu.Lock()
+ defer l.mu.Unlock()
+
+ // TODO: check it doesn't exist already?
+ l.values[name] = value
+}
+func (l *logger) WithField(name string, value interface{}) Logger {
+ clone, _ := l.Fork(context.Background())
+ clone.AddField(name, value)
+ return clone
+}
+func (l *logger) WithError(err error) Logger {
+ return l.WithField("error", err)
+}
+
+func (l *logger) Fork(ctx context.Context) (Logger, context.Context) {
+ l.mu.Lock()
+ defer l.mu.Unlock()
+
+ clone := &logger{
+ values: map[string]interface{}{},
+ }
+ for k, v := range l.values {
+ clone.values[k] = v
+ }
+ return clone, context.WithValue(ctx, loggerKey, clone)
+}
+
+func (l *logger) Debug(message string) {
+ l.mu.Lock()
+ defer l.mu.Unlock()
+
+ log.WithFields(log.Fields(l.values)).Debug(message)
+}
+func (l *logger) Info(message string) {
+ l.mu.Lock()
+ defer l.mu.Unlock()
+
+ log.WithFields(log.Fields(l.values)).Info(message)
+}
+func (l *logger) Warning(message string) {
+ l.mu.Lock()
+ defer l.mu.Unlock()
+
+ log.WithFields(log.Fields(l.values)).Warning(message)
+}
+func (l *logger) Error(message string) {
+ l.mu.Lock()
+ defer l.mu.Unlock()
+
+ log.WithFields(log.Fields(l.values)).Error(message)
+}
+func (l *logger) Fatal(message string) {
+ l.mu.Lock()
+ defer l.mu.Unlock()
+
+ log.WithFields(log.Fields(l.values)).Fatal(message)
+}