Skip to content

Commit d8312bc

Browse files
committed
fix(server): a padded OTEL value no longer lands in the middle of a URL
Whitespace around an inherited variable is formatting, not part of the endpoint, and appending the signal path buries it where nothing would report it. Signed-off-by: Yordis Prieto <yordis.prieto@gmail.com>
1 parent 8e76646 commit d8312bc

2 files changed

Lines changed: 23 additions & 5 deletions

File tree

‎apps/server/src/observability/OtelEnvironment.test.ts‎

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -527,6 +527,22 @@ describe("OtelEnvironment", () => {
527527
}),
528528
);
529529

530+
it.effect("does not carry a padded variable into the URL it builds", () =>
531+
Effect.gen(function* () {
532+
// A shell profile that lined up its exports did not mean the padding to
533+
// become part of the endpoint, and the appended signal path would put it
534+
// in the middle of the URL where nothing would report it.
535+
const resolved = yield* OtelEnvironment.load.pipe(
536+
withEnv({
537+
OTEL_EXPORTER_OTLP_ENDPOINT: " https://collector.example.com/ ",
538+
OTEL_SERVICE_NAME: " t3 ",
539+
}),
540+
);
541+
assert.strictEqual(resolved.traces.settings?.url, "https://collector.example.com/v1/traces");
542+
assert.strictEqual(resolved.resource.serviceName, "t3");
543+
}),
544+
);
545+
530546
it.effect("reads the metric protocol when it is the only one named", () =>
531547
Effect.gen(function* () {
532548
const resolved = yield* OtelEnvironment.load.pipe(

‎apps/server/src/observability/OtelEnvironment.ts‎

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -86,14 +86,16 @@ export interface OtelEnvironment {
8686
/**
8787
* An empty value means the same thing as an unset one. The specification says
8888
* so, and it is how a machine clears a variable it inherited without being
89-
* able to unset it.
89+
* able to unset it. Surrounding whitespace is dropped for the same reason a
90+
* blank value is: a shell profile that padded a line did not mean the padding
91+
* to become part of an endpoint or a service name.
9092
*/
9193
const optionalString = (name: string) =>
9294
Config.string(name).pipe(
9395
Config.option,
9496
Config.map((value) => {
95-
const raw = Option.getOrUndefined(value);
96-
return raw === undefined || raw.trim() === "" ? undefined : raw;
97+
const raw = Option.getOrUndefined(value)?.trim();
98+
return raw === undefined || raw === "" ? undefined : raw;
9799
}),
98100
);
99101

@@ -104,7 +106,7 @@ const optionalString = (name: string) =>
104106
* list.
105107
*/
106108
const specBoolean = (name: string) =>
107-
optionalString(name).pipe(Effect.map((raw) => raw?.trim().toLowerCase() === "true"));
109+
optionalString(name).pipe(Effect.map((raw) => raw?.toLowerCase() === "true"));
108110

109111
/**
110112
* A number that is not a number is warned about and dropped, which is what the
@@ -118,7 +120,7 @@ const readInt = (name: string, warnings: Array<string>) =>
118120
if (raw === undefined) {
119121
return undefined;
120122
}
121-
const value = Number(raw.trim());
123+
const value = Number(raw);
122124
if (!Number.isSafeInteger(value) || value < 0) {
123125
warnings.push(`${name}=${raw} is not a whole number and was ignored`);
124126
return undefined;

0 commit comments

Comments
 (0)