UNPKG

@dynatrace/opentelemetry-core

Version:

Dynatrace OpenTelemetry core package

243 lines (240 loc) 12.4 kB
"use strict"; /* Copyright 2022 Dynatrace LLC 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 http://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.detectConfiguration = detectConfiguration; exports.getConfiguration = getConfiguration; exports._testSetConfig = _testSetConfig; const fs = require("fs"); const path = require("path"); const Long = require("long"); const TenantId_1 = require("../utils/TenantId"); const Validators_1 = require("../utils/Validators"); const Types_1 = require("../Types"); // ============================================================================ // used to store the Configuration to avoid parsing it more then once let dtConfiguration; // ---------------------------------------------------------------------------- /** * Builds up configuration using options passed during initialization, Environment * variables and configuration files. * Following priority is used: * - Options given as arguments * - Options from environment * - Options from config file * @param options options provided programatically * @returns configuration * * Note: this function is only exported for tests, use `getConfiguration()` instead. */ function detectConfiguration(options) { var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16; const fileConfig = getConfigFromFile(); const clusterId = numberOrUndefined((_b = (_a = options === null || options === void 0 ? void 0 : options.clusterID) !== null && _a !== void 0 ? _a : getIntFromEnv("DT_CLUSTER_ID")) !== null && _b !== void 0 ? _b : fileConfig.ClusterID); const tenantUUID = stringOrUndefined((_d = (_c = options === null || options === void 0 ? void 0 : options.tenant) !== null && _c !== void 0 ? _c : process.env.DT_TENANT) !== null && _d !== void 0 ? _d : fileConfig.Tenant); // Connection options const baseUrl = stringOrUndefined((_g = (_f = (_e = options === null || options === void 0 ? void 0 : options.connection) === null || _e === void 0 ? void 0 : _e.baseUrl) !== null && _f !== void 0 ? _f : process.env.DT_CONNECTION_BASE_URL) !== null && _g !== void 0 ? _g : (_h = fileConfig.Connection) === null || _h === void 0 ? void 0 : _h.BaseUrl); const authToken = stringOrUndefined((_l = (_k = (_j = options === null || options === void 0 ? void 0 : options.connection) === null || _j === void 0 ? void 0 : _j.authToken) !== null && _k !== void 0 ? _k : process.env.DT_CONNECTION_AUTH_TOKEN) !== null && _l !== void 0 ? _l : (_m = fileConfig.Connection) === null || _m === void 0 ? void 0 : _m.AuthToken); // Testability const spanProcessingIntervalMs = numberOrUndefined((_q = (_p = (_o = options === null || options === void 0 ? void 0 : options.testability) === null || _o === void 0 ? void 0 : _o.spanProcessingIntervalMs) !== null && _p !== void 0 ? _p : getIntFromEnv("DT_TESTABILITY_SPAN_PROCESSING_INTERVAL_MS")) !== null && _q !== void 0 ? _q : (_r = fileConfig.Testability) === null || _r === void 0 ? void 0 : _r.SpanProcessingIntervalMs); // Logging const val = (_u = (_t = (_s = options === null || options === void 0 ? void 0 : options.logging) === null || _s === void 0 ? void 0 : _s.destination) !== null && _t !== void 0 ? _t : process.env.DT_LOGGING_DESTINATION) !== null && _u !== void 0 ? _u : (_v = fileConfig.Logging) === null || _v === void 0 ? void 0 : _v.Destination; let loggingDestination; switch (val) { case Types_1.LoggingDestination.Off: case Types_1.LoggingDestination.StdErr: case Types_1.LoggingDestination.StdOut: loggingDestination = val; break; } let loggingFlags; const loggingFlagsString = stringOrUndefined((_z = (_y = (_x = (_w = options === null || options === void 0 ? void 0 : options.logging) === null || _w === void 0 ? void 0 : _w.nodejs) === null || _x === void 0 ? void 0 : _x.flags) !== null && _y !== void 0 ? _y : process.env.DT_LOGGING_NODEJS_FLAGS) !== null && _z !== void 0 ? _z : (_1 = (_0 = fileConfig.Logging) === null || _0 === void 0 ? void 0 : _0.NodeJs) === null || _1 === void 0 ? void 0 : _1.Flags); if (loggingFlagsString != null) { loggingFlags = Object.create(null); const flags = parseList(loggingFlagsString, ","); for (const flag of flags) { const [name, value] = parseFlag(flag); if (name != null) { loggingFlags[name] = value; } } } // RUM let rumClientIpHeaders; if (((_2 = options === null || options === void 0 ? void 0 : options.rum) === null || _2 === void 0 ? void 0 : _2.clientIpHeaders) != null) { if ((0, Validators_1.checkStringArrayOption)((_3 = options === null || options === void 0 ? void 0 : options.rum) === null || _3 === void 0 ? void 0 : _3.clientIpHeaders)) { rumClientIpHeaders = (_4 = options === null || options === void 0 ? void 0 : options.rum) === null || _4 === void 0 ? void 0 : _4.clientIpHeaders; } } if (rumClientIpHeaders == null && typeof (process.env.DT_RUM_CLIENT_IP_HEADERS) === "string") { rumClientIpHeaders = parseList(process.env.DT_RUM_CLIENT_IP_HEADERS, ":"); } if (rumClientIpHeaders == null && ((_5 = fileConfig.RUM) === null || _5 === void 0 ? void 0 : _5.ClientIpHeaders) != null) { if ((0, Validators_1.checkStringArrayOption)((_6 = fileConfig.RUM) === null || _6 === void 0 ? void 0 : _6.ClientIpHeaders)) { rumClientIpHeaders = (_7 = fileConfig.RUM) === null || _7 === void 0 ? void 0 : _7.ClientIpHeaders; } } rumClientIpHeaders = (_8 = rumClientIpHeaders === null || rumClientIpHeaders === void 0 ? void 0 : rumClientIpHeaders.map(s => s.toLowerCase().trim())) !== null && _8 !== void 0 ? _8 : undefined; const rumApplicationId = stringOrUndefined((_11 = (_10 = (_9 = options === null || options === void 0 ? void 0 : options.rum) === null || _9 === void 0 ? void 0 : _9.applicationId) !== null && _10 !== void 0 ? _10 : process.env.DT_RUM_APPLICATION_ID) !== null && _11 !== void 0 ? _11 : (_12 = fileConfig.RUM) === null || _12 === void 0 ? void 0 : _12.ApplicationId); // Debug const debugAddStackOnStart = getBoolean((_15 = (_14 = (_13 = options === null || options === void 0 ? void 0 : options.debug) === null || _13 === void 0 ? void 0 : _13.addStackOnStart) !== null && _14 !== void 0 ? _14 : process.env.DT_DEBUG_ADD_STACK_ON_START) !== null && _15 !== void 0 ? _15 : (_16 = fileConfig.Debug) === null || _16 === void 0 ? void 0 : _16.AddStackOnStart); const sanitizedTenantUUID = tenantUUID != null ? (0, TenantId_1.sanitizeTenantUuid)(tenantUUID) : undefined; return { clusterId, tenantUUID: sanitizedTenantUUID, tenantId: sanitizedTenantUUID != null ? (0, TenantId_1.calculateTenantId)(sanitizedTenantUUID) : undefined, agentID: generateAgentId(), baseUrl, authToken, spanProcessingIntervalMs, loggingDestination, loggingFlags, rumClientIpHeaders, rumApplicationId, debugAddStackOnStart }; } // ---------------------------------------------------------------------------- /** * Builds up configuration using options passed, Environment variables and configuration files. * Following priority is used: * - Options given as function arguments * - Options from environment * - Options from config files * The detected configuration is cached and returned on followup calls. * @param options optional options provided programatically (e.g. Commandline) * @returns configuration retrieved */ function getConfiguration(options) { if (dtConfiguration == null) { dtConfiguration = detectConfiguration(options); } return dtConfiguration; } // ---------------------------------------------------------------------------- /** * Reads configuration from file. If configuration file is cached then the cached config will be returned. * Following order is used: * - File referenced by environment variable DT_CONFIG_FILE (if set) * - dtconfig.json in current working directory (if existing) * if parsing of a file fails no fallback is used. * @returns The parsed JSON read or an empty object */ function getConfigFromFile() { var _a; let configFile; try { const json = fs.readFileSync((_a = process.env.DT_CONFIG_FILE) !== null && _a !== void 0 ? _a : path.join(process.cwd(), "dtconfig.json"), { encoding: "utf8" }); configFile = JSON.parse(json); } catch (_b) { // ignore parse error/missing file configFile = Object.create(null); } return configFile; } // ---------------------------------------------------------------------------- /** * Parses a number from an environment variable. * @param name name of environment variable * @returns the parsed number (may be NaN) or undefined if variable doesn't exist */ function getIntFromEnv(name) { const val = process.env[name]; if (val != null) { return parseInt(val, 10); } return undefined; } // ---------------------------------------------------------------------------- function numberOrUndefined(val) { return (typeof (val) === "number" && !isNaN(val)) ? val : undefined; } // ---------------------------------------------------------------------------- function stringOrUndefined(val) { return (typeof (val) === "string" && val.length > 0) ? val : undefined; } /** * Gracefully parses a variable to a boolean value. * Variables with boolean values should gracefully evaluate to true or false. * All values that do not case insensitively match to "false" or "0" evaluate to true. * @param value value to parse * @returns false if the value case insensitively matches to "false", "0", or it is null; true otherwise */ function getBoolean(val) { if (val == null) { return false; } if (typeof (val) === "string") { return toBoolean(val); } if (typeof (val) === "boolean") { return val; } if (typeof (val) === "number") { if (isNaN(val)) { return false; } return val !== 0; } return true; } // ---------------------------------------------------------------------------- /** * Parse a logging flag to name/value. * @param flag flag to parse */ function parseFlag(flag) { const tokens = flag.split("=", 3); if (tokens.length !== 2 || tokens[0].length === 0 || tokens[1].length === 0) { return []; } return [tokens[0].trim(), toBoolean(tokens[1])]; } // ---------------------------------------------------------------------------- /** * Graceful convert a string to a boolean. * @param value the string to convert */ function toBoolean(value) { const lcVal = value.trim().toLowerCase(); return (lcVal !== "false") && (lcVal !== "0"); } // ---------------------------------------------------------------------------- /** * Parse string formated as list and trim whitespace from each entry. * @param value string to parse * @param separator */ function parseList(value, separator) { if (value.length === 0) { return []; } return value.split(separator).map(s => s.trim()); } // ---------------------------------------------------------------------------- /** * Generates a random agent Id * @returns The 64 bit agent id */ function generateAgentId() { const to32Bit = 2 ** 32 - 1; return new Long(Math.random() * to32Bit, Math.random() * to32Bit); } // ---------------------------------------------------------------------------- /// only exported for unittests // eslint-disable-next-line @typescript-eslint/no-explicit-any function _testSetConfig(c) { dtConfiguration = c; } //# sourceMappingURL=StartupConfig.js.map