"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const Debug = require("debug");
const configuration_1 = require("../configuration");
const path_1 = require("path");
const httpMethodToIgnore = [
    'options',
    'head'
];
const defaultTracingConfig = {
    enabled: false,
    outbound: false,
    samplingRate: 0,
    ignoreIncomingPaths: [],
    ignoreOutgoingUrls: [],
    detailedDatabasesCalls: false,
    createSpanWithNet: false
};
const enabledTracingConfig = {
    enabled: true,
    outbound: false,
    samplingRate: 0.5,
    ignoreIncomingPaths: [
        (url, request) => {
            const method = (request.method || 'GET').toLowerCase();
            return httpMethodToIgnore.indexOf(method) > -1;
        },
        /(.*).js/,
        /(.*).css/,
        /(.*).png/,
        /(.*).ico/,
        /(.*).svg/,
        /webpack/
    ],
    ignoreOutgoingUrls: [],
    detailedDatabasesCalls: false,
    createSpanWithNet: false
};
class TracingFeature {
    constructor() {
        this.logger = Debug('axm:tracing');
    }
    init(config) {
        this.logger('init tracing');
        if (config.tracing === undefined) {
            config.tracing = defaultTracingConfig;
        }
        else if (config.tracing === true) {
            config.tracing = enabledTracingConfig;
        }
        else if (config.tracing === false) {
            config.tracing = defaultTracingConfig;
        }
        if (config.tracing.enabled === false) {
            return this.logger('tracing disabled');
        }
        this.options = Object.assign(enabledTracingConfig, config.tracing);
        if (typeof config.apmOptions === 'object' && typeof config.apmOptions.appName === 'string') {
            this.options.serviceName = config.apmOptions.appName;
        }
        else if (typeof process.env.name === 'string') {
            this.options.serviceName = process.env.name;
        }
        if (config.tracing.ignoreOutgoingUrls === undefined) {
            config.tracing.ignoreOutgoingUrls = enabledTracingConfig.ignoreOutgoingUrls;
        }
        if (config.tracing.ignoreIncomingPaths === undefined) {
            config.tracing.ignoreIncomingPaths = enabledTracingConfig.ignoreIncomingPaths;
        }
        const B3Format = require('@opencensus/propagation-b3').B3Format;
        const CustomCensusExporter = require('../census/exporter').CustomCensusExporter;
        const Tracing = require('../census/tracer').Tracing;
        this.exporter = new CustomCensusExporter(this.options);
        if (this.tracer && this.tracer.active) {
            throw new Error(`Tracing was already enabled`);
        }
        this.logger('start census tracer');
        const tracer = Tracing.instance;
        const plugins = {
            'http': {
                module: path_1.resolve(__dirname, '../census/plugins/http'),
                config: config.tracing
            },
            'http2': path_1.resolve(__dirname, '../census/plugins/http2'),
            'https': path_1.resolve(__dirname, '../census/plugins/https'),
            'mongodb-core': {
                module: path_1.resolve(__dirname, '../census/plugins/mongodb'),
                config: { detailedCommands: config.tracing.detailedDatabasesCalls }
            },
            'mysql': {
                module: path_1.resolve(__dirname, '../census/plugins/mysql'),
                config: { detailedCommands: config.tracing.detailedDatabasesCalls }
            },
            'mysql2': {
                module: path_1.resolve(__dirname, '../census/plugins/mysql2'),
                config: { detailedCommands: config.tracing.detailedDatabasesCalls }
            },
            'redis': {
                module: path_1.resolve(__dirname, '../census/plugins/redis'),
                config: { detailedCommands: config.tracing.detailedDatabasesCalls }
            },
            'ioredis': {
                module: path_1.resolve(__dirname, '../census/plugins/ioredis'),
                config: { detailedCommands: config.tracing.detailedDatabasesCalls }
            },
            'pg': {
                module: path_1.resolve(__dirname, '../census/plugins/pg'),
                config: { detailedCommands: config.tracing.detailedDatabasesCalls }
            },
            'vue-server-renderer': {
                module: path_1.resolve(__dirname, '../census/plugins/vue'),
                config: {}
            }
        };
        if (this.options.createSpanWithNet === true) {
            plugins['net'] = {
                module: path_1.resolve(__dirname, '../census/plugins/net')
            };
        }
        this.tracer = tracer.start({
            exporter: this.exporter,
            plugins,
            propagation: new B3Format(),
            samplingRate: this.options.samplingRate || 0.5,
            logLevel: this.isDebugEnabled() ? 4 : 1
        });
        configuration_1.default.configureModule({
            census_tracing: true
        });
    }
    isDebugEnabled() {
        return typeof process.env.DEBUG === 'string' &&
            (process.env.DEBUG.indexOf('axm:*') >= 0 || process.env.DEBUG.indexOf('axm:tracing') >= 0);
    }
    getTracer() {
        return this.tracer ? this.tracer.tracer : undefined;
    }
    destroy() {
        if (!this.tracer)
            return;
        this.logger('stop census tracer');
        configuration_1.default.configureModule({
            census_tracing: false
        });
        this.tracer.stop();
    }
}
exports.TracingFeature = TracingFeature;
//# sourceMappingURL=data:application/json;base64,[encoded data, 6056 characters]