echootel

package module
v0.0.1 Latest Latest
Warning

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

Go to latest
Published: Feb 18, 2026 License: MIT Imports: 18 Imported by: 0

README

Sourcegraph GoDoc Go Report Card Codecov License

Echo OpenTelemetry (OTel) middleware

OpenTelemetry middleware for Echo framework.

Versioning

  • version v0.x.y tracks the latest Echo version (v5).
  • main branch is compatible with the latest Echo version (v5).

Usage

Add OpenTelemetry middleware dependency with go modules

go get github.com/labstack/echo-opentelemetry

Use as an import statement

import echootel "github.com/labstack/echo-opentelemetry"

Add middleware in simplified form, by providing only the server name

e.Use(echootel.NewMiddleware("app.example.com"))

Add middleware with configuration options

e.Use(echootel.NewMiddlewareWithConfig(echootel.Config{
  TracerProvider: tp,
}))

Retrieving the tracer from the Echo context

tp, err := echo.ContextGet[trace.Tracer](c, echootel.TracerKey)

Full example

See example

Documentation

Index

Constants

View Source
const (
	// TracerKey is the key used to store the tracer in the echo context.
	TracerKey = "labstack-echo-otelecho-tracer"
	// ScopeName is the instrumentation scope name.
	ScopeName = "github.com/labstack/echo-opentelemetry"
)
View Source
const Version = "0.0.1"

Version is the current release version of the echo instrumentation.

Variables

This section is empty.

Functions

func NewMiddleware

func NewMiddleware(serverName string) echo.MiddlewareFunc

NewMiddleware creates new echo opentelemetry middleware with the given server name.

func NewMiddlewareWithConfig

func NewMiddlewareWithConfig(config Config) echo.MiddlewareFunc

NewMiddlewareWithConfig creates new echo opentelemetry middleware with the given configuration.

func SpanNameFormatter

func SpanNameFormatter(v Values) string

SpanNameFormatter returns the default format for the span name based on the HTTP method and path.

HTTP span names SHOULD be `{method} {target}` if there is a (low-cardinality) `target` available. If there is no (low-cardinality) `{target}` available, HTTP span names SHOULD be `{method}`.

The `{method}` MUST be `{http.request.method}` if the method represents the original method known to the instrumentation. In other cases (when `{http.request.method}` is set to `_OTHER`), `{method}` MUST be `HTTP`

Spec: https://opentelemetry.io/docs/specs/semconv/http/http-spans/#name

func SplitAddress

func SplitAddress(address string) (host string, port int, err error)

SplitAddress splits server address or host into host (`server.address`) and port (`server.port`). Empty address is accepted and returns empty host and port. Port is part is not mandatory in address and can be omitted.

Types

type AttributesFunc

type AttributesFunc func(c *echo.Context, v *Values, attr []attribute.KeyValue) []attribute.KeyValue

AttributesFunc is used to extract additional attributes from the echo.Context and return them as a slice of attribute.KeyValue.

type Config

type Config struct {
	// ServerName is set as `server.address` and `server.port` for span and metrics attributes.
	// Example: "api.example.com" or "example.com:8080"
	//
	// If known, this value must be set to the server’s canonical (primary) name.
	// For example, in Apache this corresponds to the ServerName directive
	// (https://httpd.apache.org/docs/2.4/mod/core.html#servername), and in NGINX
	// to the server_name directive
	// (http://nginx.org/en/docs/http/ngx_http_core_module.html#server_name).
	//
	// More generally, the primary server name is the host header value that maps
	// to the HTTP server’s default virtual host. It must include the hostname,
	// and if the server is accessed via a non-default port, the port must be
	// appended using the standard ":port" suffix.
	//
	// If the primary server name is unknown, this field should be set to an
	// empty string. In that case, Request.Host will be used to resolve the
	// effective server name and port.
	ServerName string

	// Skipper defines a function to skip middleware.
	Skipper middleware.Skipper

	// OnNextError is used to specify how errors returned from the next middleware / handler are handled.
	OnNextError OnErrorFunc

	// OnExtractionError is used to specify how errors returned from request extraction are handled.
	OnExtractionError OnErrorFunc

	// TracerProvider allows overriding the default tracer provider.
	TracerProvider oteltrace.TracerProvider

	// MeterProvider allows overriding the default meter provider.
	MeterProvider metric.MeterProvider

	// Propagators allow overriding the default propagators.
	Propagators propagation.TextMapPropagator

	// SpanStartOptions configures an additional set of trace.SpanStartOptions, which are applied to each new span.
	SpanStartOptions []oteltrace.SpanStartOption

	// SpanStartAttributes is used to extract additional attributes from the echo.Context
	// and return them as a slice of attribute.KeyValue.
	SpanStartAttributes AttributesFunc

	// SpanEndAttributes is used to extract additional attributes from the echo.Context
	// and return them as a slice of attribute.KeyValue.
	SpanEndAttributes AttributesFunc

	// MetricAttributes is used to compose attributes just before Metrics.Record call.
	MetricAttributes MetricAttributesFunc

	// Metrics is used to record custom metrics instead of default.
	Metrics MetricsRecorder
}

Config is used to configure the middleware.

func (Config) ToMiddleware

func (config Config) ToMiddleware() (echo.MiddlewareFunc, error)

ToMiddleware returns echo opentelemetry middleware which will trace incoming requests.

type MetricAttributesFunc

type MetricAttributesFunc func(c *echo.Context, v *Values) []attribute.KeyValue

MetricAttributesFunc is used to compose attributes for Metrics.Record.

type Metrics

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

Metrics holds a standard set of OpenTelemetry global request/response metrics

func NewMetrics

func NewMetrics(meter metric.Meter) (*Metrics, error)

NewMetrics creates a new Metrics instance for Standard Required metric instances with the given Meter.

func (*Metrics) Record

func (m *Metrics) Record(ctx context.Context, v RecordValues)

Record records the given RecordValues to the Metrics instance.

type MetricsRecorder

type MetricsRecorder interface {
	Record(c *echo.Context, v RecordValues)
}

MetricsRecorder is used to record metrics.

type OnErrorFunc

type OnErrorFunc func(c *echo.Context, err error)

OnErrorFunc is used to specify how errors are handled in the middleware.

type RecordValues

type RecordValues struct {
	// RequestDuration is the duration of request processing. Will be used with `http.server.request.duration` metric.
	RequestDuration time.Duration

	// ExtractedValues are values extracted from HTTP request and response before and after processing the next middleware/handler.
	ExtractedValues Values

	// Attributes are attributes to be used for recording metrics.
	// If left empty, the Metrics.Record method will use default attributes by calling Values.MetricAttributes().
	Attributes []attribute.KeyValue
}

RecordValues represents the values to Record metrics.

type Values

type Values struct {
	// HTTPMethod (`http.request.method`) - HTTP request method.
	//
	// If the HTTP request method is not known to instrumentation, it MUST set the `http.request.method` attribute to `_OTHER`
	//
	// If the HTTP instrumentation could end up converting valid HTTP request methods to `_OTHER`, then it MUST provide a
	// way to override the list of known HTTP methods. If this override is done via environment variable, then the
	// environment variable MUST be named `OTEL_INSTRUMENTATION_HTTP_KNOWN_METHODS` and support a comma-separated list of
	// case-sensitive known HTTP methods (this list MUST be a full override of the default known method, it is not a
	// list of known methods in addition to the defaults).
	//
	// HTTP method names are case-sensitive and `http.request.method` attribute value MUST match a known HTTP method name
	// exactly. Instrumentations for specific web frameworks that consider HTTP methods to be case insensitive, SHOULD
	// populate a canonical equivalent. Tracing instrumentations that do so, MUST also set `http.request.method_original`
	// to the original value.
	//
	// Example: `GET`, `POST`, `_OTHER`
	// Spec: https://opentelemetry.io/docs/specs/semconv/registry/attributes/http/
	//
	// Requirement Level:
	//  * span - Required
	//  * metric - Required
	HTTPMethod string // metric, span

	// HTTPMethodOriginal (`http.request.method_original`) is original HTTP method sent by the client in the request line.
	// Example: `GeT`, `ACL`, `foo`
	//
	// Requirement Level:
	//  * span - conditionally required if raw value differs from `http.request.method` (different case) or `http.request.method` is `_OTHER`
	//  * metric - opt in, same rules as span
	HTTPMethodOriginal string // metric, span

	// ServerAddress (`server.address`) is the Name of the local HTTP server that received the request.
	// This value can be provided by middleware configuration or extracted from `Request.Host`.
	// Example values: `example.com` `10.1.2.80`, `/tmp/my.sock`
	// See also: https://opentelemetry.io/docs/specs/semconv/http/http-spans/#setting-serveraddress-and-serverport-attributes
	// Spec: https://opentelemetry.io/docs/specs/semconv/registry/attributes/server/
	//
	// Requirement Level:
	//  * span - Recommended
	//  * metric - Opt-In
	ServerAddress string // metric, span

	// ServerPort (`server.port`) is the Port of the local HTTP server that received the request.
	// This value can be provided by middleware configuration or extracted from `Request.Host`.
	// Example values: `80` `8080`, `443`
	// See also: https://opentelemetry.io/docs/specs/semconv/http/http-spans/#setting-serveraddress-and-serverport-attributes
	// Spec: https://opentelemetry.io/docs/specs/semconv/registry/attributes/server/
	//
	// Requirement Level:
	//  * span - conditionally Required if available and `server.address` is set
	//  * metric - Opt-In
	ServerPort int // metric, span

	// NetworkPeerAdress (`network.peer.address`) is peer address of the network connection - IP address or Unix domain socket name.
	// Spec: https://opentelemetry.io/docs/specs/semconv/registry/attributes/network/
	//
	// Go: This value is derived from `Request.RemoteAddr` field value.
	//
	// Requirement Level:
	//  * span - Recommended
	//  * metric - not used
	NetworkPeerAddress string // span (optional)

	// NetworkPeerPort (`network.peer.port`) is peer port number of the network connection.
	// Spec: https://opentelemetry.io/docs/specs/semconv/registry/attributes/network/
	//
	// Go: This value is derived from `Request.RemoteAddr` field value.
	//
	// Requirement Level:
	//  * span - Recommended if `network.peer.address` is set.
	//  * metric - not used
	NetworkPeerPort int // span (optional)

	// ClientAddress (`client.address`) is client address - domain name if available without reverse DNS lookup;
	// otherwise, IP address or Unix domain socket name.
	// Spec: https://opentelemetry.io/docs/specs/semconv/registry/attributes/client/
	//
	// Go: This value is derived by default from `Request.RemoteAddr` field value and is same as `network.peer.address`.
	//     Middleware creators or users can override with `Request.Header.Get("X-Forwarded-For")` value but be warned
	//     that it is very easy to spoof HTTP headers.
	//
	// Requirement Level:
	//  * span - Recommended if `network.peer.address` is set.
	//  * metric - not used
	ClientAddress string // span (optional)

	// URLScheme (`url.scheme`) is the [URI scheme](https://www.rfc-editor.org/rfc/rfc3986#section-3.1) component
	// identifying the used protocol.
	// The scheme of the original client request, if possible, from one of these headers:
	// - [Forwarded#proto](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Forwarded#proto)
	// - [X-Forwarded-Proto](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Forwarded-Proto)
	// - Otherwise, the scheme of the immediate peer request.
	// Example values: `http`, `https`
	//
	// Requirement Level:
	//  * span - Required
	//  * metric - Required
	URLScheme string // metric, span

	// URLPath (`url.path`) is the [URI](https://www.rfc-editor.org/rfc/rfc3986#section-3.3) path component.
	// Spec: https://opentelemetry.io/docs/specs/semconv/registry/attributes/url/
	//
	// Go: This value is taken from `Request.URL.Path` method value.
	//
	// Requirement Level:
	//  * span - Required
	//  * metric - not used
	URLPath string // span

	// UserAgentOriginal (`user_agent.original`) is the value of the [HTTP User-Agent](https://www.rfc-editor.org/rfc/rfc9110.html#field.user-agent)
	// header sent by the client.
	// Spec: https://opentelemetry.io/docs/specs/semconv/registry/attributes/user-agent/
	//
	// Go: This value is taken from `Request.UserAgent()` method value.
	//
	// Requirement Level:
	//  * span - Recommended
	//  * metric - not used
	UserAgentOriginal string // span

	// NetworkProtocolName (`network.protocol.name`) is OSI application layer or non-OSI equivalent.
	// Value is required if not value is not `http` and `network.protocol.version` value is set.
	// The value SHOULD be normalized to lowercase.
	// Example: `http`, `quic`, `spdy`
	// Spec: https://opentelemetry.io/docs/specs/semconv/registry/attributes/network/
	//
	// Go: This value is derived from `Request.Proto` field value.
	//
	// Requirement Level:
	//  * span - conditionally Required if available and `network.protocol.version` is set
	//  * metric - conditionally Required if available and `network.protocol.version` is set
	NetworkProtocolName string // metric, span

	// NetworkProtocolVersion (`network.protocol.version`) is the actual version of the protocol used for network communication.
	// Example: `1.0`, `1.1`, `2`, `3`
	// Spec: https://opentelemetry.io/docs/specs/semconv/registry/attributes/network/
	//
	// Go: This value is derived from `Request.Proto` field value.
	//
	// Requirement Level:
	//  * span - Recommended
	//  * metric - Recommended
	NetworkProtocolVersion string // metric, span

	// HTTPRoute (`http.route`) is the matched route template for the request. This MUST be low-cardinality and include
	// all static path segments, with dynamic path segments represented with placeholders.
	// Spec: https://opentelemetry.io/docs/specs/semconv/registry/attributes/http/
	//
	// Go: This value is taken from `Request.Pattern` field.
	//
	// Requirement Level:
	//  * span - Recommended
	//  * metric - Conditionally Required If and only if it's available
	HTTPRoute string // metric, span

	// HTTPRequestBodySize (`http.request.body.size`) is the size of the request payload body in bytes. This is the number
	// of bytes transferred excluding headers and is often, but not always, present as the [Content-Length](https://www.rfc-editor.org/rfc/rfc9110.html#field.content-length)
	// header. For requests using transport encoding, this should be the compressed size.
	// Spec: https://opentelemetry.io/docs/specs/semconv/http/http-metrics/#metric-httpclientrequestbodysize
	//
	// Go: This value is taken from `Request.ContentLength` can be negative (-1) if the size is unknown.
	//
	// Requirement Level:
	//  * span - opt-in attribute
	//  * metric - optional, is actual Histogram metric (`http.client.request.body.size`) and NOT attribute to metric.
	HTTPRequestBodySize int64 // metric

	// HTTPResponseStatusCode (`http.response.status_code`) is HTTP response status code.
	// See also RFC: https://datatracker.ietf.org/doc/html/rfc7231#section-6
	// Spec: https://opentelemetry.io/docs/specs/semconv/registry/attributes/http/
	//
	// Requirement Level:
	//  * span - opt-in attribute
	//  * metric - conditionally Required if and only if one was received/sent
	HTTPResponseStatusCode int // metric

	// HTTPResponseBodySize (`http.response.body.size`) is the size of the response payload body in bytes. This is
	// the number of bytes transferred excluding headers and is often, but not always, present as the
	// [Content-Length](https://www.rfc-editor.org/rfc/rfc9110.html#field.content-length) header. For requests using
	// transport encoding, this should be the compressed size.
	// Spec: https://opentelemetry.io/docs/specs/semconv/http/http-metrics/#metric-httpserverresponsebodysize
	//
	// Requirement Level:
	//  * span - opt-in attribute
	//  * metric - optional, is actual Histogram metric (`http.server.response.body.size`) and NOT attribute to metric.
	HTTPResponseBodySize int64 // metric
}

Values represent extracted values from HTTP request and response to be used for Span and Metrics attributes.

Span: Semantic Conventions for HTTP client and server spans. https://opentelemetry.io/docs/specs/semconv/http/http-spans/ Metrics: Semantic Conventions for HTTP client and server metrics. https://opentelemetry.io/docs/specs/semconv/http/http-metrics/

func (*Values) ExtractRequest

func (v *Values) ExtractRequest(r *http.Request) error

ExtractRequest extracts values from the given HTTP request and populates the Values struct.

func (*Values) MetricAttributes

func (v *Values) MetricAttributes() []attribute.KeyValue

MetricAttributes creates attributes for metric instruments from extracted values. See also: https://opentelemetry.io/docs/specs/semconv/http/http-metrics/

func (*Values) SpanEndAttributes

func (v *Values) SpanEndAttributes() []attribute.KeyValue

SpanEndAttributes returns a list of attributes to be used when ending a span, after the next handler has been executed.

func (*Values) SpanStartAttributes

func (v *Values) SpanStartAttributes() []attribute.KeyValue

SpanStartAttributes returns a list of attributes to be used when starting a span.

Jump to

Keyboard shortcuts

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