Skip to content

feat: add OTEL HTTP tracing middleware#159

Merged
intel352 merged 1 commit intomainfrom
feat/otel-http-middleware
Feb 25, 2026
Merged

feat: add OTEL HTTP tracing middleware#159
intel352 merged 1 commit intomainfrom
feat/otel-http-middleware

Conversation

@intel352
Copy link
Contributor

Summary

  • Adds http.middleware.otel module type to the observability plugin
  • Wraps HTTP handlers with otelhttp.NewHandler() to create spans for every incoming request
  • Configurable serverName (default: workflow-http) used as the span operation name
  • Works without the observability.otel module loaded (uses global TracerProvider, defaults to noop)

Test plan

  • go test ./module/ -run TestOTel -v passes
  • go build ./... succeeds
  • Configure http.middleware.otel in cloud.yaml to verify Jaeger receives HTTP spans

🤖 Generated with Claude Code

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings February 25, 2026 00:58
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds an OpenTelemetry-instrumented HTTP middleware module type so incoming HTTP requests are automatically wrapped with otelhttp.NewHandler() and emit tracing spans, wired via the observability plugin.

Changes:

  • Register new module type http.middleware.otel in the observability plugin manifest/factories/schemas.
  • Add module.OTelMiddleware implementation that wraps http.Handler with otelhttp.
  • Add unit tests for the new middleware module and add otelhttp dependency in go.mod.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
plugins/observability/schemas.go Adds UI schema for http.middleware.otel and its serverName config.
plugins/observability/plugin.go Declares http.middleware.otel in the observability plugin manifest.
plugins/observability/modules.go Registers the module factory and adds otelMiddlewareFactory.
module/http_middleware_otel.go Implements OTelMiddleware using otelhttp.NewHandler.
module/http_middleware_otel_test.go Adds basic module interface and handler-wrapping tests.
go.mod Promotes otelhttp to a direct dependency.

Comment on lines +79 to +88
{
Type: "http.middleware.otel",
Label: "OTEL HTTP Middleware",
Category: "observability",
Description: "Instruments HTTP requests with OpenTelemetry tracing spans",
ConfigFields: []schema.ConfigFieldDef{
{Key: "serverName", Label: "Server Name", Type: schema.FieldTypeString, DefaultValue: "workflow-http", Description: "Server name used as the span operation name", Placeholder: "workflow-http"},
},
DefaultConfig: map[string]any{"serverName": "workflow-http"},
},
Copy link

Copilot AI Feb 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The schema for http.middleware.otel is missing the Inputs/Outputs fields that all existing http.middleware.* schemas define (see plugins/http/schemas.go). If this type stays as http.middleware.*, consider aligning the schema shape (and likely Category: "middleware") so UI/schema consumers treat it consistently with other middleware types.

Copilot uses AI. Check for mistakes.
"log.collector",
"observability.otel",
"openapi.generator",
"http.middleware.otel",
Copy link

Copilot AI Feb 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding a new module type here requires updating the observability plugin’s unit tests (e.g., TestModuleFactories/TestModuleSchemas/TestModuleTypeCoverage in plugins/observability/plugin_test.go) which currently assert an exact set/count of module types. As-is, go test ./... will fail until the new http.middleware.otel type is included in those expected lists/maps.

Suggested change
"http.middleware.otel",

Copilot uses AI. Check for mistakes.
Comment on lines +123 to +124
if v, ok := cfg["serverName"].(string); ok && v != "" {
serverName = v
Copy link

Copilot AI Feb 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

otelMiddlewareFactory dereferences cfg without a nil check. ModuleConfig.Config can be nil when the config: section is omitted (and the engine only injects a map when ConfigDir is set), which would panic at runtime. Treat nil as an empty map (or early-return the default) before reading cfg["serverName"].

Suggested change
if v, ok := cfg["serverName"].(string); ok && v != "" {
serverName = v
if cfg != nil {
if v, ok := cfg["serverName"].(string); ok && v != "" {
serverName = v
}

Copilot uses AI. Check for mistakes.
Comment on lines 13 to 20
return map[string]plugin.ModuleFactory{
"metrics.collector": metricsCollectorFactory,
"health.checker": healthCheckerFactory,
"log.collector": logCollectorFactory,
"observability.otel": otelTracingFactory,
"openapi.generator": openAPIGeneratorFactory,
"http.middleware.otel": otelMiddlewareFactory,
}
Copy link

Copilot AI Feb 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This introduces an http.middleware.* module type in the observability plugin, but all other http.middleware.* types are owned/declared by the HTTP plugin (see plugins/http/plugin.go and plugins/http/modules.go). Consider moving the factory+schema+manifest entry to the HTTP plugin (or renaming the type) to keep module-type ownership consistent and avoid future duplicate-type registration conflicts if the HTTP plugin later adds http.middleware.otel.

Copilot uses AI. Check for mistakes.
@intel352 intel352 merged commit 59f682f into main Feb 25, 2026
17 of 18 checks passed
@intel352 intel352 deleted the feat/otel-http-middleware branch February 25, 2026 03:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants