Documentation
¶
Overview ¶
Package testing provides utilities for testing OpenTelemetry instrumentation in GoBricks applications.
This package offers in-memory exporters and helpers for asserting spans and metrics in unit tests without requiring external collectors or backends.
Usage:
// Create test trace provider tp := NewTestTraceProvider() defer tp.Shutdown(context.Background()) // Run your code that creates spans tracer := tp.TestTracer() _, span := tracer.Start(context.Background(), "test-span") span.End() // Assert spans spans := tp.Exporter.GetSpans() require.Len(t, spans, 1) AssertSpanName(t, spans[0], "test-span")
Index ¶
- Constants
- func AssertMetricCount(t *testing.T, rm metricdata.ResourceMetrics, expected int)
- func AssertMetricDescription(t *testing.T, rm metricdata.ResourceMetrics, metricName, expectedDesc string)
- func AssertMetricExists(t *testing.T, rm metricdata.ResourceMetrics, metricName string)
- func AssertMetricValue(t *testing.T, rm metricdata.ResourceMetrics, metricName string, ...)
- func AssertSpanAttribute(t *testing.T, span *tracetest.SpanStub, key string, expected any)
- func AssertSpanError(t *testing.T, span *tracetest.SpanStub, expectedDesc string)
- func AssertSpanName(t *testing.T, span *tracetest.SpanStub, expected string)
- func AssertSpanStatus(t *testing.T, span *tracetest.SpanStub, expectedCode codes.Code)
- func AssertSpanStatusDescription(t *testing.T, span *tracetest.SpanStub, expectedDesc string)
- func FindMetric(rm metricdata.ResourceMetrics, metricName string) *metricdata.Metrics
- func GetMetricHistogramCount(rm metricdata.ResourceMetrics, metricName string) (uint64, error)
- func GetMetricSumValue(rm metricdata.ResourceMetrics, metricName string) (any, error)
- type SpanCollector
- func (sc *SpanCollector) AssertCount(expected int) *SpanCollector
- func (sc *SpanCollector) AssertEmpty() *SpanCollector
- func (sc *SpanCollector) First() tracetest.SpanStub
- func (sc *SpanCollector) Get(index int) tracetest.SpanStub
- func (sc *SpanCollector) Len() int
- func (sc *SpanCollector) WithAttribute(key string, value any) *SpanCollector
- func (sc *SpanCollector) WithName(name string) *SpanCollector
- type TestMeterProvider
- type TestTraceProvider
Examples ¶
Constants ¶
const ( // TestTracerName is the default tracer name used in observability tests. // This eliminates duplication of "test" string literal across 17+ test files. TestTracerName = "test" )
Variables ¶
This section is empty.
Functions ¶
func AssertMetricCount ¶
func AssertMetricCount(t *testing.T, rm metricdata.ResourceMetrics, expected int)
AssertMetricCount asserts the total number of metrics collected.
func AssertMetricDescription ¶
func AssertMetricDescription(t *testing.T, rm metricdata.ResourceMetrics, metricName, expectedDesc string)
AssertMetricDescription asserts the description of a metric.
func AssertMetricExists ¶
func AssertMetricExists(t *testing.T, rm metricdata.ResourceMetrics, metricName string)
AssertMetricExists asserts that a metric with the given name exists.
func AssertMetricValue ¶
func AssertMetricValue(t *testing.T, rm metricdata.ResourceMetrics, metricName string, expectedValue any)
AssertMetricValue finds a metric by name and asserts its value. For Sum metrics (counters, up-down counters), it asserts the first data point value. For Histogram metrics, it asserts the count.
func AssertSpanAttribute ¶
AssertSpanAttribute asserts that a span has a specific attribute with the expected value.
func AssertSpanError ¶
AssertSpanError asserts that a span has an error status with the expected description.
func AssertSpanName ¶
AssertSpanName asserts the name of a span.
func AssertSpanStatus ¶
AssertSpanStatus asserts the status of a span.
func AssertSpanStatusDescription ¶
AssertSpanStatusDescription asserts the status description of a span.
func FindMetric ¶
func FindMetric(rm metricdata.ResourceMetrics, metricName string) *metricdata.Metrics
FindMetric finds a metric by name in the ResourceMetrics. Returns nil if not found.
func GetMetricHistogramCount ¶
func GetMetricHistogramCount(rm metricdata.ResourceMetrics, metricName string) (uint64, error)
GetMetricHistogramCount gets the count for a Histogram metric. Returns error if metric not found or wrong type.
func GetMetricSumValue ¶
func GetMetricSumValue(rm metricdata.ResourceMetrics, metricName string) (any, error)
GetMetricSumValue gets the sum value for a Sum[int64] or Sum[float64] metric. Returns error if metric not found or wrong type.
Types ¶
type SpanCollector ¶
type SpanCollector struct {
// contains filtered or unexported fields
}
SpanCollector provides a fluent API for filtering and asserting on captured spans.
Example ¶
ExampleSpanCollector demonstrates filtering spans by name and attributes. Note: In actual tests, use NewSpanCollector with a testing.T parameter for assertions.
package main
import (
"context"
"fmt"
"go.opentelemetry.io/otel/attribute"
obtest "github.com/gaborage/go-bricks/observability/testing"
)
const (
httpMethodAttr = "http.method"
dbSystemAttr = "db.system"
databaseQuerySpan = "database-query"
)
func main() {
tp := obtest.NewTestTraceProvider()
defer tp.Shutdown(context.Background())
tracer := tp.Tracer("example")
// Create multiple spans with different attributes
_, span1 := tracer.Start(context.Background(), databaseQuerySpan)
span1.SetAttributes(attribute.String(dbSystemAttr, "postgresql"))
span1.End()
_, span2 := tracer.Start(context.Background(), "http-request")
span2.SetAttributes(attribute.String(httpMethodAttr, "POST"))
span2.End()
_, span3 := tracer.Start(context.Background(), databaseQuerySpan)
span3.SetAttributes(attribute.String(dbSystemAttr, "mongodb"))
span3.End()
// Get spans and count them by filtering
spans := tp.Exporter.GetSpans()
// Count database query spans
dbCount := 0
pgCount := 0
for i := range spans {
if spans[i].Name == databaseQuerySpan {
dbCount++
// Check for PostgreSQL attribute
for _, attr := range spans[i].Attributes {
if attr.Key == attribute.Key(dbSystemAttr) && attr.Value.AsString() == "postgresql" {
pgCount++
break
}
}
}
}
fmt.Printf("Database queries: %d\n", dbCount)
fmt.Printf("PostgreSQL queries: %d\n", pgCount)
}
Output: Database queries: 2 PostgreSQL queries: 1
func NewSpanCollector ¶
func NewSpanCollector(t *testing.T, exporter *tracetest.InMemoryExporter) *SpanCollector
NewSpanCollector creates a span collector from an in-memory exporter.
func (*SpanCollector) AssertCount ¶
func (sc *SpanCollector) AssertCount(expected int) *SpanCollector
AssertCount asserts the number of collected spans.
func (*SpanCollector) AssertEmpty ¶
func (sc *SpanCollector) AssertEmpty() *SpanCollector
AssertEmpty asserts that the collection is empty.
func (*SpanCollector) First ¶
func (sc *SpanCollector) First() tracetest.SpanStub
First returns the first span in the collection. Fails the test if the collection is empty.
func (*SpanCollector) Get ¶
func (sc *SpanCollector) Get(index int) tracetest.SpanStub
Get returns the span at the given index. Fails the test if the index is out of bounds.
func (*SpanCollector) Len ¶
func (sc *SpanCollector) Len() int
Len returns the number of collected spans.
func (*SpanCollector) WithAttribute ¶
func (sc *SpanCollector) WithAttribute(key string, value any) *SpanCollector
WithAttribute filters spans by attribute key-value pair and returns a new collector.
func (*SpanCollector) WithName ¶
func (sc *SpanCollector) WithName(name string) *SpanCollector
WithName filters spans by name and returns a new collector.
type TestMeterProvider ¶
type TestMeterProvider struct {
*sdkmetric.MeterProvider
Reader *sdkmetric.ManualReader
}
TestMeterProvider wraps the SDK MeterProvider and manual reader for testing.
func NewTestMeterProvider ¶
func NewTestMeterProvider() *TestMeterProvider
NewTestMeterProvider creates a MeterProvider with a manual reader for testing. The manual reader allows collecting metrics on-demand for assertions without periodic exports.
Example:
mp := NewTestMeterProvider()
defer mp.Shutdown(context.Background())
// Use the provider in your tests
otel.SetMeterProvider(mp)
meter := mp.Meter("test")
counter, _ := meter.Int64Counter("test.counter")
counter.Add(context.Background(), 1)
// Collect metrics for assertions
rm := mp.Collect(t)
Example ¶
ExampleNewTestMeterProvider demonstrates how to use the test meter provider to assert metrics created by your code.
package main
import (
"context"
"fmt"
"go.opentelemetry.io/otel"
obtest "github.com/gaborage/go-bricks/observability/testing"
)
func main() {
// Create a test meter provider with manual reader
mp := obtest.NewTestMeterProvider()
defer mp.Shutdown(context.Background())
// Set as global provider (or use directly)
otel.SetMeterProvider(mp)
// Your code that records metrics
meter := mp.Meter("example-service")
counter, _ := meter.Int64Counter("requests.count") // Metric options can be added here
counter.Add(context.Background(), 1) // Attributes can be added to metric recordings
counter.Add(context.Background(), 2)
// Collect metrics for assertions
// In real usage, you would pass the testing.T instance
// rm := mp.Collect(t)
fmt.Println("Metrics collected successfully")
}
Output: Metrics collected successfully
func (*TestMeterProvider) Collect ¶
func (tmp *TestMeterProvider) Collect(t *testing.T) metricdata.ResourceMetrics
Collect reads all metrics from the provider and returns them as ResourceMetrics. This is a convenience wrapper around Reader.Collect() with error handling.
type TestTraceProvider ¶
type TestTraceProvider struct {
*sdktrace.TracerProvider
Exporter *tracetest.InMemoryExporter
}
TestTraceProvider wraps the SDK TracerProvider and in-memory exporter for testing.
func NewTestTraceProvider ¶
func NewTestTraceProvider() *TestTraceProvider
NewTestTraceProvider creates a TracerProvider with an in-memory exporter for testing. The returned provider captures all spans in memory for assertion without sending them to an external backend.
Example:
tp := NewTestTraceProvider() defer tp.Shutdown(context.Background()) // Use the provider in your tests otel.SetTracerProvider(tp) // Later, get spans for assertions spans := tp.Exporter.GetSpans()
Example ¶
ExampleNewTestTraceProvider demonstrates how to use the test trace provider to assert spans created by your code.
package main
import (
"context"
"fmt"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/attribute"
obtest "github.com/gaborage/go-bricks/observability/testing"
)
const httpMethodAttr = "http.method"
func main() {
// Create a test trace provider with in-memory exporter
tp := obtest.NewTestTraceProvider()
defer tp.Shutdown(context.Background())
// Set as global provider (or use directly)
otel.SetTracerProvider(tp)
// Your code that creates spans
tracer := tp.Tracer("example-service")
_, span := tracer.Start(context.Background(), "process-request")
span.SetAttributes(
attribute.String(httpMethodAttr, "GET"),
attribute.String("http.url", "/api/users"),
attribute.Int("http.status_code", 200),
)
span.End()
// Get captured spans for assertions
spans := tp.Exporter.GetSpans()
fmt.Printf("Captured %d spans\n", len(spans))
}
Output: Captured 1 spans
func (*TestTraceProvider) TestTracer ¶ added in v0.18.0
func (ttp *TestTraceProvider) TestTracer() trace.Tracer
TestTracer returns a tracer with the standard test name. This is a convenience method that eliminates the need to pass TestTracerName to the Tracer() method in every test.
Example:
tp := NewTestTraceProvider() tracer := tp.TestTracer() _, span := tracer.Start(context.Background(), "operation")