observer

package
v0.1.2 Latest Latest
Warning

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

Go to latest
Published: Mar 4, 2021 License: ISC Imports: 27 Imported by: 0

README

Go Doc

Observer

This package can be used for building observable applications in Go. It aims to unify three pillars of observability in one single package that is easy-to-use and hard-to-misuse.

This package leverages the OpenTelemetry API. OpenTelemetry is a great initiative that has brought all different standards and APIs for observability under one umbrella. However, due to the requirements for interoperability with existing systems, OpenTelemetry is complex and hard to use by design! Many packages, configurations, and options make the developer experience not so pleasant. Furthermore, due to the changing nature of this project, OpenTelemetry specification changes often so does the Go library for OpenTelemetry. In my humble opinion, this is not how a single unified observability API should be. Hopefully, many of these issues will go away once the API reaches to v1.0.0. This package intends to provide a very minimal and yet practical API for observability by hiding the complexity of configuring and using OpenTelemetry API.

An Observer encompasses a logger, a meter, and a tracer. It offers a single unified developer experience for building observable applications.

The Three Pillars of Observability

Logging

Logs are used for auditing purposes (sometimes for debugging with limited capabilities). When looking at logs, you need to know what to look for ahead of time (known unknowns vs. unknown unknowns). Since log data can have any arbitrary shape and size, they cannot be used for real-time computational purposes. Logs are hard to track across different and distributed processes. Logs are also very expensive at scale.

Metrics

Metrics are regular time-series data with low and fixed cardinality. They are aggregated by time. Metrics are used for real-time monitoring purposes. Using metrics we can implement SLIs (service-level indicators), SLOs (service-level objectives), and automated alerts. Metrics are very good at taking the distribution of data into account. Metrics cannot be used with high-cardinality data.

Tracing

Traces are used for debugging and tracking requests across different processes and services. They can be used for identifying performance bottlenecks. Due to their very data-heavy nature, traces in real-world applications need to be sampled. Insights extracted from traces cannot be aggregated since they are sampled. In other words, information captured by one trace does not tell anything about how this trace is compared against other traces, and what is the distribution of data.

Quick Start

You can find examples here. For the examples, you can use the following docker-compose.yml file to bring up an observability stack:

git clone https://github.com/moorara/docker-compose.git
cd docker-compose/observability
docker-compose up -d

Options

Most options can be set through environment variables. This lets SRE people change how the observability pipeline is configured without making any code change.

Options set explicity in the code will override those set by environment variables.

Environment Variable Description
OBSERVER_NAME The name of service or application.
OBSERVER_VERSION The version of service or application.
OBSERVER_ENVIRONMENT The name of environment in which the service or application is running.
OBSERVER_REGION The name of region in which the service or application is running.
OBSERVER_TAG_* Each variable prefixed with OBSERVER_TAG_ represents a tag for the service or application.
OBSERVER_LOGGER_ENABLED Whether or not to create a logger (boolean).
OBSERVER_LOGGER_LEVEL The verbosity level for the logger (debug, info, warn, error, or none).
OBSERVER_PROMETHEUS_ENABLED Whether or not to configure and create a Prometheus meter (boolean).
OBSERVER_JAEGER_ENABLED Whether or not to configure and create a Jaeger tracer (boolean).
OBSERVER_JAEGER_AGENT_ENDPOINT The address to the Jaeger agent (i.e. localhost:6831).
OBSERVER_JAEGER_COLLECTOR_ENDPOINT The full URL to the Jaeger HTTP Thrift collector (i.e. http://localhost:14268/api/traces).
OBSERVER_JAEGER_COLLECTOR_USERNAME The username for Jaeger collector endpoint if basic auth is required.
OBSERVER_JAEGER_COLLECTOR_PASSWORD The password for Jaeger collector endpoint if basic auth is required.
OBSERVER_OPENTELEMETRY_ENABLED Whether or not to configure and create an OpenTelemetry Collector meter and tracer (boolean).
OBSERVER_OPENTELEMETRY_COLLECTOR_ADDRESS The address to OpenTelemetry collector (i.e. localhost:55680).

OpenTelemetry

Logging

TBD

Metrics

Metric instruments capture measurements at runtime. A Meter is used for creating metric instruments.

There are two kinds of measurements:

  • Additive: measurements for which only the sum is considered useful information
  • Non-Additive: measurements for which the set of values (a.k.a. population or distribution) has useful information

Non-additive instruments capture more information than additive instruments, but non-additive measurements are more expensive.

Aggregation is the process of combining multiple measurements into exact or estimated statistics during an interval of time. Each instrument has a default aggregation. Other standard aggregations (histograms, quantile summaries, cardinality estimates, etc.) are also available.

There are six kinds of metric instruments:

Name Synchronous Additive Monotonic Default Aggregation
Counter Yes Yes Yes Sum
UpDownCounter Yes Yes No Sum
ValueRecorder Yes No No MinMaxSumCount
SumObserver No Yes Yes Sum
UpDownSumObserver No Yes No Sum
ValueObserver No No No MinMaxSumCount

The synchronous instruments are useful for measurements that are gathered in a distributed Context. The asynchronous instruments are useful when measurements are expensive, therefore should be gathered periodically. Synchronous instruments are used to capture changes in a sum, whereas asynchronous instruments are used to capture sums directly. Asynchronous (observer) instruments capture measurements about the state of the application periodically.

Tracing

TBD

Documentation

Documentation

Overview

Package observer can be used for implementing observability using OpenTelemetry API. It aims to unify three pillars of observability in one single package that is easy-to-use and hard-to-misuse.

An Observer encompasses a logger, a meter, and a tracer. It offers a single unified developer experience for observability.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func ContextWithLogger

func ContextWithLogger(ctx context.Context, logger Logger) context.Context

ContextWithLogger returns a new context that holds a reference to a logger.

func ContextWithMeter

func ContextWithMeter(ctx context.Context, meter metric.Meter) context.Context

ContextWithMeter returns a new context that holds a reference to a meter.

func ContextWithTracer

func ContextWithTracer(ctx context.Context, tracer trace.Tracer) context.Context

ContextWithTracer returns a new context that holds a reference to a tracer.

func ContextWithUUID

func ContextWithUUID(ctx context.Context, uuid string) context.Context

ContextWithUUID creates a new context with a uuid.

func MeterFromContext

func MeterFromContext(ctx context.Context) metric.Meter

MeterFromContext returns a meter set on a context. If no meter found on the context, the singleton meter will be returned!

func Set

func Set(o Observer)

Set sets the global singleton Observer.

func TracerFromContext

func TracerFromContext(ctx context.Context) trace.Tracer

TracerFromContext returns a tracer set on a context. If no tracer found on the context, the singleton tracer will be returned!

func UUIDFromContext

func UUIDFromContext(ctx context.Context) (string, bool)

UUIDFromContext retrieves a uuid from a context.

Types

type Level

type Level int

Level is the logging level.

const (
	LevelNone Level = iota
	LevelError
	LevelWarn
	LevelInfo
	LevelDebug
)

Logging level

type Logger

type Logger interface {
	Level() Level
	SetLevel(level string)
	With(kv ...interface{}) Logger
	Debug(message string, kv ...interface{})
	Debugf(format string, args ...interface{})
	Info(message string, kv ...interface{})
	Infof(format string, args ...interface{})
	Warn(message string, kv ...interface{})
	Warnf(format string, args ...interface{})
	Error(message string, kv ...interface{})
	Errorf(format string, args ...interface{})
	Close() error
}

Logger is a levelled structured logger. It is concurrently safe to be used by multiple goroutines.

func LoggerFromContext

func LoggerFromContext(ctx context.Context) Logger

LoggerFromContext returns a logger set on a context. If no logger found on the context, the singleton logger will be returned!

type Observer

type Observer interface {
	http.Handler

	Name() string
	Logger() Logger
	Meter() metric.Meter
	Tracer() trace.Tracer
	Close(context.Context) error
}

Observer provides logging, metrics, and tracing capabilities for observability.

func Get

func Get() Observer

Get returns the global singleton Observer.

func New

func New(opts ...Option) Observer

New creates a new observer.

func Nop

func Nop() Observer

Nop creates a no-op observer.

type Option

type Option func(*options)

Option is used for configuring an observer.

func WithJaeger

func WithJaeger(agentEndpoint, collectorEndpoint, collectorUserName, collectorPassword string) Option

WithJaeger is the option for enabling Jaeger. Only one of agentEndpoint or collectorEndpoint is required. collectorUserName and collectorPassword are optional. The default agent endpoint is localhost:6831.

func WithLogger

func WithLogger(level string) Option

WithLogger is the option for enabling the logger.

func WithMetadata

func WithMetadata(name, version, environment, region string, tags map[string]string) Option

WithMetadata is the option for specifying and reporting metadata. All arguments are optional.

func WithOpenTelemetry

func WithOpenTelemetry(collectorAddress string, collectorCredentials credentials.TransportCredentials) Option

WithOpenTelemetry is the option for enabling OpenTelemetry Collector. collectorCredentials is optional. If not specified, the connection will be insecure. The default collector address is localhost:55680.

func WithPrometheus

func WithPrometheus() Option

WithPrometheus is the option for enabling Prometheus.

Directories

Path Synopsis
example
Package ohttp is an observable http package.
Package ohttp is an observable http package.

Jump to

Keyboard shortcuts

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