UNPKG

@opentelemetry/resources

Version:
105 lines 4.74 kB
"use strict"; /* * Copyright The OpenTelemetry Authors * SPDX-License-Identifier: Apache-2.0 */ Object.defineProperty(exports, "__esModule", { value: true }); exports.envDetector = void 0; const api_1 = require("@opentelemetry/api"); const semantic_conventions_1 = require("@opentelemetry/semantic-conventions"); const core_1 = require("@opentelemetry/core"); /** * EnvDetector can be used to detect the presence of and create a Resource * from the OTEL_RESOURCE_ATTRIBUTES environment variable. */ class EnvDetector { // Type, attribute keys, and attribute values should not exceed 256 characters. _MAX_LENGTH = 255; // OTEL_RESOURCE_ATTRIBUTES is a comma-separated list of attributes. _COMMA_SEPARATOR = ','; // OTEL_RESOURCE_ATTRIBUTES contains key value pair separated by '='. _LABEL_KEY_VALUE_SPLITTER = '='; /** * Returns a {@link Resource} populated with attributes from the * OTEL_RESOURCE_ATTRIBUTES environment variable. Note this is an async * function to conform to the Detector interface. * * @param config The resource detection config */ detect(_config) { const attributes = {}; const rawAttributes = (0, core_1.getStringFromEnv)('OTEL_RESOURCE_ATTRIBUTES'); const serviceName = (0, core_1.getStringFromEnv)('OTEL_SERVICE_NAME'); if (rawAttributes) { try { const parsedAttributes = this._parseResourceAttributes(rawAttributes); Object.assign(attributes, parsedAttributes); } catch (e) { api_1.diag.debug(`EnvDetector failed: ${e instanceof Error ? e.message : e}`); } } if (serviceName) { attributes[semantic_conventions_1.ATTR_SERVICE_NAME] = serviceName; } return { attributes }; } /** * Creates an attribute map from the OTEL_RESOURCE_ATTRIBUTES environment * variable. * * OTEL_RESOURCE_ATTRIBUTES: A comma-separated list of attributes in the * format "key1=value1,key2=value2". The ',' and '=' characters in keys * and values MUST be percent-encoded. Other characters MAY be percent-encoded. * * Per the spec, on any error (e.g., decoding failure), the entire environment * variable value is discarded. * * @param rawEnvAttributes The resource attributes as a comma-separated list * of key/value pairs. * @returns The parsed resource attributes. * @throws Error if parsing fails (caller handles by discarding all attributes) */ _parseResourceAttributes(rawEnvAttributes) { if (!rawEnvAttributes) return {}; const attributes = {}; const rawAttributes = rawEnvAttributes .split(this._COMMA_SEPARATOR) .filter(attr => attr.trim() !== ''); // Filter out empty entries for (const rawAttribute of rawAttributes) { const keyValuePair = rawAttribute.split(this._LABEL_KEY_VALUE_SPLITTER); // Per spec: ',' and '=' MUST be percent-encoded in keys and values. // If we get != 2 parts, there's an unencoded '=' which is an error. if (keyValuePair.length !== 2) { throw new Error(`Invalid format for OTEL_RESOURCE_ATTRIBUTES: "${rawAttribute}". ` + "Expected format: key=value. The ',' and '=' characters must be percent-encoded in keys and values."); } const [rawKey, rawValue] = keyValuePair; const key = rawKey.trim(); const value = rawValue.trim(); if (key.length === 0) { throw new Error(`Invalid OTEL_RESOURCE_ATTRIBUTES: empty attribute key in "${rawAttribute}".`); } let decodedKey; let decodedValue; try { decodedKey = decodeURIComponent(key); decodedValue = decodeURIComponent(value); } catch (e) { throw new Error(`Failed to percent-decode OTEL_RESOURCE_ATTRIBUTES entry "${rawAttribute}": ${e instanceof Error ? e.message : e}`, { cause: e }); } if (decodedKey.length > this._MAX_LENGTH) { throw new Error(`Attribute key exceeds the maximum length of ${this._MAX_LENGTH} characters: "${decodedKey}".`); } if (decodedValue.length > this._MAX_LENGTH) { throw new Error(`Attribute value exceeds the maximum length of ${this._MAX_LENGTH} characters for key "${decodedKey}".`); } attributes[decodedKey] = decodedValue; } return attributes; } } exports.envDetector = new EnvDetector(); //# sourceMappingURL=EnvDetector.js.map