Part of duplicate code analysis: #7509
Summary
The four Start*Span factory functions in internal/tracing/span_helpers.go share an identical structural skeleton — only the span name, log message, attributes, and span kind differ. This is 4 instances of the same ~10-line pattern, meeting the 3+ similar patterns threshold.
Duplication Details
Pattern: Repeated tracer.Start boilerplate across 4 span factory functions
- Severity: Low
- Occurrences: 4
- Locations:
internal/tracing/span_helpers.go (lines 36-86)
- Code Sample:
// All four functions follow this identical skeleton:
func StartXxxSpan(ctx context.Context, tracer oteltrace.Tracer, <params>) (context.Context, oteltrace.Span) {
logTracing.Printf("Starting X span: <fields>")
return tracer.Start(ctx, "span.name",
oteltrace.WithAttributes(<attrs>...),
oteltrace.WithSpanKind(oteltrace.SpanKind<Kind>),
)
}
Concrete instances:
StartToolCallSpan (line 36) – SpanKindInternal, 4 attributes
StartBackendExecuteSpan (line 51) – SpanKindClient, 2 attributes
StartDIFCPipelineSpan (line 64) – SpanKindInternal, 2 attributes
StartProxyForwardSpan (line 77) – SpanKindClient, 2 attributes
Impact Analysis
- Maintainability: Every new span type requires copy-pasting the same structure; easy to omit the
logTracing.Printf call or misconfigure SpanKind
- Bug Risk: Low currently, but will increase as more span types are added
- Code Bloat: ~40 lines that could be reduced to ~10 with a shared private helper
Refactoring Recommendations
-
Extract a private startSpan helper
// startSpan is the shared inner implementation used by all public Start*Span helpers.
func startSpan(ctx context.Context, tracer oteltrace.Tracer, spanName string, kind oteltrace.SpanKind, attrs ...attribute.KeyValue) (context.Context, oteltrace.Span) {
return tracer.Start(ctx, spanName,
oteltrace.WithAttributes(attrs...),
oteltrace.WithSpanKind(kind),
)
}
Public wrappers then delegate to it, keeping their log lines and specific attribute construction.
-
Location: internal/tracing/span_helpers.go
-
Estimated effort: ~1 hour
-
Benefits: New span types become one-liners; SpanKind is harder to misconfigure; consistent log format
Implementation Checklist
Parent Issue
See parent analysis report: #7509
Related to #7509
Generated by Duplicate Code Detector · 1.9K AIC · ⊞ 35.7K · ◷
Part of duplicate code analysis: #7509
Summary
The four
Start*Spanfactory functions ininternal/tracing/span_helpers.goshare an identical structural skeleton — only the span name, log message, attributes, and span kind differ. This is 4 instances of the same ~10-line pattern, meeting the 3+ similar patterns threshold.Duplication Details
Pattern: Repeated
tracer.Startboilerplate across 4 span factory functionsinternal/tracing/span_helpers.go(lines 36-86)Concrete instances:
StartToolCallSpan(line 36) –SpanKindInternal, 4 attributesStartBackendExecuteSpan(line 51) –SpanKindClient, 2 attributesStartDIFCPipelineSpan(line 64) –SpanKindInternal, 2 attributesStartProxyForwardSpan(line 77) –SpanKindClient, 2 attributesImpact Analysis
logTracing.Printfcall or misconfigureSpanKindRefactoring Recommendations
Extract a private
startSpanhelperPublic wrappers then delegate to it, keeping their log lines and specific attribute construction.
Location:
internal/tracing/span_helpers.goEstimated effort: ~1 hour
Benefits: New span types become one-liners;
SpanKindis harder to misconfigure; consistent log formatImplementation Checklist
startSpanhelper inspan_helpers.goStart*Spanfunctions to delegate to itmake test)Parent Issue
See parent analysis report: #7509
Related to #7509