@opentelemetry/resource-detector-instana
Version:
OpenTelemetry SDK resource detector for Instana
110 lines • 4.42 kB
JavaScript
;
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.instanaAgentDetector = void 0;
const api_1 = require("@opentelemetry/api");
const core_1 = require("@opentelemetry/core");
const semconv_1 = require("../semconv");
const http = require("http");
class InstanaAgentDetector {
INSTANA_AGENT_DEFAULT_HOST = 'localhost';
INSTANA_AGENT_DEFAULT_PORT = 42699;
detect() {
const dataPromise = api_1.context.with((0, core_1.suppressTracing)(api_1.context.active()), () => this._gatherData());
const attrNames = [semconv_1.ATTR_PROCESS_PID, semconv_1.ATTR_SERVICE_INSTANCE_ID];
const attributes = {};
attrNames.forEach(name => {
// Each resource attribute is determined asynchronously in _gatherData().
attributes[name] = dataPromise.then(data => data[name]);
});
return { attributes };
}
async _gatherData() {
const host = process.env.INSTANA_AGENT_HOST || this.INSTANA_AGENT_DEFAULT_HOST;
const port = Number(process.env.INSTANA_AGENT_PORT || this.INSTANA_AGENT_DEFAULT_PORT);
try {
const data = await this._retryHandler(host, port, 0);
return {
[semconv_1.ATTR_PROCESS_PID]: data.pid,
[semconv_1.ATTR_SERVICE_INSTANCE_ID]: data.agentUuid,
};
}
catch {
return {};
}
}
timeout(ms) {
return new Promise(resolve => setTimeout(resolve, ms).unref());
}
async _retryHandler(host, port, tries) {
const MAX_TRIES = 3;
try {
return await this._fetchAgentData(host, port);
}
catch (err) {
if (tries < MAX_TRIES) {
api_1.diag.debug(`Retrying to connect to the Instana agent on ${host}:${port}....`);
const retryTimeout = process.env.INSTANA_RETRY_TIMEOUT_MS
? Number(process.env.INSTANA_RETRY_TIMEOUT_MS)
: 1000;
await this.timeout(retryTimeout);
return await this._retryHandler(host, port, tries + 1);
}
throw err;
}
}
async _fetchAgentData(host, port) {
const agentTimeoutMs = process.env.INSTANA_AGENT_TIMEOUT_MS
? Number(process.env.INSTANA_AGENT_TIMEOUT_MS)
: 3 * 1000;
const payload = {
pid: process.pid,
};
const payloadStr = JSON.stringify(payload);
const contentLength = Buffer.from(payloadStr, 'utf8').length;
api_1.diag.debug(`Instana Agent: ${host}, ${port}`);
return new Promise((resolve, reject) => {
const opts = {
host,
port,
method: 'PUT',
path: '/com.instana.plugin.nodejs.discovery',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json; charset=UTF-8',
'Content-Length': contentLength,
},
timeout: agentTimeoutMs,
};
const req = http.request(opts, res => {
res.setEncoding('utf8');
let rawData = '';
res.on('data', chunk => (rawData += chunk));
res.on('end', () => {
if (!res.statusCode || res.statusCode !== 200) {
return reject(new Error(`Instana Agent returned status code ${res.statusCode}`));
}
try {
const data = JSON.parse(rawData);
if (data.pid && data.agentUuid) {
return resolve(data);
}
reject(new Error(`Invalid Instana Agent response format: ${data}.`));
}
catch (e) {
reject(e);
}
});
});
req.on('timeout', () => reject(new Error('Instana Agent request timed out.')));
req.on('error', err => reject(err));
req.write(Buffer.from(payloadStr), 'utf8');
req.end();
});
}
}
exports.instanaAgentDetector = new InstanaAgentDetector();
//# sourceMappingURL=InstanaAgentDetector.js.map