"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.instrument = exports.getTracerProvider = exports.disableInstrumentations = exports.shutdown = exports.init = void 0;
const tslib_1 = require("tslib");
const http_1 = require("http");
const api = tslib_1.__importStar(require("@opentelemetry/api"));
const api_1 = require("@opentelemetry/api");
const context_async_hooks_1 = require("@opentelemetry/context-async-hooks");
const exporter_trace_otlp_http_1 = require("@opentelemetry/exporter-trace-otlp-http");
const instrumentation_1 = require("@opentelemetry/instrumentation");
const instrumentation_bunyan_1 = require("@opentelemetry/instrumentation-bunyan");
const instrumentation_http_1 = require("@opentelemetry/instrumentation-http");
const resources_1 = require("@opentelemetry/resources");
const sdk_trace_base_1 = require("@opentelemetry/sdk-trace-base");
const sdk_trace_node_1 = require("@opentelemetry/sdk-trace-node");
const semantic_conventions_1 = require("@opentelemetry/semantic-conventions");
const expose_cjs_1 = require("../expose.cjs");
const utils_1 = require("./utils");
let instrumentations = [];
init();
function init() {
    if (!(0, utils_1.isTracingEnabled)()) {
        return;
    }
    const traceProvider = new sdk_trace_node_1.NodeTracerProvider({
        resource: new resources_1.Resource({
            // https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/resource/semantic_conventions/README.md#semantic-attributes-with-sdk-provided-default-value
            [semantic_conventions_1.SemanticResourceAttributes.SERVICE_NAME]: 'renovate',
            [semantic_conventions_1.SemanticResourceAttributes.SERVICE_NAMESPACE]: 'renovatebot.com',
            [semantic_conventions_1.SemanticResourceAttributes.SERVICE_VERSION]: expose_cjs_1.pkg.version,
        }),
    });
    // add processors
    if ((0, utils_1.isTraceDebuggingEnabled)()) {
        traceProvider.addSpanProcessor(new sdk_trace_base_1.SimpleSpanProcessor(new sdk_trace_base_1.ConsoleSpanExporter()));
    }
    // OTEL specification environment variable
    if ((0, utils_1.isTraceSendingEnabled)()) {
        const exporter = new exporter_trace_otlp_http_1.OTLPTraceExporter();
        traceProvider.addSpanProcessor(new sdk_trace_base_1.BatchSpanProcessor(exporter));
    }
    const contextManager = new context_async_hooks_1.AsyncLocalStorageContextManager();
    traceProvider.register({
        contextManager,
    });
    instrumentations = [
        new instrumentation_http_1.HttpInstrumentation({
            applyCustomAttributesOnSpan: /* istanbul ignore next */ (span, request, response) => {
                // ignore 404 errors when the branch protection of Github could not be found. This is expected if no rules are configured
                if (request instanceof http_1.ClientRequest &&
                    request.host === `api.github.com` &&
                    request.path.endsWith(`/protection`) &&
                    response.statusCode === 404) {
                    span.setStatus({ code: api_1.SpanStatusCode.OK });
                }
            },
        }),
        new instrumentation_bunyan_1.BunyanInstrumentation(),
    ];
    (0, instrumentation_1.registerInstrumentations)({
        instrumentations,
    });
}
exports.init = init;
/* istanbul ignore next */
// https://github.com/open-telemetry/opentelemetry-js-api/issues/34
async function shutdown() {
    const traceProvider = getTracerProvider();
    if (traceProvider instanceof sdk_trace_node_1.NodeTracerProvider) {
        await traceProvider.shutdown();
    }
    else if (traceProvider instanceof api_1.ProxyTracerProvider) {
        const delegateProvider = traceProvider.getDelegate();
        if (delegateProvider instanceof sdk_trace_node_1.NodeTracerProvider) {
            await delegateProvider.shutdown();
        }
    }
}
exports.shutdown = shutdown;
/* istanbul ignore next */
function disableInstrumentations() {
    for (const instrumentation of instrumentations) {
        instrumentation.disable();
    }
}
exports.disableInstrumentations = disableInstrumentations;
function getTracerProvider() {
    return api.trace.getTracerProvider();
}
exports.getTracerProvider = getTracerProvider;
function getTracer() {
    return getTracerProvider().getTracer('renovate');
}
function instrument(name, fn, options = {}, context = api.context.active()) {
    return getTracer().startActiveSpan(name, options, context, (span) => {
        try {
            const ret = fn(span);
            if (ret instanceof Promise) {
                return ret
                    .catch((e) => {
                    span.setStatus({
                        code: api_1.SpanStatusCode.ERROR,
                        message: e,
                    });
                    throw e;
                })
                    .finally(() => span.end());
            }
            span.end();
            return ret;
        }
        catch (e) {
            span.setStatus({
                code: api_1.SpanStatusCode.ERROR,
                message: e,
            });
            span.end();
            throw e;
        }
    });
}
exports.instrument = instrument;
//# sourceMappingURL=index.js.map