telemetry

package module
v0.8.2 Latest Latest
Warning

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

Go to latest
Published: Jan 17, 2024 License: Apache-2.0 Imports: 2 Imported by: 34

README

Telemetry

CI codecov

This package provides a set of Telemetry interfaces allowing you to completely decouple your libraries and packages from Logging and Metrics instrumentation implementations.

For more information on the interfaces, see: https://pkg.go.dev/github.com/tetratelabs/telemetry

Implementations

Below you can find a list of known interface implementations. As a consumer of this package, you might want to select existing implementations to use in your application binaries. If looking to write your own, take a look at existing ones for inspiration.

If you have an OSS implementation you want to share, feel free to submit a PR to this file so it may be included in this list.

repository supported interfaces notes
tetratelabs/telemetry-gokit-log Logger Go kit log bridge
tetratelabs/log Logger Scoped structured/unstructured logger bridge
tetratelabs/telemetry-opencensus Metrics OpenCensus metrics bridge
tetratelabs/telemetry-opentelemetry Metrics OpenTelemetry metrics bridge

Documentation

Overview

Package telemetry holds observability facades for our services and libraries.

The provided interface here allows for instrumenting libraries and packages without any dependencies on Logging and Metric instrumentation implementations. This allows a consistent way of authoring Log lines and Metrics for the producers of these libraries and packages while providing consumers the ability to plug in the implementations of their choice.

The following requirements helped shape the form of the interfaces.

  • Simple to use!

Or developers will resort to using `fmt.Printf()`

  • No elaborate amount of logging levels.

Error: something happened that we can't gracefully recover from. This is a log line that should be actionable by an operator and be alerted on.

Info: something happened that might be of interest but does not impact the application stability. E.g. someone gave the wrong credentials and was therefore denied access, parsing error on external input, etc.

Debug: anything that can help to understand application state during development.

More levels get tricky to reason about when writing log lines or establishing the right level of verbosity at runtime. By the above explanations fatal folds into error, warning folds into info, and trace folds into debug.

We trust more in partitioning loggers per domain, component, etc. and allow them to be individually addressed to required log levels than controlling a single logger with more levels.

We also believe that most logs should be metrics. Anything above Debug level should be able to emit a metric which can be use for dashboards, alerting, etc.

  • Structured logging from the interface side.

We want the ability to rollup / aggregate over the same message while allowing for contextual data to be added. A logging implementation can make the choice how to present to provided log data. This can be 100% structured, a single log line, or a combination.

  • Allow pass through of contextual values.

Allow the Go Context object to be passed and have a registry for values of interest we want to pull from context. A good example of an item we want to automatically include in log lines is the `x-request-id` so we can tie log lines produced in the request path together.

  • Allow each component to have their own "scope".

This allows us to control per component which levels of log lines we want to output at runtime. The interface design allows for this to be implemented without having an opinion on it. By providing at each library or component entry point the ability to provide a Logger implementation, this can be easily achieved.

  • Zero dependencies.

Look at that lovely very empty go.mod and non-existent go.sum file.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func KeyValuesFromContext

func KeyValuesFromContext(ctx context.Context) (keyValuePairs []interface{})

KeyValuesFromContext retrieves key-value pairs that might be stored in the provided Context. Logging implementations must use this function to retrieve the key-value pairs they need to include if a Context object was attached to them.

func KeyValuesToContext

func KeyValuesToContext(ctx context.Context, keyValuePairs ...interface{}) context.Context

KeyValuesToContext takes provided Context, retrieves the already stored key-value pairs from it, appends the in this function provided key-value pairs and stores the result in the returned Context.

func RemoveKeyValuesFromContext added in v0.2.0

func RemoveKeyValuesFromContext(ctx context.Context) context.Context

RemoveKeyValuesFromContext returns a Context that copies the provided Context but removes the key-value pairs that were stored.

func SetGlobalMetricSink added in v0.6.0

func SetGlobalMetricSink(ms MetricSink)

SetGlobalMetricSink allows one to set a global MetricSink, after which all registered OnGlobalMetricSinkFn callback functions are executed.

func ToGlobalMetricSink added in v0.6.0

func ToGlobalMetricSink(callback OnGlobalMetricSinkFn)

ToGlobalMetricSink allows one to set callback functions to bootstrap Metrics as soon as the Global MetricSink has been registered. If the MetricSink has already been registered, this callback will happen immediately.

Types

type DerivedMetric added in v0.8.0

type DerivedMetric interface {
	// Name returns the name value of a DerivedMetric.
	Name() string

	// ValueFrom is used to update the derived value with the provided
	// function and the associated label values. If the metric is unlabeled,
	// ValueFrom may be called without any labelValues. Otherwise, the labelValues
	// supplied MUST match the label keys supplied at creation time both in number
	// and in order.
	ValueFrom(valueFn func() float64, labelValues ...LabelValue) DerivedMetric
}

DerivedMetric can be used to supply values that dynamically derive from internal state, but are not updated based on any specific event. Their value will be calculated based on a value func that executes when the metrics are exported.

At the moment, only a Gauge type is supported.

type DerivedMetricSink added in v0.8.0

type DerivedMetricSink interface {
	// NewDerivedGauge intents to create a new Metric with an aggregation type
	// of LastValue. That means that data collected by the new Metric will
	// export only the last recorded value.
	// Unlike NewGauge, the DerivedGauge accepts functions which are called to
	// get the current value.
	NewDerivedGauge(name, description string) DerivedMetric
}

DerivedMetricSink bridges libraries bootstrapping metrics from metrics instrumentation implementations.

type Label

type Label interface {
	// Insert will insert the provided value for the Label if not set.
	Insert(value string) LabelValue

	// Update will update the Label with provided value if already set.
	Update(value string) LabelValue

	// Upsert will insert or replace the provided value for the Label.
	Upsert(value string) LabelValue

	// Delete will remove the Label's value.
	Delete() LabelValue
}

Label holds a metric dimension which can be operated on using the interface methods.

type LabelValue

type LabelValue interface{}

LabelValue holds an action to take on a metric dimension's value.

type Level added in v0.7.0

type Level int32

Level is an enumeration of the available log levels.

const (
	LevelNone  Level = 0
	LevelError Level = 1
	LevelInfo  Level = 5
	LevelDebug Level = 10
)

Available log levels.

func FromLevel added in v0.7.0

func FromLevel(level string) (Level, bool)

FromLevel returns the logging level corresponding to the given string representation.

func (Level) String added in v0.7.0

func (v Level) String() string

String returns the string representation of the logging level.

type Logger

type Logger interface {
	// Debug logging with key-value pairs. Don't be shy, use it.
	Debug(msg string, keyValuePairs ...interface{})

	// Info logging with key-value pairs. This is for informational, but not
	// directly actionable conditions. It is highly recommended you attach a
	// Metric to these types of messages. Where a single informational or
	// warning style message might not be reason for action, a change in
	// occurrence does warrant action. By attaching a Metric for these logging
	// situations, you make this easy through histograms, thresholds, etc.
	Info(msg string, keyValuePairs ...interface{})

	// Error logging with key-value pairs. Use this when application state and
	// stability are at risk. These types of conditions are actionable and often
	// alerted on. It is very strongly encouraged to add a Metric to each of
	// these types of messages. Metrics provide the easiest way to coordinate
	// processing of these concerns and triggering alerting systems through your
	// metrics backend.
	Error(msg string, err error, keyValuePairs ...interface{})

	// SetLevel provides the ability to set the desired logging level.
	// This function can be used at runtime and must be safe for concurrent use.
	//
	// Note for Logger implementations, When creating a new Logger with the
	// With, Context, or Metric methods, the level should be set-able for all
	// from any of the Loggers sharing the same root Logger.
	SetLevel(lvl Level)

	// Level returns the currently configured logging level.
	Level() Level

	// With returns a new Logger decorated with the provided key-value pairs.
	With(keyValuePairs ...interface{}) Logger

	// Context returns a new Logger having access to Context for inclusion of
	// registered key-value pairs found in Context. If a Metric is also attached
	// to the Logger, the Metric LabelValue directives found in Context will
	// also be processed.
	Context(ctx context.Context) Logger

	// Metric returns a new Logger which will emit a measurement for the
	// provided Metric when the Log level is either Info or Error.
	// **Note** that in the event the Logger is set to only output Error level
	// messages, Info messages even though silenced from a logging perspective,
	// will still emit their Metric measurements.
	Metric(m Metric) Logger

	// Clone returns a new Logger based on the original implementation.
	Clone() Logger
}

Logger provides a simple yet powerful logging abstraction.

func NoopLogger added in v0.6.0

func NoopLogger() Logger

NoopLogger returns a no-op logger.

type Metric

type Metric interface {
	// Increment records a value of 1 for the current Metric.
	// For Sums, this is equivalent to adding 1 to the current value.
	// For Gauges, this is equivalent to setting the value to 1.
	// For Distributions, this is equivalent to making an observation of value 1.
	Increment()

	// Decrement records a value of -1 for the current Metric.
	// For Sums, this is equivalent to subtracting -1 to the current value.
	// For Gauges, this is equivalent to setting the value to -1.
	// For Distributions, this is equivalent to making an observation of value -1.
	Decrement()

	// Name returns the name value of a Metric.
	Name() string

	// Record makes an observation of the provided value for the given Metric.
	// LabelValues added through With will be processed in sequence.
	Record(value float64)

	// RecordContext makes an observation of the provided value for the given
	// Metric.
	// If LabelValues for registered Labels are found in context, they will be
	// processed in sequence, after which the LabelValues added through With
	// are handled.
	RecordContext(ctx context.Context, value float64)

	// With returns the Metric with the provided LabelValues encapsulated. This
	// allows creating a set of pre-dimensioned data for recording purposes.
	// It also allows a way to clear out LabelValues found in an attached
	// Context if needing to sanitize.
	With(labelValues ...LabelValue) Metric
}

Metric collects numerical observations.

type MetricOption

type MetricOption func(*MetricOptions)

MetricOption implements a functional option type for our Metrics.

func WithEnabled added in v0.8.0

func WithEnabled(enabled func() bool) MetricOption

WithEnabled allows a metric to be conditionally enabled if the provided function returns true. If disabled, metric operations will do nothing.

func WithLabels

func WithLabels(labels ...Label) MetricOption

WithLabels provides a configuration MetricOption for a new Metric, providing the required dimensions for data collection of that Metric.

func WithUnit

func WithUnit(unit Unit) MetricOption

WithUnit provides a configuration MetricOption for a new Metric, providing Unit of measure information for a new Metric.

type MetricOptions

type MetricOptions struct {
	// EnabledCondition can hold a function which decides if metric is enabled.
	EnabledCondition func() bool
	// Unit holds the unit specifier of a Metric.
	Unit Unit
	// Labels holds the registered dimensions for the Metric.
	Labels []Label
}

MetricOptions hold commonly used but optional Metric configuration.

type MetricSink

type MetricSink interface {
	// NewSum intents to create a new Metric with an aggregation type of Sum
	// (the values will be cumulative). That means that data collected by the
	// new Metric will be summed before export.
	NewSum(name, description string, opts ...MetricOption) Metric

	// NewGauge intents to creates a new Metric with an aggregation type of
	// LastValue. That means that data collected by the new Metric will export
	// only the last recorded value.
	NewGauge(name, description string, opts ...MetricOption) Metric

	// NewDistribution intents to create a new Metric with an aggregation type
	// of Distribution. This means that the data collected by the Metric will be
	// collected and exported as a histogram, with the specified bounds.
	NewDistribution(name, description string, bounds []float64, opts ...MetricOption) Metric

	// NewLabel creates a new Label to be used as a metrics dimension.
	NewLabel(name string) Label

	// ContextWithLabels takes the existing LabelValue collection found in
	// Context and appends the Label operations as received from the provided
	// values on top, which is then added to the returned Context. The function
	// can return an error in case the provided values contain invalid label
	// names.
	ContextWithLabels(ctx context.Context, values ...LabelValue) (context.Context, error)
}

MetricSink bridges libraries bootstrapping metrics from metrics instrumentation implementations.

type OnGlobalMetricSinkFn added in v0.6.0

type OnGlobalMetricSinkFn func(m MetricSink)

OnGlobalMetricSinkFn holds a function signature which can be used to register Metric bootstrapping that needs to be called after the GlobalMetricSink has been registered.

type Unit

type Unit string

Unit encodes the standard name for describing the quantity measured by a Metric (if applicable).

const (
	None         Unit = "1"
	Bytes        Unit = "By"
	Seconds      Unit = "s"
	Milliseconds Unit = "ms"
)

Predefined units for use with the monitoring package.

Directories

Path Synopsis
Package function provides an implementation of the telemetry.Logger interface that uses a given function to emit logs.
Package function provides an implementation of the telemetry.Logger interface that uses a given function to emit logs.
group module
Package scope provides a scoped logger facade for telemetry.Logger implementations.
Package scope provides a scoped logger facade for telemetry.Logger implementations.

Jump to

Keyboard shortcuts

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