trace

package
v0.0.0-...-4693a02 Latest Latest
Warning

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

Go to latest
Published: Mar 10, 2024 License: Apache-2.0 Imports: 7 Imported by: 176

README

Trace

This package provides an interface for recording the latency of operations and logging details about all operations where the latency exceeds a limit.

Usage

To create a trace:

func doSomething() {
    opTrace := trace.New("operation", Field{Key: "fieldKey1", Value: "fieldValue1"})
    defer opTrace.LogIfLong(100 * time.Millisecond)
    // do something
}

To split an trace into multiple steps:

func doSomething() {
    opTrace := trace.New("operation")
    defer opTrace.LogIfLong(100 * time.Millisecond)
    // do step 1
    opTrace.Step("step1", Field{Key: "stepFieldKey1", Value: "stepFieldValue1"})
    // do step 2
    opTrace.Step("step2")
}

To nest traces:

func doSomething() {
    rootTrace := trace.New("rootOperation")
    defer rootTrace.LogIfLong(100 * time.Millisecond)
    
    func() {
        nestedTrace := rootTrace.Nest("nested", Field{Key: "nestedFieldKey1", Value: "nestedFieldValue1"})
        defer nestedTrace.LogIfLong(50 * time.Millisecond)
        // do nested operation
    }()
}

Traces can also be logged unconditionally or introspected:

opTrace.TotalTime() // Duration since the Trace was created
opTrace.Log() // unconditionally log the trace
Using context.Context to nest traces

context.Context can be used to manage nested traces. Create traces by calling trace.GetTraceFromContext(ctx).Nest. This is safe even if there is no parent trace already in the context because (*(Trace)nil).Nest() returns a top level trace.

func doSomething(ctx context.Context) {
    opTrace := trace.FromContext(ctx).Nest("operation") // create a trace, possibly nested
    ctx = trace.ContextWithTrace(ctx, opTrace) // make this trace the parent trace of the context
    defer opTrace.LogIfLong(50 * time.Millisecond)
    
    doSomethingElse(ctx)
}

Documentation

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func ContextWithTrace

func ContextWithTrace(ctx context.Context, trace *Trace) context.Context

ContextWithTrace returns a context with trace included in the context values, keyed by ContextTraceKey.

Types

type ContextTraceKey

type ContextTraceKey struct{}

ContextTraceKey provides a common key for traces in context.Context values.

type Field

type Field struct {
	Key   string
	Value interface{}
}

Field is a key value pair that provides additional details about the trace.

type Trace

type Trace struct {
	// contains filtered or unexported fields
}

Trace keeps track of a set of "steps" and allows us to log a specific step if it took longer than its share of the total allowed time

func FromContext

func FromContext(ctx context.Context) *Trace

FromContext returns the trace keyed by ContextTraceKey in the context values, if one is present, or nil If there is no trace in the Context. It is safe to call Nest() on the returned value even if it is nil because ((*Trace)nil).Nest returns a top level trace.

func New

func New(name string, fields ...Field) *Trace

New creates a Trace with the specified name. The name identifies the operation to be traced. The Fields add key value pairs to provide additional details about the trace, such as operation inputs.

func (*Trace) Log

func (t *Trace) Log()

Log is used to dump all the steps in the Trace. It also logs the nested trace messages using indentation. If the Trace is nested it is not immediately logged. Instead, it is logged when the trace it is nested within is logged.

func (*Trace) LogIfLong

func (t *Trace) LogIfLong(threshold time.Duration)

LogIfLong only logs the trace if the duration of the trace exceeds the threshold. Only steps that took longer than their share or the given threshold are logged. If klog is at verbosity level 4 or higher and the trace took longer than the threshold, all substeps and subtraces are logged. Otherwise, only those which took longer than their own threshold. If the Trace is nested it is not immediately logged. Instead, it is logged when the trace it is nested within is logged.

func (*Trace) Nest

func (t *Trace) Nest(msg string, fields ...Field) *Trace

Nest adds a nested trace with the given message and fields and returns it. As a convenience, if the receiver is nil, returns a top level trace. This allows one to call FromContext(ctx).Nest without having to check if the trace in the context is nil.

func (*Trace) Step

func (t *Trace) Step(msg string, fields ...Field)

Step adds a new step with a specific message. Call this at the end of an execution step to record how long it took. The Fields add key value pairs to provide additional details about the trace step.

Example
t := New("frobber")

time.Sleep(5 * time.Millisecond)
t.Step("reticulated splines") // took 5ms

time.Sleep(10 * time.Millisecond)
t.Step("sequenced particles") // took 10ms

klog.SetOutput(os.Stdout) // change output from stderr to stdout
t.Log()
Output:

func (*Trace) TotalTime

func (t *Trace) TotalTime() time.Duration

TotalTime can be used to figure out how long it took since the Trace was created

Jump to

Keyboard shortcuts

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