"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Tracer = exports.installTraceContextManager = exports.isTraceContextWorking = exports.getActiveSpan = exports.runWithTrace = exports.SpanStatusCode = void 0;
const utils_1 = require("../utils");
var SpanStatusCode;
(function (SpanStatusCode) {
    /**
     * The default status.
     */
    SpanStatusCode[SpanStatusCode["UNSET"] = 0] = "UNSET";
    /**
     * The operation has been validated by an Application developer or
     * Operator to have completed successfully.
     */
    SpanStatusCode[SpanStatusCode["OK"] = 1] = "OK";
    /**
     * The operation contains an error.
     */
    SpanStatusCode[SpanStatusCode["ERROR"] = 2] = "ERROR";
})(SpanStatusCode || (exports.SpanStatusCode = SpanStatusCode = {}));
class StubSpan {
    attributes = {};
    setStatus(_status) {
        return this;
    }
    setAttribute(_key, _attribute) {
        return this;
    }
    addEvent(_name, _attributesOrStartTime, _timeStamp) {
        return this;
    }
}
function runWithTrace(span, func) {
    if (!utils_1.globalParams.tracingEnabled) {
        return func();
    }
    const { context, trace } = require('@opentelemetry/api');
    return context.with(trace.setSpan(context.active(), span), func);
}
exports.runWithTrace = runWithTrace;
function getActiveSpan() {
    if (!utils_1.globalParams.tracingEnabled) {
        return undefined;
    }
    const { trace } = require('@opentelemetry/api');
    return trace.getActiveSpan();
}
exports.getActiveSpan = getActiveSpan;
function isTraceContextWorking() {
    if (!utils_1.globalParams.tracingEnabled) {
        return false;
    }
    const { context, trace } = require('@opentelemetry/api');
    const span = trace.getTracer('otel-bootstrap-check').startSpan('probe');
    const testContext = trace.setSpan(context.active(), span);
    let visible;
    context.with(testContext, () => {
        visible = trace.getSpan(context.active()) === span;
    });
    span.end?.();
    return visible === true;
}
exports.isTraceContextWorking = isTraceContextWorking;
function installTraceContextManager(appName = 'dbos') {
    if (!utils_1.globalParams.tracingEnabled) {
        return;
    }
    const { AsyncLocalStorageContextManager } = require('@opentelemetry/context-async-hooks');
    const { context, trace } = require('@opentelemetry/api');
    const { BasicTracerProvider } = require('@opentelemetry/sdk-trace-base');
    // setGlobalTracerProvider and setGlobalContextManager are "first one wins."
    // If an external provider is already registered, these calls are safely ignored.
    const contextManager = new AsyncLocalStorageContextManager();
    contextManager.enable();
    context.setGlobalContextManager(contextManager);
    const provider = new BasicTracerProvider({
        resource: {
            attributes: {
                'service.name': appName,
            },
        },
    });
    trace.setGlobalTracerProvider(provider);
}
exports.installTraceContextManager = installTraceContextManager;
class Tracer {
    telemetryCollector;
    applicationID;
    executorID;
    constructor(telemetryCollector) {
        this.telemetryCollector = telemetryCollector;
        this.applicationID = utils_1.globalParams.appID;
        this.executorID = utils_1.globalParams.executorID;
    }
    startSpanWithContext(spanContext, name, attributes) {
        if (!utils_1.globalParams.tracingEnabled) {
            return new StubSpan();
        }
        const opentelemetry = require('@opentelemetry/api');
        const tracer = opentelemetry.trace.getTracer('dbos-tracer');
        const ctx = opentelemetry.trace.setSpanContext(opentelemetry.context.active(), spanContext);
        return tracer.startSpan(name, { startTime: performance.now(), attributes: attributes }, ctx);
    }
    startSpan(name, attributes, inputSpan) {
        if (!utils_1.globalParams.tracingEnabled) {
            return new StubSpan();
        }
        const parentSpan = inputSpan;
        const opentelemetry = require('@opentelemetry/api');
        const { hrTime } = require('@opentelemetry/core');
        const tracer = opentelemetry.trace.getTracer('dbos-tracer');
        const startTime = hrTime(performance.now());
        if (parentSpan) {
            const ctx = opentelemetry.trace.setSpan(opentelemetry.context.active(), parentSpan);
            return tracer.startSpan(name, { startTime: startTime, attributes: attributes }, ctx);
        }
        else {
            return tracer.startSpan(name, { startTime: startTime, attributes: attributes });
        }
    }
    endSpan(inputSpan) {
        if (!utils_1.globalParams.tracingEnabled) {
            return;
        }
        const { hrTime } = require('@opentelemetry/core');
        const span = inputSpan;
        span.setAttributes({
            applicationID: this.applicationID,
            applicationVersion: utils_1.globalParams.appVersion,
        });
        if (span.attributes && !('executorID' in span.attributes)) {
            span.setAttribute('executorID', this.executorID);
        }
        span.end(hrTime(performance.now()));
        // Only push to DBOS's own collector when DBOS manages export.
        // When an external TracerProvider is used, span.end() triggers its processors.
        if (utils_1.globalParams.enableOTLP) {
            this.telemetryCollector.push(span);
        }
    }
}
exports.Tracer = Tracer;
//# sourceMappingURL=traces.js.map