go11y

package module
v0.3.1 Latest Latest
Warning

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

Go to latest
Published: Oct 15, 2025 License: MIT Imports: 30 Imported by: 1

README

go11y1 for observability in Go

Opinionated but simple Go implementation of structured logging and open telemetry tracing for your application.

Features

Structured Logging

go11y wraps the Go standard lib slog package, so it's structured logging with JSON from the outset, just more convenient.

_, o, _ := go11y.Initialise(ctx, nil, os.Stdout, "arg1", "val1")
o.Info("structured logging", nil, "arg2", "val2")
{
    "time":"2025-08-04T10:14:19.780509481+08:00",
    "level":"INFO",
    "source":{
        "function":"main.main",
        "file":"/home/user/demo/main.go",
        "line":81
    },
    "msg":"structured logging",
    "arg1": "val1",
    "arg2": "val2",
}
Tracing

go11y doesn't handle the tracing for you (yet) but it does leave room for it so you don't need to go to too much effort to integrate it.

_, o, _ := go11y.Initialise(ctx, nil, os.Stdout)

ctx, span := otel.Tracer("packageName").Start(ctx, "functionName", trace.WithSpanKind(trace.SpanKindClient))

o.Info("structured logging", span)
Roundtrippers
Middleware

Configuration

Hard Coded - BYO or Built in
Environment Variables

Examples

Used by

Todo

  • Implement integration tests for log ingestion and tracing with Grafana-LGTM testcontainer
  • Expand GoDoc details and add examples
  • Try to get tracing integrated into go11y so there is less boilerplate needed

Notes

1 sounds like golly

Documentation

Overview

Package go11y provides observability features including logging, tracing, and database logging of roundtrip requests to third-party APIs.

Index

Examples

Constants

View Source
const (
	FieldRequestID       = "request_id"
	FieldRequestMethod   = "request_method"
	FieldRequestPath     = "request_path"
	FieldRequestHeaders  = "request_headers"
	FieldRequestURL      = "request_url"
	FieldRequestBody     = "request_body"
	FieldResponseHeaders = "response_headers"
	FieldResponseBody    = "response_body"
	FieldCallDuration    = "call_duration"
	FieldStatusCode      = "status_code"
	FieldSpanID          = "span_id"
	FieldTraceID         = "trace_id"
	FieldRemoteTraceID   = "remote_trace_id"
	FieldRemoteSpanID    = "remote_span_id"
	FieldEnvironment     = "environment"
)
View Source
const (
	LevelDevelop = slog.Level(-8) // Custom level for development only logging, will be disabled in staging and production
	LevelDebug   = slog.Level(-4)
	LevelInfo    = slog.Level(0)
	LevelNotice  = slog.Level(2)
	LevelWarning = slog.Level(4)
	LevelError   = slog.Level(8)
	LevelFatal   = slog.Level(12)
)
View Source
const (
	SeverityLowest  string = "lowest"  // No threat to system/process operation - the user can fix this themselves and continue this one operation
	SeverityLow     string = "low"     // No threat to system/process operation - the user can fix this themselves but will need to restart the operation
	SeverityMedium  string = "medium"  // The error may cause some disruption to system/process operation - the user may be able to fix this themselves but may need support
	SeverityHigh    string = "high"    // The error will cause disruption to system/process operation - something outside the user's control will need to be fixed
	SeverityHighest string = "highest" // The error will cause major disruption to system/process operation - something outside the user's control will need to be fixed, and there may be wider implications for the system/process as a whole
)
View Source
const (
	SpanKindServer   = otelTrace.SpanKindServer
	SpanKindClient   = otelTrace.SpanKindClient
	SpanKindProducer = otelTrace.SpanKindProducer
	SpanKindConsumer = otelTrace.SpanKindConsumer
	SpanKindInternal = otelTrace.SpanKindInternal
)
View Source
const RequestIDInstance requestIDKey = "requestID"

Variables

This section is empty.

Functions

func AddDBStoreToHTTPClient

func AddDBStoreToHTTPClient(httpClient *http.Client) (fault error)
Example
package main

import ()

func main() {
	// Example usage of AddDBStoreToHTTPClient function
	// TODO @jsnfwlr: Write the example
}

func AddLoggingToHTTPClient

func AddLoggingToHTTPClient(httpClient *http.Client) (fault error)
Example
package main

import ()

func main() {
	// Example usage of AddLoggingToHTTPClient function
	// TODO @jsnfwlr: Write the example
}

func AddPropagationToHTTPClient added in v0.2.0

func AddPropagationToHTTPClient(httpClient *http.Client) (fault error)

func AddTracingToHTTPClient

func AddTracingToHTTPClient(httpClient *http.Client) (fault error)

AddTracingToHTTPClient wraps a HTTP client's transporter with OpenTelemetry instrumentation If the provided httpClient is nil, it creates a new http.Client with a default timeout of 2 minutes and a transport that is instrumented with OpenTelemetry to This allows us to capture request and response details in our telemetry data

Note: Ensure that the OpenTelemetry SDK and otelhttp package are properly initialized before using this client

Example
package main

import ()

func main() {
	// Example usage of AddTracingToHTTPClient function
	// TODO @jsnfwlr: Write the example
}

func DBStoreRoundTripper

func DBStoreRoundTripper(next http.RoundTripper) http.RoundTripper

func Fatal added in v0.3.1

func Fatal(msg string, err error, ephemeralArgs ...any)

Fatal logs a fatal error message with the highest severity level and then exits the application with a status code of 1. This is intended to for use in situations where an Observer instance is not available such as in the main function before the observer has been initialised.

func GetRequestID

func GetRequestID(ctx context.Context) string
Example
package main

import ()

func main() {
	// Example usage of GetRequestID function
	// TODO @jsnfwlr: Write the example
}

func LogRequest

func LogRequest(next http.Handler) http.Handler

LogRequest is a middleware that logs incoming HTTP requests and their details It extracts tracing information from the request headers and starts a new span for the request It also logs the request details using go11y, adding the go11y Observer to the request context in the process

Example
package main

import ()

func main() {
	// Example usage of LogRequest function
	// TODO @jsnfwlr: Write the example
}

func LogRoundTripper

func LogRoundTripper(next http.RoundTripper) http.RoundTripper

func PropagateRoundTripper added in v0.2.0

func PropagateRoundTripper(next http.RoundTripper) http.RoundTripper

func RedactHeaders

func RedactHeaders(headers http.Header) http.Header

func Reset

func Reset(ctxWithGo11y context.Context) (ctxWithResetObservability context.Context)

func SetRequestID

func SetRequestID(next http.Handler) http.Handler
Example
package main

import ()

func main() {
	// Example usage of SetRequestID middleware
	// TODO @jsnfwlr: Write the example
}

func StringToLevel added in v0.3.1

func StringToLevel(level string) slog.Level

Types

type Configuration added in v0.3.1

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

Configuration is a struct that holds the reference configuration for go11y.

func CreateConfig added in v0.3.1

func CreateConfig(logLevel slog.Level, otelURL, dbConStr, serviceName string, trimModules, trimPaths []string) *Configuration

CreateConfig creates a new Configuration instance populated with the provided parameters. This is intended to be used for when you want to create a config without loading from environment variables. The Configuration returned satisfies the Configurator interface, allowing it to be used interchangeably with configurations loaded from environment variables.

func LoadConfig added in v0.3.1

func LoadConfig() (cfg *Configuration, fault error)

LoadConfig loads the configuration from environment variables. It returns a Configuration instance that implements the Configurator interface. If any required environment variable is missing or invalid, it returns an error.

func (*Configuration) DBConStr added in v0.3.1

func (c *Configuration) DBConStr() string

DBConStr returns the database connection string. This method is part of the Configurator interface.

func (*Configuration) LogLevel added in v0.3.1

func (c *Configuration) LogLevel() slog.Level

LogLevel returns the configured log level for the observer. This method is part of the Configurator interface.

func (*Configuration) ServiceName added in v0.3.1

func (c *Configuration) ServiceName() string

ServiceName returns the configured service name for OpenTelemetry. This method is part of the Configurator interface.

func (*Configuration) TrimModules added in v0.3.1

func (c *Configuration) TrimModules() []string

TrimModules returns the configured strings to be trimmed from the source.function attribute. This method is part of the Configurator interface.

func (*Configuration) TrimPaths added in v0.3.1

func (c *Configuration) TrimPaths() []string

TrimPaths returns the configured strings to be trimmed from the source.file attribute. This method is part of the Configurator interface.

func (*Configuration) URL added in v0.3.1

func (c *Configuration) URL() string

URL returns the configured OpenTelemetry URL (scheme, host, port, path). This method is part of the Configurator interface.

type Configurator added in v0.3.1

type Configurator interface {
	LogLevel() slog.Level
	URL() string
	DBConStr() string
	ServiceName() string
	TrimPaths() []string
	TrimModules() []string
}

Configurator is an interface that defines the methods required for configuration of go11y. It is used to abstract the configuration details from the observer implementation. This allows for different implementations of configuration, such as loading from environment variables or using a custom configuration struct - ideal for our unit tests or when you want to use a your own bespoke configuration source

type Fields

type Fields map[string]any

type Observer

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

func Expand added in v0.2.0

func Expand(ctx context.Context, tracer otelTrace.Tracer, spanName string, spanKind otelTrace.SpanKind, newArgs ...any) (ctxWithSpan context.Context, observer *Observer)

Expand retrieves the Observer from the context, starts a new tracing span with the given name, and adds new arguments to its logger. If no Observer exists in the context, it initializes a new one with default settings and adds the arguments.

func Extend

func Extend(ctx context.Context, newArgs ...any) (ctxWithGo11y context.Context, observer *Observer)

Extend retrieves the Observer from the context and adds new arguments to its logger. If no Observer exists in the context, it initializes a new one with default settings and adds the arguments.

func Get

func Get(ctx context.Context) (ctxWithObserver context.Context, observer *Observer)

Get retrieves the Observer from the context. If none exists, it initializes a new one with default settings.

func Initialise

func Initialise(ctx context.Context, cfg Configurator, logOutput io.Writer, initialArgs ...any) (ctxWithGo11y context.Context, observer *Observer, fault error)
Example (JustLogging)
package main

import ()

func main() {
	// Example of setting up logging, using the different functions to sending
	// log messages with different severity levels, extending the context with
	// additional information, changing the minimum severity level, and passing
	// the context-with-observability to another function that retrieves the
	// logger from the context and uses it.

	// TODO @jsnfwlr: Write the example
}
Example (LoggingAndTracing)
package main

import ()

func main() {
	// Example of adding tracing to the JustLogging example, showing how to set
	// up tracing, create spans, and log messages with different severity
	// levels, while also extending the context with additional information.

	// TODO @jsnfwlr: Write the example
}

func Span added in v0.2.0

func Span(ctx context.Context, tracer otelTrace.Tracer, spanName string, spanKind otelTrace.SpanKind) (ctxWithSpan context.Context, observer *Observer)

Span gets the Observer from the context and starts a new tracing span with the given name. If no Observer exists in the context, it initializes a new one with default settings and starts the span. The tracing equivalent of Get()

func (*Observer) AddArgs

func (o *Observer) AddArgs(args ...any) (filteredArgs []any)

AddArgs processes the provided arguments, ensuring that they are stable and formatted correctly.

func (*Observer) CheckStore

func (o *Observer) CheckStore() (record db.RemoteApiRequest, fault error)

func (*Observer) Close

func (o *Observer) Close()

Close ends all active spans and shuts down the trace provider to ensure all traces are flushed.

func (*Observer) Debug

func (o *Observer) Debug(msg string, ephemeralArgs ...any)

Debug records an event on the tracing span if it is available and logs a debug message via the observer (if the observer's log-level allows).

func (*Observer) Develop

func (o *Observer) Develop(msg string, ephemeralArgs ...any)

Develop records an event on the tracing span if it is available and logs a develop message via the observer (if the observer's log-level allows). This is intended for use during development and may be too verbose or could leak secrets in production use, and should be filtered out in such environments.

func (*Observer) End added in v0.2.0

func (o *Observer) End()

func (*Observer) Error

func (o *Observer) Error(msg string, err error, severity string, ephemeralArgs ...any)

Error records an error on the tracing span if it is available and logs an error message via the observer (if the observer's log-level allows), with the specified severity level.

func (*Observer) Fatal

func (o *Observer) Fatal(msg string, err error, ephemeralArgs ...any)

Fatal records an error on the tracing span if it is available and logs a fatal error message via the observer with the highest severity level and then exits the application with a status code of 1.

func (*Observer) Info

func (o *Observer) Info(msg string, ephemeralArgs ...any)

Info records an event on the tracing span if it is available and logs an information message via the observer (if the observer's log-level allows).

func (*Observer) Mute

func (o *Observer) Mute(ctx context.Context)

func (*Observer) Notice

func (o *Observer) Notice(msg string, ephemeralArgs ...any)

Notice records an event on the tracing span if it is available and logs a notice message via the observer (if the observer's log-level allows).

func (*Observer) Tracer

func (o *Observer) Tracer(name string, opts ...otelTrace.TracerOption) otelTrace.Tracer

func (*Observer) Warn

func (o *Observer) Warn(msg string, ephemeralArgs ...any)

Warn is an alias for Warning to maintain compatibility with other logging libraries.

func (*Observer) Warning

func (o *Observer) Warning(msg string, ephemeralArgs ...any)

Warning records an event on the tracing span if it is available and logs a warning message via the observer (if the observer's log-level allows).

type ObserverDB

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

type Origin added in v0.2.0

type Origin struct {
	ClientIP  string `json:"client_ip"`
	UserAgent string `json:"user_agent"`
	Method    string `json:"method"`
	Path      string `json:"path"`
}

type RoundTripperFunc

type RoundTripperFunc func(*http.Request) (*http.Response, error)

func (RoundTripperFunc) RoundTrip

func (rt RoundTripperFunc) RoundTrip(r *http.Request) (*http.Response, error)

type Tracer added in v0.3.1

type Tracer otelTrace.Tracer

func NewTracer added in v0.3.1

func NewTracer(packageAddress string, options ...TracerOption) Tracer

type TracerOption added in v0.3.1

type TracerOption otelTrace.TracerOption

Directories

Path Synopsis
etc

Jump to

Keyboard shortcuts

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