node

package
v0.0.0-...-61a3e3c Latest Latest
Warning

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

Go to latest
Published: Dec 5, 2024 License: MIT Imports: 30 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func AsTraceMapCarrier

func AsTraceMapCarrier[C TraceMapCarrierBase](
	carrier C,
) propagation.TextMapCarrier

AsTraceMapCarrier converts a traceMapCarrier interface to its propagation package implementation for that structure. ie: map becomes a MapCarrier, headers become HeaderCarriers.

func EmbedInCtx

func EmbedInCtx(ctx context.Context, dn *Node) context.Context

EmbedInCtx adds the node in the context, and returns the updated context.

func GetCaller

func GetCaller(depth int) string

GetCaller retrieves the func name of the caller. Depth is the skip-caller count. Clues funcs that call this one should provide either `1` (if they do not already have a depth value), or `depth+1` otherwise.`

func GetDirAndFile

func GetDirAndFile(
	depth int,
) (dir, fileAndLine, parentAndFileAndLine string)

GetDirAndFile retrieves the file and line number of the caller. Depth is the skip-caller count. Clues funcs that call this one should provide either `1` (if they do not already have a depth value), or `depth+1` otherwise`.

formats: dir `absolute/os/path/to/parent/folder` fileAndLine `<file>:<line>` parentAndFileAndLine `<parent>/<file>:<line>`

Types

type Agent

type Agent struct {
	// the name of the agent
	ID string

	// Data is used here instead of a basic value map so that
	// we can extend the usage of agents in the future by allowing
	// the full set of node behavior.  We'll need a builder for that,
	// but we'll get there eventually.
	Data *Node
}

type Annotation

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

func NewAttribute

func NewAttribute(k string, v any) Annotation

func (Annotation) IsAttribute

func (a Annotation) IsAttribute() bool

func (Annotation) KV

func (a Annotation) KV() log.KeyValue

type Annotationer

type Annotationer interface {
	IsAttribute() bool
	KV() attribute.KeyValue
}

type CluesCtxKey

type CluesCtxKey string

func CtxKey

func CtxKey(namespace string) CluesCtxKey

type Comment

type Comment struct {
	// the func name in which the comment was created.
	Caller string
	// the name of the file owning the caller.
	File string
	// the comment message itself.
	Message string
}

func NewComment

func NewComment(
	depth int,
	template string,
	values ...any,
) Comment

NewComment formats the provided values, and grabs the caller and trace info according to the depth. Depth is a skip-caller count, and any func calling this one should provide either `1` (for itself) or `depth+1` (if it was already given a depth value).

func (Comment) IsEmpty

func (c Comment) IsEmpty() bool

shorthand for checking if an empty comment was generated.

type CommentHistory

type CommentHistory []Comment

CommentHistory allows us to put a stringer on a slice of CommentHistory.

func (CommentHistory) String

func (cs CommentHistory) String() string

String formats the slice of comments as a stack, much like you'd see with an error stacktrace. Comments are listed top-to-bottom from first- to-last.

The format for each comment in the stack is:

<caller> - <file>:<line>
  <message>

type Node

type Node struct {
	Parent *Node

	// OTEL contains the client instance for the in memory OTEL runtime.  It is only
	// present if the end user calls the clues initialization step.
	OTEL *OTELClient

	// Span is the current otel Span.
	// Spans are kept separately from the otelClient because we want the client to
	// maintain a consistent reference to otel initialization, while the Span can
	// get replaced at arbitrary points.
	Span trace.Span

	// ids are optional and are used primarily as tracing markers.
	// if empty, the trace for that node will get skipped when building the
	// full trace along the node's ancestry path in the tree.
	ID string

	// Values are they arbitrary key:value pairs that appear in clues when callers
	// use the Add(ctx, k, v) or err.With(k, v) adders.  Each key-value pair added
	// to the node is used to produce the final set of Values() in the node,
	// with lower nodes in the tree taking priority over higher nodes for any
	// collision resolution.
	Values map[string]any

	// each node can hold a single commment.  The history of comments produced
	// by the ancestry path through the tree will get concatenated from oldest
	// ancestor to the current node to produce the Comment history.
	Comment Comment

	// Agents act as proxy node that can relay specific, intentional data
	// additions.  They're namespaced so that additions to the Agents don't accidentally
	// clobber other values in the node. This also allows Agents to protect
	// variations of data from each other, in case users need to compare differences
	// on the same keys.  That's not the goal for Agents, exactly, but it is capable.
	Agents map[string]*Agent
}

Node contains the data tracked by both clues in contexts and in errors.

These nodes compose a tree, such that nodes can walk their ancestry path from leaf (the current node) to root (the highest ancestor), but not from root to child. This allows clues to establish sets of common ancestor data with unique branches for individual descendants, making the addition of new data inherently theadsafe.

For collisions during aggregation, distance from the root denotes priority, with the root having the lowest priority. IE: if a child overwrites a key declared by an ancestor, the child's entry takes priority.

func FromBytes

func FromBytes(bs []byte) (*Node, error)

FromBytes deserializes the bytes to a new Node. No clients, agents, or hooks are initialized in this process.

func FromCtx

func FromCtx(ctx context.Context) *Node

FromCtx pulls the node within a given namespace out of the context.

func (*Node) AddAgent

func (dn *Node) AddAgent(name string) *Node

AddAgent adds a new named agent to the node.

func (*Node) AddComment

func (dn *Node) AddComment(
	depth int,
	msg string,
	vs ...any,
) *Node

AddComment creates a new nodewith a comment but no other properties.

func (*Node) AddSpan

func (dn *Node) AddSpan(
	ctx context.Context,
	name string,
) (context.Context, *Node)

AddSpan adds a new otel span. If the otel client is nil, no-ops. Attrs can be added to the span with addSpanAttrs. This span will continue to be used for that purpose until replaced with another span, which will appear in a separate context (and thus a separate, node).

func (*Node) AddSpanAttributes

func (dn *Node) AddSpanAttributes(
	values map[string]any,
)

AddSpanAttributes adds the values to the current span. If the span is nil (such as if otel wasn't initialized or no span has been generated), this call no-ops.

func (*Node) AddValues

func (dn *Node) AddValues(m map[string]any) *Node

AddValues adds all entries in the map to the node's values. automatically propagates values onto the current span.

func (*Node) AppendToTree

func (dn *Node) AppendToTree(name string) *Node

AppendToTree adds a new leaf with the provided name.

func (*Node) Bytes

func (dn *Node) Bytes() ([]byte, error)

Bytes serializes the Node to a slice of bytes. Only attributes and comments are maintained. All values are stringified in the process.

Node hierarchy, clients (such as otel), agents, and hooks (such as labelCounter) are all sliced from the result.

func (*Node) CloseSpan

func (dn *Node) CloseSpan(ctx context.Context) *Node

CloseSpan closes the otel span and removes it span from the data node. If no span is present, no ops.

func (*Node) Comments

func (dn *Node) Comments() CommentHistory

Comments retrieves the full ancestor comment chain. The return value is ordered from the first added comment (closest to the root) to the most recent one (closest to the leaf).

func (*Node) InitOTEL

func (dn *Node) InitOTEL(
	ctx context.Context,
	name string,
	config OTELConfig,
) error

Init sets up persistent clients in the clues ecosystem such as otel. Initialization is NOT required. It is an optional step that end users can take if and when they want those clients running in their clues instance.

Multiple initializations will no-op.

func (*Node) InjectTrace

func (dn *Node) InjectTrace(
	ctx context.Context,
	carrier propagation.TextMapCarrier,
)

injectTrace adds the current trace details to the provided carrier. If otel is not initialized, no-ops.

The carrier data is mutated by this call.

func (*Node) Map

func (dn *Node) Map() map[string]any

Map flattens the tree of node.values into a map. Descendant nodes take priority over ancestors in cases of collision.

func (*Node) OTELLogger

func (dn *Node) OTELLogger() log.Logger

logger gets the otel logger instance from the otel client. Returns nil if otel wasn't initialized.

func (*Node) OTELMeter

func (dn *Node) OTELMeter() metric.Meter

OTELMeter gets the otel logger instance from the otel client. Returns nil if otel wasn't initialized.

func (*Node) ReceiveTrace

func (dn *Node) ReceiveTrace(
	ctx context.Context,
	carrier propagation.TextMapCarrier,
) context.Context

receiveTrace extracts the current trace details from the carrier and adds them to the context. If otel is not initialized, no-ops.

The carrier data is mutated by this call.

func (*Node) RunLineage

func (dn *Node) RunLineage(fn func(id string, vs map[string]any))

RunLineage runs the fn on every valueNode in the ancestry tree, starting at the root and ending at the node.

func (*Node) SetValues

func (dn *Node) SetValues(m map[string]any)

SetValues is generally a helper called by addValues. In certain corner cases (like agents) it may get called directly.

func (*Node) Slice

func (dn *Node) Slice() []any

Slice flattens the tree of node.values into a Slice where all even indices contain the keys, and all odd indices contain values. Descendant nodes take priority over ancestors in cases of collision.

func (*Node) SpawnDescendant

func (dn *Node) SpawnDescendant() *Node

SpawnDescendant generates a new node that is a descendant of the current node. A descendant maintains a pointer to its parent, and carries any genetic necessities (ie, copies of fields) that must be present for continued functionality.

type Noder

type Noder interface {
	Node() *Node
}

type OTELClient

type OTELClient struct {
	ServiceName string

	LoggerProvider *sdkLog.LoggerProvider
	Logger         log.Logger

	MeterProvider *sdkMetric.MeterProvider
	Meter         metric.Meter

	TracerProvider *sdkTrace.TracerProvider
	Tracer         trace.Tracer
	// contains filtered or unexported fields
}

func NewOTELClient

func NewOTELClient(
	ctx context.Context,
	serviceName string,
	config OTELConfig,
) (*OTELClient, error)

NewOTELClient bootstraps the OpenTelemetry pipeline to run against a local server instance. If it does not return an error, make sure to call the client.Close() method for proper cleanup. The service name is used to match traces across backends.

func (*OTELClient) Close

func (cli *OTELClient) Close(ctx context.Context) error

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
	GRPCEndpoint string
}

type TraceMapCarrierBase

type TraceMapCarrierBase interface {
	map[string]string | http.Header
}

TraceMapCarrierBase defines the structures that support otel TraceMapCarrier behavior. A traceMapCarrier is used to pass and receive traces using message delivery headers and other metadata.

Jump to

Keyboard shortcuts

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