Documentation ¶
Index ¶
- Constants
- Variables
- func Add(ctx context.Context, kvs ...any) context.Context
- func AddAgent(ctx context.Context, name string) context.Context
- func AddComment(ctx context.Context, msg string, vs ...any) context.Context
- func AddMap[K comparable, V any](ctx context.Context, m map[K]V) context.Context
- func AddSpan(ctx context.Context, name string, kvs ...any) context.Context
- func Close(ctx context.Context) error
- func CloseSpan(ctx context.Context) context.Context
- func In(ctx context.Context) *node.Node
- func Inherit(from, to context.Context, clobber bool) context.Context
- func InitializeOTEL(ctx context.Context, serviceName string, config OTELConfig) (context.Context, error)
- func InjectTrace[C node.TraceMapCarrierBase](ctx context.Context, mapCarrier C) C
- func ReceiveTrace[C node.TraceMapCarrierBase](ctx context.Context, mapCarrier C) context.Context
- func Relay(ctx context.Context, agent string, vs ...any)
- type OTELConfig
Constants ¶
const (
DefaultOTELGRPCEndpoint = "localhost:4317"
)
Variables ¶
var ErrMissingOtelGRPCEndpoint = errors.New("missing otel grpc endpoint")
Functions ¶
func AddAgent ¶
AddAgent adds an agent with a given name to the context. What's an agent? It's a special case data adder that you can spawn to collect clues for you. Unlike standard clues additions, you have to tell the agent exactly what data you want it to Relay() for you.
Agents are recorded in the current clues node and all of its descendants. Data relayed by the agent will appear as part of the standard data map, namespaced by each agent.
Agents are specifically handy in a certain set of uncommon cases where retrieving clues is otherwise difficult to do, such as working with middleware that doesn't allow control over error creation. In these cases your only option is to relay that data back to some prior clues node.
func AddComment ¶
AddComment adds a long form comment to the clues.
Comments are special case additions to the context. They're here to, well, let you add comments! Why? Because sometimes it's not sufficient to have a log let you know that a line of code was reached. Even a bunch of clues to describe system state may not be enough. Sometimes what you need in order to debug the situation is a long-form explanation (you do already add that to your code, don't you?). Or, even better, a linear history of long-form explanations, each one building on the prior (which you can't easily do in code).
Should you transfer all your comments to clues? Absolutely not. But in cases where extra explantion is truly important to debugging production, when all you've got are some logs and (maybe if you're lucky) a span trace? Those are the ones you want.
Unlike other additions, which are added as top-level key:value pairs to the context, comments are all held as a single array of additions, persisted in order of appearance, and prefixed by the file and line in which they appeared. This means comments are always added to the context and never clobber each other, regardless of their location. IE: don't add them to a loop.
func AddSpan ¶
AddSpan stacks a clues node onto this context and uses the provided name for the trace id, instead of a randomly generated hash. AddSpan can be called without additional values if you only want to add a trace marker. The assumption is that an otel span is generated and attached to the node. Callers should always follow this addition with a closing `defer clues.CloseSpan(ctx)`.
func Close ¶
Close will flush all buffered data waiting to be read. If Initialize was not called, this call is a no-op. Should be called in a defer after initializing.
func CloseSpan ¶
CloseSpan closes the current span in the clues node. Should only be called following a `clues.AddSpan()` call.
func Inherit ¶
Inherit propagates all clients from one context to another. This is particularly useful for taking an initialized context from a main() func and ensuring its clients are available for request-bound conetxts, such as in a http server pattern.
If the 'to' context already contains an initialized client, no change is made. Callers can force a 'from' client to override a 'to' client by setting clobber=true.
func InitializeOTEL ¶
func InitializeOTEL( ctx context.Context, serviceName string, config OTELConfig, ) (context.Context, error)
InitializeOTEL will spin up the OTEL clients that are held by clues, Clues will eagerly use these clients in the background to provide additional telemetry hook-ins.
Clues will operate as expected in the event of an error, or if OTEL is not initialized. This is a purely optional step.
func InjectTrace ¶
func InjectTrace[C node.TraceMapCarrierBase]( ctx context.Context, mapCarrier C, ) C
InjectTrace adds the current trace details to the provided headers. If otel is not initialized, no-ops.
The mapCarrier is mutated by this request. The passed reference is returned mostly as a quality-of-life step so that callers don't need to declare the map outside of this call.
func ReceiveTrace ¶
ReceiveTrace extracts the current trace details from the headers and adds them to the context. If otel is not initialized, no-ops.
Types ¶
type OTELConfig ¶
type OTELConfig struct { // specify the endpoint location to use for grpc communication. // If empty, no telemetry exporter will be generated. // ex: localhost:4317 // ex: 0.0.0.0:4317 // ex: opentelemetry-collector.monitoring.svc.cluster.local:4317 GRPCEndpoint string }