Skip to content

Commit 9a8c6e0

Browse files
authored
fix(otlp-exporter-base)!: split node and browser config types in two (#5917)
1 parent b37bfa7 commit 9a8c6e0

16 files changed

+163
-88
lines changed

experimental/CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,13 @@ For notes on migrating to 2.x / 0.200.x see [the upgrade guide](doc/upgrade-to-2
88

99
### :boom: Breaking Changes
1010

11+
* fix(otlp-exporter-base)!: split node and browser config types in two [#5917](https://github.com/open-telemetry/opentelemetry-js/pull/5917) @pichlermarc
12+
* Fixes a bug where Node.js modules would be incorrectly used in the instantiation of a web-targeted exporter
13+
* Breaking changes:
14+
* (user-facing) `createOtlpHttpExportDelegate(OtlpHttpConfiguration)` has been changed to take a different, but identical type `OtlpNodeHttpConfiguration` to differentiate it from the web-targeted exporters
15+
* (user-facing) `convertLegacyHttpOptions(...)` now returns `OtlpNodeHttpConfiguration`, the returned object's contents remain identical.
16+
* (user-facing) `agentFactory` has been dropped from `OtlpHttpConfiguration` as it is node-specific and is now part of `OtlpNodeHttpConfiguration` instead
17+
1118
### :rocket: Features
1219

1320
### :bug: Bug Fixes

experimental/packages/otlp-exporter-base/src/configuration/convert-legacy-node-http-options.ts

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,16 @@
1414
* limitations under the License.
1515
*/
1616
import { OTLPExporterNodeConfigBase } from './legacy-node-configuration';
17-
import {
18-
getHttpConfigurationDefaults,
19-
HttpAgentFactory,
20-
httpAgentFactoryFromOptions,
21-
mergeOtlpHttpConfigurationWithDefaults,
22-
OtlpHttpConfiguration,
23-
} from './otlp-http-configuration';
24-
import { getHttpConfigurationFromEnvironment } from './otlp-http-env-configuration';
2517
import { diag } from '@opentelemetry/api';
2618
import { wrapStaticHeadersInFunction } from './shared-configuration';
19+
import {
20+
getNodeHttpConfigurationDefaults,
21+
HttpAgentFactory,
22+
mergeOtlpNodeHttpConfigurationWithDefaults,
23+
OtlpNodeHttpConfiguration,
24+
} from './otlp-node-http-configuration';
25+
import { httpAgentFactoryFromOptions } from '../index-node-http';
26+
import { getNodeHttpConfigurationFromEnvironment } from './otlp-node-http-env-configuration';
2727

2828
function convertLegacyAgentOptions(
2929
config: OTLPExporterNodeConfigBase
@@ -56,13 +56,13 @@ export function convertLegacyHttpOptions(
5656
signalIdentifier: string,
5757
signalResourcePath: string,
5858
requiredHeaders: Record<string, string>
59-
): OtlpHttpConfiguration {
59+
): OtlpNodeHttpConfiguration {
6060
// eslint-disable-next-line @typescript-eslint/no-explicit-any
6161
if ((config as any).metadata) {
6262
diag.warn('Metadata cannot be set when using http');
6363
}
6464

65-
return mergeOtlpHttpConfigurationWithDefaults(
65+
return mergeOtlpNodeHttpConfigurationWithDefaults(
6666
{
6767
url: config.url,
6868
headers: wrapStaticHeadersInFunction(config.headers),
@@ -71,7 +71,10 @@ export function convertLegacyHttpOptions(
7171
compression: config.compression,
7272
agentFactory: convertLegacyAgentOptions(config),
7373
},
74-
getHttpConfigurationFromEnvironment(signalIdentifier, signalResourcePath),
75-
getHttpConfigurationDefaults(requiredHeaders, signalResourcePath)
74+
getNodeHttpConfigurationFromEnvironment(
75+
signalIdentifier,
76+
signalResourcePath
77+
),
78+
getNodeHttpConfigurationDefaults(requiredHeaders, signalResourcePath)
7679
);
7780
}

experimental/packages/otlp-exporter-base/src/configuration/legacy-node-configuration.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import type * as http from 'http';
1919
import type * as https from 'https';
2020

2121
import type { OTLPExporterConfigBase } from './legacy-base-configuration';
22-
import type { HttpAgentFactory } from './otlp-http-configuration';
22+
import type { HttpAgentFactory } from './otlp-node-http-configuration';
2323

2424
/**
2525
* Collector Exporter node base config

experimental/packages/otlp-exporter-base/src/configuration/otlp-http-configuration.ts

Lines changed: 0 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -21,28 +21,9 @@ import {
2121
} from './shared-configuration';
2222
import { validateAndNormalizeHeaders } from '../util';
2323

24-
// NOTE: do not change these imports to be actual imports, otherwise they WILL break `@opentelemetry/instrumentation-http`
25-
import type * as http from 'http';
26-
import type * as https from 'https';
27-
28-
export type HttpAgentFactory = (
29-
protocol: string
30-
) => http.Agent | https.Agent | Promise<http.Agent> | Promise<https.Agent>;
31-
3224
export interface OtlpHttpConfiguration extends OtlpSharedConfiguration {
3325
url: string;
3426
headers: () => Record<string, string>;
35-
/**
36-
* Factory function for creating agents.
37-
*
38-
* @remarks
39-
* Prefer using {@link httpAgentFactoryFromOptions} over manually writing a factory function wherever possible.
40-
* If using a factory function (`HttpAgentFactory`), **do not import `http.Agent` or `https.Agent`
41-
* statically at the top of the file**.
42-
* Instead, use dynamic `import()` or `require()` to load the module. This ensures that the `http` or `https`
43-
* module is not loaded before `@opentelemetry/instrumentation-http` can instrument it.
44-
*/
45-
agentFactory: HttpAgentFactory;
4627
}
4728

4829
function mergeHeaders(
@@ -86,16 +67,6 @@ function validateUserProvidedUrl(url: string | undefined): string | undefined {
8667
}
8768
}
8869

89-
export function httpAgentFactoryFromOptions(
90-
options: http.AgentOptions | https.AgentOptions
91-
): HttpAgentFactory {
92-
return async protocol => {
93-
const module = protocol === 'http:' ? import('http') : import('https');
94-
const { Agent } = await module;
95-
return new Agent(options);
96-
};
97-
}
98-
9970
/**
10071
* @param userProvidedConfiguration Configuration options provided by the user in code.
10172
* @param fallbackConfiguration Fallback to use when the {@link userProvidedConfiguration} does not specify an option.
@@ -121,10 +92,6 @@ export function mergeOtlpHttpConfigurationWithDefaults(
12192
validateUserProvidedUrl(userProvidedConfiguration.url) ??
12293
fallbackConfiguration.url ??
12394
defaultConfiguration.url,
124-
agentFactory:
125-
userProvidedConfiguration.agentFactory ??
126-
fallbackConfiguration.agentFactory ??
127-
defaultConfiguration.agentFactory,
12895
};
12996
}
13097

@@ -136,6 +103,5 @@ export function getHttpConfigurationDefaults(
136103
...getSharedConfigurationDefaults(),
137104
headers: () => requiredHeaders,
138105
url: 'http://localhost:4318/' + signalResourcePath,
139-
agentFactory: httpAgentFactoryFromOptions({ keepAlive: true }),
140106
};
141107
}
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
import {
17+
getHttpConfigurationDefaults,
18+
mergeOtlpHttpConfigurationWithDefaults,
19+
OtlpHttpConfiguration,
20+
} from './otlp-http-configuration';
21+
22+
// NOTE: do not change these imports to be actual imports, otherwise they WILL break `@opentelemetry/instrumentation-http`
23+
import type * as http from 'http';
24+
import type * as https from 'https';
25+
26+
export type HttpAgentFactory = (
27+
protocol: string
28+
) => http.Agent | https.Agent | Promise<http.Agent> | Promise<https.Agent>;
29+
30+
export interface OtlpNodeHttpConfiguration extends OtlpHttpConfiguration {
31+
/**
32+
* Factory function for creating agents.
33+
*
34+
* @remarks
35+
* Prefer using {@link httpAgentFactoryFromOptions} over manually writing a factory function wherever possible.
36+
* If using a factory function (`HttpAgentFactory`), **do not import `http.Agent` or `https.Agent`
37+
* statically at the top of the file**.
38+
* Instead, use dynamic `import()` or `require()` to load the module. This ensures that the `http` or `https`
39+
* module is not loaded before `@opentelemetry/instrumentation-http` can instrument it.
40+
*/
41+
agentFactory: HttpAgentFactory;
42+
}
43+
44+
export function httpAgentFactoryFromOptions(
45+
options: http.AgentOptions | https.AgentOptions
46+
): HttpAgentFactory {
47+
return async protocol => {
48+
const module = protocol === 'http:' ? import('http') : import('https');
49+
const { Agent } = await module;
50+
return new Agent(options);
51+
};
52+
}
53+
54+
/**
55+
* @param userProvidedConfiguration Configuration options provided by the user in code.
56+
* @param fallbackConfiguration Fallback to use when the {@link userProvidedConfiguration} does not specify an option.
57+
* @param defaultConfiguration The defaults as defined by the exporter specification
58+
*/
59+
export function mergeOtlpNodeHttpConfigurationWithDefaults(
60+
userProvidedConfiguration: Partial<OtlpNodeHttpConfiguration>,
61+
fallbackConfiguration: Partial<OtlpNodeHttpConfiguration>,
62+
defaultConfiguration: OtlpNodeHttpConfiguration
63+
): OtlpNodeHttpConfiguration {
64+
return {
65+
...mergeOtlpHttpConfigurationWithDefaults(
66+
userProvidedConfiguration,
67+
fallbackConfiguration,
68+
defaultConfiguration
69+
),
70+
agentFactory:
71+
userProvidedConfiguration.agentFactory ??
72+
fallbackConfiguration.agentFactory ??
73+
defaultConfiguration.agentFactory,
74+
};
75+
}
76+
77+
export function getNodeHttpConfigurationDefaults(
78+
requiredHeaders: Record<string, string>,
79+
signalResourcePath: string
80+
): OtlpNodeHttpConfiguration {
81+
return {
82+
...getHttpConfigurationDefaults(requiredHeaders, signalResourcePath),
83+
agentFactory: httpAgentFactoryFromOptions({ keepAlive: true }),
84+
};
85+
}

experimental/packages/otlp-exporter-base/src/configuration/otlp-http-env-configuration.ts renamed to experimental/packages/otlp-exporter-base/src/configuration/otlp-node-http-env-configuration.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@
1616
import { getStringFromEnv, parseKeyPairsIntoRecord } from '@opentelemetry/core';
1717
import { diag } from '@opentelemetry/api';
1818
import { getSharedConfigurationFromEnvironment } from './shared-env-configuration';
19-
import { OtlpHttpConfiguration } from './otlp-http-configuration';
2019
import { wrapStaticHeadersInFunction } from './shared-configuration';
20+
import { OtlpNodeHttpConfiguration } from './otlp-node-http-configuration';
2121

2222
function getStaticHeadersFromEnv(
2323
signalIdentifier: string
@@ -123,10 +123,10 @@ function getSpecificUrlFromEnv(signalIdentifier: string): string | undefined {
123123
* @param signalIdentifier all caps part in environment variables that identifies the signal (e.g.: METRICS, TRACES, LOGS)
124124
* @param signalResourcePath signal resource path to append if necessary (e.g.: v1/metrics, v1/traces, v1/logs)
125125
*/
126-
export function getHttpConfigurationFromEnvironment(
126+
export function getNodeHttpConfigurationFromEnvironment(
127127
signalIdentifier: string,
128128
signalResourcePath: string
129-
): Partial<OtlpHttpConfiguration> {
129+
): Partial<OtlpNodeHttpConfiguration> {
130130
return {
131131
...getSharedConfigurationFromEnvironment(signalIdentifier),
132132
url:

experimental/packages/otlp-exporter-base/src/index-node-http.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
* limitations under the License.
1515
*/
1616

17-
export { httpAgentFactoryFromOptions } from './configuration/otlp-http-configuration';
17+
export { httpAgentFactoryFromOptions } from './configuration/otlp-node-http-configuration';
1818
export { createOtlpHttpExportDelegate } from './otlp-http-export-delegate';
1919
export { getSharedConfigurationFromEnvironment } from './configuration/shared-env-configuration';
2020
export { convertLegacyHttpOptions } from './configuration/convert-legacy-node-http-options';

experimental/packages/otlp-exporter-base/src/otlp-http-export-delegate.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,14 @@ import {
1717
createOtlpExportDelegate,
1818
IOtlpExportDelegate,
1919
} from './otlp-export-delegate';
20-
import { OtlpHttpConfiguration } from './configuration/otlp-http-configuration';
2120
import { ISerializer } from '@opentelemetry/otlp-transformer';
2221
import { createHttpExporterTransport } from './transport/http-exporter-transport';
2322
import { createBoundedQueueExportPromiseHandler } from './bounded-queue-export-promise-handler';
2423
import { createRetryingTransport } from './retrying-transport';
24+
import { OtlpNodeHttpConfiguration } from './configuration/otlp-node-http-configuration';
2525

2626
export function createOtlpHttpExportDelegate<Internal, Response>(
27-
options: OtlpHttpConfiguration,
27+
options: OtlpNodeHttpConfiguration,
2828
serializer: ISerializer<Internal, Response>
2929
): IOtlpExportDelegate<Internal> {
3030
return createOtlpExportDelegate(

experimental/packages/otlp-exporter-base/src/transport/http-exporter-transport.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,14 @@
1414
* limitations under the License.
1515
*/
1616

17-
import type { HttpRequestParameters } from './http-transport-types';
18-
1917
// NOTE: do not change these type imports to actual imports. Doing so WILL break `@opentelemetry/instrumentation-http`,
2018
// as they'd be imported before the http/https modules can be wrapped.
2119
import type * as https from 'https';
2220
import type * as http from 'http';
2321
import { ExportResponse } from '../export-response';
2422
import { IExporterTransport } from '../exporter-transport';
2523
import { sendWithHttp } from './http-transport-utils';
24+
import { NodeHttpRequestParameters } from './node-http-transport-types';
2625

2726
interface Utils {
2827
agent: http.Agent | https.Agent;
@@ -32,7 +31,7 @@ interface Utils {
3231
class HttpExporterTransport implements IExporterTransport {
3332
private _utils: Utils | null = null;
3433

35-
constructor(private _parameters: HttpRequestParameters) {}
34+
constructor(private _parameters: NodeHttpRequestParameters) {}
3635

3736
async send(data: Uint8Array, timeoutMillis: number): Promise<ExportResponse> {
3837
const { agent, request } = await this._loadUtils();
@@ -80,7 +79,7 @@ async function requestFunctionFactory(
8079
}
8180

8281
export function createHttpExporterTransport(
83-
parameters: HttpRequestParameters
82+
parameters: NodeHttpRequestParameters
8483
): IExporterTransport {
8584
return new HttpExporterTransport(parameters);
8685
}

experimental/packages/otlp-exporter-base/src/transport/http-transport-types.ts

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,8 @@
1414
* limitations under the License.
1515
*/
1616

17-
import { HttpAgentFactory } from '../configuration/otlp-http-configuration';
18-
1917
export interface HttpRequestParameters {
2018
url: string;
2119
headers: () => Record<string, string>;
2220
compression: 'gzip' | 'none';
23-
agentFactory: HttpAgentFactory;
2421
}

0 commit comments

Comments
 (0)