text: package log
  
  import "errors"
  
  // Logger is the fundamental interface for all log operations. Log creates a
  // log event from keyvals, a variadic sequence of alternating keys and values.
  // Implementations must be safe for concurrent use by multiple goroutines. In
  // particular, any implementation of Logger that appends to keyvals or
  // modifies any of its elements must make a copy first.
  type Logger interface {
  	Log(keyvals ...interface{}) error
  }
  
  // ErrMissingValue is appended to keyvals slices with odd length to substitute
  // the missing value.
  var ErrMissingValue = errors.New("(MISSING)")
  
  // NewContext returns a new Context that logs to logger.
  func NewContext(logger Logger) *Context {
  	if c, ok := logger.(*Context); ok {
  		return c
  	}
  	return &Context{logger: logger}
  }
  
  // Context must always have the same number of stack frames between calls to
  // its Log method and the eventual binding of Valuers to their value. This
  // requirement comes from the functional requirement to allow a context to
  // resolve application call site information for a log.Caller stored in the
  // context. To do this we must be able to predict the number of logging
  // functions on the stack when bindValues is called.
  //
  // Three implementation details provide the needed stack depth consistency.
  // The first two of these details also result in better amortized performance,
  // and thus make sense even without the requirements regarding stack depth.
  // The third detail, however, is subtle and tied to the implementation of the
  // Go compiler.
  //
  //    1. NewContext avoids introducing an additional layer when asked to
  //       wrap another Context.
  //    2. With avoids introducing an additional layer by returning a newly
  //       constructed Context with a merged keyvals rather than simply
  //       wrapping the existing Context.
  //    3. All of Context's methods take pointer receivers even though they
  //       do not mutate the Context.
  //
  // Before explaining the last detail, first some background. The Go compiler
  // generates wrapper methods to implement the auto dereferencing behavior when
  // calling a value method through a pointer variable. These wrapper methods
  // are also used when calling a value method through an interface variable
  // because interfaces store a pointer to the underlying concrete value.
  // Calling a pointer receiver through an interface does not require generating
  // an additional function.
  //
  // If Context had value methods then calling Context.Log through a variable
  // with type Logger would have an extra stack frame compared to calling
  // Context.Log through a variable with type Context. Using pointer receivers
  // avoids this problem.
  
  // A Context wraps a Logger and holds keyvals that it includes in all log
  // events. When logging, a Context replaces all value elements (odd indexes)
  // containing a Valuer with their generated value for each call to its Log
  // method.
  type Context struct {
  	logger    Logger
  	keyvals   []interface{}
  	hasValuer bool
  }
  
  // Log replaces all value elements (odd indexes) containing a Valuer in the
  // stored context with their generated value, appends keyvals, and passes the
  // result to the wrapped Logger.
  func (l *Context) Log(keyvals ...interface{}) error {
  	kvs := append(l.keyvals, keyvals...)
  	if len(kvs)%2 != 0 {
  		kvs = append(kvs, ErrMissingValue)
  	}
  	if l.hasValuer {
  		// If no keyvals were appended above then we must copy l.keyvals so
  		// that future log events will reevaluate the stored Valuers.
  		if len(keyvals) == 0 {
  			kvs = append([]interface{}{}, l.keyvals...)
  		}
  		bindValues(kvs[:len(l.keyvals)])
  	}
  	return l.logger.Log(kvs...)
  }
  
  // With returns a new Context with keyvals appended to those of the receiver.
  func (l *Context) With(keyvals ...interface{}) *Context {
  	if len(keyvals) == 0 {
  		return l
  	}
  	kvs := append(l.keyvals, keyvals...)
  	if len(kvs)%2 != 0 {
  		kvs = append(kvs, ErrMissingValue)
  	}
  	return &Context{
  		logger: l.logger,
  		// Limiting the capacity of the stored keyvals ensures that a new
  		// backing array is created if the slice must grow in Log or With.
  		// Using the extra capacity without copying risks a data race that
  		// would violate the Logger interface contract.
  		keyvals:   kvs[:len(kvs):len(kvs)],
  		hasValuer: l.hasValuer || containsValuer(keyvals),
  	}
  }
  
  // WithPrefix returns a new Context with keyvals prepended to those of the
  // receiver.
  func (l *Context) WithPrefix(keyvals ...interface{}) *Context {
  	if len(keyvals) == 0 {
  		return l
  	}
  	// Limiting the capacity of the stored keyvals ensures that a new
  	// backing array is created if the slice must grow in Log or With.
  	// Using the extra capacity without copying risks a data race that
  	// would violate the Logger interface contract.
  	n := len(l.keyvals) + len(keyvals)
  	if len(keyvals)%2 != 0 {
  		n++
  	}
  	kvs := make([]interface{}, 0, n)
  	kvs = append(kvs, keyvals...)
  	if len(kvs)%2 != 0 {
  		kvs = append(kvs, ErrMissingValue)
  	}
  	kvs = append(kvs, l.keyvals...)
  	return &Context{
  		logger:    l.logger,
  		keyvals:   kvs,
  		hasValuer: l.hasValuer || containsValuer(keyvals),
  	}
  }
  
  // LoggerFunc is an adapter to allow use of ordinary functions as Loggers. If
  // f is a function with the appropriate signature, LoggerFunc(f) is a Logger
  // object that calls f.
  type LoggerFunc func(...interface{}) error
  
  // Log implements Logger by calling f(keyvals...).
  func (f LoggerFunc) Log(keyvals ...interface{}) error {
  	return f(keyvals...)
  }
  