Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 2 additions & 24 deletions apps/sim/instrumentation-node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import type {
import { createLogger } from '@sim/logger'
import { TraceAttr } from '@/lib/copilot/generated/trace-attributes-v1'
import { env } from './lib/core/config/env'
import { parseOtlpHeaders } from './lib/monitoring/otlp'

diag.setLogger(new DiagConsoleLogger(), DiagLogLevel.ERROR)

Expand Down Expand Up @@ -47,29 +48,6 @@ function isBusinessSpan(spanName: string): boolean {
return ALLOWED_SPAN_PREFIXES.some((prefix) => spanName.startsWith(prefix))
}

// Parse `OTEL_EXPORTER_OTLP_HEADERS`: `key1=value1,key2=value2`
// (URL-encoded values, whitespace tolerated).
function parseOtlpHeadersEnv(raw: string): Record<string, string> {
const out: Record<string, string> = {}
if (!raw) return out
for (const part of raw.split(',')) {
const trimmed = part.trim()
if (!trimmed) continue
const eq = trimmed.indexOf('=')
if (eq <= 0) continue
const key = trimmed.slice(0, eq).trim()
const rawVal = trimmed.slice(eq + 1).trim()
let val = rawVal
try {
val = decodeURIComponent(rawVal)
} catch {
// value wasn't URL-encoded; keep as-is.
}
if (key) out[key] = val
}
return out
}

// Append `/v1/traces` to the OTLP base URL unless already present.
// The HTTP exporter doesn't auto-suffix the signal path even though
// the spec says the env var is a base URL.
Expand Down Expand Up @@ -214,7 +192,7 @@ async function initializeOpenTelemetry() {
},
})

const otlpHeaders = parseOtlpHeadersEnv(process.env.OTEL_EXPORTER_OTLP_HEADERS || '')
const otlpHeaders = parseOtlpHeaders(process.env.OTEL_EXPORTER_OTLP_HEADERS || '')
const exporterUrl = normalizeOtlpTracesUrl(telemetryConfig.endpoint)

const exporter = new OTLPTraceExporter({
Expand Down
27 changes: 27 additions & 0 deletions apps/sim/lib/monitoring/otlp.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/**
* Parse OTLP headers per the OTEL spec format `key1=value1,key2=value2`.
* Values are URL-decoded; the raw value is preserved if decoding fails.
* Keys and values are trimmed; empty or malformed entries are skipped.
* @see https://opentelemetry.io/docs/specs/otel/protocol/exporter/
*/
export function parseOtlpHeaders(raw: string): Record<string, string> {
const out: Record<string, string> = {}
if (!raw) return out
for (const part of raw.split(',')) {
const trimmed = part.trim()
if (!trimmed) continue
const eq = trimmed.indexOf('=')
if (eq <= 0) continue
const key = trimmed.slice(0, eq).trim()
if (!key) continue
const rawVal = trimmed.slice(eq + 1).trim()
let val = rawVal
try {
val = decodeURIComponent(rawVal)
} catch {
// value wasn't URL-encoded; keep as-is.
}
out[key] = val
}
return out
}
19 changes: 1 addition & 18 deletions apps/sim/trigger.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { resourceFromAttributes } from '@opentelemetry/resources'
import { additionalFiles, additionalPackages } from '@trigger.dev/build/extensions/core'
import { defineConfig } from '@trigger.dev/sdk'
import { env } from './lib/core/config/env'
import { parseOtlpHeaders } from './lib/monitoring/otlp'

const grafanaEndpoint = env.GRAFANA_OTLP_ENDPOINT
const grafanaHeaders = env.GRAFANA_OTLP_HEADERS
Expand All @@ -20,24 +21,6 @@ if (grafanaConfigured && !grafanaFullyConfigured) {
)
}

/**
* Parse OTLP headers per the OTEL spec format `key1=value1,key2=value2`.
* Values are URL-decoded; keys/values are trimmed; empty entries are skipped.
* @see https://opentelemetry.io/docs/specs/otel/protocol/exporter/
*/
function parseOtlpHeaders(raw: string): Record<string, string> {
const out: Record<string, string> = {}
for (const pair of raw.split(',')) {
const eq = pair.indexOf('=')
if (eq === -1) continue
const key = pair.slice(0, eq).trim()
const value = pair.slice(eq + 1).trim()
if (!key) continue
out[key] = decodeURIComponent(value)
}
return out
}

const grafanaTelemetry = grafanaFullyConfigured
? (() => {
const baseUrl = grafanaEndpoint!.replace(/\/+$/, '')
Expand Down
Loading