github.com/nya3jp/tast@v0.0.0-20230601000426-85c8e4d83a9b/src/go.chromium.org/tast/core/internal/logging/context.go (about) 1 // Copyright 2021 The ChromiumOS Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 package logging 6 7 import ( 8 "context" 9 "fmt" 10 "time" 11 ) 12 13 // loggerKey is the type of the key used for attaching a Logger to a 14 // context.Context. 15 type loggerKey struct{} 16 17 // AttachLogger creates a new context with logger attached. Logs emitted via 18 // the new context are propagated to the parent context. 19 func AttachLogger(ctx context.Context, logger Logger) context.Context { 20 if parent, ok := loggerFromContext(ctx); ok { 21 logger = NewMultiLogger(logger, parent) 22 } 23 return context.WithValue(ctx, loggerKey{}, logger) 24 } 25 26 // AttachLoggerNoPropagation creates a new context with logger attached. In 27 // contrast to AttachLogger, logs emitted via the new context are not propagated 28 // to the parent context. 29 func AttachLoggerNoPropagation(ctx context.Context, logger Logger) context.Context { 30 return context.WithValue(ctx, loggerKey{}, logger) 31 } 32 33 // HasLogger checks if any logger is attached to ctx. 34 func HasLogger(ctx context.Context) bool { 35 _, ok := loggerFromContext(ctx) 36 return ok 37 } 38 39 // loggerFromContext extracts a logger from a context. 40 // This function is unexported so that users cannot extract a logger from 41 // contexts. If you need to access a logger after associating it to a context, 42 // pass the logger explicitly to functions. 43 func loggerFromContext(ctx context.Context) (Logger, bool) { 44 logger, ok := ctx.Value(loggerKey{}).(Logger) 45 return logger, ok 46 } 47 48 // Info emits a log with info level. 49 func Info(ctx context.Context, args ...interface{}) { 50 log(ctx, LevelInfo, args...) 51 } 52 53 // Infof is similar to Info but formats its arguments using fmt.Sprintf. 54 func Infof(ctx context.Context, format string, args ...interface{}) { 55 logf(ctx, LevelInfo, format, args...) 56 } 57 58 // Debug emits a log with debug level. 59 func Debug(ctx context.Context, args ...interface{}) { 60 log(ctx, LevelDebug, args...) 61 } 62 63 // Debugf is similar to Debug but formats its arguments using fmt.Sprintf. 64 func Debugf(ctx context.Context, format string, args ...interface{}) { 65 logf(ctx, LevelDebug, format, args...) 66 } 67 68 func log(ctx context.Context, level Level, args ...interface{}) { 69 ts := time.Now() // get the time as early as possible 70 logger, ok := loggerFromContext(ctx) 71 if !ok { 72 return 73 } 74 logger.Log(level, ts, fmt.Sprint(args...)) 75 } 76 77 func logf(ctx context.Context, level Level, format string, args ...interface{}) { 78 ts := time.Now() // get the time as early as possible 79 logger, ok := loggerFromContext(ctx) 80 if !ok { 81 return 82 } 83 logger.Log(level, ts, fmt.Sprintf(format, args...)) 84 }