2015-02-05 21:56:50 +00:00
|
|
|
// Package context provides several utilities for working with
|
2018-01-18 00:01:41 +00:00
|
|
|
// Go's context in http requests. Primarily, the focus is on logging relevant
|
|
|
|
// request information but this package is not limited to that purpose.
|
2015-02-05 21:56:50 +00:00
|
|
|
//
|
2015-09-11 03:41:58 +00:00
|
|
|
// The easiest way to get started is to get the background context:
|
|
|
|
//
|
2022-11-02 21:05:45 +00:00
|
|
|
// ctx := context.Background()
|
2015-09-11 03:41:58 +00:00
|
|
|
//
|
|
|
|
// 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:
|
|
|
|
//
|
2022-11-02 21:05:45 +00:00
|
|
|
// ctx := context.WithVersion(context.Background(), version)
|
2015-09-11 03:41:58 +00:00
|
|
|
//
|
|
|
|
// The above will store the version in the context and will be available to
|
|
|
|
// the logger.
|
|
|
|
//
|
2022-11-02 21:05:45 +00:00
|
|
|
// # Logging
|
2015-02-05 21:56:50 +00:00
|
|
|
//
|
|
|
|
// 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:
|
|
|
|
//
|
2022-11-02 21:05:45 +00:00
|
|
|
// GetLogger(ctx).Infof("something interesting happened")
|
2015-02-05 21:56:50 +00:00
|
|
|
//
|
|
|
|
// 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:
|
|
|
|
//
|
2022-11-02 21:05:45 +00:00
|
|
|
// ctx := context.Context(context.Background(), "version", version)
|
|
|
|
// GetLogger(ctx, "version").Infof("this log message has a version field")
|
2015-02-05 21:56:50 +00:00
|
|
|
//
|
|
|
|
// The above would print out a log message like this:
|
|
|
|
//
|
2022-11-02 21:05:45 +00:00
|
|
|
// INFO[0000] this log message has a version field version=v2.0.0-alpha.2.m
|
2015-02-05 21:56:50 +00:00
|
|
|
//
|
|
|
|
// 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:
|
|
|
|
//
|
2022-11-02 21:05:45 +00:00
|
|
|
// ctx = WithLogger(ctx, GetLogger(ctx, "version"))
|
2015-02-05 21:56:50 +00:00
|
|
|
//
|
|
|
|
// 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:
|
|
|
|
//
|
2022-11-02 21:05:45 +00:00
|
|
|
// GetLogger(ctx).Infof("this log message has a version field")
|
2015-02-05 21:56:50 +00:00
|
|
|
//
|
|
|
|
// 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:
|
|
|
|
//
|
2022-11-02 21:05:45 +00:00
|
|
|
// ctx = context.WithValue(ctx, "http.request.id", "unique id") // called when building request context
|
|
|
|
// ctx = WithLogger(ctx, GetLogger(ctx, "http.request.id"))
|
2015-02-05 21:56:50 +00:00
|
|
|
//
|
|
|
|
// When GetLogger is called on the new context, "http.request.id" will be
|
|
|
|
// included as a logger field, along with the original "version" field:
|
|
|
|
//
|
2022-11-02 21:05:45 +00:00
|
|
|
// INFO[0000] this log message has a version field http.request.id=unique id version=v2.0.0-alpha.2.m
|
2015-02-05 21:56:50 +00:00
|
|
|
//
|
|
|
|
// 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
|
2017-02-27 06:06:18 +00:00
|
|
|
// request scoped variables.
|
2015-02-05 21:56:50 +00:00
|
|
|
//
|
2022-11-02 21:05:45 +00:00
|
|
|
// # HTTP Requests
|
2015-02-05 21:56:50 +00:00
|
|
|
//
|
|
|
|
// 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:
|
|
|
|
//
|
2022-11-02 21:05:45 +00:00
|
|
|
// ctx = WithRequest(ctx, req)
|
|
|
|
// GetRequestLogger(ctx).Infof("request variables")
|
2015-02-05 21:56:50 +00:00
|
|
|
//
|
|
|
|
// 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:
|
|
|
|
//
|
2022-11-02 21:05:45 +00:00
|
|
|
// ctx = WithLogger(ctx, GetRequestLogger(ctx))
|
2015-02-05 21:56:50 +00:00
|
|
|
//
|
|
|
|
// 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.
|
|
|
|
package context
|