context

package module
v0.0.0-...-798504f Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 16, 2016 License: Apache-2.0 Imports: 8 Imported by: 1

README

context

Build Status GoDoc Coverage Status

Context helpers inspired by https://godoc.org/github.com/docker/distribution/context.

Documentation

Differences:

  1. Package github.com/satori/go.uuid used for uuid generation instead of github.com/docker/distribution/uuid
  2. Package github.com/apex/log used to log instead of github.com/Sirupsen/logrus
  3. gorilla mux extracted because I don't need it.

Documentation

Overview

Package context provides several utilities for working with golang.org/x/net/context in http requests. Primarily, the focus is on logging relevant request information but this package is not limited to that purpose.

The easiest way to get started is to get the background context:

ctx := context.Background()

The returned context should be passed around your application and be the root of all other context instances. If the application has a version, this line should be called before anything else:

ctx := context.WithVersion(context.Background(), version)

The above will store the version in the context and will be available to the logger.

Logging

The most useful aspect of this package is GetLogger. This function takes any context.Context interface and returns the current logger from the context. Canonical usage looks like this:

GetLogger(ctx).Infof("something interesting happened")

GetLogger also takes optional key arguments. The keys will be looked up in the context and reported with the logger. The following example would return a logger that prints the version with each log message:

ctx := context.Context(context.Background(), "version", version)
GetLogger(ctx, "version").Infof("this log message has a version field")

The above would print out a log message like this:

INFO[0000] this log message has a version field        version=v2.0.0-alpha.2.m

When used with WithLogger, we gain the ability to decorate the context with loggers that have information from disparate parts of the call stack. Following from the version example, we can build a new context with the configured logger such that we always print the version field:

ctx = WithLogger(ctx, GetLogger(ctx, "version"))

Since the logger has been pushed to the context, we can now get the version field for free with our log messages. Future calls to GetLogger on the new context will have the version field:

GetLogger(ctx).Infof("this log message has a version field")

This becomes more powerful when we start stacking loggers. Let's say we have the version logger from above but also want a request id. Using the context above, in our request scoped function, we place another logger in the context:

ctx = context.WithValue(ctx, "http.request.id", "unique id") // called when building request context
ctx = WithLogger(ctx, GetLogger(ctx, "http.request.id"))

When GetLogger is called on the new context, "http.request.id" will be included as a logger field, along with the original "version" field:

INFO[0000] this log message has a version field        http.request.id=unique id version=v2.0.0-alpha.2.m

Note that this only affects the new context, the previous context, with the version field, can be used independently. Put another way, the new logger, added to the request context, is unique to that context and can have request scoped varaibles.

HTTP Requests

This package also contains several methods for working with http requests. The concepts are very similar to those described above. We simply place the request in the context using WithRequest. This makes the request variables available. GetRequestLogger can then be called to get request specific variables in a log line:

ctx = WithRequest(ctx, req)
GetRequestLogger(ctx).Infof("request variables")

Like above, if we want to include the request data in all log messages in the context, we push the logger to a new context and use that one:

ctx = WithLogger(ctx, GetRequestLogger(ctx))

The concept is fairly powerful and ensures that calls throughout the stack can be traced in log messages. Using the fields like "http.request.id", one can analyze call flow for a particular request with a simple grep of the logs.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Background

func Background() context.Context

Background returns a non-nil, empty Context. The background context provides a single key, "instance.id" that is globally unique to the process.

func GetStringValue

func GetStringValue(ctx context.Context, key interface{}) (value string)

GetStringValue returns a string value from the context. The empty string will be returned if not found.

func GetVersion

func GetVersion(ctx context.Context) string

GetVersion returns the application version from the context. An empty string may returned if the version was not set on the context.

func Since

func Since(ctx context.Context, key interface{}) time.Duration

Since looks up key, which should be a time.Time, and returns the duration since that time. If the key is not found, the value returned will be zero. This is helpful when inferring metrics related to context execution times.

func WithLogger

func WithLogger(ctx context.Context, logger Logger) context.Context

WithLogger creates a new context with provided logger.

func WithTrace

func WithTrace(ctx context.Context) (context.Context, func(format string, a ...interface{}))

WithTrace allocates a traced timing span in a new context. This allows a caller to track the time between calling WithTrace and the returned done function. When the done function is called, a log message is emitted with a "trace.duration" field, corresponding to the elapsed time and a "trace.func" field, corresponding to the function that called WithTrace.

The logging keys "trace.id" and "trace.parent.id" are provided to implement dapper-like tracing. This function should be complemented with a WithSpan method that could be used for tracing distributed RPC calls.

The main benefit of this function is to post-process log messages or intercept them in a hook to provide timing data. Trace ids and parent ids can also be linked to provide call tracing, if so required.

Here is an example of the usage:

func timedOperation(ctx Context) {
	ctx, done := WithTrace(ctx)
	defer done("this will be the log message")
	// ... function body ...
}

If the function ran for roughly 1s, such a usage would emit a log message as follows:

INFO[0001] this will be the log message  trace.duration=1.004575763s trace.func=github.com/docker/distribution/context.traceOperation trace.id=<id> ...

Notice that the function name is automatically resolved, along with the package and a trace id is emitted that can be linked with parent ids.

func WithValue

func WithValue(parent context.Context, key, val interface{}) context.Context

WithValue returns a copy of parent in which the value associated with key is val. Use context Values only for request-scoped data that transits processes and APIs, not for passing optional parameters to functions.

func WithValues

func WithValues(ctx context.Context, m map[string]interface{}) context.Context

WithValues returns a context that proxies lookups through a map. Only supports string keys.

func WithVersion

func WithVersion(ctx context.Context, version string) context.Context

WithVersion stores the application version in the context. The new context gets a logger to ensure log messages are marked with the application version.

Types

type Logger

type Logger interface {
	log.Interface
}

Logger provides a leveled-logging interface.

func GetLogger

func GetLogger(ctx context.Context, keys ...interface{}) Logger

GetLogger returns the logger from the current context, if present. If one or more keys are provided, they will be resolved on the context and included in the logger. While context.Value takes an interface, any key argument passed to GetLogger will be passed to fmt.Sprint when expanded as a logging key field. If context keys are integer constants, for example, its recommended that a String method is implemented.

func GetLoggerWithField

func GetLoggerWithField(ctx context.Context, key, value interface{}, keys ...interface{}) Logger

GetLoggerWithField returns a logger instance with the specified field key and value without affecting the context. Extra specified keys will be resolved from the context.

func GetLoggerWithFields

func GetLoggerWithFields(ctx context.Context, fields map[interface{}]interface{}, keys ...interface{}) Logger

GetLoggerWithFields returns a logger instance with the specified fields without affecting the context. Extra specified keys will be resolved from the context.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL