Conversation
Prepend a URL scheme to bare IP:port endpoints so the OTel SDK can parse them. Use WithEndpointURL consistently for all exporters and update the env var so the SDK reads a valid URL internally. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Issue: LFXV2-612 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: Trevor Bramwell <tbramwell@linuxfoundation.org>
WithEndpointURL receives the normalized endpoint explicitly, making the env var mutation unnecessary. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Issue: LFXV2-612 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: Trevor Bramwell <tbramwell@linuxfoundation.org>
WalkthroughOTLP endpoint handling is normalized by introducing a helper function that prepends URL schemes when missing. This helper is applied early during SDK setup, and all exporter constructors are updated to use the normalized endpoint value. Changes
Estimated code review effort🎯 2 (Simple) | ⏱️ ~12 minutes 🚥 Pre-merge checks | ✅ 4✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
🧪 Generate unit tests (beta)
No actionable comments were generated in the recent review. 🎉 🧹 Recent nitpick comments
Comment |
There was a problem hiding this comment.
Pull request overview
This pull request fixes an issue where bare IP:port endpoint values (e.g., 127.0.0.1:4317) would cause URL parsing errors in the OpenTelemetry SDK. The solution normalizes endpoints by adding proper URL schemes based on the insecure flag before passing them to the SDK.
Changes:
- Added
endpointURLhelper function to prependhttp://orhttps://scheme to endpoints that lack one - Updated all OTel exporter initializations (traces, metrics, logs for both HTTP and gRPC) to use
WithEndpointURLinstead ofWithEndpoint - Added comprehensive unit tests for the
endpointURLhelper and integration test for bare IP:port endpoint handling
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.
| File | Description |
|---|---|
| pkg/utils/otel.go | Added endpointURL helper function and endpoint normalization in SetupOTelSDKWithConfig; updated all 6 exporter initializations to use WithEndpointURL |
| pkg/utils/otel_test.go | Added unit tests for endpointURL helper covering various endpoint formats; added integration test for bare IP:port endpoint; minor import formatting change |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| func TestEndpointURL(t *testing.T) { | ||
| tests := []struct { | ||
| name string | ||
| raw string | ||
| insecure bool | ||
| want string | ||
| }{ | ||
| { | ||
| name: "IP:port insecure", | ||
| raw: "127.0.0.1:4317", | ||
| insecure: true, | ||
| want: "http://127.0.0.1:4317", | ||
| }, | ||
| { | ||
| name: "IP:port secure", | ||
| raw: "127.0.0.1:4317", | ||
| insecure: false, | ||
| want: "https://127.0.0.1:4317", | ||
| }, | ||
| { | ||
| name: "localhost:port insecure", | ||
| raw: "localhost:4317", | ||
| insecure: true, | ||
| want: "http://localhost:4317", | ||
| }, | ||
| { | ||
| name: "hostname without port", | ||
| raw: "collector", | ||
| insecure: true, | ||
| want: "http://collector", | ||
| }, | ||
| { | ||
| name: "http URL preserved", | ||
| raw: "http://collector.example.com:4318", | ||
| insecure: false, | ||
| want: "http://collector.example.com:4318", | ||
| }, | ||
| { | ||
| name: "https URL preserved", | ||
| raw: "https://collector.example.com:4318", | ||
| insecure: true, | ||
| want: "https://collector.example.com:4318", | ||
| }, | ||
| { | ||
| name: "https URL with path preserved", | ||
| raw: "https://collector.example.com:4318/v1/traces", | ||
| insecure: false, | ||
| want: "https://collector.example.com:4318/v1/traces", | ||
| }, | ||
| } | ||
|
|
||
| for _, tt := range tests { | ||
| t.Run(tt.name, func(t *testing.T) { | ||
| got := endpointURL(tt.raw, tt.insecure) | ||
| if got != tt.want { | ||
| t.Errorf("endpointURL(%q, %t) = %q, want %q", tt.raw, tt.insecure, got, tt.want) | ||
| } | ||
| }) | ||
| } | ||
| } |
There was a problem hiding this comment.
Test coverage is missing for IPv6 address formats. IPv6 endpoints use bracket notation like [::1]:4317 or [2001:db8::1]:4317. The endpointURL function should handle these correctly (resulting in http://[::1]:4317), but there are no test cases to verify this behavior. Consider adding test cases for IPv6 addresses to ensure they work correctly.
| t.Setenv("OTEL_EXPORTER_OTLP_ENDPOINT", "127.0.0.1:4317") | ||
|
|
There was a problem hiding this comment.
The t.Setenv("OTEL_EXPORTER_OTLP_ENDPOINT", "127.0.0.1:4317") call appears unnecessary in this test. The test is using SetupOTelSDKWithConfig directly with a config object that already has Endpoint: "127.0.0.1:4317" set. The environment variable would only be used if calling OTelConfigFromEnv(), which this test does not do. This could be confusing for future maintainers. Consider removing this line unless it's testing environment variable interaction specifically.
| t.Setenv("OTEL_EXPORTER_OTLP_ENDPOINT", "127.0.0.1:4317") |
| func TestEndpointURL(t *testing.T) { | ||
| tests := []struct { | ||
| name string | ||
| raw string | ||
| insecure bool | ||
| want string | ||
| }{ | ||
| { | ||
| name: "IP:port insecure", | ||
| raw: "127.0.0.1:4317", | ||
| insecure: true, | ||
| want: "http://127.0.0.1:4317", | ||
| }, | ||
| { | ||
| name: "IP:port secure", | ||
| raw: "127.0.0.1:4317", | ||
| insecure: false, | ||
| want: "https://127.0.0.1:4317", | ||
| }, | ||
| { | ||
| name: "localhost:port insecure", | ||
| raw: "localhost:4317", | ||
| insecure: true, | ||
| want: "http://localhost:4317", | ||
| }, | ||
| { | ||
| name: "hostname without port", | ||
| raw: "collector", | ||
| insecure: true, | ||
| want: "http://collector", | ||
| }, | ||
| { | ||
| name: "http URL preserved", | ||
| raw: "http://collector.example.com:4318", | ||
| insecure: false, | ||
| want: "http://collector.example.com:4318", | ||
| }, | ||
| { | ||
| name: "https URL preserved", | ||
| raw: "https://collector.example.com:4318", | ||
| insecure: true, | ||
| want: "https://collector.example.com:4318", | ||
| }, | ||
| { | ||
| name: "https URL with path preserved", | ||
| raw: "https://collector.example.com:4318/v1/traces", | ||
| insecure: false, | ||
| want: "https://collector.example.com:4318/v1/traces", | ||
| }, | ||
| } | ||
|
|
||
| for _, tt := range tests { | ||
| t.Run(tt.name, func(t *testing.T) { | ||
| got := endpointURL(tt.raw, tt.insecure) | ||
| if got != tt.want { | ||
| t.Errorf("endpointURL(%q, %t) = %q, want %q", tt.raw, tt.insecure, got, tt.want) | ||
| } | ||
| }) | ||
| } | ||
| } |
There was a problem hiding this comment.
Test coverage is missing for edge cases including empty string and whitespace-only inputs. While the code at line 194 in otel.go checks for empty endpoint before calling endpointURL, the function itself is not tested with empty or whitespace-only strings. If endpointURL is ever called directly elsewhere, these edge cases could cause issues. Consider adding test cases for:
- Empty string:
"" - Whitespace-only:
" " - Already has scheme but it's unusual:
"ftp://example.com:4317"
|
|
||
| "testing" | ||
| ) | ||
|
|
There was a problem hiding this comment.
Unnecessary blank line between standard library imports. Both context and testing are standard library packages and should not be separated by a blank line. The Go convention (and goimports tool) groups imports as: standard library imports (no separation), blank line, then third-party imports.
For comparison, see pkg/log/log_test.go lines 6-9 where context, log/slog, and testing are all grouped together without blank lines as they're all from the standard library.
| "testing" | |
| ) | |
| "testing" | |
| ) |
This pull request improves the OpenTelemetry (OTel) SDK configuration in the
pkg/utils/otel.gopackage to ensure endpoint URLs are always valid, preventing parsing errors when using bare IP:port or hostname values. The changes introduce a helper to normalize endpoints, update all OTel exporter initializations to use the correct URL-based option, and add comprehensive tests to verify this behavior.Endpoint normalization and SDK configuration:
endpointURLhelper function to ensure any OTel endpoint has a proper URL scheme (http://orhttps://), fixing the issue where bare IP:port values (like127.0.0.1:4317) would fail parsing in the OTel SDK. (pkg/utils/otel.go) [1] [2]WithEndpointURL(instead ofWithEndpoint) and ensure the endpoint is normalized before use, covering traces, metrics, and logs for both HTTP and gRPC protocols. (pkg/utils/otel.go) [1] [2] [3] [4] [5] [6]Testing improvements:
endpointURLhelper to verify correct scheme prepending and preservation of existing schemes. (pkg/utils/otel_test.go)SetupOTelSDKWithConfigcorrectly normalizes a bare IP:port endpoint and prevents the OTel SDK parsing error. (pkg/utils/otel_test.go)Minor cleanup:
pkg/utils/otel_test.go)