"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.withTracing = exports.configureTracer = exports.retrieveTraceId = void 0;
const api_1 = require("@opentelemetry/api");
const instrumentation_1 = require("@opentelemetry/instrumentation");
const instrumentation_http_1 = require("@opentelemetry/instrumentation-http");
const instrumentation_winston_1 = require("@opentelemetry/instrumentation-winston");
const propagator_b3_1 = require("@opentelemetry/propagator-b3");
const resources_1 = require("@opentelemetry/resources");
const sdk_trace_node_1 = require("@opentelemetry/sdk-trace-node");
const semantic_conventions_1 = require("@opentelemetry/semantic-conventions");
const envs_1 = require("../envs");
const retrieveTraceId = () => {
    const context = api_1.context.active();
    return api_1.trace.getSpanContext(context);
};
exports.retrieveTraceId = retrieveTraceId;
// singleton required
let tracer;
const configureTracer = (partialConf) => {
    if (tracer)
        return tracer;
    const defaultConf = {
        serviceName: (0, envs_1.maybeGetEnvParam)(envs_1.EnvVar.SERVICE_NAME),
        environment: (0, envs_1.maybeGetEnvParam)(envs_1.EnvVar.ENVIRONMENT),
        withHttpTrace: true,
        withLogTrace: true,
    };
    const conf = Object.assign(Object.assign({}, defaultConf), partialConf);
    const { serviceName, environment, withLogTrace, withHttpTrace } = conf;
    const provider = new sdk_trace_node_1.NodeTracerProvider({
        resource: new resources_1.Resource({
            [semantic_conventions_1.SemanticResourceAttributes.SERVICE_NAME]: serviceName,
            [semantic_conventions_1.SemanticResourceAttributes.DEPLOYMENT_ENVIRONMENT]: environment,
        }),
    });
    const instrumentations = [];
    if (withHttpTrace) {
        instrumentations.push(new instrumentation_http_1.HttpInstrumentation());
    }
    if (withLogTrace) {
        instrumentations.push(new instrumentation_winston_1.WinstonInstrumentation());
    }
    (0, instrumentation_1.registerInstrumentations)({
        tracerProvider: provider,
        instrumentations,
    });
    provider.register({
        propagator: new propagator_b3_1.B3Propagator(),
    });
    tracer = api_1.trace.getTracer(serviceName);
    return tracer;
};
exports.configureTracer = configureTracer;
function withTracing(spanName, callback, parentContext) {
    parentContext = parentContext || api_1.context.active();
    const span = (0, exports.configureTracer)().startSpan(spanName, undefined, parentContext);
    const childContext = api_1.trace.setSpan(parentContext, span);
    return new Promise((resolve, reject) => {
        api_1.context.with(childContext, async () => {
            try {
                const res = await callback(api_1.context.active());
                span.setStatus({ code: api_1.SpanStatusCode.OK });
                return resolve(res);
            }
            catch (e) {
                span.recordException(String(e));
                span.setStatus({ code: api_1.SpanStatusCode.ERROR, message: String(e) });
                return reject(e);
            }
            finally {
                span.end();
            }
        });
    });
}
exports.withTracing = withTracing;
//# sourceMappingURL=tracer.js.map