import { getNodeAutoInstrumentations } from '@opentelemetry/auto-instrumentations-node';
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http';
import { NodeSDK, resources, tracing } from '@opentelemetry/sdk-node';
import { ATTR_SERVICE_NAME, ATTR_SERVICE_NAMESPACE } from '@opentelemetry/semantic-conventions';
import { env } from '../environment.js';
const ATTR_DEPLOYMENT_ENVIRONMENT_NAME = 'deployment.environment.name';
const HEALTH_CHECK_PATHS = new Set(['/health', '/ready', '/readiness']);
function shouldIgnoreIncomingRequest(url) {
    if (!url) {
        return false;
    }
    try {
        const pathname = new URL(url, 'http://localhost').pathname;
        return HEALTH_CHECK_PATHS.has(pathname);
    }
    catch {
        const pathname = url.split('?')[0] ?? '';
        return HEALTH_CHECK_PATHS.has(pathname);
    }
}
/**
 * Parses an OTLP header string of the form "key1=value1,key2=value2" into a
 * Record<string, string>. Returns undefined when the input is absent or empty.
 */
function parseHeaders(headersStr) {
    if (!headersStr)
        return undefined;
    const result = {};
    for (const part of headersStr.split(',')) {
        const eqIdx = part.indexOf('=');
        if (eqIdx === -1)
            continue;
        const key = part.slice(0, eqIdx).trim();
        const value = part.slice(eqIdx + 1).trim();
        if (key)
            result[key] = value;
    }
    return Object.keys(result).length > 0 ? result : undefined;
}
function buildSampler(samplerType, arg) {
    switch (samplerType) {
        case 'always_off':
            return new tracing.AlwaysOffSampler();
        case 'parentbased_traceidratio': {
            const ratio = arg ?? 1.0;
            return new tracing.ParentBasedSampler({
                root: new tracing.TraceIdRatioBasedSampler(ratio),
            });
        }
        case 'traceidratio': {
            const ratio = arg ?? 1.0;
            return new tracing.TraceIdRatioBasedSampler(ratio);
        }
        case 'parentbased_always_on':
            return new tracing.ParentBasedSampler({
                root: new tracing.AlwaysOnSampler(),
            });
        case 'parentbased_always_off':
            return new tracing.ParentBasedSampler({
                root: new tracing.AlwaysOffSampler(),
            });
        default:
            return new tracing.AlwaysOnSampler();
    }
}
/**
 * Builds and returns a configured (but not yet started) NodeSDK instance using
 * the OTEL settings from `env`. Returns null when OTEL is disabled.
 */
export function buildOtelSdk() {
    const otel = env.otel;
    if (!otel.enabled) {
        return null;
    }
    const resource = resources.resourceFromAttributes({
        [ATTR_SERVICE_NAME]: otel.serviceName,
        [ATTR_SERVICE_NAMESPACE]: otel.serviceNamespace,
        [ATTR_DEPLOYMENT_ENVIRONMENT_NAME]: otel.deploymentEnv,
    });
    const traceExporter = new OTLPTraceExporter({
        url: otel.exporterEndpoint,
        headers: parseHeaders(otel.exporterHeaders),
    });
    const sampler = buildSampler(otel.tracesSampler, otel.tracesSamplerArg);
    return new NodeSDK({
        resource,
        traceExporter,
        sampler,
        instrumentations: [
            getNodeAutoInstrumentations({
                '@opentelemetry/instrumentation-fs': {
                    enabled: false,
                },
                '@opentelemetry/instrumentation-http': {
                    ignoreIncomingRequestHook: request => shouldIgnoreIncomingRequest(request.url),
                },
                '@opentelemetry/instrumentation-graphql': {
                    enabled: true,
                },
                '@opentelemetry/instrumentation-pg': {
                    enhancedDatabaseReporting: false,
                },
            }),
        ],
    });
}
//# sourceMappingURL=builder.js.map