@vtex/diagnostics-nodejs
Version:
Diagnostics library for Node.js applications
184 lines • 6.71 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.configureDefaults = configureDefaults;
const tslib_1 = require("tslib");
const resources_1 = require("@opentelemetry/resources");
const semantic_conventions_1 = require("@opentelemetry/semantic-conventions");
const diagnostics_semconv_1 = require("@vtex/diagnostics-semconv");
const os = tslib_1.__importStar(require("os"));
const uuid_1 = require("uuid");
const fs = tslib_1.__importStar(require("fs/promises"));
const resource_detector_aws_1 = require("@opentelemetry/resource-detector-aws");
const utils_1 = require("../utils");
const config_1 = require("../config");
const ENV_SERVICE_VERSION = 'SERVICE_VERSION';
const ENV_DEPLOYMENT_ENV = 'DEPLOYMENT_ENVIRONMENT';
const ENV_KUBERNETES_HOST = 'KUBERNETES_SERVICE_HOST';
const ENV_KUBERNETES_NAMESPACE = 'KUBERNETES_NAMESPACE';
const ENV_KUBERNETES_NODE_NAME = 'KUBERNETES_NODE_NAME';
const ENV_KUBERNETES_POD_NAME = 'KUBERNETES_POD_NAME';
let cachedHostname = null;
const envVarsCache = {};
let isKubernetesEnv = null;
function getHostname() {
if (cachedHostname === null) {
try {
cachedHostname = os.hostname();
}
catch {
cachedHostname = 'unknown-host';
}
}
return cachedHostname;
}
function getEnvVarsWithPrefix(prefix) {
if (!envVarsCache[prefix]) {
const result = {};
for (const key in process.env) {
if (key.startsWith(prefix)) {
result[key] = process.env[key];
}
}
envVarsCache[prefix] = result;
}
return envVarsCache[prefix];
}
async function configureDefaults(config) {
const resourceAttrs = await discoverResourceAttributes(config);
const instanceId = generateInstanceId(config.clientName);
const baseAttrs = {
[diagnostics_semconv_1.ATTR_VTEX_DIAGNOSTICS_VERSION]: (0, config_1.getLibraryVersion)(),
[diagnostics_semconv_1.ATTR_VTEX_DIAGNOSTICS_NAME]: (0, config_1.getLibraryName)(),
[semantic_conventions_1.ATTR_SERVICE_NAME]: config.serviceName,
[semantic_conventions_1.SEMRESATTRS_SERVICE_INSTANCE_ID]: instanceId,
[semantic_conventions_1.ATTR_SERVICE_VERSION]: process.env[ENV_SERVICE_VERSION] || 'unknown',
[semantic_conventions_1.SEMRESATTRS_DEPLOYMENT_ENVIRONMENT]: process.env[ENV_DEPLOYMENT_ENV] || config.environment || 'unknown',
'application.id': config.applicationID,
...resourceAttrs
};
let resource = (0, utils_1.createResource)(baseAttrs);
if (!config.disableCloudDetect) {
resource = await detectCloudResources(resource);
}
if (config.additionalAttrs) {
resource = resource.merge((0, utils_1.createResource)(config.additionalAttrs));
}
return resource;
}
async function discoverResourceAttributes(config) {
const attrs = {
[semantic_conventions_1.SEMRESATTRS_HOST_NAME]: getHostname()
};
if (inKubernetes() && !config.disableK8sDetect) {
Object.assign(attrs, getKubernetesAttributes());
}
const envAttrs = await getEnvironmentAttributes(config);
return { ...attrs, ...envAttrs };
}
async function getEnvironmentAttributes(config) {
const attrs = {};
if (config.envMappings?.length) {
for (const mapping of config.envMappings) {
const value = process.env[mapping.envVar] || mapping.defaultValue;
if (value !== undefined) {
attrs[mapping.attributeName] = value;
}
}
}
if (!config.disableEnvPrefixDetection) {
const prefix = config.envPrefix || 'TELEMETRY_ATTR_';
const prefixedVars = getEnvVarsWithPrefix(prefix);
for (const key in prefixedVars) {
const attrKey = key.substring(prefix.length)
.toLowerCase()
.replace(/_/g, '.');
attrs[attrKey] = prefixedVars[key];
}
}
if (!config.disableEnvMappingsFromEnv) {
const mappingsEnv = process.env.TELEMETRY_ATTR_MAPPINGS;
if (mappingsEnv) {
const mappings = mappingsEnv.split(',');
for (const mapping of mappings) {
const parts = mapping.trim().split(':');
if (parts.length === 2) {
const [envVar, attrKey] = parts;
if (process.env[envVar]) {
attrs[attrKey] = process.env[envVar];
}
}
}
}
}
if (config.customAttributesFile) {
try {
const customAttrs = await readCustomAttributesFile(config.customAttributesFile);
if (customAttrs.environmentVariables) {
for (const [envVar, attrKey] of Object.entries(customAttrs.environmentVariables)) {
if (process.env[envVar]) {
attrs[attrKey] = process.env[envVar];
}
}
}
if (customAttrs.attributes) {
Object.assign(attrs, customAttrs.attributes);
}
}
catch { }
}
return attrs;
}
async function readCustomAttributesFile(filePath) {
try {
const fileContent = await fs.readFile(filePath, 'utf8');
return JSON.parse(fileContent);
}
catch {
return {};
}
}
async function detectCloudResources(baseResource) {
let detectedResources = await (0, resources_1.detectResources)({
detectors: [
new resource_detector_aws_1.AwsEcsDetectorSync(),
]
});
return baseResource.merge(detectedResources);
}
function getKubernetesAttributes() {
const attrs = {};
const k8sVars = {
[ENV_KUBERNETES_NAMESPACE]: semantic_conventions_1.SemanticResourceAttributes.K8S_NAMESPACE_NAME,
[ENV_KUBERNETES_NODE_NAME]: semantic_conventions_1.SemanticResourceAttributes.K8S_NODE_NAME,
};
for (const [envVar, semAttr] of Object.entries(k8sVars)) {
const value = process.env[envVar];
if (value) {
attrs[semAttr] = value;
}
}
return attrs;
}
function inKubernetes() {
if (isKubernetesEnv === null) {
isKubernetesEnv = Boolean(process.env[ENV_KUBERNETES_HOST]);
}
return isKubernetesEnv;
}
function generateInstanceId(clientName) {
const parts = [clientName, getHostname()];
if (inKubernetes()) {
const podName = process.env[ENV_KUBERNETES_POD_NAME];
if (podName) {
parts.push(podName);
}
}
if (parts.length < 2) {
parts.push((0, uuid_1.v4)());
}
return parts.join('-');
}
exports.default = {
configureDefaults
};
//# sourceMappingURL=resource-discovery.js.map