Documentation ¶
Overview ¶
This module makes it easy to register a Span (and associated Trace) in GCP (Google Cloud Platform) CloudTrace (API v2).
References to "ct2." refer to items imported from the "google.golang.org/api/cloudtrace/v2" module. References to "lager." refer to items imported from "github.com/TyeMcQueen/go-lager". "spans." refers to "github.com/TyeMcQueen/go-lager/gcp-spans".
Index ¶
- Constants
- func ContextPushSpan(ctx context.Context, name string) (context.Context, spans.Factory)
- func EnvInteger(tacit int, envvar string) int
- func NewSpanID(oldSpanID uint64) (spanID uint64)
- func NewTraceID(oldTraceID string) string
- func PushSpan(pReq **http.Request, pCtx *context.Context, name string) spans.Factory
- func RequestPushSpan(req *http.Request, ctx context.Context, name string) (*http.Request, context.Context, spans.Factory)
- func StartServer(pCtx *context.Context, runners int, pRegs ...**Registrar) func()
- func TimeAsString(when time.Time) string
- type Client
- type Registrar
- type Span
- func (s *Span) AddAttribute(key string, val interface{}) error
- func (s *Span) AddPairs(pairs ...interface{}) spans.Factory
- func (s *Span) Finish() time.Duration
- func (s Span) GetDuration() time.Duration
- func (s Span) GetStart() time.Time
- func (s Span) Import(traceID string, spanID uint64) (spans.Factory, error)
- func (s Span) ImportFromHeaders(headers http.Header) spans.Factory
- func (s *Span) NewSpan() spans.Factory
- func (s *Span) NewSubSpan() spans.Factory
- func (s Span) NewTrace() spans.Factory
- func (s *Span) SetDisplayName(desc string) spans.Factory
- func (s *Span) SetIsClient() spans.Factory
- func (s *Span) SetIsPublisher() spans.Factory
- func (s *Span) SetIsServer() spans.Factory
- func (s *Span) SetIsSubscriber() spans.Factory
- func (s *Span) SetStatusCode(code int64) spans.Factory
- func (s *Span) SetStatusMessage(msg string) spans.Factory
- type Stringer
Constants ¶
const ZuluTime = "2006-01-02T15:04:05.999999Z"
Variables ¶
This section is empty.
Functions ¶
func ContextPushSpan ¶ added in v0.3.5
ContextPushSpan() takes a Context which should already be decorated with a span Factory [see spans.ContextStoreSpan()]. If so, it calls NewSpan() on that span, calls 'SetDisplayName(name)' on the new child span, and returns both a Context (decorated with the new span) and the new span.
If not, it logs the lack of a span in the Context (including a stack trace) and returns an empty Factory that is mostly useless other than not being 'nil' (and the original Context).
Example usage:
ctx2, span := trace.ContextPushSpan(ctx, "span.name") defer span.Finish()
If you do not need to retain access to the prior 'ctx', then you may want to use PushSpan() instead.
func EnvInteger ¶ added in v0.3.5
func NewSpanID ¶
NewSpanID() just generates a random uint64 value. You are never expected to call this directly. It prefers to use cryptographically strong random values but will resort to math/rand.Uint64() if that fails. Such a failure will be logged via lager.Warn() only once but the attempt is always made.
func NewTraceID ¶
NewTraceID() returns a new trace ID that can be used with GCP CloudTrace. It is just a randomly generated sequence of 32 hexadecimal digits. You are not expected to call this directly.
If 'oldTraceID' is a valid trace ID, then it is used to add more randomness to the new trace ID (and can't return that same trace ID).
func PushSpan ¶ added in v0.3.5
PushSpan() takes pointers to an *http.Request and to a Context and takes a name to give to a new span. If 'pCtx' or '*pCtx' is 'nil', then '(*pReq).Context()' is used. If 'pReq' or '*pReq' is also 'nil' or the Context is not decorated [see spans.ContextStoreSpan()] with a Factory, then the lack of a span is logged (with a stack trace) and an empty Factory that is mostly useless other than not being 'nil'.
Otherwise, it calls 'NewSpan().SetDisplayName(name)' on the span and returns the new span. If 'pCtx' is not 'nil', then '*pCtx' is set to a copy of the Context decorated with the new span. If 'pReq' and '*pReq' are not 'nil', then '*pReq' is set to a *shallow* copy of '*pReq' (with the new Context).
Example usage:
defer trace.PushSpan(&req, &ctx, "span.name").AddPairs( "user", user, ).Finish()
func RequestPushSpan ¶ added in v0.3.5
func RequestPushSpan( req *http.Request, ctx context.Context, name string, ) (*http.Request, context.Context, spans.Factory)
RequestPushSpan() takes an *http.Request and a Context which should already be decorated with a span Factory [see spans.ContextStoreSpan()]. If so, it calls NewSpan() on that span, calls 'SetDisplayName(name)' on the new child span, and returns (in reverse order) the new span, a copy of the Context decorated with the new span, and a *deep* copy of the Request (with the new Context).
If not, it logs the lack of a span in the Context (including a stack trace) and returns an empty Factory that is mostly useless other than not being 'nil' along with the original Context and a *deep* copy of the original Request (with the original Context).
Passing in a separate Context can allow you to avoid making yet another (shallow) copy of the Request by calling 'req.WithContext(ctx)'. If you pass in 'ctx' as 'nil', then 'req.Context()' is used.
Example usage:
// req2 is a *deep* copy to avoid simultaneous access to 'req' req2, ctx2, span := trace.RequestPushSpan(req, ctx, "span.name") go func() { defer span.Finish() resp, err := transport.RoundTrip(req2) ... }() resp, err := transport.RoundTrip(req) ...
If you do not need a *deep* copy to be made, then you may want to use PushSpan() instead (you can save the value of the prior Request and/or Context before you call it, if needed).
func StartServer ¶
StartServer() is the simplest start-up code to include in a server to enable GCP-based tracing, usually called like:
ctx := context.Background() defer trace.StartServer(&ctx, 1)() // Have 'ctx' returned by the http.Server.BaseContext func.
This assumes that the calling function will not exit until the server is shutting down.
You can also add an extra argument that is a pointer to a variable of type '*Registrar' to have that variable set to the span Registrar (mostly useful when testing).
func TimeAsString ¶ added in v0.3.5
Types ¶
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
See NewClient().
func MustNewClient ¶
MustNewClient() calls NewClient(). If that fails, then lager.Exit() is used to log the error and abort the process.
func NewClient ¶
NewClient() creates a new client capable of registering Spans in the GCP CloudTrace API v2. This client has no methods but should be passed in when starting the Registrar.
To get a default connection, pass in 'nil' for 'svc'. Otherwise you can use ct2.NewService() or ct2.New() to create a base service to use and pass the result in as 'svc'.
If 'svc' is 'nil', then 'ctx' is the Context used when creating the base service using default options. If 'svc' is not 'nil', then 'ctx' is ignored.
type Registrar ¶
type Registrar struct {
// contains filtered or unexported fields
}
Registrar is mostly just an object to use to Halt() the registration runners that got started when you created the Registrar.
It also can create an empty spans.Factory that can be used to create and manipulate spans.
func MustNewRegistrar ¶
MustNewRegistrar() calls NewRegistrar() and, if that fails, uses lager.Exit() to abort the process.
func NewRegistrar ¶
NewRegistrar() starts a number of go-routines (given by 'runners') that wait to receive Finish()ed Spans and then register them with GCP Cloud Trace.
func (*Registrar) Halt ¶
func (r *Registrar) Halt()
Halt() tells the runners to terminate and waits for them all to finish before returning.
Halt() should only be called after you are sure that no more spans will be Finish()ed. Any spans Finish()ed after Halt() has been called may cause a panic(). Not waiting for Halt() to return can mean that recently Finish()ed spans might not be registered.
func (*Registrar) NewFactory ¶
func (r *Registrar) NewFactory() spans.Factory
NewFactory() returns a spans.Factory that can be used to create and manipulate spans and eventually register them with GCP Cloud Trace.
func (*Registrar) WaitForIdleRunners ¶ added in v0.3.5
func (r *Registrar) WaitForIdleRunners()
WaitForIdleRunners() is only meant to be used by tests. It allows you to ensure that all prior Finish()ed Spans have been processed so the test can check for any errors that were logged.
It works by sending one request per runner that will cause that runner to wait when it receives it. Then it reads the responses from all of the runners (which ends their waiting) and then returns.
type Span ¶
type Span struct { spans.ROSpan // contains filtered or unexported fields }
Span tracks a span inside of a trace and can be used to create new child spans within it. It also registers the span with GCP when Finish() is called on it [unless it was created via Import()].
A Span object is expected to be modified only from a single goroutine and so no locking is implemented. Creation of sub-spans does implement locking so that multiple go routines can safely create sub-spans from the same span without additional locking.
func (*Span) AddAttribute ¶
AddAttribute() adds an attribute key/value pair to the contained span. Does nothing except log a failure with a stack trace if the Factory is empty or Import()ed (even returning a 'nil' error).
'val' can be a 'string', 'int64', or a 'bool'. 'int' values will be promoted to 'int64'. Other values that have a String() or an Error() method will have that method used to convert them to a string. If 'key' is empty or 'val' is not one of the listed types, then an error is returned and the attribute is not added.
func (*Span) AddPairs ¶ added in v0.3.5
func (s *Span) AddPairs(pairs ...interface{}) spans.Factory
AddPairs() takes a list of attribute key/value pairs. For each pair, AddAttribute() is called and any returned error is logged (including a reference to the line of code that called AddPairs). Always returns the calling Factory so further method calls can be chained.
AddPairs() silently ignores 'zero' values except "" ('0', 'false', 'nil') rather than either logging an error or adding them only to have the value show up as "undefined".
Does nothing except log a single failure with a stack trace if the Factory is empty or Import()ed.
func (*Span) Finish ¶
Finish() notifies the Factory that the contained span is finished. The Factory will be read-only (as if empty) afterward. The Factory will arrange for the span to be registered.
The returned value is the duration of the span's life. If the Factory was already empty or the contained span was Import()ed, then a failure with a stack trace is logged and a 0 duration is returned.
func (Span) GetDuration ¶ added in v0.3.5
GetDuration() returns a negative duration if the Factory is empty or if the span has not been Finish()ed yet. Otherwise, it returns the span's duration.
func (Span) GetStart ¶
GetStart() returns the time at which the span began. Returns a zero time if the Factory is empty or the contained span was Import()ed.
func (Span) Import ¶
Import() returns a new Factory containing a span created somewhere else. If the traceID or spanID is invalid, then a 'nil' Factory and an error are returned. The usual reason to do this is so that you can then call NewSubSpan().
func (Span) ImportFromHeaders ¶
ImportFromHeaders() returns a new Factory containing a span created somewhere else based on the "X-Cloud-Trace-Context:" header. If the header does not contain a valid CloudContext value, then a valid but empty Factory is returned.
func (*Span) NewSpan ¶
func (s *Span) NewSpan() spans.Factory
NewSpan() returns a new Factory holding a new span; either NewTrace() or NewSubSpan(), depending on whether the invoking Factory is empty.
func (*Span) NewSubSpan ¶
func (s *Span) NewSubSpan() spans.Factory
NewSubSpan() returns a new Factory holding a new span that is a sub-span of the span contained in the invoking Factory. If the invoking Factory was empty, then a failure with a stack trace is logged and the empty Factory is returned.
NewSubSpan() locks the calling span so that you can safely call NewSubSpan() on the same parent span from multiple go routines.
func (Span) NewTrace ¶
func (s Span) NewTrace() spans.Factory
NewTrace() returns a new Factory holding a new span, part of a new trace. Any span held in the invoking Factory is ignored.
func (*Span) SetDisplayName ¶
SetDisplayName() sets the display name on the contained span. Does nothing except log a failure with a stack trace if the Factory is empty or Import()ed. Always returns the calling Factory so further method calls can be chained.
func (*Span) SetIsClient ¶
func (s *Span) SetIsClient() spans.Factory
Sets the span kind to "CLIENT". Does nothing except log a failure with a stack trace if the Factory is empty or Import()ed. Always returns the calling Factory so further method calls can be chained.
func (*Span) SetIsPublisher ¶
func (s *Span) SetIsPublisher() spans.Factory
Sets the span kind to "PRODUCER". Does nothing except log a failure with a stack trace if the Factory is empty or Import()ed. Always returns the calling Factory so further method calls can be chained.
func (*Span) SetIsServer ¶
func (s *Span) SetIsServer() spans.Factory
Sets the span kind to "SERVER". Does nothing except log a failure with a stack trace if the Factory is empty or Import()ed. Always returns the calling Factory so further method calls can be chained.
func (*Span) SetIsSubscriber ¶
func (s *Span) SetIsSubscriber() spans.Factory
Sets the span kind to "CONSUMER". Does nothing except log a failure with a stack trace if the Factory is empty or Import()ed. Always returns the calling Factory so further method calls can be chained.
func (*Span) SetStatusCode ¶
SetStatusCode() sets the status code on the contained span. 'code' is expected to be a value from google.golang.org/genproto/googleapis/rpc/code but this is not verified. HTTP status codes are also understood by the library. Does nothing except log a failure with a stack trace if the Factory is empty or Import()ed. Always returns the calling Factory so further method calls can be chained.
func (*Span) SetStatusMessage ¶
SetStatusMessage() sets the status message string on the contained span. By convention, only a failure should set a status message. Does nothing except log a failure with a stack trace if the Factory is empty or Import()ed. Always returns the calling Factory so further method calls can be chained.