Repository navigation
fix(tracing): derive OTLP transport security from the TRACER_URL scheme - #4205
Conversation
aryanmehrotra
left a comment
There was a problem hiding this comment.
Thanks for this — the fix itself is correct, and I verified it end to end rather than by reading. Recording what I checked so the next reviewer doesn't repeat it:
Verified against the pinned SDK (otlptracegrpc v1.44.0), not docs:
| Claim | Evidence at the pin |
|---|---|
WithEndpointURL derives security from the scheme |
internal/otlpconfig/options.go:289 → cfg.Traces.Insecure = u.Scheme != "https" |
A later WithInsecure() overrides it |
options.go:328 sets Insecure = true; opts applied in slice order |
| SDK applies env first, options after | NewGRPCConfig — ApplyGRPCEnvConfigs(cfg) at options.go:128, opts loop at 129–131 |
| Non-insecure default is system root CAs | credentials.NewTLS(nil) — matches what the docs now say |
Verified on the wire and end to end (real plaintext OTLP gRPC TraceServiceServer, spans emitted through App.initTracer()):
TRACER_URL |
First bytes on the socket | Spans reached the plaintext collector |
|---|---|---|
schemeless host:port |
PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n (h2c) |
yes |
http://host:port |
PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n (h2c) |
yes |
https://host:port |
16 03 01 05 c7 01 (TLS ClientHello) |
no — correct |
schemeless + TRACER_INSECURE=false |
TLS | no — correct |
All four transport decisions are right, the deprecated TRACER_HOST/TRACER_PORT path stays plaintext, and TRACE_EXPORTER=zipkin is untouched. Perf is a non-issue: resolveOtlpTransport is 4.2–6.9 ns/op with 0 allocs and runs once per process; binary grows +224 B. Shape matches the merged metrics exporter (pkg/gofr/metrics/exporters/otlp.go:57,100-112), and traces actually improves on it by warning about an invalid flag where metrics swallows it. Observability of a misconfiguration is good too — a TLS mismatch surfaces on stderr in 15 s with the exact cause (tls: first record does not look like a TLS handshake).
I also agree with the TRACER_INSECURE=true default diverging from METRICS_INSECURE=false. Defaulting existing host:4317 deployments to TLS would break them silently in a minor release. The reasoning is sound and it is commented at both call sites.
So the code is good. What I'm asking to change is the description, plus one test gap.
1. The "verified on the wire" claim does not reproduce
"the new code sends a TLS ClientHello for an
https://endpoint, while the old code sends the h2c connection preface for the same config"
I ran exactly that probe with the pre-fix wiring restored (opts := []otlptracegrpc.Option{WithInsecure(), WithEndpoint(url)}):
PRE-FIX https://127.0.0.1:PORT -> WIRE: NOTHING - no connection was ever made
PRE-FIX http://127.0.0.1:PORT -> WIRE: NOTHING - no connection was ever made
PRE-FIX 127.0.0.1:PORT -> "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n"
The old code emitted zero bytes. WithEndpoint("https://host:4317") is an invalid gRPC target:
rpc error: code = Unavailable desc = invalid target address https://127.0.0.1:65382,
error info: address https://127.0.0.1:65382:443: too many colons in address
The dialer never opened a socket, so it cannot have sent an h2c preface. Could you re-run that probe and correct the line?
2. Consequence: the headline framing is wrong
"An
https://TRACER_URLwas silently exported over plaintext"
Per the above, pre-fix an https:// URL produced an invalid target — traces were never exported at all, not leaked in the clear. That is still a real bug and this is still the right fix, but it is "the feature was completely broken", not "a TLS downgrade". Worth getting right before it reaches the changelog, since it changes the severity a reader will assign.
3. The OTEL_EXPORTER_OTLP_INSECURE half of the bug is still present
"
OTEL_EXPORTER_OTLP_INSECURE=falsecould not override it either"
Measured on this branch — OTEL_EXPORTER_OTLP_INSECURE=false, schemeless TRACER_URL, TRACER_INSECURE unset:
=> err=<nil> // spans reached a PLAINTEXT collector
The default insecure=true still appends WithInsecure(), which lands after ApplyGRPCEnvConfigs, so the OTel-standard variable is still silently overridden. Either is fine by me:
- (a) skip
WithInsecure()whenOTEL_EXPORTER_OTLP_INSECURE/OTEL_EXPORTER_OTLP_TRACES_INSECUREis set andTRACER_INSECUREis not; or - (b) drop the claim and document the precedence (
TRACER_INSECURE>OTEL_EXPORTER_OTLP_*).
4. otlptracehttp is not in this repo
"
buildOtlpExporterappendedotlptracegrpc.WithInsecure()/otlptracehttp.WithInsecure()unconditionally"
$ grep -rn 'otlptracehttp' --include='*.go' --include='go.mod' .
(no matches)
pkg/gofr/otel.go:10 imports only otlptracegrpc. Please drop the reference.
5. The fix is not guarded by a test
Every new function is at 100% line coverage, and the original bug can still be reintroduced with CI fully green. I replaced the new opts block with the exact pre-fix line and ran the package:
ok gofr.dev/pkg/gofr 5.713s
The whole suite passes. Test_resolveOtlpTransport exercises a pure function that is not connected to the wiring, and Test_buildOtlpExporter only asserts err == nil && exp != nil, which holds for any option set. Swapping the two branches would also go unnoticed.
A ~40-line test does catch it: stand up a real plaintext TraceServiceServer on 127.0.0.1:0 and assert ExportSpans succeeds for http:// and schemeless, and fails for https://. Under the mutant the http:// case fails with too many colons; on this branch it passes and https:// fails with tls: first record does not look like a TLS handshake. Happy to hand over the file if it saves you time — keep the ExportSpans deadline at ~1 s so the TLS case doesn't sit on the default timeout.
Non-blocking
Docs that now contradict this change (none are in the diff):
| File | Line | Problem |
|---|---|---|
docs/quick-start/observability/page.md |
481-484 | TRACER_URL=otlp-gateway-prod-us-east-0.grafana.net:443 with Authorization=Basic .... Schemeless, so it defaults to plaintext — this PR's own new warning fires on our own documented example, and I confirmed it does: traces are exported to ... over plaintext with headers configured. Needs https://. |
docs/guides/production-tracing/page.md |
15 | The {% howto %} step still says "Set TRACER_URL to a bare host:port (no http:// scheme)" — same file as the new TLS section you added. |
docs/guides/twelve-factor-config/page.md |
89-91 | "TRACER_URL must be a bare host:port — no http:// scheme" — no longer true. |
Nits:
strings.HasPrefix(url, "http://")is case-sensitive.HTTP://host:4317is a legal URL (RFC 3986 §3.1) and falls through toWithEndpoint("HTTP://...")→ invalid target.url.ParseinsideWithEndpointURLis case-insensitive, so lowercasing before the prefix check closes the gap in one line.a.tracerInsecure()is evaluated ingetExporterfor every exporter, so a malformedTRACER_INSECUREwarns underTRACE_EXPORTER=zipkin/gofrwhere it means nothing — while a valid one there is ignored with no warning at all. Inverse of the otlp path.Test_buildOtlpExporter_warnsOnPlaintextCredentialspasses bothurl="collector:4317"andport="9411"; the port is dead sinceurlwins.- CONTRIBUTING asks for American English — "behaviour" in the Breaking Changes section.
- Please strip the
Co-Authored-By: Claude ...trailer and theClaude-Session:line fromce80050a7, and the🤖 Generated withfooter plus session link from the PR description. Same note as #4208 — and sincece80050a7is the base commit of the stack, it propagates into #4206 and #4207.
Adjacent, pre-existing, not yours: pkg/gofr/otel.go:81 registers sdktrace.NewBatchSpanProcessor(exporter) even when getExporter returned an error and exporter is nil. Worth a separate issue.
Stack note: I checked what #4206 does to this code — it moves otlpTransport, resolveOtlpTransport and all five new tests verbatim into pkg/gofr/traces/exporters/, and all seven sub-cases survive, so no coverage is lost. That means the structural shape here is transient and I have not commented on it. Two things do survive the move and are worth a thought there rather than here: the otlpTransport.insecure field is derivable (insecure == !useEndpointURL && plaintext in all four reachable states), and the added block runs at 0.64 comments per line of code against a 0.20 baseline for pkg/gofr.
buildOtlpExporter passed TRACER_URL straight to otlptracegrpc.WithEndpoint,
which stores it verbatim as the gRPC target, and appended an unconditional
WithInsecure(). A scheme-bearing TRACER_URL is not a valid gRPC target ("too
many colons in address"), so the dialer never opened a socket and no span was
ever exported: https:// and http:// endpoints were unusable, not downgraded.
Only a schemeless host:port worked, and only over plaintext.
Transport security now comes from the URL scheme when there is one
(WithEndpointURL alone, never combined with WithInsecure -- the SDK applies
options in slice order, so a trailing WithInsecure would override the scheme),
and from the new TRACER_INSECURE config only for a schemeless host:port.
TRACER_INSECURE defaults to true, diverging from METRICS_INSECURE, which
defaults to false. Every existing TRACER_URL=host:4317 deployment points at a
plaintext collector because that was the only transport the exporter could
produce; defaulting them to TLS would break them silently in a minor release.
The divergence is commented at both call sites.
Precedence is the TRACER_URL scheme, then TRACER_INSECURE, then the OTel
standard OTEL_EXPORTER_OTLP_INSECURE / OTEL_EXPORTER_OTLP_TRACES_INSECURE: the
SDK applies its environment config before explicit options, so a GoFr config
always wins over them. Documented rather than changed.
Also warns when TRACER_INSECURE is set on a scheme-bearing URL (ignored), and
when TRACER_HEADERS/TRACER_AUTH_KEY credentials would ride a plaintext
connection, mirroring the metrics exporter.
Test_buildOtlpExporter_wireTransport asserts the first bytes the exporter puts
on the socket (h2c preface vs TLS ClientHello) for all four transport
decisions; restoring the pre-fix option line fails three of its four subtests.
Docs updated where they still told users TRACER_URL must be schemeless.
4f444c6 to
df89d87
Compare
|
Thank you — this is an unusually thorough review, and the wire probe caught a real error in my description. I re-ran your probe before changing anything and confirm all five points. 1 & 2. The probe and the framing — you are right, correctedReproduced with the pre-fix wiring restored (
The description and the commit message now say what actually happened: an 3.
|
| config | asserted |
|---|---|
| schemeless | PRI * HTTP/2.0 |
http:// |
PRI * HTTP/2.0 |
https:// |
0x16 (TLS ClientHello) |
schemeless + TRACER_INSECURE=false |
0x16 |
I went with a raw listener rather than a real TraceServiceServer so the test adds no dependency — go.opentelemetry.io/proto/otlp is currently indirect, and promoting it to direct in the root go.mod for one test seemed the wrong trade. The assertion is on the wire either way.
Your mutant is caught. Restoring the exact pre-fix line:
--- FAIL: Test_buildOtlpExporter_wireTransport (8.01s)
--- FAIL: .../http_scheme_speaks_h2c (3.00s)
--- FAIL: .../https_scheme_speaks_TLS (3.00s)
--- FAIL: .../schemeless_with_TRACER_INSECURE=false_speaks_TLS (1.00s)
Three of four subtests fail — swapping the two branches is caught as well, not just deleting the block.
Docs
All three fixed in this PR:
docs/quick-start/observability/page.md— the Grafana Cloud example is nowhttps://otlp-gateway-prod-us-east-0.grafana.net:443. Good catch that our own documented example tripped this PR's new warning.docs/guides/production-tracing/page.md:15— the{% howto %}step no longer says "bare host:port (no http:// scheme)".docs/guides/twelve-factor-config/page.md:89-91— same, and it now points atTRACER_INSECUREfor upgrading a barehost:port.
Nits
- Case-sensitivity — fixed; the prefix check lowercases first, with a table case for
HTTPS://collector:4317.url.ParseinsideWithEndpointURLlowercases the scheme, so this is now consistent end to end. a.tracerInsecure()evaluated for every exporter — fixed; it is resolved inside theotlp/jaegercase, so a malformed value no longer warns underzipkin/gofr. One thing to flag honestly: in feat(tracing): add a trace exporter registry, resource and shutdown flush #4206 this field moves intoexporters.Configand is populated for every exporter again, because the config is built before the exporter is selected. The right home for that warning there is the OTLP builder that actually reads the flag, and I would rather make that change under feat(tracing): add a trace exporter registry, resource and shutdown flush #4206's own review than reshape it here.- Dead
portargument inTest_buildOtlpExporter_warnsOnPlaintextCredentials— removed. - "behaviour" — now "behavior".
- Trailers — removed from the commit and from all four PR descriptions. As you noted, the base commit changed, so feat(tracing): add a trace exporter registry, resource and shutdown flush #4206 and feat(tracing): keyless trace export to Google Cloud (TRACE_EXPORTER=gcp) #4207 have been rebased onto it and force-pushed.
Adjacent
Agreed that pkg/gofr/otel.go:81 registering a BatchSpanProcessor over a nil exporter is a real and separate bug, and it is pre-existing and out of scope here. Two details I checked while filing it:
- It does not panic —
batch_span_processor.go:153guardsbsp.e == nil, so the batcher is installed and silently drops every span. Thedefault:branch ofgetExporterreaches the same state with a nil error, so an unsupportedTRACE_EXPORTERalso leaves a provider that looks configured and exports nothing. - feat(tracing): add a trace exporter registry, resource and shutdown flush #4206 already fixes it:
exporters.Buildreturns the NeverSample provider when the builder yields no exporter (provider.go:52-55), so the degrade path is explicit there. I have filed the issue anyway since it is live ondevelopmentuntil that merges.
Stack note
Thank you for checking the move in #4206 — that saved a round trip. Both observations you parked there are fair: otlpTransport.insecure is derivable from the other two fields, and the comment density on the new block is high. I will take both up on #4206 rather than churn this one.
All three branches build, test and lint clean at the rebased commits.
aryanmehrotra
left a comment
There was a problem hiding this comment.
All five addressed, and I re-verified each rather than taking the reply on trust. Reviewed at df89d8725.
| # | Ask | Verified |
|---|---|---|
| 1+2 | Wire claim / framing corrected | ✅ description now says "unusable, not downgraded" |
| 3 | OTEL_EXPORTER_OTLP_INSECURE |
✅ claim dropped, precedence documented in otel.go and docs/references/configs/page.md |
| 4 | otlptracehttp |
✅ 0 matches in the description |
| 5 | Test guards the fix | ✅ Test_buildOtlpExporter_wireTransport — and I ran your mutant |
Mutation result — restoring the exact pre-fix line opts := []otlptracegrpc.Option{WithInsecure(), WithEndpoint(url)}:
--- FAIL: Test_buildOtlpExporter_wireTransport/http_scheme_speaks_h2c
--- FAIL: Test_buildOtlpExporter_wireTransport/https_scheme_speaks_TLS
--- FAIL: Test_buildOtlpExporter_wireTransport/schemeless_with_TRACER_INSECURE=false_speaks_TLS
FAIL gofr.dev/pkg/gofr 8.866s
Three of four subtests fail; clean run is ok 5.072s. The gap is closed, and asserting on first bytes rather than standing up a TraceServiceServer was the right call — it keeps go.opentelemetry.io/proto/otlp indirect in the root go.mod. I used a real collector in my probe and would have had to promote that dependency; yours is the better trade.
Nits: case-insensitive prefix ✅ (with an HTTPS:// table case), tracerInsecure() moved into the otlp/jaeger arm ✅, dead port argument removed ✅, "behavior" ✅, trailers gone from the commit and all four descriptions ✅. Docs: all three corrected, including the Grafana Cloud example that tripped this PR's own warning.
On the nil BatchSpanProcessor — you are right and I was wrong. I probed for a panic and could not produce one but did not find the reason; batch_span_processor.go:153-155 guards bsp.e == nil and returns early, exactly as you say. Your added detail is the important part: the default: branch reaches that state with a nil error, so an unsupported TRACE_EXPORTER leaves a provider that looks configured and silently drops every span. Thanks for filing it.
Noted on tracerInsecure moving back into exporters.Config under #4206 — agreed that belongs in #4206's review, and I will pick it up there.
LGTM.
Umang01-hash
left a comment
There was a problem hiding this comment.
Verified against head df89d87. Correct, backward-compatible fix. Confirmed the bug at the wire: reverting to the old WithInsecure()+WithEndpoint(url) line makes scheme-bearing TRACER_URLs never open a connection and downgrades a schemeless TRACER_INSECURE=false to h2c — Test_buildOtlpExporter_wireTransport catches all of it (asserts real h2c preface vs TLS ClientHello). Checked the SDK source directly: WithEndpointURL sets Insecure = scheme != "https", and NewGRPCConfig applies env before opts, so the precedence comment holds. Default path (host:4317, no TRACER_INSECURE) stays byte-identical plaintext — no regression. No exported-API break; docs + config reference accurate; gofmt/vet/lint/build clean, otel suite green under -race.
Two optional nits, noted here rather than inline (both on unchanged lines):
- TRACER_INSECURE defaults to plaintext while METRICS_INSECURE defaults to TLS — intentional and documented for backward compat, just flagging the two-knobs-opposite-defaults for possible future convergence.
- resolveOtlpTransport detects the scheme on the untrimmed url (tracerInsecure trims its value, url isn't), so a stray-whitespace TRACER_URL would miss the scheme. Pre-existing and negligible.
…h-otlp Brings in development through 23852af. #4205 rewrote buildOtlpExporter in otel.go, which this branch had moved to the gofr_nootlp-tagged otlp_trace.go: - carry otlpTransport, resolveOtlpTransport and the new buildOtlpExporter into otlp_trace.go, and drop them from otel.go - give the gofr_nootlp stub the two new insecure flags - move #4205's resolveOtlpTransport/buildOtlpExporter tests from otel_test.go into otlp_trace_test.go, so a gofr_nootlp test build still compiles; Test_App_tracerInsecure stays, since tracerInsecure lives in otel.go
Since #4205 a scheme-bearing TRACER_URL is a real URL, so it can carry credentials in userinfo or its query string, and every tracer startup log wrote it verbatim. Endpoints are now logged through redactURL, the exporter name is logged as the matched constant, and the raw TRACER_INSECURE and unsupported TRACE_EXPORTER values are no longer echoed. This clears CodeQL go/clear-text-logging alerts 179-184 on pkg/gofr/otel.go, which failed the CodeQL check on the v1.61.0 release PR (#4246).
* Merge pull request #4147 from gofr-dev/chore/gcp-exporter-pin-v1.60.1 chore(metrics): pin gcp exporter to gofr.dev v1.60.1 * fix(middleware): require a path separator in the well-known auth exemption (#4099) * fix(middleware): require a path separator in the well-known auth exemption * test(middleware): cover the rate limiter well-known exemption * chore(middleware): satisfy goconst and noctx in the well-known check * docs(auth): describe the separator requirement in the well-known exemption --------- Co-authored-by: Aryan Mehrotra <aryanmehrotra2000@gmail.com> Co-authored-by: Umang Mundhra <mundhraumang.02@gmail.com> * perf(metrics): build the measurement option once per route, method and status (#3972) * perf(http): pool the response envelope and stop recanonicalising Content-Type (#3973) * perf(cors): build the fixed response headers once, not per request (#3971) * fix: prevent concurrent map panic during kafka client teardown (#3502) Co-authored-by: aryanmehrotra <aryanmehrotra2000@gmail.com> * fix(sql): correct query duration logging unit to microseconds (#3878) * chore(deps): consolidate minor/patch dependency updates (2026-08-21) (#4048) * fix(tools): require a path separator in the framework route check (#4102) Co-authored-by: Umang Mundhra <mundhraumang.02@gmail.com> Co-authored-by: Aryan Mehrotra <aryanmehrotra2000@gmail.com> * perf(container): run health checks concurrently, and collapse concurrent probes (#3496) * feat(mqtt): add span links for pub/sub tracing (#3595) * fix(pubsub/google): guard shared subscription maps against concurrent writes (#4054) (#4055) --------- Co-authored-by: Umang Mundhra <mundhraumang.02@gmail.com> Co-authored-by: Aryan Mehrotra <aryanmehrotra2000@gmail.com> * feat: implement EventHub Health check (#3649) * test(terminal): add unit tests for SetColor and ResetColor (#3648) * fix: add transaction support for dgraph migration (#3186) * fix(crud): keep digits intact in toSnakeCase for auto-generated SQL (#3676) * feat(metrics): add app_server_error/app_circuit_open_count counters + global metrics accessor (#3856) * test(service): fix flaky CB test intervals and add deterministic concurrent recovery test (#3755) * chore(deps): bump the go_modules group across 12 directories with 1 update (#4153) Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Aryan Mehrotra <aryanmehrotra2000@gmail.com> * feat(metrics): configurable per-instrument cardinality limit (#4160) * fix(websocket): don't panic on a plain HTTP request to a WebSocket route (#3932) * ci: run the full pipeline and a website build on docs-only PRs (#4195) * Fix CONTRIBUTING.md wording (#3647) Co-authored-by: Aryan Mehrotra <aryanmehrotra2000@gmail.com> Co-authored-by: Umang Mundhra <mundhraumang.02@gmail.com> * fix: broken links in README and CONTRIBUTING (#3798) Co-authored-by: Aryan Mehrotra <aryanmehrotra2000@gmail.com> * chore(deps): bump crate-ci/typos from 1.50.0 to 1.50.1 in the actions group (#4197) Closes: #4171 Co-authored-by: Aryan Mehrotra <aryanmehrotra2000@gmail.com> * chore(deps): consolidate minor/patch dependency updates (2026-09-09) (#4196) Applied surgically per direct-dependency module (per-module go get + go mod tidy; no go work sync). All bumps are minor/patch/security — no majors, no go-redis mock regen needed (miniredis is a test double, not go-redis). Updates: - go.opentelemetry.io/otel/sdk 1.45.0 -> 1.46.0 (root, metrics/exporters/gcp, pubsub/nats, pubsub/sqs) - go.opentelemetry.io/otel/exporters/zipkin 1.44.0 -> 1.46.0 (root) - go.opentelemetry.io/contrib/detectors/gcp 1.44.0 -> 1.46.0 (metrics/exporters/gcp) - github.com/aws/aws-sdk-go-v2/config 1.32.37 -> 1.33.3 (file/s3, kv-store/dynamodb, pubsub/sqs, examples/using-s3-filestore) - github.com/aws/aws-sdk-go-v2/service/dynamodb 1.63.3 -> 1.67.0 (kv-store/dynamodb) - github.com/aws/aws-sdk-go-v2/service/sqs 1.46.6 -> 1.51.0 (pubsub/sqs) - github.com/nats-io/nats-server/v2 2.14.5 -> 2.14.6 (pubsub/nats) - golang.org/x/sync 0.22.0 -> 0.23.0 (root) - modernc.org/sqlite 1.56.0 -> 1.58.0 (root) - github.com/alicebob/miniredis/v2 2.38.0 -> 2.39.0 (root, test) - google.golang.org/grpc 1.83.1 -> 1.83.2 security (root + library modules + examples; pulls golang.org/x/net 0.57.0 -> 0.58.0). examples/using-gcp-metrics is excluded: it is baseline-untidy (excluded from the CI tidy gate) and tidying it to apply grpc would settle unrelated versions. Closes: #4172, #4173, #4174, #4175, #4176, #4177, #4178, #4179, #4180, #4181, #4182, #4183, #4184, #4185, #4186, #4187, #4188, #4189, #4190, #4191, #4192, #4194 Co-authored-by: Aryan Mehrotra <aryanmehrotra2000@gmail.com> * docs: fix American English spelling of canceled (#3651) Co-authored-by: Umang Mundhra <mundhraumang.02@gmail.com> Co-authored-by: Aryan Mehrotra <aryanmehrotra2000@gmail.com> * docs(cron): correct the minimum-interval claim and the "every 5 hours" example (#3876) (#3977) Co-authored-by: Aryan Mehrotra <aryanmehrotra2000@gmail.com> * docs(readme): link Custom Middleware and update the Go version prerequisite (#3461) The broken Auth Middleware link this PR also carried has since landed via #3798, so what remains is: - "Custom Middleware" was plain text next to the linked Auth Middleware; it now points at docs/advanced-guide/middlewares. - The prerequisite said Go 1.24. Every go.mod in the repo declares go 1.26.0, and CI's 1.24/1.25 matrix entries only pass because a setup-go-toolchain step auto-upgrades them, so 1.26 is the real floor. Co-authored-by: Aryan Mehrotra <aryanmehrotra2000@gmail.com> Co-authored-by: Umang Mundhra <mundhraumang.02@gmail.com> * fix(file): correct SFTP/S3 observability defects and stale comments (#3227) Co-authored-by: Umang Mundhra <mundhraumang.02@gmail.com> Co-authored-by: Aryan Mehrotra <aryanmehrotra2000@gmail.com> * fix(sql): validate unsigned int not-null fields without panicking (#3677) * ci(website-prod): move prod build and deploy to asia-south1 zopdev-tech (#4198) Point the prod website image build/push at the asia-south1 zopdev Artifact Registry and deploy to the zopdev-tech cluster (asia-south1), replacing the us-central1 kops-dev registry and raramuri-tech cluster. Namespace, app name, and image tagging are unchanged. * feat(health): optional readiness check for /.well-known/health (#3857) (#3858) * ci(website-stage): move stage build and deploy to asia-south1 zopdev-tech (#4199) Co-authored-by: Aryan Mehrotra <aryanmehrotra2000@gmail.com> * chore(deps): bump zopdev/static-server v0.0.9 -> v1.0.0 in (#4050) Major version bump (v0 -> v1) of the docs static-server base image. Consolidated from Dependabot #3990. Closes: #3990 Co-authored-by: Aryan Mehrotra <aryanmehrotra2000@gmail.com> * Add HTTP QUERY Method Support (RFC 10008) (#3760) * fix(rbac): make wildcard-method rules reachable and resolve overlapping patterns deterministically (#3808) (#3934) Co-authored-by: Aryan Mehrotra <aryanmehrotra2000@gmail.com> * fix(rbac): compile endpoint patterns once at load, not per rule per request (#3979) (#4047) * fix(ci): pull MinIO from quay.io — docker.io/minio/minio is no longer public (#4208) quay.io/minio/minio:RELEASE.2025-09-07T16-13-09Z carries the identical manifest list — sha256:14cea493… , byte-for-byte the digest already pinned — so this changes the registry and nothing else. The image CI runs is provably the one it ran on 2026-09-11, and the digest pin protecting the integration guard for #3804 stays intact. Bumping to a newer release instead would have changed two things at once. * fix(http,metrics,mcp): don't lose a shutdown that arrives before the server starts (#3801) (#4139) * fix(tracing): derive OTLP transport security from the TRACER_URL scheme (#4205) * ci: stop passing -short to submodule tests, which skipped 10 mongo tests entirely (#4201) Co-authored-by: Aryan Mehrotra <aryanmehrotra2000@gmail.com> * ci: measure every in-repo pkg/gofr package, not just the 29 top-level files (#4202) (#4203) * chore(deps): consolidate minor dependency updates (2026-09-16) (#4244) * update release version to v1.61.0 * fix(metrics): keep caller-controlled labels from crowding out real routes (#4163) * fix(tracing): redact tracer config in logs (#4247) Co-authored-by: Umang Mundhra <mundhraumang.02@gmail.com> * fix(tracing): stop tracer parameters shadowing the net/url import (#4249) --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: Ronan Donnelly <ronan.donnelly@ymail.com> Co-authored-by: Umang Mundhra <mundhraumang.02@gmail.com> Co-authored-by: Aditya Kumar Mishra <154746713+adityakrmishra@users.noreply.github.com> Co-authored-by: Pritesh jena <priteshjena16@gmail.com> Co-authored-by: Yash Israni <118755067+yashisrani@users.noreply.github.com> Co-authored-by: Sujan Vulasala <154114096+SujanVulasala@users.noreply.github.com> Co-authored-by: Suhas-zs <110016885+Suhas-zs@users.noreply.github.com> Co-authored-by: Lokesh Malik <lokeshmalik2910@gmail.com> Co-authored-by: Hari Antara <hariantara.iputu@gmail.com> Co-authored-by: Krishna Potdar <potdarkrishna352@gmail.com> Co-authored-by: umar ahad uddin ahmed usmani <150610336+umarahad2005@users.noreply.github.com> Co-authored-by: Om Kulkarni <127368012+om7057@users.noreply.github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Nivaas V <nivaas9293@gmail.com> Co-authored-by: Ryanisyyds <129717677+RyanisyydsTT@users.noreply.github.com> Co-authored-by: Salvatore Damon <rajarajanselvarajan02@gmail.com> Co-authored-by: Akshat Singhal <65562230+akshat-kumar-singhal@users.noreply.github.com> Co-authored-by: Napat Rungruangbangchan <Napat.joe@gmail.com> Co-authored-by: Rohit Nair P <rohitnairmuttathethu@gmail.com> Co-authored-by: Piyush Singh <piyush.singh@zop.dev> Co-authored-by: Gajendra Malviya <gajendra.malviya@zop.dev>
Description:
buildOtlpExporterpassedTRACER_URLstraight tootlptracegrpc.WithEndpoint, which stores it verbatim as the gRPC target, and appended an unconditionalotlptracegrpc.WithInsecure().A scheme-bearing
TRACER_URLis not a valid gRPC target, so the dialer never opened a socket and no span was ever exported:So
http://…andhttps://…endpoints were unusable, not downgraded — the feature was broken for anyone who wrote a scheme. Only a schemelesshost:portworked, and only over plaintext, becauseWithInsecure()was unconditional.Transport security now comes from the URL scheme when the endpoint has one (
WithEndpointURLalone, never combined withWithInsecure— the SDK applies options in slice order, so a trailingWithInsecure()would override the scheme), and from a newTRACER_INSECUREconfig only for a schemelesshost:portendpoint.TRACER_INSECUREdefaults totrue, which deliberately diverges fromMETRICS_INSECURE(defaults tofalse). Every existingTRACER_URL=host:4317deployment today points at a plaintext collector, because plaintext was the only transport the exporter could produce. Defaulting those to TLS would break them silently in a minor release. The divergence is commented at both call sites.Precedence is the
TRACER_URLscheme, thenTRACER_INSECURE, then the OTel standardOTEL_EXPORTER_OTLP_INSECURE/OTEL_EXPORTER_OTLP_TRACES_INSECURE. The SDK applies its environment config before any explicit option, so whatever GoFr passes wins over them. This PR documents that precedence rather than changing it.Also added:
TRACER_INSECUREis set alongside a scheme-bearing URL (it is ignored).TRACER_HEADERS/TRACER_AUTH_KEYcredentials would ride a plaintext connection — mirroring what the metrics exporter already does.Breaking Changes (if applicable):
None. An
https://TRACER_URLnow actually works and uses TLS, which is the documented and intended behavior; schemeless endpoints keep their existing plaintext transport by default.Additional Information:
Test_buildOtlpExporter_wireTransportasserts the first bytes the exporter puts on the socket for all four transport decisions — h2c preface (PRI * HTTP/2.0) for schemeless andhttp://, TLS ClientHello (0x16) forhttps://and for schemeless withTRACER_INSECURE=false. Restoring the pre-fix option line fails three of its four subtests, because the scheme-bearing endpoints never open a connection at all.TRACER_URLmust be schemeless:docs/guides/production-tracing/page.md,docs/guides/twelve-factor-config/page.md,docs/quick-start/observability/page.md(the Grafana Cloud example tripped this PR's own plaintext-credentials warning),docs/references/configs/page.md.Checklist:
goimportandgolangci-lint.