@opentelemetry/exporter-jaeger
Version:
OpenTelemetry Exporter Jaeger allows user to send collected traces to Jaeger
170 lines • 6.94 kB
JavaScript
;
/*
* Copyright The OpenTelemetry Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.JaegerExporter = void 0;
const api_1 = require("@opentelemetry/api");
const core_1 = require("@opentelemetry/core");
const dgram_1 = require("dgram");
const semantic_conventions_1 = require("@opentelemetry/semantic-conventions");
const transform_1 = require("./transform");
const jaegerTypes = require("./types");
/**
* Format and sends span information to Jaeger Exporter.
*
* @deprecated Jaeger supports the OpenTelemetry protocol natively
* (see https://www.jaegertracing.io/docs/1.41/apis/#opentelemetry-protocol-stable).
* This exporter will not be required by the OpenTelemetry specification starting July 2023, and
* will not receive any security fixes past March 2024.
*
* Please migrate to any of the following packages:
* - `@opentelemetry/exporter-trace-otlp-proto`
* - `@opentelemetry/exporter-trace-otlp-grpc`
* - `@opentelemetry/exporter-trace-otlp-http`
*/
class JaegerExporter {
_onShutdownFlushTimeout;
_localConfig;
_shutdownOnce;
_sender;
constructor(config) {
const localConfig = Object.assign({}, config);
this._onShutdownFlushTimeout =
typeof localConfig.flushTimeout === 'number'
? localConfig.flushTimeout
: 2000;
// https://github.com/jaegertracing/jaeger-client-node#environment-variables
// By default, the client sends traces via UDP to the agent at localhost:6832. Use OTEL_EXPORTER_JAEGER_AGENT_HOST and
// JAEGER_AGENT_PORT to send UDP traces to a different host:port. If OTEL_EXPORTER_JAEGER_ENDPOINT is set, the client sends traces
// to the endpoint via HTTP, making the OTEL_EXPORTER_JAEGER_AGENT_HOST and JAEGER_AGENT_PORT unused. If OTEL_EXPORTER_JAEGER_ENDPOINT is secured,
// HTTP basic authentication can be performed by setting the OTEL_EXPORTER_JAEGER_USER and OTEL_EXPORTER_JAEGER_PASSWORD environment variables.
localConfig.endpoint =
localConfig.endpoint ||
((0, core_1.getStringFromEnv)('OTEL_EXPORTER_JAEGER_ENDPOINT') ?? '');
localConfig.username =
localConfig.username ||
((0, core_1.getStringFromEnv)('OTEL_EXPORTER_JAEGER_USER') ?? '');
localConfig.password =
localConfig.password ||
((0, core_1.getStringFromEnv)('OTEL_EXPORTER_JAEGER_PASSWORD') ?? '');
localConfig.host =
localConfig.host ||
((0, core_1.getStringFromEnv)('OTEL_EXPORTER_JAEGER_AGENT_HOST') ?? '');
localConfig.port =
localConfig.port ||
((0, core_1.getNumberFromEnv)('OTEL_EXPORTER_JAEGER_AGENT_PORT') ?? 6832);
this._localConfig = localConfig;
this._shutdownOnce = new core_1.BindOnceFuture(this._shutdown, this);
}
/** Exports a list of spans to Jaeger. */
export(spans, resultCallback) {
if (this._shutdownOnce.isCalled) {
return;
}
if (spans.length === 0) {
return resultCallback({ code: core_1.ExportResultCode.SUCCESS });
}
api_1.diag.debug('Jaeger exporter export');
this._sendSpans(spans, resultCallback).catch(error => {
return resultCallback({ code: core_1.ExportResultCode.FAILED, error });
});
}
/** Shutdown exporter. */
shutdown() {
return this._shutdownOnce.call();
}
/**
* Exports any pending spans in exporter
*/
forceFlush() {
return this._flush();
}
_shutdown() {
return Promise.race([
new Promise((_resolve, reject) => {
setTimeout(() => reject(new Error('Flush timeout')), this._onShutdownFlushTimeout);
}),
this._flush(),
]).finally(() => {
this._sender?.close();
});
}
/** Transform spans and sends to Jaeger service. */
async _sendSpans(spans, done) {
const thriftSpan = spans.map(span => (0, transform_1.spanToThrift)(span));
for (const span of thriftSpan) {
try {
await this._append(span);
}
catch (error) {
// TODO right now we break out on first error, is that desirable?
if (done)
return done({ code: core_1.ExportResultCode.FAILED, error });
}
}
api_1.diag.debug(`successful append for : ${thriftSpan.length}`);
// Flush all spans on each export. No-op if span buffer is empty
await this._flush();
if (done)
return process.nextTick(done, { code: core_1.ExportResultCode.SUCCESS });
}
async _append(span) {
return new Promise((resolve, reject) => {
this._getSender(span).append(span, (count, err) => {
if (err) {
return reject(new Error(err));
}
resolve(count);
});
});
}
_getSender(span) {
if (this._sender) {
return this._sender;
}
const sender = this._localConfig.endpoint
? new jaegerTypes.HTTPSender(this._localConfig)
: new jaegerTypes.UDPSender(this._localConfig);
if (sender._client instanceof dgram_1.Socket) {
// unref socket to prevent it from keeping the process running
sender._client.unref();
}
const serviceNameTag = span.tags.find(t => t.key === semantic_conventions_1.ATTR_SERVICE_NAME);
const serviceName = serviceNameTag?.vStr || 'unknown_service';
sender.setProcess({
serviceName,
tags: jaegerTypes.ThriftUtils.getThriftTags(this._localConfig.tags || []),
});
this._sender = sender;
return sender;
}
async _flush() {
await new Promise((resolve, reject) => {
if (!this._sender) {
return resolve();
}
this._sender.flush((_count, err) => {
if (err) {
return reject(new Error(err));
}
api_1.diag.debug(`successful flush for ${_count} spans`);
resolve();
});
});
}
}
exports.JaegerExporter = JaegerExporter;
//# sourceMappingURL=jaeger.js.map