feat: Complete zCode CLI X with Telegram bot integration

- Add full Telegram bot functionality with Z.AI API integration
- Implement 4 tools: Bash, FileEdit, WebSearch, Git
- Add 3 agents: Code Reviewer, Architect, DevOps Engineer
- Add 6 skills for common coding tasks
- Add systemd service file for 24/7 operation
- Add nginx configuration for HTTPS webhook
- Add comprehensive documentation
- Implement WebSocket server for real-time updates
- Add logging system with Winston
- Add environment validation

🤖 zCode CLI X - Agentic coder with Z.AI + Telegram integration
This commit is contained in:
admin
2026-05-05 09:01:26 +00:00
Unverified
parent 4a7035dd92
commit 875c7f9b91
24688 changed files with 3224957 additions and 221 deletions

View File

@@ -0,0 +1,11 @@
import type { OtlpHttpConfiguration } from './otlp-http-configuration';
import type { OTLPExporterNodeConfigBase } from './legacy-node-configuration';
/**
* @deprecated this will be removed in 2.0
*
* @param config
* @param signalResourcePath
* @param requiredHeaders
*/
export declare function convertLegacyBrowserHttpOptions(config: OTLPExporterNodeConfigBase, signalResourcePath: string, requiredHeaders: Record<string, string>): OtlpHttpConfiguration;
//# sourceMappingURL=convert-legacy-browser-http-options.d.ts.map

View File

@@ -0,0 +1,23 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.convertLegacyBrowserHttpOptions = void 0;
const otlp_http_configuration_1 = require("./otlp-http-configuration");
const convert_legacy_http_options_1 = require("./convert-legacy-http-options");
/**
* @deprecated this will be removed in 2.0
*
* @param config
* @param signalResourcePath
* @param requiredHeaders
*/
function convertLegacyBrowserHttpOptions(config, signalResourcePath, requiredHeaders) {
return (0, otlp_http_configuration_1.mergeOtlpHttpConfigurationWithDefaults)({
url: config.url,
timeoutMillis: config.timeoutMillis,
headers: (0, convert_legacy_http_options_1.convertLegacyHeaders)(config),
concurrencyLimit: config.concurrencyLimit,
}, {}, // no fallback for browser case
(0, otlp_http_configuration_1.getHttpConfigurationDefaults)(requiredHeaders, signalResourcePath));
}
exports.convertLegacyBrowserHttpOptions = convertLegacyBrowserHttpOptions;
//# sourceMappingURL=convert-legacy-browser-http-options.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"convert-legacy-browser-http-options.js","sourceRoot":"","sources":["../../../src/configuration/convert-legacy-browser-http-options.ts"],"names":[],"mappings":";;;AAKA,uEAGmC;AAEnC,+EAAqE;AAErE;;;;;;GAMG;AACH,SAAgB,+BAA+B,CAC7C,MAAkC,EAClC,kBAA0B,EAC1B,eAAuC;IAEvC,OAAO,IAAA,gEAAsC,EAC3C;QACE,GAAG,EAAE,MAAM,CAAC,GAAG;QACf,aAAa,EAAE,MAAM,CAAC,aAAa;QACnC,OAAO,EAAE,IAAA,kDAAoB,EAAC,MAAM,CAAC;QACrC,gBAAgB,EAAE,MAAM,CAAC,gBAAgB;KAC1C,EACD,EAAE,EAAE,+BAA+B;IACnC,IAAA,sDAA4B,EAAC,eAAe,EAAE,kBAAkB,CAAC,CAClE,CAAC;AACJ,CAAC;AAfD,0EAeC","sourcesContent":["/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n */\nimport type { OtlpHttpConfiguration } from './otlp-http-configuration';\nimport {\n getHttpConfigurationDefaults,\n mergeOtlpHttpConfigurationWithDefaults,\n} from './otlp-http-configuration';\nimport type { OTLPExporterNodeConfigBase } from './legacy-node-configuration';\nimport { convertLegacyHeaders } from './convert-legacy-http-options';\n\n/**\n * @deprecated this will be removed in 2.0\n *\n * @param config\n * @param signalResourcePath\n * @param requiredHeaders\n */\nexport function convertLegacyBrowserHttpOptions(\n config: OTLPExporterNodeConfigBase,\n signalResourcePath: string,\n requiredHeaders: Record<string, string>\n): OtlpHttpConfiguration {\n return mergeOtlpHttpConfigurationWithDefaults(\n {\n url: config.url,\n timeoutMillis: config.timeoutMillis,\n headers: convertLegacyHeaders(config),\n concurrencyLimit: config.concurrencyLimit,\n },\n {}, // no fallback for browser case\n getHttpConfigurationDefaults(requiredHeaders, signalResourcePath)\n );\n}\n"]}

View File

@@ -0,0 +1,4 @@
import type { OTLPExporterConfigBase } from './legacy-base-configuration';
import type { HeadersFactory } from './otlp-http-configuration';
export declare function convertLegacyHeaders(config: OTLPExporterConfigBase): HeadersFactory | undefined;
//# sourceMappingURL=convert-legacy-http-options.d.ts.map

View File

@@ -0,0 +1,16 @@
"use strict";
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.convertLegacyHeaders = void 0;
const shared_configuration_1 = require("./shared-configuration");
function convertLegacyHeaders(config) {
if (typeof config.headers === 'function') {
return config.headers;
}
return (0, shared_configuration_1.wrapStaticHeadersInFunction)(config.headers);
}
exports.convertLegacyHeaders = convertLegacyHeaders;
//# sourceMappingURL=convert-legacy-http-options.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"convert-legacy-http-options.js","sourceRoot":"","sources":["../../../src/configuration/convert-legacy-http-options.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAGH,iEAAqE;AAGrE,SAAgB,oBAAoB,CAClC,MAA8B;IAE9B,IAAI,OAAO,MAAM,CAAC,OAAO,KAAK,UAAU,EAAE;QACxC,OAAO,MAAM,CAAC,OAAO,CAAC;KACvB;IACD,OAAO,IAAA,kDAA2B,EAAC,MAAM,CAAC,OAAO,CAAC,CAAC;AACrD,CAAC;AAPD,oDAOC","sourcesContent":["/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport type { OTLPExporterConfigBase } from './legacy-base-configuration';\nimport { wrapStaticHeadersInFunction } from './shared-configuration';\nimport type { HeadersFactory } from './otlp-http-configuration';\n\nexport function convertLegacyHeaders(\n config: OTLPExporterConfigBase\n): HeadersFactory | undefined {\n if (typeof config.headers === 'function') {\n return config.headers;\n }\n return wrapStaticHeadersInFunction(config.headers);\n}\n"]}

View File

@@ -0,0 +1,11 @@
import type { OTLPExporterNodeConfigBase } from './legacy-node-configuration';
import type { OtlpNodeHttpConfiguration } from './otlp-node-http-configuration';
/**
* @deprecated this will be removed in 2.0
* @param config
* @param signalIdentifier
* @param signalResourcePath
* @param requiredHeaders
*/
export declare function convertLegacyHttpOptions(config: OTLPExporterNodeConfigBase, signalIdentifier: string, signalResourcePath: string, requiredHeaders: Record<string, string>): OtlpNodeHttpConfiguration;
//# sourceMappingURL=convert-legacy-node-http-options.d.ts.map

View File

@@ -0,0 +1,47 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.convertLegacyHttpOptions = void 0;
const api_1 = require("@opentelemetry/api");
const otlp_node_http_configuration_1 = require("./otlp-node-http-configuration");
const index_node_http_1 = require("../index-node-http");
const otlp_node_http_env_configuration_1 = require("./otlp-node-http-env-configuration");
const convert_legacy_http_options_1 = require("./convert-legacy-http-options");
function convertLegacyAgentOptions(config) {
if (typeof config.httpAgentOptions === 'function') {
return config.httpAgentOptions;
}
let legacy = config.httpAgentOptions;
if (config.keepAlive != null) {
legacy = { keepAlive: config.keepAlive, ...legacy };
}
if (legacy != null) {
return (0, index_node_http_1.httpAgentFactoryFromOptions)(legacy);
}
else {
return undefined;
}
}
/**
* @deprecated this will be removed in 2.0
* @param config
* @param signalIdentifier
* @param signalResourcePath
* @param requiredHeaders
*/
function convertLegacyHttpOptions(config, signalIdentifier, signalResourcePath, requiredHeaders) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
if (config.metadata) {
api_1.diag.warn('Metadata cannot be set when using http');
}
return (0, otlp_node_http_configuration_1.mergeOtlpNodeHttpConfigurationWithDefaults)({
url: config.url,
headers: (0, convert_legacy_http_options_1.convertLegacyHeaders)(config),
concurrencyLimit: config.concurrencyLimit,
timeoutMillis: config.timeoutMillis,
compression: config.compression,
agentFactory: convertLegacyAgentOptions(config),
userAgent: config.userAgent,
}, (0, otlp_node_http_env_configuration_1.getNodeHttpConfigurationFromEnvironment)(signalIdentifier, signalResourcePath), (0, otlp_node_http_configuration_1.getNodeHttpConfigurationDefaults)(requiredHeaders, signalResourcePath));
}
exports.convertLegacyHttpOptions = convertLegacyHttpOptions;
//# sourceMappingURL=convert-legacy-node-http-options.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"convert-legacy-node-http-options.js","sourceRoot":"","sources":["../../../src/configuration/convert-legacy-node-http-options.ts"],"names":[],"mappings":";;;AAKA,4CAA0C;AAK1C,iFAGwC;AACxC,wDAAiE;AACjE,yFAA6F;AAC7F,+EAAqE;AAErE,SAAS,yBAAyB,CAChC,MAAkC;IAElC,IAAI,OAAO,MAAM,CAAC,gBAAgB,KAAK,UAAU,EAAE;QACjD,OAAO,MAAM,CAAC,gBAAgB,CAAC;KAChC;IAED,IAAI,MAAM,GAAG,MAAM,CAAC,gBAAgB,CAAC;IACrC,IAAI,MAAM,CAAC,SAAS,IAAI,IAAI,EAAE;QAC5B,MAAM,GAAG,EAAE,SAAS,EAAE,MAAM,CAAC,SAAS,EAAE,GAAG,MAAM,EAAE,CAAC;KACrD;IAED,IAAI,MAAM,IAAI,IAAI,EAAE;QAClB,OAAO,IAAA,6CAA2B,EAAC,MAAM,CAAC,CAAC;KAC5C;SAAM;QACL,OAAO,SAAS,CAAC;KAClB;AACH,CAAC;AAED;;;;;;GAMG;AACH,SAAgB,wBAAwB,CACtC,MAAkC,EAClC,gBAAwB,EACxB,kBAA0B,EAC1B,eAAuC;IAEvC,8DAA8D;IAC9D,IAAK,MAAc,CAAC,QAAQ,EAAE;QAC5B,UAAI,CAAC,IAAI,CAAC,wCAAwC,CAAC,CAAC;KACrD;IAED,OAAO,IAAA,yEAA0C,EAC/C;QACE,GAAG,EAAE,MAAM,CAAC,GAAG;QACf,OAAO,EAAE,IAAA,kDAAoB,EAAC,MAAM,CAAC;QACrC,gBAAgB,EAAE,MAAM,CAAC,gBAAgB;QACzC,aAAa,EAAE,MAAM,CAAC,aAAa;QACnC,WAAW,EAAE,MAAM,CAAC,WAAW;QAC/B,YAAY,EAAE,yBAAyB,CAAC,MAAM,CAAC;QAC/C,SAAS,EAAE,MAAM,CAAC,SAAS;KAC5B,EACD,IAAA,0EAAuC,EACrC,gBAAgB,EAChB,kBAAkB,CACnB,EACD,IAAA,+DAAgC,EAAC,eAAe,EAAE,kBAAkB,CAAC,CACtE,CAAC;AACJ,CAAC;AA3BD,4DA2BC","sourcesContent":["/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n */\nimport type { OTLPExporterNodeConfigBase } from './legacy-node-configuration';\nimport { diag } from '@opentelemetry/api';\nimport type {\n HttpAgentFactory,\n OtlpNodeHttpConfiguration,\n} from './otlp-node-http-configuration';\nimport {\n getNodeHttpConfigurationDefaults,\n mergeOtlpNodeHttpConfigurationWithDefaults,\n} from './otlp-node-http-configuration';\nimport { httpAgentFactoryFromOptions } from '../index-node-http';\nimport { getNodeHttpConfigurationFromEnvironment } from './otlp-node-http-env-configuration';\nimport { convertLegacyHeaders } from './convert-legacy-http-options';\n\nfunction convertLegacyAgentOptions(\n config: OTLPExporterNodeConfigBase\n): HttpAgentFactory | undefined {\n if (typeof config.httpAgentOptions === 'function') {\n return config.httpAgentOptions;\n }\n\n let legacy = config.httpAgentOptions;\n if (config.keepAlive != null) {\n legacy = { keepAlive: config.keepAlive, ...legacy };\n }\n\n if (legacy != null) {\n return httpAgentFactoryFromOptions(legacy);\n } else {\n return undefined;\n }\n}\n\n/**\n * @deprecated this will be removed in 2.0\n * @param config\n * @param signalIdentifier\n * @param signalResourcePath\n * @param requiredHeaders\n */\nexport function convertLegacyHttpOptions(\n config: OTLPExporterNodeConfigBase,\n signalIdentifier: string,\n signalResourcePath: string,\n requiredHeaders: Record<string, string>\n): OtlpNodeHttpConfiguration {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n if ((config as any).metadata) {\n diag.warn('Metadata cannot be set when using http');\n }\n\n return mergeOtlpNodeHttpConfigurationWithDefaults(\n {\n url: config.url,\n headers: convertLegacyHeaders(config),\n concurrencyLimit: config.concurrencyLimit,\n timeoutMillis: config.timeoutMillis,\n compression: config.compression,\n agentFactory: convertLegacyAgentOptions(config),\n userAgent: config.userAgent,\n },\n getNodeHttpConfigurationFromEnvironment(\n signalIdentifier,\n signalResourcePath\n ),\n getNodeHttpConfigurationDefaults(requiredHeaders, signalResourcePath)\n );\n}\n"]}

View File

@@ -0,0 +1,12 @@
import type { ISerializer } from '@opentelemetry/otlp-transformer';
import type { IOtlpExportDelegate } from '../otlp-export-delegate';
import type { OTLPExporterConfigBase } from './legacy-base-configuration';
/**
* @deprecated
* @param config
* @param serializer
* @param signalResourcePath
* @param requiredHeaders
*/
export declare function createLegacyOtlpBrowserExportDelegate<Internal, Response>(config: OTLPExporterConfigBase, serializer: ISerializer<Internal, Response>, signalResourcePath: string, requiredHeaders: Record<string, string>): IOtlpExportDelegate<Internal>;
//# sourceMappingURL=create-legacy-browser-delegate.d.ts.map

View File

@@ -0,0 +1,18 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.createLegacyOtlpBrowserExportDelegate = void 0;
const otlp_browser_http_export_delegate_1 = require("../otlp-browser-http-export-delegate");
const convert_legacy_browser_http_options_1 = require("./convert-legacy-browser-http-options");
/**
* @deprecated
* @param config
* @param serializer
* @param signalResourcePath
* @param requiredHeaders
*/
function createLegacyOtlpBrowserExportDelegate(config, serializer, signalResourcePath, requiredHeaders) {
const options = (0, convert_legacy_browser_http_options_1.convertLegacyBrowserHttpOptions)(config, signalResourcePath, requiredHeaders);
return (0, otlp_browser_http_export_delegate_1.createOtlpFetchExportDelegate)(options, serializer);
}
exports.createLegacyOtlpBrowserExportDelegate = createLegacyOtlpBrowserExportDelegate;
//# sourceMappingURL=create-legacy-browser-delegate.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"create-legacy-browser-delegate.js","sourceRoot":"","sources":["../../../src/configuration/create-legacy-browser-delegate.ts"],"names":[],"mappings":";;;AAKA,4FAAqF;AACrF,+FAAwF;AAIxF;;;;;;GAMG;AACH,SAAgB,qCAAqC,CACnD,MAA8B,EAC9B,UAA2C,EAC3C,kBAA0B,EAC1B,eAAuC;IAEvC,MAAM,OAAO,GAAG,IAAA,qEAA+B,EAC7C,MAAM,EACN,kBAAkB,EAClB,eAAe,CAChB,CAAC;IAEF,OAAO,IAAA,iEAA6B,EAAC,OAAO,EAAE,UAAU,CAAC,CAAC;AAC5D,CAAC;AAbD,sFAaC","sourcesContent":["/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n */\nimport type { ISerializer } from '@opentelemetry/otlp-transformer';\nimport { createOtlpFetchExportDelegate } from '../otlp-browser-http-export-delegate';\nimport { convertLegacyBrowserHttpOptions } from './convert-legacy-browser-http-options';\nimport type { IOtlpExportDelegate } from '../otlp-export-delegate';\nimport type { OTLPExporterConfigBase } from './legacy-base-configuration';\n\n/**\n * @deprecated\n * @param config\n * @param serializer\n * @param signalResourcePath\n * @param requiredHeaders\n */\nexport function createLegacyOtlpBrowserExportDelegate<Internal, Response>(\n config: OTLPExporterConfigBase,\n serializer: ISerializer<Internal, Response>,\n signalResourcePath: string,\n requiredHeaders: Record<string, string>\n): IOtlpExportDelegate<Internal> {\n const options = convertLegacyBrowserHttpOptions(\n config,\n signalResourcePath,\n requiredHeaders\n );\n\n return createOtlpFetchExportDelegate(options, serializer);\n}\n"]}

View File

@@ -0,0 +1,34 @@
import type { HeadersFactory } from './otlp-http-configuration';
export interface OTLPExporterConfigBase {
/**
* Custom headers that will be attached to the HTTP request that's sent to the endpoint.
*
* @remarks
* Prefer using a plain object over a factory function wherever possible.
* If using a factory function (`HttpAgentFactory`), **do not import `http` or `https` at the top of the file**
* Instead, use dynamic `import()` or `require()` to load the module. This ensures that the `http` or `https`
* module is not loaded before `@opentelemetry/instrumentation-http` can instrument it.
*
* Functions passed to the exporter MUST NOT throw errors.
*
* @example <caption> Using headers options directly: </caption>
* headers: {
* Authorization: "Api-Token my-secret-token",
* }
*
* @example <caption> Using a custom factory function </caption>
* headers: async () => {
* // ... do whatever you need to obtain the headers, ensuring you `await import('your-library')` to avoid breaking instrumentations ...
* return {
* Authorization: `Bearer ${token}`,
* };
* };
*/
headers?: Record<string, string> | HeadersFactory;
url?: string;
concurrencyLimit?: number;
/** Maximum time the OTLP exporter will wait for each batch export.
* The default value is 10000ms. */
timeoutMillis?: number;
}
//# sourceMappingURL=legacy-base-configuration.d.ts.map

View File

@@ -0,0 +1,3 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
//# sourceMappingURL=legacy-base-configuration.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"legacy-base-configuration.js","sourceRoot":"","sources":["../../../src/configuration/legacy-base-configuration.ts"],"names":[],"mappings":"","sourcesContent":["/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n */\nimport type { HeadersFactory } from './otlp-http-configuration';\n\nexport interface OTLPExporterConfigBase {\n /**\n * Custom headers that will be attached to the HTTP request that's sent to the endpoint.\n *\n * @remarks\n * Prefer using a plain object over a factory function wherever possible.\n * If using a factory function (`HttpAgentFactory`), **do not import `http` or `https` at the top of the file**\n * Instead, use dynamic `import()` or `require()` to load the module. This ensures that the `http` or `https`\n * module is not loaded before `@opentelemetry/instrumentation-http` can instrument it.\n *\n * Functions passed to the exporter MUST NOT throw errors.\n *\n * @example <caption> Using headers options directly: </caption>\n * headers: {\n * Authorization: \"Api-Token my-secret-token\",\n * }\n *\n * @example <caption> Using a custom factory function </caption>\n * headers: async () => {\n * // ... do whatever you need to obtain the headers, ensuring you `await import('your-library')` to avoid breaking instrumentations ...\n * return {\n * Authorization: `Bearer ${token}`,\n * };\n * };\n */\n headers?: Record<string, string> | HeadersFactory;\n url?: string;\n concurrencyLimit?: number;\n /** Maximum time the OTLP exporter will wait for each batch export.\n * The default value is 10000ms. */\n timeoutMillis?: number;\n}\n"]}

View File

@@ -0,0 +1,47 @@
/// <reference types="node" />
/// <reference types="node" />
import type * as http from 'http';
import type * as https from 'https';
import type { OTLPExporterConfigBase } from './legacy-base-configuration';
import type { HttpAgentFactory } from './otlp-node-http-configuration';
/**
* Collector Exporter node base config
*/
export interface OTLPExporterNodeConfigBase extends OTLPExporterConfigBase {
keepAlive?: boolean;
compression?: CompressionAlgorithm;
/**
* Custom HTTP agent options or a factory function for creating agents.
*
* @remarks
* Prefer using `http.AgentOptions` or `https.AgentOptions` over a factory function wherever possible.
* If using a factory function (`HttpAgentFactory`), **do not import `http.Agent` or `https.Agent`
* statically at the top of the file**.
* Instead, use dynamic `import()` or `require()` to load the module. This ensures that the `http` or `https`
* module is not loaded before `@opentelemetry/instrumentation-http` can instrument it.
*
* @example <caption> Using agent options directly: </caption>
* httpAgentOptions: {
* keepAlive: true,
* maxSockets: 10
* }
*
* @example <caption> Using a factory with dynamic import: </caption>
* httpAgentOptions: async (protocol) => {
* const module = protocol === 'http:' ? await import('http') : await import('https');
* return new module.Agent({ keepAlive: true });
* }
*/
httpAgentOptions?: http.AgentOptions | https.AgentOptions | HttpAgentFactory;
/**
* User agent header string to be prepended to the exporter's default value.
* Availablie since v1.49.0 of the spec.
* Ref: https://opentelemetry.io/docs/specs/otel/protocol/exporter/#user-agent
*/
userAgent?: string;
}
export declare enum CompressionAlgorithm {
NONE = "none",
GZIP = "gzip"
}
//# sourceMappingURL=legacy-node-configuration.d.ts.map

View File

@@ -0,0 +1,13 @@
"use strict";
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.CompressionAlgorithm = void 0;
var CompressionAlgorithm;
(function (CompressionAlgorithm) {
CompressionAlgorithm["NONE"] = "none";
CompressionAlgorithm["GZIP"] = "gzip";
})(CompressionAlgorithm = exports.CompressionAlgorithm || (exports.CompressionAlgorithm = {}));
//# sourceMappingURL=legacy-node-configuration.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"legacy-node-configuration.js","sourceRoot":"","sources":["../../../src/configuration/legacy-node-configuration.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AA8CH,IAAY,oBAGX;AAHD,WAAY,oBAAoB;IAC9B,qCAAa,CAAA;IACb,qCAAa,CAAA;AACf,CAAC,EAHW,oBAAoB,GAApB,4BAAoB,KAApB,4BAAoB,QAG/B","sourcesContent":["/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n */\n\n// NOTE: do not change these imports to be actual imports, otherwise they WILL break `@opentelemetry/instrumentation-http`\nimport type * as http from 'http';\nimport type * as https from 'https';\n\nimport type { OTLPExporterConfigBase } from './legacy-base-configuration';\nimport type { HttpAgentFactory } from './otlp-node-http-configuration';\n\n/**\n * Collector Exporter node base config\n */\nexport interface OTLPExporterNodeConfigBase extends OTLPExporterConfigBase {\n keepAlive?: boolean;\n compression?: CompressionAlgorithm;\n /**\n * Custom HTTP agent options or a factory function for creating agents.\n *\n * @remarks\n * Prefer using `http.AgentOptions` or `https.AgentOptions` over a factory function wherever possible.\n * If using a factory function (`HttpAgentFactory`), **do not import `http.Agent` or `https.Agent`\n * statically at the top of the file**.\n * Instead, use dynamic `import()` or `require()` to load the module. This ensures that the `http` or `https`\n * module is not loaded before `@opentelemetry/instrumentation-http` can instrument it.\n *\n * @example <caption> Using agent options directly: </caption>\n * httpAgentOptions: {\n * keepAlive: true,\n * maxSockets: 10\n * }\n *\n * @example <caption> Using a factory with dynamic import: </caption>\n * httpAgentOptions: async (protocol) => {\n * const module = protocol === 'http:' ? await import('http') : await import('https');\n * return new module.Agent({ keepAlive: true });\n * }\n */\n httpAgentOptions?: http.AgentOptions | https.AgentOptions | HttpAgentFactory;\n /**\n * User agent header string to be prepended to the exporter's default value.\n * Availablie since v1.49.0 of the spec.\n * Ref: https://opentelemetry.io/docs/specs/otel/protocol/exporter/#user-agent\n */\n userAgent?: string;\n}\n\nexport enum CompressionAlgorithm {\n NONE = 'none',\n GZIP = 'gzip',\n}\n"]}

View File

@@ -0,0 +1,14 @@
import type { OtlpSharedConfiguration } from './shared-configuration';
export type HeadersFactory = () => Promise<Record<string, string>>;
export interface OtlpHttpConfiguration extends OtlpSharedConfiguration {
url: string;
headers: HeadersFactory;
}
/**
* @param userProvidedConfiguration Configuration options provided by the user in code.
* @param fallbackConfiguration Fallback to use when the {@link userProvidedConfiguration} does not specify an option.
* @param defaultConfiguration The defaults as defined by the exporter specification
*/
export declare function mergeOtlpHttpConfigurationWithDefaults(userProvidedConfiguration: Partial<OtlpHttpConfiguration>, fallbackConfiguration: Partial<OtlpHttpConfiguration>, defaultConfiguration: OtlpHttpConfiguration): OtlpHttpConfiguration;
export declare function getHttpConfigurationDefaults(requiredHeaders: Record<string, string>, signalResourcePath: string): OtlpHttpConfiguration;
//# sourceMappingURL=otlp-http-configuration.d.ts.map

View File

@@ -0,0 +1,64 @@
"use strict";
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.getHttpConfigurationDefaults = exports.mergeOtlpHttpConfigurationWithDefaults = void 0;
const shared_configuration_1 = require("./shared-configuration");
const util_1 = require("../util");
function mergeHeaders(userProvidedHeaders, fallbackHeaders, defaultHeaders) {
return async () => {
const requiredHeaders = {
...(await defaultHeaders()),
};
const headers = {};
// add fallback ones first
if (fallbackHeaders != null) {
Object.assign(headers, await fallbackHeaders());
}
// override with user-provided ones
if (userProvidedHeaders != null) {
Object.assign(headers, (0, util_1.validateAndNormalizeHeaders)(await userProvidedHeaders()));
}
// override required ones.
return Object.assign(headers, requiredHeaders);
};
}
function validateUserProvidedUrl(url) {
if (url == null) {
return undefined;
}
try {
// NOTE: In non-browser environments, `globalThis.location` will be `undefined`.
const base = globalThis.location?.href;
return new URL(url, base).href;
}
catch {
throw new Error(`Configuration: Could not parse user-provided export URL: '${url}'`);
}
}
/**
* @param userProvidedConfiguration Configuration options provided by the user in code.
* @param fallbackConfiguration Fallback to use when the {@link userProvidedConfiguration} does not specify an option.
* @param defaultConfiguration The defaults as defined by the exporter specification
*/
function mergeOtlpHttpConfigurationWithDefaults(userProvidedConfiguration, fallbackConfiguration, defaultConfiguration) {
return {
...(0, shared_configuration_1.mergeOtlpSharedConfigurationWithDefaults)(userProvidedConfiguration, fallbackConfiguration, defaultConfiguration),
headers: mergeHeaders(userProvidedConfiguration.headers, fallbackConfiguration.headers, defaultConfiguration.headers),
url: validateUserProvidedUrl(userProvidedConfiguration.url) ??
fallbackConfiguration.url ??
defaultConfiguration.url,
};
}
exports.mergeOtlpHttpConfigurationWithDefaults = mergeOtlpHttpConfigurationWithDefaults;
function getHttpConfigurationDefaults(requiredHeaders, signalResourcePath) {
return {
...(0, shared_configuration_1.getSharedConfigurationDefaults)(),
headers: async () => requiredHeaders,
url: 'http://localhost:4318/' + signalResourcePath,
};
}
exports.getHttpConfigurationDefaults = getHttpConfigurationDefaults;
//# sourceMappingURL=otlp-http-configuration.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"otlp-http-configuration.js","sourceRoot":"","sources":["../../../src/configuration/otlp-http-configuration.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAGH,iEAGgC;AAChC,kCAAsD;AAStD,SAAS,YAAY,CACnB,mBAAsD,EACtD,eAAkD,EAClD,cAA8B;IAE9B,OAAO,KAAK,IAAI,EAAE;QAChB,MAAM,eAAe,GAAG;YACtB,GAAG,CAAC,MAAM,cAAc,EAAE,CAAC;SAC5B,CAAC;QACF,MAAM,OAAO,GAAG,EAAE,CAAC;QAEnB,0BAA0B;QAC1B,IAAI,eAAe,IAAI,IAAI,EAAE;YAC3B,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,MAAM,eAAe,EAAE,CAAC,CAAC;SACjD;QAED,mCAAmC;QACnC,IAAI,mBAAmB,IAAI,IAAI,EAAE;YAC/B,MAAM,CAAC,MAAM,CACX,OAAO,EACP,IAAA,kCAA2B,EAAC,MAAM,mBAAmB,EAAE,CAAC,CACzD,CAAC;SACH;QAED,0BAA0B;QAC1B,OAAO,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,eAAe,CAAC,CAAC;IACjD,CAAC,CAAC;AACJ,CAAC;AAED,SAAS,uBAAuB,CAAC,GAAuB;IACtD,IAAI,GAAG,IAAI,IAAI,EAAE;QACf,OAAO,SAAS,CAAC;KAClB;IACD,IAAI;QACF,gFAAgF;QAChF,MAAM,IAAI,GAAG,UAAU,CAAC,QAAQ,EAAE,IAAI,CAAC;QACvC,OAAO,IAAI,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC,IAAI,CAAC;KAChC;IAAC,MAAM;QACN,MAAM,IAAI,KAAK,CACb,6DAA6D,GAAG,GAAG,CACpE,CAAC;KACH;AACH,CAAC;AAED;;;;GAIG;AACH,SAAgB,sCAAsC,CACpD,yBAAyD,EACzD,qBAAqD,EACrD,oBAA2C;IAE3C,OAAO;QACL,GAAG,IAAA,+DAAwC,EACzC,yBAAyB,EACzB,qBAAqB,EACrB,oBAAoB,CACrB;QACD,OAAO,EAAE,YAAY,CACnB,yBAAyB,CAAC,OAAO,EACjC,qBAAqB,CAAC,OAAO,EAC7B,oBAAoB,CAAC,OAAO,CAC7B;QACD,GAAG,EACD,uBAAuB,CAAC,yBAAyB,CAAC,GAAG,CAAC;YACtD,qBAAqB,CAAC,GAAG;YACzB,oBAAoB,CAAC,GAAG;KAC3B,CAAC;AACJ,CAAC;AArBD,wFAqBC;AAED,SAAgB,4BAA4B,CAC1C,eAAuC,EACvC,kBAA0B;IAE1B,OAAO;QACL,GAAG,IAAA,qDAA8B,GAAE;QACnC,OAAO,EAAE,KAAK,IAAI,EAAE,CAAC,eAAe;QACpC,GAAG,EAAE,wBAAwB,GAAG,kBAAkB;KACnD,CAAC;AACJ,CAAC;AATD,oEASC","sourcesContent":["/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport type { OtlpSharedConfiguration } from './shared-configuration';\nimport {\n getSharedConfigurationDefaults,\n mergeOtlpSharedConfigurationWithDefaults,\n} from './shared-configuration';\nimport { validateAndNormalizeHeaders } from '../util';\n\nexport type HeadersFactory = () => Promise<Record<string, string>>;\n\nexport interface OtlpHttpConfiguration extends OtlpSharedConfiguration {\n url: string;\n headers: HeadersFactory;\n}\n\nfunction mergeHeaders(\n userProvidedHeaders: HeadersFactory | undefined | null,\n fallbackHeaders: HeadersFactory | undefined | null,\n defaultHeaders: HeadersFactory\n): HeadersFactory {\n return async () => {\n const requiredHeaders = {\n ...(await defaultHeaders()),\n };\n const headers = {};\n\n // add fallback ones first\n if (fallbackHeaders != null) {\n Object.assign(headers, await fallbackHeaders());\n }\n\n // override with user-provided ones\n if (userProvidedHeaders != null) {\n Object.assign(\n headers,\n validateAndNormalizeHeaders(await userProvidedHeaders())\n );\n }\n\n // override required ones.\n return Object.assign(headers, requiredHeaders);\n };\n}\n\nfunction validateUserProvidedUrl(url: string | undefined): string | undefined {\n if (url == null) {\n return undefined;\n }\n try {\n // NOTE: In non-browser environments, `globalThis.location` will be `undefined`.\n const base = globalThis.location?.href;\n return new URL(url, base).href;\n } catch {\n throw new Error(\n `Configuration: Could not parse user-provided export URL: '${url}'`\n );\n }\n}\n\n/**\n * @param userProvidedConfiguration Configuration options provided by the user in code.\n * @param fallbackConfiguration Fallback to use when the {@link userProvidedConfiguration} does not specify an option.\n * @param defaultConfiguration The defaults as defined by the exporter specification\n */\nexport function mergeOtlpHttpConfigurationWithDefaults(\n userProvidedConfiguration: Partial<OtlpHttpConfiguration>,\n fallbackConfiguration: Partial<OtlpHttpConfiguration>,\n defaultConfiguration: OtlpHttpConfiguration\n): OtlpHttpConfiguration {\n return {\n ...mergeOtlpSharedConfigurationWithDefaults(\n userProvidedConfiguration,\n fallbackConfiguration,\n defaultConfiguration\n ),\n headers: mergeHeaders(\n userProvidedConfiguration.headers,\n fallbackConfiguration.headers,\n defaultConfiguration.headers\n ),\n url:\n validateUserProvidedUrl(userProvidedConfiguration.url) ??\n fallbackConfiguration.url ??\n defaultConfiguration.url,\n };\n}\n\nexport function getHttpConfigurationDefaults(\n requiredHeaders: Record<string, string>,\n signalResourcePath: string\n): OtlpHttpConfiguration {\n return {\n ...getSharedConfigurationDefaults(),\n headers: async () => requiredHeaders,\n url: 'http://localhost:4318/' + signalResourcePath,\n };\n}\n"]}

View File

@@ -0,0 +1,34 @@
/// <reference types="node" />
/// <reference types="node" />
import type { OtlpHttpConfiguration } from './otlp-http-configuration';
import type * as http from 'http';
import type * as https from 'https';
export type HttpAgentFactory = (protocol: string) => http.Agent | https.Agent | Promise<http.Agent> | Promise<https.Agent>;
export interface OtlpNodeHttpConfiguration extends OtlpHttpConfiguration {
/**
* Factory function for creating agents.
*
* @remarks
* Prefer using {@link httpAgentFactoryFromOptions} over manually writing a factory function wherever possible.
* If using a factory function (`HttpAgentFactory`), **do not import `http.Agent` or `https.Agent`
* statically at the top of the file**.
* Instead, use dynamic `import()` or `require()` to load the module. This ensures that the `http` or `https`
* module is not loaded before `@opentelemetry/instrumentation-http` can instrument it.
*/
agentFactory: HttpAgentFactory;
/**
* User agent header string to be appended to the exporter's value as a prefix.
* Availablie since v1.49.0 of the spec.
* Ref: https://opentelemetry.io/docs/specs/otel/protocol/exporter/#user-agent
*/
userAgent?: string;
}
export declare function httpAgentFactoryFromOptions(options: http.AgentOptions | https.AgentOptions): HttpAgentFactory;
/**
* @param userProvidedConfiguration Configuration options provided by the user in code.
* @param fallbackConfiguration Fallback to use when the {@link userProvidedConfiguration} does not specify an option.
* @param defaultConfiguration The defaults as defined by the exporter specification
*/
export declare function mergeOtlpNodeHttpConfigurationWithDefaults(userProvidedConfiguration: Partial<OtlpNodeHttpConfiguration>, fallbackConfiguration: Partial<OtlpNodeHttpConfiguration>, defaultConfiguration: OtlpNodeHttpConfiguration): OtlpNodeHttpConfiguration;
export declare function getNodeHttpConfigurationDefaults(requiredHeaders: Record<string, string>, signalResourcePath: string): OtlpNodeHttpConfiguration;
//# sourceMappingURL=otlp-node-http-configuration.d.ts.map

View File

@@ -0,0 +1,41 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getNodeHttpConfigurationDefaults = exports.mergeOtlpNodeHttpConfigurationWithDefaults = exports.httpAgentFactoryFromOptions = void 0;
const otlp_http_configuration_1 = require("./otlp-http-configuration");
function httpAgentFactoryFromOptions(options) {
return async (protocol) => {
const isInsecure = protocol === 'http:';
const module = isInsecure ? import('http') : import('https');
const { Agent } = await module;
if (isInsecure) {
// eslint-disable-next-line @typescript-eslint/no-unused-vars -- these props should not be used in agent options
const { ca, cert, key, ...insecureOptions } = options;
return new Agent(insecureOptions);
}
return new Agent(options);
};
}
exports.httpAgentFactoryFromOptions = httpAgentFactoryFromOptions;
/**
* @param userProvidedConfiguration Configuration options provided by the user in code.
* @param fallbackConfiguration Fallback to use when the {@link userProvidedConfiguration} does not specify an option.
* @param defaultConfiguration The defaults as defined by the exporter specification
*/
function mergeOtlpNodeHttpConfigurationWithDefaults(userProvidedConfiguration, fallbackConfiguration, defaultConfiguration) {
return {
...(0, otlp_http_configuration_1.mergeOtlpHttpConfigurationWithDefaults)(userProvidedConfiguration, fallbackConfiguration, defaultConfiguration),
agentFactory: userProvidedConfiguration.agentFactory ??
fallbackConfiguration.agentFactory ??
defaultConfiguration.agentFactory,
userAgent: userProvidedConfiguration.userAgent,
};
}
exports.mergeOtlpNodeHttpConfigurationWithDefaults = mergeOtlpNodeHttpConfigurationWithDefaults;
function getNodeHttpConfigurationDefaults(requiredHeaders, signalResourcePath) {
return {
...(0, otlp_http_configuration_1.getHttpConfigurationDefaults)(requiredHeaders, signalResourcePath),
agentFactory: httpAgentFactoryFromOptions({ keepAlive: true }),
};
}
exports.getNodeHttpConfigurationDefaults = getNodeHttpConfigurationDefaults;
//# sourceMappingURL=otlp-node-http-configuration.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"otlp-node-http-configuration.js","sourceRoot":"","sources":["../../../src/configuration/otlp-node-http-configuration.ts"],"names":[],"mappings":";;;AAKA,uEAGmC;AA8BnC,SAAgB,2BAA2B,CACzC,OAA+C;IAE/C,OAAO,KAAK,EAAC,QAAQ,EAAC,EAAE;QACtB,MAAM,UAAU,GAAG,QAAQ,KAAK,OAAO,CAAC;QACxC,MAAM,MAAM,GAAG,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QAC7D,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,MAAM,CAAC;QAE/B,IAAI,UAAU,EAAE;YACd,gHAAgH;YAChH,MAAM,EAAE,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,eAAe,EAAE,GACzC,OAA6B,CAAC;YAChC,OAAO,IAAI,KAAK,CAAC,eAAe,CAAC,CAAC;SACnC;QACD,OAAO,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC;IAC5B,CAAC,CAAC;AACJ,CAAC;AAhBD,kEAgBC;AAED;;;;GAIG;AACH,SAAgB,0CAA0C,CACxD,yBAA6D,EAC7D,qBAAyD,EACzD,oBAA+C;IAE/C,OAAO;QACL,GAAG,IAAA,gEAAsC,EACvC,yBAAyB,EACzB,qBAAqB,EACrB,oBAAoB,CACrB;QACD,YAAY,EACV,yBAAyB,CAAC,YAAY;YACtC,qBAAqB,CAAC,YAAY;YAClC,oBAAoB,CAAC,YAAY;QACnC,SAAS,EAAE,yBAAyB,CAAC,SAAS;KAC/C,CAAC;AACJ,CAAC;AAjBD,gGAiBC;AAED,SAAgB,gCAAgC,CAC9C,eAAuC,EACvC,kBAA0B;IAE1B,OAAO;QACL,GAAG,IAAA,sDAA4B,EAAC,eAAe,EAAE,kBAAkB,CAAC;QACpE,YAAY,EAAE,2BAA2B,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;KAC/D,CAAC;AACJ,CAAC;AARD,4EAQC","sourcesContent":["/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n */\nimport type { OtlpHttpConfiguration } from './otlp-http-configuration';\nimport {\n getHttpConfigurationDefaults,\n mergeOtlpHttpConfigurationWithDefaults,\n} from './otlp-http-configuration';\n\n// NOTE: do not change these imports to be actual imports, otherwise they WILL break `@opentelemetry/instrumentation-http`\nimport type * as http from 'http';\nimport type * as https from 'https';\n\nexport type HttpAgentFactory = (\n protocol: string\n) => http.Agent | https.Agent | Promise<http.Agent> | Promise<https.Agent>;\n\nexport interface OtlpNodeHttpConfiguration extends OtlpHttpConfiguration {\n /**\n * Factory function for creating agents.\n *\n * @remarks\n * Prefer using {@link httpAgentFactoryFromOptions} over manually writing a factory function wherever possible.\n * If using a factory function (`HttpAgentFactory`), **do not import `http.Agent` or `https.Agent`\n * statically at the top of the file**.\n * Instead, use dynamic `import()` or `require()` to load the module. This ensures that the `http` or `https`\n * module is not loaded before `@opentelemetry/instrumentation-http` can instrument it.\n */\n agentFactory: HttpAgentFactory;\n /**\n * User agent header string to be appended to the exporter's value as a prefix.\n * Availablie since v1.49.0 of the spec.\n * Ref: https://opentelemetry.io/docs/specs/otel/protocol/exporter/#user-agent\n */\n userAgent?: string;\n}\n\nexport function httpAgentFactoryFromOptions(\n options: http.AgentOptions | https.AgentOptions\n): HttpAgentFactory {\n return async protocol => {\n const isInsecure = protocol === 'http:';\n const module = isInsecure ? import('http') : import('https');\n const { Agent } = await module;\n\n if (isInsecure) {\n // eslint-disable-next-line @typescript-eslint/no-unused-vars -- these props should not be used in agent options\n const { ca, cert, key, ...insecureOptions } =\n options as https.AgentOptions;\n return new Agent(insecureOptions);\n }\n return new Agent(options);\n };\n}\n\n/**\n * @param userProvidedConfiguration Configuration options provided by the user in code.\n * @param fallbackConfiguration Fallback to use when the {@link userProvidedConfiguration} does not specify an option.\n * @param defaultConfiguration The defaults as defined by the exporter specification\n */\nexport function mergeOtlpNodeHttpConfigurationWithDefaults(\n userProvidedConfiguration: Partial<OtlpNodeHttpConfiguration>,\n fallbackConfiguration: Partial<OtlpNodeHttpConfiguration>,\n defaultConfiguration: OtlpNodeHttpConfiguration\n): OtlpNodeHttpConfiguration {\n return {\n ...mergeOtlpHttpConfigurationWithDefaults(\n userProvidedConfiguration,\n fallbackConfiguration,\n defaultConfiguration\n ),\n agentFactory:\n userProvidedConfiguration.agentFactory ??\n fallbackConfiguration.agentFactory ??\n defaultConfiguration.agentFactory,\n userAgent: userProvidedConfiguration.userAgent,\n };\n}\n\nexport function getNodeHttpConfigurationDefaults(\n requiredHeaders: Record<string, string>,\n signalResourcePath: string\n): OtlpNodeHttpConfiguration {\n return {\n ...getHttpConfigurationDefaults(requiredHeaders, signalResourcePath),\n agentFactory: httpAgentFactoryFromOptions({ keepAlive: true }),\n };\n}\n"]}

View File

@@ -0,0 +1,9 @@
import type { OtlpNodeHttpConfiguration } from './otlp-node-http-configuration';
/**
* Reads and returns configuration from the environment
*
* @param signalIdentifier all caps part in environment variables that identifies the signal (e.g.: METRICS, TRACES, LOGS)
* @param signalResourcePath signal resource path to append if necessary (e.g.: v1/metrics, v1/traces, v1/logs)
*/
export declare function getNodeHttpConfigurationFromEnvironment(signalIdentifier: string, signalResourcePath: string): Partial<OtlpNodeHttpConfiguration>;
//# sourceMappingURL=otlp-node-http-env-configuration.d.ts.map

View File

@@ -0,0 +1,123 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getNodeHttpConfigurationFromEnvironment = void 0;
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
const fs = require("fs");
const path = require("path");
const core_1 = require("@opentelemetry/core");
const api_1 = require("@opentelemetry/api");
const shared_env_configuration_1 = require("./shared-env-configuration");
const shared_configuration_1 = require("./shared-configuration");
const otlp_node_http_configuration_1 = require("./otlp-node-http-configuration");
function getStaticHeadersFromEnv(signalIdentifier) {
const signalSpecificRawHeaders = (0, core_1.getStringFromEnv)(`OTEL_EXPORTER_OTLP_${signalIdentifier}_HEADERS`);
const nonSignalSpecificRawHeaders = (0, core_1.getStringFromEnv)('OTEL_EXPORTER_OTLP_HEADERS');
const signalSpecificHeaders = (0, core_1.parseKeyPairsIntoRecord)(signalSpecificRawHeaders);
const nonSignalSpecificHeaders = (0, core_1.parseKeyPairsIntoRecord)(nonSignalSpecificRawHeaders);
if (Object.keys(signalSpecificHeaders).length === 0 &&
Object.keys(nonSignalSpecificHeaders).length === 0) {
return undefined;
}
// headers are combined instead of overwritten, with the specific headers taking precedence over
// the non-specific ones.
return Object.assign({}, (0, core_1.parseKeyPairsIntoRecord)(nonSignalSpecificRawHeaders), (0, core_1.parseKeyPairsIntoRecord)(signalSpecificRawHeaders));
}
function appendRootPathToUrlIfNeeded(url) {
try {
const parsedUrl = new URL(url);
// This will automatically append '/' if there's no root path.
return parsedUrl.toString();
}
catch {
api_1.diag.warn(`Configuration: Could not parse environment-provided export URL: '${url}', falling back to undefined`);
return undefined;
}
}
function appendResourcePathToUrl(url, path) {
try {
// just try to parse, if it fails we catch and warn.
new URL(url);
}
catch {
api_1.diag.warn(`Configuration: Could not parse environment-provided export URL: '${url}', falling back to undefined`);
return undefined;
}
if (!url.endsWith('/')) {
url = url + '/';
}
url += path;
try {
// just try to parse, if it fails we catch and warn.
new URL(url);
}
catch {
api_1.diag.warn(`Configuration: Provided URL appended with '${path}' is not a valid URL, using 'undefined' instead of '${url}'`);
return undefined;
}
return url;
}
function getNonSpecificUrlFromEnv(signalResourcePath) {
const envUrl = (0, core_1.getStringFromEnv)('OTEL_EXPORTER_OTLP_ENDPOINT');
if (envUrl === undefined) {
return undefined;
}
return appendResourcePathToUrl(envUrl, signalResourcePath);
}
function getSpecificUrlFromEnv(signalIdentifier) {
const envUrl = (0, core_1.getStringFromEnv)(`OTEL_EXPORTER_OTLP_${signalIdentifier}_ENDPOINT`);
if (envUrl === undefined) {
return undefined;
}
return appendRootPathToUrlIfNeeded(envUrl);
}
function readFileFromEnv(signalSpecificEnvVar, nonSignalSpecificEnvVar, warningMessage) {
const signalSpecificPath = (0, core_1.getStringFromEnv)(signalSpecificEnvVar);
const nonSignalSpecificPath = (0, core_1.getStringFromEnv)(nonSignalSpecificEnvVar);
const filePath = signalSpecificPath ?? nonSignalSpecificPath;
if (filePath != null) {
try {
return fs.readFileSync(path.resolve(process.cwd(), filePath));
}
catch {
api_1.diag.warn(warningMessage);
return undefined;
}
}
else {
return undefined;
}
}
function getClientCertificateFromEnv(signalIdentifier) {
return readFileFromEnv(`OTEL_EXPORTER_OTLP_${signalIdentifier}_CLIENT_CERTIFICATE`, 'OTEL_EXPORTER_OTLP_CLIENT_CERTIFICATE', 'Failed to read client certificate chain file');
}
function getClientKeyFromEnv(signalIdentifier) {
return readFileFromEnv(`OTEL_EXPORTER_OTLP_${signalIdentifier}_CLIENT_KEY`, 'OTEL_EXPORTER_OTLP_CLIENT_KEY', 'Failed to read client certificate private key file');
}
function getRootCertificateFromEnv(signalIdentifier) {
return readFileFromEnv(`OTEL_EXPORTER_OTLP_${signalIdentifier}_CERTIFICATE`, 'OTEL_EXPORTER_OTLP_CERTIFICATE', 'Failed to read root certificate file');
}
/**
* Reads and returns configuration from the environment
*
* @param signalIdentifier all caps part in environment variables that identifies the signal (e.g.: METRICS, TRACES, LOGS)
* @param signalResourcePath signal resource path to append if necessary (e.g.: v1/metrics, v1/traces, v1/logs)
*/
function getNodeHttpConfigurationFromEnvironment(signalIdentifier, signalResourcePath) {
return {
...(0, shared_env_configuration_1.getSharedConfigurationFromEnvironment)(signalIdentifier),
url: getSpecificUrlFromEnv(signalIdentifier) ??
getNonSpecificUrlFromEnv(signalResourcePath),
headers: (0, shared_configuration_1.wrapStaticHeadersInFunction)(getStaticHeadersFromEnv(signalIdentifier)),
agentFactory: (0, otlp_node_http_configuration_1.httpAgentFactoryFromOptions)({
keepAlive: true,
ca: getRootCertificateFromEnv(signalIdentifier),
cert: getClientCertificateFromEnv(signalIdentifier),
key: getClientKeyFromEnv(signalIdentifier),
}),
};
}
exports.getNodeHttpConfigurationFromEnvironment = getNodeHttpConfigurationFromEnvironment;
//# sourceMappingURL=otlp-node-http-env-configuration.js.map

View File

@@ -0,0 +1,24 @@
import type { HeadersFactory } from './otlp-http-configuration';
/**
* Configuration shared across all OTLP exporters
*
* Implementation note: anything added here MUST be
* - platform-agnostic
* - signal-agnostic
* - transport-agnostic
*/
export interface OtlpSharedConfiguration {
timeoutMillis: number;
concurrencyLimit: number;
compression: 'gzip' | 'none';
}
export declare function validateTimeoutMillis(timeoutMillis: number): number;
export declare function wrapStaticHeadersInFunction(headers: Record<string, string> | undefined): HeadersFactory | undefined;
/**
* @param userProvidedConfiguration Configuration options provided by the user in code.
* @param fallbackConfiguration Fallback to use when the {@link userProvidedConfiguration} does not specify an option.
* @param defaultConfiguration The defaults as defined by the exporter specification
*/
export declare function mergeOtlpSharedConfigurationWithDefaults(userProvidedConfiguration: Partial<OtlpSharedConfiguration>, fallbackConfiguration: Partial<OtlpSharedConfiguration>, defaultConfiguration: OtlpSharedConfiguration): OtlpSharedConfiguration;
export declare function getSharedConfigurationDefaults(): OtlpSharedConfiguration;
//# sourceMappingURL=shared-configuration.d.ts.map

View File

@@ -0,0 +1,49 @@
"use strict";
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.getSharedConfigurationDefaults = exports.mergeOtlpSharedConfigurationWithDefaults = exports.wrapStaticHeadersInFunction = exports.validateTimeoutMillis = void 0;
function validateTimeoutMillis(timeoutMillis) {
if (Number.isFinite(timeoutMillis) && timeoutMillis > 0) {
return timeoutMillis;
}
throw new Error(`Configuration: timeoutMillis is invalid, expected number greater than 0 (actual: '${timeoutMillis}')`);
}
exports.validateTimeoutMillis = validateTimeoutMillis;
function wrapStaticHeadersInFunction(headers) {
if (headers == null) {
return undefined;
}
return async () => headers;
}
exports.wrapStaticHeadersInFunction = wrapStaticHeadersInFunction;
/**
* @param userProvidedConfiguration Configuration options provided by the user in code.
* @param fallbackConfiguration Fallback to use when the {@link userProvidedConfiguration} does not specify an option.
* @param defaultConfiguration The defaults as defined by the exporter specification
*/
function mergeOtlpSharedConfigurationWithDefaults(userProvidedConfiguration, fallbackConfiguration, defaultConfiguration) {
return {
timeoutMillis: validateTimeoutMillis(userProvidedConfiguration.timeoutMillis ??
fallbackConfiguration.timeoutMillis ??
defaultConfiguration.timeoutMillis),
concurrencyLimit: userProvidedConfiguration.concurrencyLimit ??
fallbackConfiguration.concurrencyLimit ??
defaultConfiguration.concurrencyLimit,
compression: userProvidedConfiguration.compression ??
fallbackConfiguration.compression ??
defaultConfiguration.compression,
};
}
exports.mergeOtlpSharedConfigurationWithDefaults = mergeOtlpSharedConfigurationWithDefaults;
function getSharedConfigurationDefaults() {
return {
timeoutMillis: 10000,
concurrencyLimit: 30,
compression: 'none',
};
}
exports.getSharedConfigurationDefaults = getSharedConfigurationDefaults;
//# sourceMappingURL=shared-configuration.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"shared-configuration.js","sourceRoot":"","sources":["../../../src/configuration/shared-configuration.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAkBH,SAAgB,qBAAqB,CAAC,aAAqB;IACzD,IAAI,MAAM,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,aAAa,GAAG,CAAC,EAAE;QACvD,OAAO,aAAa,CAAC;KACtB;IACD,MAAM,IAAI,KAAK,CACb,qFAAqF,aAAa,IAAI,CACvG,CAAC;AACJ,CAAC;AAPD,sDAOC;AAED,SAAgB,2BAA2B,CACzC,OAA2C;IAE3C,IAAI,OAAO,IAAI,IAAI,EAAE;QACnB,OAAO,SAAS,CAAC;KAClB;IAED,OAAO,KAAK,IAAI,EAAE,CAAC,OAAO,CAAC;AAC7B,CAAC;AARD,kEAQC;AAED;;;;GAIG;AACH,SAAgB,wCAAwC,CACtD,yBAA2D,EAC3D,qBAAuD,EACvD,oBAA6C;IAE7C,OAAO;QACL,aAAa,EAAE,qBAAqB,CAClC,yBAAyB,CAAC,aAAa;YACrC,qBAAqB,CAAC,aAAa;YACnC,oBAAoB,CAAC,aAAa,CACrC;QACD,gBAAgB,EACd,yBAAyB,CAAC,gBAAgB;YAC1C,qBAAqB,CAAC,gBAAgB;YACtC,oBAAoB,CAAC,gBAAgB;QACvC,WAAW,EACT,yBAAyB,CAAC,WAAW;YACrC,qBAAqB,CAAC,WAAW;YACjC,oBAAoB,CAAC,WAAW;KACnC,CAAC;AACJ,CAAC;AApBD,4FAoBC;AAED,SAAgB,8BAA8B;IAC5C,OAAO;QACL,aAAa,EAAE,KAAK;QACpB,gBAAgB,EAAE,EAAE;QACpB,WAAW,EAAE,MAAM;KACpB,CAAC;AACJ,CAAC;AAND,wEAMC","sourcesContent":["/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport type { HeadersFactory } from './otlp-http-configuration';\n\n/**\n * Configuration shared across all OTLP exporters\n *\n * Implementation note: anything added here MUST be\n * - platform-agnostic\n * - signal-agnostic\n * - transport-agnostic\n */\nexport interface OtlpSharedConfiguration {\n timeoutMillis: number;\n concurrencyLimit: number;\n compression: 'gzip' | 'none';\n}\n\nexport function validateTimeoutMillis(timeoutMillis: number) {\n if (Number.isFinite(timeoutMillis) && timeoutMillis > 0) {\n return timeoutMillis;\n }\n throw new Error(\n `Configuration: timeoutMillis is invalid, expected number greater than 0 (actual: '${timeoutMillis}')`\n );\n}\n\nexport function wrapStaticHeadersInFunction(\n headers: Record<string, string> | undefined\n): HeadersFactory | undefined {\n if (headers == null) {\n return undefined;\n }\n\n return async () => headers;\n}\n\n/**\n * @param userProvidedConfiguration Configuration options provided by the user in code.\n * @param fallbackConfiguration Fallback to use when the {@link userProvidedConfiguration} does not specify an option.\n * @param defaultConfiguration The defaults as defined by the exporter specification\n */\nexport function mergeOtlpSharedConfigurationWithDefaults(\n userProvidedConfiguration: Partial<OtlpSharedConfiguration>,\n fallbackConfiguration: Partial<OtlpSharedConfiguration>,\n defaultConfiguration: OtlpSharedConfiguration\n): OtlpSharedConfiguration {\n return {\n timeoutMillis: validateTimeoutMillis(\n userProvidedConfiguration.timeoutMillis ??\n fallbackConfiguration.timeoutMillis ??\n defaultConfiguration.timeoutMillis\n ),\n concurrencyLimit:\n userProvidedConfiguration.concurrencyLimit ??\n fallbackConfiguration.concurrencyLimit ??\n defaultConfiguration.concurrencyLimit,\n compression:\n userProvidedConfiguration.compression ??\n fallbackConfiguration.compression ??\n defaultConfiguration.compression,\n };\n}\n\nexport function getSharedConfigurationDefaults(): OtlpSharedConfiguration {\n return {\n timeoutMillis: 10000,\n concurrencyLimit: 30,\n compression: 'none',\n };\n}\n"]}

View File

@@ -0,0 +1,3 @@
import type { OtlpSharedConfiguration } from './shared-configuration';
export declare function getSharedConfigurationFromEnvironment(signalIdentifier: string): Partial<OtlpSharedConfiguration>;
//# sourceMappingURL=shared-env-configuration.d.ts.map

View File

@@ -0,0 +1,45 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getSharedConfigurationFromEnvironment = void 0;
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
const core_1 = require("@opentelemetry/core");
const api_1 = require("@opentelemetry/api");
function parseAndValidateTimeoutFromEnv(timeoutEnvVar) {
const envTimeout = (0, core_1.getNumberFromEnv)(timeoutEnvVar);
if (envTimeout != null) {
if (Number.isFinite(envTimeout) && envTimeout > 0) {
return envTimeout;
}
api_1.diag.warn(`Configuration: ${timeoutEnvVar} is invalid, expected number greater than 0 (actual: ${envTimeout})`);
}
return undefined;
}
function getTimeoutFromEnv(signalIdentifier) {
const specificTimeout = parseAndValidateTimeoutFromEnv(`OTEL_EXPORTER_OTLP_${signalIdentifier}_TIMEOUT`);
const nonSpecificTimeout = parseAndValidateTimeoutFromEnv('OTEL_EXPORTER_OTLP_TIMEOUT');
return specificTimeout ?? nonSpecificTimeout;
}
function parseAndValidateCompressionFromEnv(compressionEnvVar) {
const compression = (0, core_1.getStringFromEnv)(compressionEnvVar)?.trim();
if (compression == null || compression === 'none' || compression === 'gzip') {
return compression;
}
api_1.diag.warn(`Configuration: ${compressionEnvVar} is invalid, expected 'none' or 'gzip' (actual: '${compression}')`);
return undefined;
}
function getCompressionFromEnv(signalIdentifier) {
const specificCompression = parseAndValidateCompressionFromEnv(`OTEL_EXPORTER_OTLP_${signalIdentifier}_COMPRESSION`);
const nonSpecificCompression = parseAndValidateCompressionFromEnv('OTEL_EXPORTER_OTLP_COMPRESSION');
return specificCompression ?? nonSpecificCompression;
}
function getSharedConfigurationFromEnvironment(signalIdentifier) {
return {
timeoutMillis: getTimeoutFromEnv(signalIdentifier),
compression: getCompressionFromEnv(signalIdentifier),
};
}
exports.getSharedConfigurationFromEnvironment = getSharedConfigurationFromEnvironment;
//# sourceMappingURL=shared-env-configuration.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"shared-env-configuration.js","sourceRoot":"","sources":["../../../src/configuration/shared-env-configuration.ts"],"names":[],"mappings":";;;AAAA;;;GAGG;AACH,8CAAyE;AAEzE,4CAA0C;AAE1C,SAAS,8BAA8B,CACrC,aAAqB;IAErB,MAAM,UAAU,GAAG,IAAA,uBAAgB,EAAC,aAAa,CAAC,CAAC;IACnD,IAAI,UAAU,IAAI,IAAI,EAAE;QACtB,IAAI,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,UAAU,GAAG,CAAC,EAAE;YACjD,OAAO,UAAU,CAAC;SACnB;QACD,UAAI,CAAC,IAAI,CACP,kBAAkB,aAAa,wDAAwD,UAAU,GAAG,CACrG,CAAC;KACH;IAED,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,SAAS,iBAAiB,CAAC,gBAAwB;IACjD,MAAM,eAAe,GAAG,8BAA8B,CACpD,sBAAsB,gBAAgB,UAAU,CACjD,CAAC;IACF,MAAM,kBAAkB,GAAG,8BAA8B,CACvD,4BAA4B,CAC7B,CAAC;IAEF,OAAO,eAAe,IAAI,kBAAkB,CAAC;AAC/C,CAAC;AAED,SAAS,kCAAkC,CACzC,iBAAyB;IAEzB,MAAM,WAAW,GAAG,IAAA,uBAAgB,EAAC,iBAAiB,CAAC,EAAE,IAAI,EAAE,CAAC;IAEhE,IAAI,WAAW,IAAI,IAAI,IAAI,WAAW,KAAK,MAAM,IAAI,WAAW,KAAK,MAAM,EAAE;QAC3E,OAAO,WAAW,CAAC;KACpB;IAED,UAAI,CAAC,IAAI,CACP,kBAAkB,iBAAiB,oDAAoD,WAAW,IAAI,CACvG,CAAC;IACF,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,SAAS,qBAAqB,CAC5B,gBAAwB;IAExB,MAAM,mBAAmB,GAAG,kCAAkC,CAC5D,sBAAsB,gBAAgB,cAAc,CACrD,CAAC;IACF,MAAM,sBAAsB,GAAG,kCAAkC,CAC/D,gCAAgC,CACjC,CAAC;IAEF,OAAO,mBAAmB,IAAI,sBAAsB,CAAC;AACvD,CAAC;AAED,SAAgB,qCAAqC,CACnD,gBAAwB;IAExB,OAAO;QACL,aAAa,EAAE,iBAAiB,CAAC,gBAAgB,CAAC;QAClD,WAAW,EAAE,qBAAqB,CAAC,gBAAgB,CAAC;KACrD,CAAC;AACJ,CAAC;AAPD,sFAOC","sourcesContent":["/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n */\nimport { getNumberFromEnv, getStringFromEnv } from '@opentelemetry/core';\nimport type { OtlpSharedConfiguration } from './shared-configuration';\nimport { diag } from '@opentelemetry/api';\n\nfunction parseAndValidateTimeoutFromEnv(\n timeoutEnvVar: string\n): number | undefined {\n const envTimeout = getNumberFromEnv(timeoutEnvVar);\n if (envTimeout != null) {\n if (Number.isFinite(envTimeout) && envTimeout > 0) {\n return envTimeout;\n }\n diag.warn(\n `Configuration: ${timeoutEnvVar} is invalid, expected number greater than 0 (actual: ${envTimeout})`\n );\n }\n\n return undefined;\n}\n\nfunction getTimeoutFromEnv(signalIdentifier: string) {\n const specificTimeout = parseAndValidateTimeoutFromEnv(\n `OTEL_EXPORTER_OTLP_${signalIdentifier}_TIMEOUT`\n );\n const nonSpecificTimeout = parseAndValidateTimeoutFromEnv(\n 'OTEL_EXPORTER_OTLP_TIMEOUT'\n );\n\n return specificTimeout ?? nonSpecificTimeout;\n}\n\nfunction parseAndValidateCompressionFromEnv(\n compressionEnvVar: string\n): 'none' | 'gzip' | undefined {\n const compression = getStringFromEnv(compressionEnvVar)?.trim();\n\n if (compression == null || compression === 'none' || compression === 'gzip') {\n return compression;\n }\n\n diag.warn(\n `Configuration: ${compressionEnvVar} is invalid, expected 'none' or 'gzip' (actual: '${compression}')`\n );\n return undefined;\n}\n\nfunction getCompressionFromEnv(\n signalIdentifier: string\n): 'none' | 'gzip' | undefined {\n const specificCompression = parseAndValidateCompressionFromEnv(\n `OTEL_EXPORTER_OTLP_${signalIdentifier}_COMPRESSION`\n );\n const nonSpecificCompression = parseAndValidateCompressionFromEnv(\n 'OTEL_EXPORTER_OTLP_COMPRESSION'\n );\n\n return specificCompression ?? nonSpecificCompression;\n}\n\nexport function getSharedConfigurationFromEnvironment(\n signalIdentifier: string\n): Partial<OtlpSharedConfiguration> {\n return {\n timeoutMillis: getTimeoutFromEnv(signalIdentifier),\n compression: getCompressionFromEnv(signalIdentifier),\n };\n}\n"]}