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  }