X-Git-Url: https://git.arvados.org/arvados.git/blobdiff_plain/ba57b6537679889b42693ecd839a94d59c716aaf..2f66d4cc05e9442a9bb69969744d0750a02a1ed4:/sdk/go/ctxlog/log.go diff --git a/sdk/go/ctxlog/log.go b/sdk/go/ctxlog/log.go index 6565c88f07..acbb11a361 100644 --- a/sdk/go/ctxlog/log.go +++ b/sdk/go/ctxlog/log.go @@ -1,9 +1,16 @@ +// Copyright (C) The Arvados Authors. All rights reserved. +// +// SPDX-License-Identifier: Apache-2.0 + package ctxlog import ( + "bytes" "context" + "io" + "os" - "github.com/Sirupsen/logrus" + "github.com/sirupsen/logrus" ) var ( @@ -15,45 +22,93 @@ const rfc3339NanoFixed = "2006-01-02T15:04:05.000000000Z07:00" // Context returns a new child context such that FromContext(child) // returns the given logger. -func Context(ctx context.Context, logger *logrus.Entry) context.Context { +func Context(ctx context.Context, logger logrus.FieldLogger) context.Context { return context.WithValue(ctx, loggerCtxKey, logger) } // FromContext returns the logger suitable for the given context -- the one // attached by contextWithLogger() if applicable, otherwise the // top-level logger with no fields/values. -func FromContext(ctx context.Context) *logrus.Entry { +func FromContext(ctx context.Context) logrus.FieldLogger { if ctx != nil { - if logger, ok := ctx.Value(loggerCtxKey).(*logrus.Entry); ok { + if logger, ok := ctx.Value(loggerCtxKey).(logrus.FieldLogger); ok { return logger } } return rootLogger.WithFields(nil) } +// New returns a new logger with the indicated format and +// level. +func New(out io.Writer, format, level string) *logrus.Logger { + logger := logrus.New() + logger.Out = out + setFormat(logger, format) + setLevel(logger, level) + return logger +} + +func TestLogger(c interface{ Log(...interface{}) }) *logrus.Logger { + logger := logrus.New() + logger.Out = &logWriter{c.Log} + setFormat(logger, "text") + if d := os.Getenv("ARVADOS_DEBUG"); d != "0" && d != "" { + setLevel(logger, "debug") + } else { + setLevel(logger, "info") + } + return logger +} + +// LogWriter returns an io.Writer that writes to the given log func, +// which is typically (*check.C).Log(). +func LogWriter(log func(...interface{})) io.Writer { + return &logWriter{log} +} + // SetLevel sets the current logging level. See logrus for level // names. func SetLevel(level string) { - lvl, err := logrus.ParseLevel(level) - if err != nil { - logrus.Fatal(err) + setLevel(rootLogger, level) +} + +func setLevel(logger *logrus.Logger, level string) { + if level == "" { + } else if lvl, err := logrus.ParseLevel(level); err != nil { + logrus.WithField("Level", level).Fatal("unknown log level") + } else { + logger.Level = lvl } - rootLogger.Level = lvl } // SetFormat sets the current logging format to "json" or "text". func SetFormat(format string) { + setFormat(rootLogger, format) +} + +func setFormat(logger *logrus.Logger, format string) { switch format { case "text": - rootLogger.Formatter = &logrus.TextFormatter{ + logger.Formatter = &logrus.TextFormatter{ FullTimestamp: true, TimestampFormat: rfc3339NanoFixed, } - case "json": - rootLogger.Formatter = &logrus.JSONFormatter{ + case "json", "": + logger.Formatter = &logrus.JSONFormatter{ TimestampFormat: rfc3339NanoFixed, } default: - logrus.WithField("LogFormat", format).Fatal("unknown log format") + logrus.WithField("Format", format).Fatal("unknown log format") } } + +// logWriter is an io.Writer that writes by calling a "write log" +// function, typically (*check.C)Log(). +type logWriter struct { + logfunc func(...interface{}) +} + +func (tl *logWriter) Write(buf []byte) (int, error) { + tl.logfunc(string(bytes.TrimRight(buf, "\n"))) + return len(buf), nil +}