appdynamics
Version:
Performance Profiler and Monitor
121 lines (105 loc) • 4.91 kB
JavaScript
;
const opentelemetry_api = require('@opentelemetry/api');
const { ROOT_CONTEXT } = require('@opentelemetry/api');
const { BatchSpanProcessor, BasicTracerProvider } = require('@opentelemetry/sdk-trace-base');
const { OTLPTraceExporter } = require("@opentelemetry/exporter-trace-otlp-proto");
const { AsyncHooksContextManager, AsyncLocalStorageContextManager } = require("@opentelemetry/context-async-hooks");
const { ParentBasedSampler, AlwaysOnSampler, TraceIdRatioBasedSampler } = require("@opentelemetry/core");
const { Resource, envDetectorSync, processDetectorSync, hostDetectorSync } = require('@opentelemetry/resources');
const { SemanticResourceAttributes } = require('@opentelemetry/semantic-conventions');
const AppdynamicsSpanExporter = require('./appdynamics_span_exporter').AppdynamicsSpanExporter;
const url = require('url');
module.exports = TracerProvider;
function TracerProvider(logger) {
this.host = 'localhost';
this.port = '4318';
this.url = process.env.OTEL_EXPORTER_OTLP_ENDPOINT ? process.env.OTEL_EXPORTER_OTLP_ENDPOINT + '/v1/traces'
: `http://${this.host}:${this.port}/v1/traces`;
this.ot_api = opentelemetry_api;
this.ROOT_CONTEXT = ROOT_CONTEXT;
this.logger = logger;
}
function getSamplerFromConfig(config) {
if(config.sampler && config.sampler.TraceIdRatioBasedSampler) {
const ratio = config.sampler.TraceIdRatioBasedSampler.Ratio || 1;
return new TraceIdRatioBasedSampler(ratio);
} else {
return new AlwaysOnSampler();
}
}
TracerProvider.prototype.register = function(config) {
const envResource = envDetectorSync.detect();
const processResource = processDetectorSync.detect();
const hostResource = hostDetectorSync.detect();
const configResourceAttributes = {
[SemanticResourceAttributes.SERVICE_NAME]: config.tierName,
[SemanticResourceAttributes.SERVICE_NAMESPACE]: config.applicationName,
[SemanticResourceAttributes.CONTAINER_ID]: ""
};
const mergedResource = new Resource(configResourceAttributes)
.merge(envResource)
.merge(processResource)
.merge(hostResource);
const provider = new BasicTracerProvider({
sampler: new ParentBasedSampler({
root: getSamplerFromConfig(config.openTelemetry)
}),
resource: mergedResource,
});
// default collector configuration, can be overridden from agent config
const collectorOptions = {
url: this.url,
attributes: {'service.name': config.tierName,
'service.namespace': config.applicationName}
};
// batch export config, empty by default
const batchProcessorConfig = {};
if (config.openTelemetry) {
if (config.openTelemetry.collector) {
Object.assign(collectorOptions, config.openTelemetry.collector);
this.url = collectorOptions.url;
this.logger.debug('Exporter using config ' + JSON.stringify(collectorOptions));
try {
var urlObj = url.parse(this.url);
this.host = urlObj.hostname;
this.port = urlObj.port;
} catch (e) {
this.logger.error('Collector url must be in <host>:<port> format');
return false;
}
}
if(config.openTelemetry.exporter) {
if(config.openTelemetry.exporter.maxExportBatchSize) {
batchProcessorConfig.maxExportBatchSize = config.openTelemetry.exporter.maxExportBatchSize;
}
if(config.openTelemetry.exporter.maxQueueSize) {
batchProcessorConfig.maxQueueSize = config.openTelemetry.exporter.maxQueueSize;
}
if(config.openTelemetry.exporter.exportTimeoutMillis) {
batchProcessorConfig.exportTimeoutMillis = config.openTelemetry.exporter.exportTimeoutMillis;
}
if(config.openTelemetry.exporter.maxExportBatchSize) {
batchProcessorConfig.maxExportBatchSize = config.openTelemetry.exporter.maxExportBatchSize;
}
}
this.logger.debug('Batch Processor config ' + JSON.stringify(batchProcessorConfig));
}
const exporter = new OTLPTraceExporter(collectorOptions);
provider.addSpanProcessor(new BatchSpanProcessor(exporter, batchProcessorConfig));
const appdExporter = new AppdynamicsSpanExporter(this.logger, batchProcessorConfig);
provider.addSpanProcessor(new BatchSpanProcessor(appdExporter, batchProcessorConfig));
const majorVersion = parseInt(process.versions.node.split('.')[0]);
const minorVersion = parseInt(process.versions.node.split('.')[1]);
const contextManager = majorVersion > 14 || majorVersion == 14 && minorVersion >= 8 ?
AsyncLocalStorageContextManager : AsyncHooksContextManager;
provider.register({contextManager: new contextManager()});
return true;
};
TracerProvider.prototype.getTracer = function(name) {
return opentelemetry_api.trace.getTracer(name);
};
TracerProvider.prototype.updateResourceAttributes = function(attrs) {
for(let [key, value] of Object.entries(attrs)) {
this.getTracer().resource.attributes[key] = value;
}
};