DataDog and StatsD Metrics Support
* Added support for DataDog and StatsD monitoring * Added documentation
This commit is contained in:
parent
cd28e7b24f
commit
69c628b626
39 changed files with 3921 additions and 13 deletions
144
vendor/github.com/go-kit/kit/log/log.go
generated
vendored
Normal file
144
vendor/github.com/go-kit/kit/log/log.go
generated
vendored
Normal file
|
@ -0,0 +1,144 @@
|
|||
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...)
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue