From cbb1b577a3c4739d65af6df31e50704d85cf1fa7 Mon Sep 17 00:00:00 2001 From: alighaznavi Date: Thu, 9 Oct 2025 20:50:49 +0000 Subject: [PATCH 1/5] Add support for App Check --- common/api-review/telemetry-react.api.md | 5 ++ common/api-review/telemetry.api.md | 5 ++ docs-devsite/_toc.yaml | 4 + .../telemetry_.dynamicheaderprovider.md | 43 ++++++++++ docs-devsite/telemetry_.md | 1 + .../telemetry_react.dynamicheaderprovider.md | 43 ++++++++++ docs-devsite/telemetry_react.md | 1 + .../src/logging/appcheck-provider.ts | 51 ++++++++++++ .../src/logging/fetch-transport.edge.test.ts | 78 +++++++++++++++++++ .../src/logging/fetch-transport.edge.ts | 22 +++++- .../telemetry/src/logging/logger-provider.ts | 45 ++++++----- packages/telemetry/src/public-types.ts | 17 ++++ packages/telemetry/src/register.node.ts | 3 +- packages/telemetry/src/register.ts | 9 ++- packages/telemetry/src/service.ts | 16 +--- yarn.lock | 31 +------- 16 files changed, 303 insertions(+), 71 deletions(-) create mode 100644 docs-devsite/telemetry_.dynamicheaderprovider.md create mode 100644 docs-devsite/telemetry_react.dynamicheaderprovider.md create mode 100644 packages/telemetry/src/logging/appcheck-provider.ts diff --git a/common/api-review/telemetry-react.api.md b/common/api-review/telemetry-react.api.md index 53e344cc1ab..a57b8027e49 100644 --- a/common/api-review/telemetry-react.api.md +++ b/common/api-review/telemetry-react.api.md @@ -8,6 +8,11 @@ import { FirebaseApp } from '@firebase/app'; import { FirebaseOptions } from '@firebase/app'; import { LoggerProvider } from '@opentelemetry/sdk-logs'; +// @public +export interface DynamicHeaderProvider { + getHeader(): Promise | null>; +} + // @public export function FirebaseTelemetry({ firebaseOptions, telemetryOptions }: { firebaseOptions?: FirebaseOptions; diff --git a/common/api-review/telemetry.api.md b/common/api-review/telemetry.api.md index 6a23ce03b80..ef9fbb27ea2 100644 --- a/common/api-review/telemetry.api.md +++ b/common/api-review/telemetry.api.md @@ -12,6 +12,11 @@ import { LoggerProvider } from '@opentelemetry/sdk-logs'; // @public export function captureError(telemetry: Telemetry, error: unknown, attributes?: AnyValueMap): void; +// @public +export interface DynamicHeaderProvider { + getHeader(): Promise | null>; +} + // @public export function flush(telemetry: Telemetry): Promise; diff --git a/docs-devsite/_toc.yaml b/docs-devsite/_toc.yaml index 81078cb2618..e0227cf3c94 100644 --- a/docs-devsite/_toc.yaml +++ b/docs-devsite/_toc.yaml @@ -697,6 +697,8 @@ toc: - title: telemetry path: /docs/reference/js/telemetry_.md section: + - title: DynamicHeaderProvider + path: /docs/reference/js/telemetry_.dynamicheaderprovider.md - title: Telemetry path: /docs/reference/js/telemetry_.telemetry.md - title: TelemetryOptions @@ -704,6 +706,8 @@ toc: - title: telemetry/react path: /docs/reference/js/telemetry_react.md section: + - title: DynamicHeaderProvider + path: /docs/reference/js/telemetry_react.dynamicheaderprovider.md - title: Telemetry path: /docs/reference/js/telemetry_react.telemetry.md - title: TelemetryOptions diff --git a/docs-devsite/telemetry_.dynamicheaderprovider.md b/docs-devsite/telemetry_.dynamicheaderprovider.md new file mode 100644 index 00000000000..e4d81fd5cd8 --- /dev/null +++ b/docs-devsite/telemetry_.dynamicheaderprovider.md @@ -0,0 +1,43 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# DynamicHeaderProvider interface +An interface for classes that provide dynamic headers. + +Classes that implement this interface can be used to supply custom headers for logging. + +Signature: + +```typescript +export interface DynamicHeaderProvider +``` + +## Methods + +| Method | Description | +| --- | --- | +| [getHeader()](./telemetry_.dynamicheaderprovider.md#dynamicheaderprovidergetheader) | Returns a record of headers to be added to a request. | + +## DynamicHeaderProvider.getHeader() + +Returns a record of headers to be added to a request. + +Signature: + +```typescript +getHeader(): Promise | null>; +``` +Returns: + +Promise<Record<string, string> \| null> + +A that resolves to a of header key-value pairs, or null if no headers are to be added. + diff --git a/docs-devsite/telemetry_.md b/docs-devsite/telemetry_.md index ae1f827c9e3..a351203e44a 100644 --- a/docs-devsite/telemetry_.md +++ b/docs-devsite/telemetry_.md @@ -27,6 +27,7 @@ https://github.com/firebase/firebase-js-sdk | Interface | Description | | --- | --- | +| [DynamicHeaderProvider](./telemetry_.dynamicheaderprovider.md#dynamicheaderprovider_interface) | An interface for classes that provide dynamic headers.Classes that implement this interface can be used to supply custom headers for logging. | | [Telemetry](./telemetry_.telemetry.md#telemetry_interface) | An instance of the Firebase Telemetry SDK.Do not create this instance directly. Instead, use [getTelemetry()](./telemetry_.md#gettelemetry_448bdc6). | | [TelemetryOptions](./telemetry_.telemetryoptions.md#telemetryoptions_interface) | Options for initialized the Telemetry service using [getTelemetry()](./telemetry_.md#gettelemetry_448bdc6). | diff --git a/docs-devsite/telemetry_react.dynamicheaderprovider.md b/docs-devsite/telemetry_react.dynamicheaderprovider.md new file mode 100644 index 00000000000..b9b56dd56d8 --- /dev/null +++ b/docs-devsite/telemetry_react.dynamicheaderprovider.md @@ -0,0 +1,43 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# DynamicHeaderProvider interface +An interface for classes that provide dynamic headers. + +Classes that implement this interface can be used to supply custom headers for logging. + +Signature: + +```typescript +export interface DynamicHeaderProvider +``` + +## Methods + +| Method | Description | +| --- | --- | +| [getHeader()](./telemetry_react.dynamicheaderprovider.md#dynamicheaderprovidergetheader) | Returns a record of headers to be added to a request. | + +## DynamicHeaderProvider.getHeader() + +Returns a record of headers to be added to a request. + +Signature: + +```typescript +getHeader(): Promise | null>; +``` +Returns: + +Promise<Record<string, string> \| null> + +A that resolves to a of header key-value pairs, or null if no headers are to be added. + diff --git a/docs-devsite/telemetry_react.md b/docs-devsite/telemetry_react.md index 40d58284958..84d49ee790d 100644 --- a/docs-devsite/telemetry_react.md +++ b/docs-devsite/telemetry_react.md @@ -21,6 +21,7 @@ https://github.com/firebase/firebase-js-sdk | Interface | Description | | --- | --- | +| [DynamicHeaderProvider](./telemetry_react.dynamicheaderprovider.md#dynamicheaderprovider_interface) | An interface for classes that provide dynamic headers.Classes that implement this interface can be used to supply custom headers for logging. | | [Telemetry](./telemetry_react.telemetry.md#telemetry_interface) | An instance of the Firebase Telemetry SDK.Do not create this instance directly. Instead, use [getTelemetry()](./telemetry_.md#gettelemetry_448bdc6). | | [TelemetryOptions](./telemetry_react.telemetryoptions.md#telemetryoptions_interface) | Options for initialized the Telemetry service using [getTelemetry()](./telemetry_.md#gettelemetry_448bdc6). | diff --git a/packages/telemetry/src/logging/appcheck-provider.ts b/packages/telemetry/src/logging/appcheck-provider.ts new file mode 100644 index 00000000000..a961e0cccdc --- /dev/null +++ b/packages/telemetry/src/logging/appcheck-provider.ts @@ -0,0 +1,51 @@ +/** + * @license + * Copyright 2025 Google 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. + */ + +import { DynamicHeaderProvider } from '../public-types'; +import { Provider } from '@firebase/component'; +import { + FirebaseAppCheckInternal, + AppCheckInternalComponentName +} from '@firebase/app-check-interop-types'; + +export class AppCheckProvider implements DynamicHeaderProvider { + appCheck: FirebaseAppCheckInternal | null; + + constructor(appCheckProvider: Provider) { + this.appCheck = appCheckProvider?.getImmediate({ optional: true }); + if (!this.appCheck) { + void appCheckProvider + ?.get() + .then(appCheck => (this.appCheck = appCheck)) + .catch(); + } + } + + async getHeader(): Promise | null> { + if (!this.appCheck) { + return null; + } + + const appCheckToken = await this.appCheck.getToken(); + // If the error field is defined, the token field will be populated with a dummy token + if (!appCheckToken || !!appCheckToken.error) { + return null; + } + + return {'X-Firebase-AppCheck': appCheckToken.token}; + } +} \ No newline at end of file diff --git a/packages/telemetry/src/logging/fetch-transport.edge.test.ts b/packages/telemetry/src/logging/fetch-transport.edge.test.ts index 0e954495067..464157e0f3b 100644 --- a/packages/telemetry/src/logging/fetch-transport.edge.test.ts +++ b/packages/telemetry/src/logging/fetch-transport.edge.test.ts @@ -20,6 +20,7 @@ import * as sinon from 'sinon'; import * as assert from 'assert'; +import { DynamicHeaderProvider } from '../public-types'; import { FetchTransportEdge } from './fetch-transport.edge'; import { ExportResponseRetryable, @@ -173,5 +174,82 @@ describe('FetchTransportEdge', () => { }, done /* catch any rejections */); clock.tick(requestTimeout + 100); }); + + it('attaches static and dynamic headers to the request', done => { + // arrange + const fetchStub = sinon + .stub(globalThis, 'fetch') + .resolves(new Response('test response', { status: 200 })); + + const dynamicProvider: DynamicHeaderProvider = { + getHeader: sinon.stub().resolves({ 'dynamic-header': 'dynamic-value' }) + }; + + const transport = new FetchTransportEdge({ + ...testTransportParameters, + dynamicHeaders: [dynamicProvider] + }); + + //act + transport.send(testPayload, requestTimeout).then(response => { + // assert + try { + assert.strictEqual(response.status, 'success'); + sinon.assert.calledOnceWithMatch( + fetchStub, + testTransportParameters.url, + { + method: 'POST', + headers: { + foo: 'foo-value', + bar: 'bar-value', + 'Content-Type': 'application/json', + 'dynamic-header': 'dynamic-value' + }, + body: testPayload + } + ); + done(); + } catch (e) { + done(e); + } + }, done /* catch any rejections */); + }); + + it('handles dynamic header providers that return null', done => { + // arrange + const fetchStub = sinon + .stub(globalThis, 'fetch') + .resolves(new Response('test response', { status: 200 })); + + const dynamicProvider: DynamicHeaderProvider = { + getHeader: sinon.stub().resolves(null) + }; + + const transport = new FetchTransportEdge({ + ...testTransportParameters, + dynamicHeaders: [dynamicProvider] + }); + + //act + transport.send(testPayload, requestTimeout).then(response => { + // assert + try { + assert.strictEqual(response.status, 'success'); + sinon.assert.calledOnceWithMatch( + fetchStub, + testTransportParameters.url, + { + method: 'POST', + headers: testTransportParameters.headers(), + body: testPayload + } + ); + done(); + } catch (e) { + done(e); + } + }, done /* catch any rejections */); + }); }); }); diff --git a/packages/telemetry/src/logging/fetch-transport.edge.ts b/packages/telemetry/src/logging/fetch-transport.edge.ts index 9b095b779fc..967148ecc72 100644 --- a/packages/telemetry/src/logging/fetch-transport.edge.ts +++ b/packages/telemetry/src/logging/fetch-transport.edge.ts @@ -23,6 +23,7 @@ import { ExportResponse } from '@opentelemetry/otlp-exporter-base'; import { diag } from '@opentelemetry/api'; +import { DynamicHeaderProvider } from '../public-types'; function isExportRetryable(statusCode: number): boolean { const retryCodes = [429, 502, 503, 504]; @@ -53,6 +54,7 @@ function parseRetryAfterToMills( export interface FetchTransportParameters { url: string; headers: () => Record; + dynamicHeaders?: DynamicHeaderProvider[]; } /** @@ -68,9 +70,27 @@ export class FetchTransportEdge implements IExporterTransport { const timeout = setTimeout(() => abortController.abort(), timeoutMillis); try { const url = new URL(this.parameters.url); + const headers = this.parameters.headers(); + + if ( + this.parameters.dynamicHeaders && + this.parameters.dynamicHeaders.length > 0 + ) { + const dynamicHeaderPromises = this.parameters.dynamicHeaders.map( + provider => provider.getHeader() + ); + const resolvedHeaders = await Promise.all(dynamicHeaderPromises); + + for (const header of resolvedHeaders) { + if (header) { + Object.assign(headers, header); + } + } + } + const body = { method: 'POST', - headers: this.parameters.headers(), + headers, signal: abortController.signal, keepalive: false, mode: 'cors', diff --git a/packages/telemetry/src/logging/logger-provider.ts b/packages/telemetry/src/logging/logger-provider.ts index cc22e22a297..006997fb56b 100644 --- a/packages/telemetry/src/logging/logger-provider.ts +++ b/packages/telemetry/src/logging/logger-provider.ts @@ -23,7 +23,6 @@ import { } from '@opentelemetry/sdk-logs'; import { ATTR_SERVICE_NAME } from '@opentelemetry/semantic-conventions'; import { resourceFromAttributes } from '@opentelemetry/resources'; -import { OTLPLogExporter } from '@opentelemetry/exporter-logs-otlp-http'; import { JsonLogsSerializer } from '@opentelemetry/otlp-transformer'; import type { OTLPExporterConfigBase } from '@opentelemetry/otlp-exporter-base'; import { @@ -31,13 +30,17 @@ import { createOtlpNetworkExportDelegate } from '@opentelemetry/otlp-exporter-base'; import { FetchTransportEdge } from './fetch-transport.edge'; +import { DynamicHeaderProvider } from '../public-types'; /** * Create a logger provider for the current execution environment. * * @internal */ -export function createLoggerProvider(endpointUrl: string): LoggerProvider { +export function createLoggerProvider( + endpointUrl: string, + dynamicHeaders: DynamicHeaderProvider[] = [] +): LoggerProvider { const resource = resourceFromAttributes({ [ATTR_SERVICE_NAME]: 'firebase_telemetry_service' }); @@ -45,32 +48,27 @@ export function createLoggerProvider(endpointUrl: string): LoggerProvider { endpointUrl = endpointUrl.slice(0, -1); } const otlpEndpoint = `${endpointUrl}/api/v1/logs`; + const logExporter = new OTLPLogExporter( + { url: otlpEndpoint }, + dynamicHeaders + ); - if (typeof process !== 'undefined' && process?.env?.NEXT_RUNTIME === 'edge') { - // We need a slightly custom implementation for the Edge Runtime, because it doesn't have access - // to many features available in Node. - const logExporter = new OTLPLogExporterEdge({ url: otlpEndpoint }); - const provider = new LoggerProvider({ - resource, - processors: [new BatchLogRecordProcessor(logExporter)], - logRecordLimits: {} - }); - return provider; - } else { - const logExporter = new OTLPLogExporter({ url: otlpEndpoint }); - return new LoggerProvider({ - resource, - processors: [new BatchLogRecordProcessor(logExporter)] - }); - } + return new LoggerProvider({ + resource, + processors: [new BatchLogRecordProcessor(logExporter)], + logRecordLimits: {} + }); } -/** OTLP exporter that uses custom FetchTransport for use in the Edge Runtime. */ -class OTLPLogExporterEdge +/** OTLP exporter that uses custom FetchTransportEdge. */ +class OTLPLogExporter extends OTLPExporterBase implements LogRecordExporter { - constructor(config: OTLPExporterConfigBase = {}) { + constructor( + config: OTLPExporterConfigBase = {}, + dynamicHeaders: DynamicHeaderProvider[] = [] + ) { super( createOtlpNetworkExportDelegate( { @@ -83,7 +81,8 @@ class OTLPLogExporterEdge url: config.url!, headers: () => ({ 'Content-Type': 'application/json' - }) + }), + dynamicHeaders }) ) ); diff --git a/packages/telemetry/src/public-types.ts b/packages/telemetry/src/public-types.ts index 852c72221fd..a19c2fb04fa 100644 --- a/packages/telemetry/src/public-types.ts +++ b/packages/telemetry/src/public-types.ts @@ -47,3 +47,20 @@ export interface TelemetryOptions { */ endpointUrl?: string; } + +/** + * An interface for classes that provide dynamic headers. + * + * Classes that implement this interface can be used to supply custom headers for logging. + * + * @public + */ +export interface DynamicHeaderProvider { + /** + * Returns a record of headers to be added to a request. + * + * @returns A {@link Promise} that resolves to a {@link Record} of header + * key-value pairs, or null if no headers are to be added. + */ + getHeader(): Promise | null>; +} diff --git a/packages/telemetry/src/register.node.ts b/packages/telemetry/src/register.node.ts index 58988dd6f13..8a5b233f960 100644 --- a/packages/telemetry/src/register.node.ts +++ b/packages/telemetry/src/register.node.ts @@ -37,9 +37,8 @@ export function registerTelemetry(): void { // getImmediate for FirebaseApp will always succeed const app = container.getProvider('app').getImmediate(); const loggerProvider = createLoggerProvider(endpointUrl); - const appCheckProvider = container.getProvider('app-check-internal'); - return new TelemetryService(app, loggerProvider, appCheckProvider); + return new TelemetryService(app, loggerProvider); }, ComponentType.PUBLIC ).setMultipleInstances(true) diff --git a/packages/telemetry/src/register.ts b/packages/telemetry/src/register.ts index 8d7fb8d5397..f410a59d8ae 100644 --- a/packages/telemetry/src/register.ts +++ b/packages/telemetry/src/register.ts @@ -21,6 +21,7 @@ import { TELEMETRY_TYPE } from './constants'; import { name, version } from '../package.json'; import { TelemetryService } from './service'; import { createLoggerProvider } from './logging/logger-provider'; +import { AppCheckProvider } from './logging/appcheck-provider'; export function registerTelemetry(): void { _registerComponent( @@ -36,10 +37,14 @@ export function registerTelemetry(): void { // getImmediate for FirebaseApp will always succeed const app = container.getProvider('app').getImmediate(); - const loggerProvider = createLoggerProvider(endpointUrl); const appCheckProvider = container.getProvider('app-check-internal'); + const dynamicHeaders = [new AppCheckProvider(appCheckProvider)]; + const loggerProvider = createLoggerProvider( + endpointUrl, + dynamicHeaders + ); - return new TelemetryService(app, loggerProvider, appCheckProvider); + return new TelemetryService(app, loggerProvider); }, ComponentType.PUBLIC ).setMultipleInstances(true) diff --git a/packages/telemetry/src/service.ts b/packages/telemetry/src/service.ts index a93059ad9fa..e09e861d3dc 100644 --- a/packages/telemetry/src/service.ts +++ b/packages/telemetry/src/service.ts @@ -18,23 +18,9 @@ import { _FirebaseService, FirebaseApp } from '@firebase/app'; import { Telemetry } from './public-types'; import { LoggerProvider } from '@opentelemetry/sdk-logs'; -import { Provider } from '@firebase/component'; -import { - AppCheckInternalComponentName, - FirebaseAppCheckInternal -} from '@firebase/app-check-interop-types'; export class TelemetryService implements Telemetry, _FirebaseService { - appCheck: FirebaseAppCheckInternal | null; - - constructor( - public app: FirebaseApp, - public loggerProvider: LoggerProvider, - appCheckProvider?: Provider - ) { - const appCheck = appCheckProvider?.getImmediate({ optional: true }); - this.appCheck = appCheck || null; - } + constructor(public app: FirebaseApp, public loggerProvider: LoggerProvider) {} _delete(): Promise { return Promise.resolve(); diff --git a/yarn.lock b/yarn.lock index e6e4692d51e..70c7e806773 100644 --- a/yarn.lock +++ b/yarn.lock @@ -15718,7 +15718,7 @@ string-argv@~0.3.1: resolved "https://registry.npmjs.org/string-argv/-/string-argv-0.3.2.tgz#2b6d0ef24b656274d957d54e0a4bbf6153dc02b6" integrity sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q== -"string-width-cjs@npm:string-width@^4.2.0": +"string-width-cjs@npm:string-width@^4.2.0", "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3: version "4.2.3" resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -15736,15 +15736,6 @@ string-width@^1.0.1, string-width@^1.0.2: is-fullwidth-code-point "^1.0.0" strip-ansi "^3.0.0" -"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3: - version "4.2.3" - resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" - integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.1" - string-width@^2.1.1: version "2.1.1" resolved "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" @@ -15808,7 +15799,7 @@ string_decoder@~1.1.1: dependencies: safe-buffer "~5.1.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1": +"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -15829,13 +15820,6 @@ strip-ansi@^4.0.0: dependencies: ansi-regex "^3.0.0" -strip-ansi@^6.0.0, strip-ansi@^6.0.1: - version "6.0.1" - resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== - dependencies: - ansi-regex "^5.0.1" - strip-ansi@^7.0.1: version "7.1.0" resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" @@ -17515,7 +17499,7 @@ workerpool@6.2.0: resolved "https://registry.npmjs.org/workerpool/-/workerpool-6.2.0.tgz#827d93c9ba23ee2019c3ffaff5c27fccea289e8b" integrity sha512-Rsk5qQHJ9eowMH28Jwhe8HEbmdYDX4lwoMWshiCXugjtHqMD9ZbiqSDLxcsfdqsETPzVUtX5s1Z5kStiIM6l4A== -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: version "7.0.0" resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== @@ -17549,15 +17533,6 @@ wrap-ansi@^6.0.1, wrap-ansi@^6.2.0: string-width "^4.1.0" strip-ansi "^6.0.0" -wrap-ansi@^7.0.0: - version "7.0.0" - resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" - integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== - dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - wrap-ansi@^8.1.0: version "8.1.0" resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" From 4d071b54c1dd68432df1cffb12a5da5d95f66856 Mon Sep 17 00:00:00 2001 From: alighaznavi Date: Fri, 10 Oct 2025 15:51:45 +0000 Subject: [PATCH 2/5] Maked DynamicHeaderProvider an internal interface and addresses other comments on PR --- common/api-review/telemetry-react.api.md | 5 --- common/api-review/telemetry.api.md | 5 --- docs-devsite/_toc.yaml | 4 -- .../telemetry_.dynamicheaderprovider.md | 43 ------------------- docs-devsite/telemetry_.md | 1 - .../telemetry_react.dynamicheaderprovider.md | 43 ------------------- docs-devsite/telemetry_react.md | 1 - .../src/logging/appcheck-provider.ts | 14 ++++-- ...t.edge.test.ts => fetch-transport.test.ts} | 20 ++++----- ...h-transport.edge.ts => fetch-transport.ts} | 6 +-- .../telemetry/src/logging/logger-provider.ts | 8 ++-- packages/telemetry/src/public-types.ts | 17 -------- packages/telemetry/src/types.ts | 33 ++++++++++++++ 13 files changed, 60 insertions(+), 140 deletions(-) delete mode 100644 docs-devsite/telemetry_.dynamicheaderprovider.md delete mode 100644 docs-devsite/telemetry_react.dynamicheaderprovider.md rename packages/telemetry/src/logging/{fetch-transport.edge.test.ts => fetch-transport.test.ts} (91%) rename packages/telemetry/src/logging/{fetch-transport.edge.ts => fetch-transport.ts} (94%) create mode 100644 packages/telemetry/src/types.ts diff --git a/common/api-review/telemetry-react.api.md b/common/api-review/telemetry-react.api.md index a57b8027e49..53e344cc1ab 100644 --- a/common/api-review/telemetry-react.api.md +++ b/common/api-review/telemetry-react.api.md @@ -8,11 +8,6 @@ import { FirebaseApp } from '@firebase/app'; import { FirebaseOptions } from '@firebase/app'; import { LoggerProvider } from '@opentelemetry/sdk-logs'; -// @public -export interface DynamicHeaderProvider { - getHeader(): Promise | null>; -} - // @public export function FirebaseTelemetry({ firebaseOptions, telemetryOptions }: { firebaseOptions?: FirebaseOptions; diff --git a/common/api-review/telemetry.api.md b/common/api-review/telemetry.api.md index ef9fbb27ea2..6a23ce03b80 100644 --- a/common/api-review/telemetry.api.md +++ b/common/api-review/telemetry.api.md @@ -12,11 +12,6 @@ import { LoggerProvider } from '@opentelemetry/sdk-logs'; // @public export function captureError(telemetry: Telemetry, error: unknown, attributes?: AnyValueMap): void; -// @public -export interface DynamicHeaderProvider { - getHeader(): Promise | null>; -} - // @public export function flush(telemetry: Telemetry): Promise; diff --git a/docs-devsite/_toc.yaml b/docs-devsite/_toc.yaml index e0227cf3c94..81078cb2618 100644 --- a/docs-devsite/_toc.yaml +++ b/docs-devsite/_toc.yaml @@ -697,8 +697,6 @@ toc: - title: telemetry path: /docs/reference/js/telemetry_.md section: - - title: DynamicHeaderProvider - path: /docs/reference/js/telemetry_.dynamicheaderprovider.md - title: Telemetry path: /docs/reference/js/telemetry_.telemetry.md - title: TelemetryOptions @@ -706,8 +704,6 @@ toc: - title: telemetry/react path: /docs/reference/js/telemetry_react.md section: - - title: DynamicHeaderProvider - path: /docs/reference/js/telemetry_react.dynamicheaderprovider.md - title: Telemetry path: /docs/reference/js/telemetry_react.telemetry.md - title: TelemetryOptions diff --git a/docs-devsite/telemetry_.dynamicheaderprovider.md b/docs-devsite/telemetry_.dynamicheaderprovider.md deleted file mode 100644 index e4d81fd5cd8..00000000000 --- a/docs-devsite/telemetry_.dynamicheaderprovider.md +++ /dev/null @@ -1,43 +0,0 @@ -Project: /docs/reference/js/_project.yaml -Book: /docs/reference/_book.yaml -page_type: reference - -{% comment %} -DO NOT EDIT THIS FILE! -This is generated by the JS SDK team, and any local changes will be -overwritten. Changes should be made in the source code at -https://github.com/firebase/firebase-js-sdk -{% endcomment %} - -# DynamicHeaderProvider interface -An interface for classes that provide dynamic headers. - -Classes that implement this interface can be used to supply custom headers for logging. - -Signature: - -```typescript -export interface DynamicHeaderProvider -``` - -## Methods - -| Method | Description | -| --- | --- | -| [getHeader()](./telemetry_.dynamicheaderprovider.md#dynamicheaderprovidergetheader) | Returns a record of headers to be added to a request. | - -## DynamicHeaderProvider.getHeader() - -Returns a record of headers to be added to a request. - -Signature: - -```typescript -getHeader(): Promise | null>; -``` -Returns: - -Promise<Record<string, string> \| null> - -A that resolves to a of header key-value pairs, or null if no headers are to be added. - diff --git a/docs-devsite/telemetry_.md b/docs-devsite/telemetry_.md index a351203e44a..ae1f827c9e3 100644 --- a/docs-devsite/telemetry_.md +++ b/docs-devsite/telemetry_.md @@ -27,7 +27,6 @@ https://github.com/firebase/firebase-js-sdk | Interface | Description | | --- | --- | -| [DynamicHeaderProvider](./telemetry_.dynamicheaderprovider.md#dynamicheaderprovider_interface) | An interface for classes that provide dynamic headers.Classes that implement this interface can be used to supply custom headers for logging. | | [Telemetry](./telemetry_.telemetry.md#telemetry_interface) | An instance of the Firebase Telemetry SDK.Do not create this instance directly. Instead, use [getTelemetry()](./telemetry_.md#gettelemetry_448bdc6). | | [TelemetryOptions](./telemetry_.telemetryoptions.md#telemetryoptions_interface) | Options for initialized the Telemetry service using [getTelemetry()](./telemetry_.md#gettelemetry_448bdc6). | diff --git a/docs-devsite/telemetry_react.dynamicheaderprovider.md b/docs-devsite/telemetry_react.dynamicheaderprovider.md deleted file mode 100644 index b9b56dd56d8..00000000000 --- a/docs-devsite/telemetry_react.dynamicheaderprovider.md +++ /dev/null @@ -1,43 +0,0 @@ -Project: /docs/reference/js/_project.yaml -Book: /docs/reference/_book.yaml -page_type: reference - -{% comment %} -DO NOT EDIT THIS FILE! -This is generated by the JS SDK team, and any local changes will be -overwritten. Changes should be made in the source code at -https://github.com/firebase/firebase-js-sdk -{% endcomment %} - -# DynamicHeaderProvider interface -An interface for classes that provide dynamic headers. - -Classes that implement this interface can be used to supply custom headers for logging. - -Signature: - -```typescript -export interface DynamicHeaderProvider -``` - -## Methods - -| Method | Description | -| --- | --- | -| [getHeader()](./telemetry_react.dynamicheaderprovider.md#dynamicheaderprovidergetheader) | Returns a record of headers to be added to a request. | - -## DynamicHeaderProvider.getHeader() - -Returns a record of headers to be added to a request. - -Signature: - -```typescript -getHeader(): Promise | null>; -``` -Returns: - -Promise<Record<string, string> \| null> - -A that resolves to a of header key-value pairs, or null if no headers are to be added. - diff --git a/docs-devsite/telemetry_react.md b/docs-devsite/telemetry_react.md index 84d49ee790d..40d58284958 100644 --- a/docs-devsite/telemetry_react.md +++ b/docs-devsite/telemetry_react.md @@ -21,7 +21,6 @@ https://github.com/firebase/firebase-js-sdk | Interface | Description | | --- | --- | -| [DynamicHeaderProvider](./telemetry_react.dynamicheaderprovider.md#dynamicheaderprovider_interface) | An interface for classes that provide dynamic headers.Classes that implement this interface can be used to supply custom headers for logging. | | [Telemetry](./telemetry_react.telemetry.md#telemetry_interface) | An instance of the Firebase Telemetry SDK.Do not create this instance directly. Instead, use [getTelemetry()](./telemetry_.md#gettelemetry_448bdc6). | | [TelemetryOptions](./telemetry_react.telemetryoptions.md#telemetryoptions_interface) | Options for initialized the Telemetry service using [getTelemetry()](./telemetry_.md#gettelemetry_448bdc6). | diff --git a/packages/telemetry/src/logging/appcheck-provider.ts b/packages/telemetry/src/logging/appcheck-provider.ts index a961e0cccdc..655b55bcfd2 100644 --- a/packages/telemetry/src/logging/appcheck-provider.ts +++ b/packages/telemetry/src/logging/appcheck-provider.ts @@ -15,13 +15,18 @@ * limitations under the License. */ -import { DynamicHeaderProvider } from '../public-types'; +import { DynamicHeaderProvider } from '../types'; import { Provider } from '@firebase/component'; import { FirebaseAppCheckInternal, AppCheckInternalComponentName } from '@firebase/app-check-interop-types'; +/** + * An implementation of DynamicHeaderProvider that can be used to provide App Check token headers. + * + * @internal + */ export class AppCheckProvider implements DynamicHeaderProvider { appCheck: FirebaseAppCheckInternal | null; @@ -41,11 +46,12 @@ export class AppCheckProvider implements DynamicHeaderProvider { } const appCheckToken = await this.appCheck.getToken(); - // If the error field is defined, the token field will be populated with a dummy token + // The error field must be checked as when there is an error, the token field is populated with + // a dummy error. if (!appCheckToken || !!appCheckToken.error) { return null; } - return {'X-Firebase-AppCheck': appCheckToken.token}; + return { 'X-Firebase-AppCheck': appCheckToken.token }; } -} \ No newline at end of file +} diff --git a/packages/telemetry/src/logging/fetch-transport.edge.test.ts b/packages/telemetry/src/logging/fetch-transport.test.ts similarity index 91% rename from packages/telemetry/src/logging/fetch-transport.edge.test.ts rename to packages/telemetry/src/logging/fetch-transport.test.ts index 464157e0f3b..a3ae5501a7e 100644 --- a/packages/telemetry/src/logging/fetch-transport.edge.test.ts +++ b/packages/telemetry/src/logging/fetch-transport.test.ts @@ -20,8 +20,8 @@ import * as sinon from 'sinon'; import * as assert from 'assert'; -import { DynamicHeaderProvider } from '../public-types'; -import { FetchTransportEdge } from './fetch-transport.edge'; +import { DynamicHeaderProvider } from '../types'; +import { FetchTransport } from './fetch-transport'; import { ExportResponseRetryable, ExportResponseFailure, @@ -40,7 +40,7 @@ const testTransportParameters = { const requestTimeout = 1000; const testPayload = Uint8Array.from([1, 2, 3]); -describe('FetchTransportEdge', () => { +describe('FetchTransport', () => { afterEach(() => { sinon.restore(); }); @@ -51,7 +51,7 @@ describe('FetchTransportEdge', () => { const fetchStub = sinon .stub(globalThis, 'fetch') .resolves(new Response('test response', { status: 200 })); - const transport = new FetchTransportEdge(testTransportParameters); + const transport = new FetchTransport(testTransportParameters); //act transport.send(testPayload, requestTimeout).then(response => { @@ -88,7 +88,7 @@ describe('FetchTransportEdge', () => { sinon .stub(globalThis, 'fetch') .resolves(new Response('', { status: 404 })); - const transport = new FetchTransportEdge(testTransportParameters); + const transport = new FetchTransport(testTransportParameters); //act transport.send(testPayload, requestTimeout).then(response => { @@ -109,7 +109,7 @@ describe('FetchTransportEdge', () => { .resolves( new Response('', { status: 503, headers: { 'Retry-After': '5' } }) ); - const transport = new FetchTransportEdge(testTransportParameters); + const transport = new FetchTransport(testTransportParameters); //act transport.send(testPayload, requestTimeout).then(response => { @@ -133,7 +133,7 @@ describe('FetchTransportEdge', () => { abortError.name = 'AbortError'; sinon.stub(globalThis, 'fetch').rejects(abortError); const clock = sinon.useFakeTimers(); - const transport = new FetchTransportEdge(testTransportParameters); + const transport = new FetchTransport(testTransportParameters); //act transport.send(testPayload, requestTimeout).then(response => { @@ -156,7 +156,7 @@ describe('FetchTransportEdge', () => { // arrange sinon.stub(globalThis, 'fetch').throws(new Error('fetch failed')); const clock = sinon.useFakeTimers(); - const transport = new FetchTransportEdge(testTransportParameters); + const transport = new FetchTransport(testTransportParameters); //act transport.send(testPayload, requestTimeout).then(response => { @@ -185,7 +185,7 @@ describe('FetchTransportEdge', () => { getHeader: sinon.stub().resolves({ 'dynamic-header': 'dynamic-value' }) }; - const transport = new FetchTransportEdge({ + const transport = new FetchTransport({ ...testTransportParameters, dynamicHeaders: [dynamicProvider] }); @@ -226,7 +226,7 @@ describe('FetchTransportEdge', () => { getHeader: sinon.stub().resolves(null) }; - const transport = new FetchTransportEdge({ + const transport = new FetchTransport({ ...testTransportParameters, dynamicHeaders: [dynamicProvider] }); diff --git a/packages/telemetry/src/logging/fetch-transport.edge.ts b/packages/telemetry/src/logging/fetch-transport.ts similarity index 94% rename from packages/telemetry/src/logging/fetch-transport.edge.ts rename to packages/telemetry/src/logging/fetch-transport.ts index 967148ecc72..ad5a4b253a7 100644 --- a/packages/telemetry/src/logging/fetch-transport.edge.ts +++ b/packages/telemetry/src/logging/fetch-transport.ts @@ -23,7 +23,7 @@ import { ExportResponse } from '@opentelemetry/otlp-exporter-base'; import { diag } from '@opentelemetry/api'; -import { DynamicHeaderProvider } from '../public-types'; +import { DynamicHeaderProvider } from '../types'; function isExportRetryable(statusCode: number): boolean { const retryCodes = [429, 502, 503, 504]; @@ -58,11 +58,11 @@ export interface FetchTransportParameters { } /** - * An implementation of IExporterTransport that can be used in the Edge Runtime. + * An implementation of IExporterTransport. * * @internal */ -export class FetchTransportEdge implements IExporterTransport { +export class FetchTransport implements IExporterTransport { constructor(private parameters: FetchTransportParameters) {} async send(data: Uint8Array, timeoutMillis: number): Promise { diff --git a/packages/telemetry/src/logging/logger-provider.ts b/packages/telemetry/src/logging/logger-provider.ts index 006997fb56b..24a626e11a9 100644 --- a/packages/telemetry/src/logging/logger-provider.ts +++ b/packages/telemetry/src/logging/logger-provider.ts @@ -29,8 +29,8 @@ import { OTLPExporterBase, createOtlpNetworkExportDelegate } from '@opentelemetry/otlp-exporter-base'; -import { FetchTransportEdge } from './fetch-transport.edge'; -import { DynamicHeaderProvider } from '../public-types'; +import { FetchTransport } from './fetch-transport'; +import { DynamicHeaderProvider } from '../types'; /** * Create a logger provider for the current execution environment. @@ -60,7 +60,7 @@ export function createLoggerProvider( }); } -/** OTLP exporter that uses custom FetchTransportEdge. */ +/** OTLP exporter that uses custom FetchTransport. */ class OTLPLogExporter extends OTLPExporterBase implements LogRecordExporter @@ -77,7 +77,7 @@ class OTLPLogExporter compression: 'none' }, JsonLogsSerializer, - new FetchTransportEdge({ + new FetchTransport({ url: config.url!, headers: () => ({ 'Content-Type': 'application/json' diff --git a/packages/telemetry/src/public-types.ts b/packages/telemetry/src/public-types.ts index a19c2fb04fa..852c72221fd 100644 --- a/packages/telemetry/src/public-types.ts +++ b/packages/telemetry/src/public-types.ts @@ -47,20 +47,3 @@ export interface TelemetryOptions { */ endpointUrl?: string; } - -/** - * An interface for classes that provide dynamic headers. - * - * Classes that implement this interface can be used to supply custom headers for logging. - * - * @public - */ -export interface DynamicHeaderProvider { - /** - * Returns a record of headers to be added to a request. - * - * @returns A {@link Promise} that resolves to a {@link Record} of header - * key-value pairs, or null if no headers are to be added. - */ - getHeader(): Promise | null>; -} diff --git a/packages/telemetry/src/types.ts b/packages/telemetry/src/types.ts new file mode 100644 index 00000000000..f1041e5dbc9 --- /dev/null +++ b/packages/telemetry/src/types.ts @@ -0,0 +1,33 @@ +/** + * @license + * Copyright 2025 Google 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. + */ + +/** + * An interface for classes that provide dynamic headers. + * + * Classes that implement this interface can be used to supply custom headers for logging. + * + * @internal + */ +export interface DynamicHeaderProvider { + /** + * Returns a record of headers to be added to a request. + * + * @returns A {@link Promise} that resolves to a {@link Record} of header + * key-value pairs, or null if no headers are to be added. + */ + getHeader(): Promise | null>; +} From 10fa5b631c4b0a3e71e122457ccbbf6be594d45a Mon Sep 17 00:00:00 2001 From: alighaznavi Date: Fri, 10 Oct 2025 15:56:59 +0000 Subject: [PATCH 3/5] Fix typo in comment --- packages/telemetry/src/logging/appcheck-provider.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/telemetry/src/logging/appcheck-provider.ts b/packages/telemetry/src/logging/appcheck-provider.ts index 655b55bcfd2..e2e0b199ebb 100644 --- a/packages/telemetry/src/logging/appcheck-provider.ts +++ b/packages/telemetry/src/logging/appcheck-provider.ts @@ -47,7 +47,7 @@ export class AppCheckProvider implements DynamicHeaderProvider { const appCheckToken = await this.appCheck.getToken(); // The error field must be checked as when there is an error, the token field is populated with - // a dummy error. + // a dummy token. if (!appCheckToken || !!appCheckToken.error) { return null; } From 97888a25312cbbf9e8719ff36b5f0df8d81230bc Mon Sep 17 00:00:00 2001 From: alighaznavi Date: Tue, 14 Oct 2025 15:41:53 +0000 Subject: [PATCH 4/5] Use the Headers object for better typing --- .../telemetry/src/logging/appcheck-provider.ts | 6 +++--- .../telemetry/src/logging/fetch-transport.test.ts | 14 +++++++------- packages/telemetry/src/logging/fetch-transport.ts | 6 +++--- packages/telemetry/src/logging/logger-provider.ts | 2 +- packages/telemetry/src/types.ts | 9 ++++++++- 5 files changed, 22 insertions(+), 15 deletions(-) diff --git a/packages/telemetry/src/logging/appcheck-provider.ts b/packages/telemetry/src/logging/appcheck-provider.ts index e2e0b199ebb..a0a7e78d501 100644 --- a/packages/telemetry/src/logging/appcheck-provider.ts +++ b/packages/telemetry/src/logging/appcheck-provider.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { DynamicHeaderProvider } from '../types'; +import { DynamicHeaderProvider, HttpHeader } from '../types'; import { Provider } from '@firebase/component'; import { FirebaseAppCheckInternal, @@ -40,7 +40,7 @@ export class AppCheckProvider implements DynamicHeaderProvider { } } - async getHeader(): Promise | null> { + async getHeader(): Promise { if (!this.appCheck) { return null; } @@ -52,6 +52,6 @@ export class AppCheckProvider implements DynamicHeaderProvider { return null; } - return { 'X-Firebase-AppCheck': appCheckToken.token }; + return ['X-Firebase-AppCheck', appCheckToken.token]; } } diff --git a/packages/telemetry/src/logging/fetch-transport.test.ts b/packages/telemetry/src/logging/fetch-transport.test.ts index a3ae5501a7e..d13b6ed9534 100644 --- a/packages/telemetry/src/logging/fetch-transport.test.ts +++ b/packages/telemetry/src/logging/fetch-transport.test.ts @@ -30,7 +30,7 @@ import { const testTransportParameters = { url: 'http://example.test', - headers: () => ({ + headers: new Headers({ foo: 'foo-value', bar: 'bar-value', 'Content-Type': 'application/json' @@ -68,11 +68,11 @@ describe('FetchTransport', () => { testTransportParameters.url, { method: 'POST', - headers: { + headers: new Headers({ foo: 'foo-value', bar: 'bar-value', 'Content-Type': 'application/json' - }, + }), body: testPayload } ); @@ -182,7 +182,7 @@ describe('FetchTransport', () => { .resolves(new Response('test response', { status: 200 })); const dynamicProvider: DynamicHeaderProvider = { - getHeader: sinon.stub().resolves({ 'dynamic-header': 'dynamic-value' }) + getHeader: sinon.stub().resolves(['dynamic-header', 'dynamic-value']) }; const transport = new FetchTransport({ @@ -200,12 +200,12 @@ describe('FetchTransport', () => { testTransportParameters.url, { method: 'POST', - headers: { + headers: new Headers({ foo: 'foo-value', bar: 'bar-value', 'Content-Type': 'application/json', 'dynamic-header': 'dynamic-value' - }, + }), body: testPayload } ); @@ -241,7 +241,7 @@ describe('FetchTransport', () => { testTransportParameters.url, { method: 'POST', - headers: testTransportParameters.headers(), + headers: testTransportParameters.headers, body: testPayload } ); diff --git a/packages/telemetry/src/logging/fetch-transport.ts b/packages/telemetry/src/logging/fetch-transport.ts index ad5a4b253a7..f27a9fc90d4 100644 --- a/packages/telemetry/src/logging/fetch-transport.ts +++ b/packages/telemetry/src/logging/fetch-transport.ts @@ -53,7 +53,7 @@ function parseRetryAfterToMills( /** @internal */ export interface FetchTransportParameters { url: string; - headers: () => Record; + headers: Headers; dynamicHeaders?: DynamicHeaderProvider[]; } @@ -70,7 +70,7 @@ export class FetchTransport implements IExporterTransport { const timeout = setTimeout(() => abortController.abort(), timeoutMillis); try { const url = new URL(this.parameters.url); - const headers = this.parameters.headers(); + const headers = this.parameters.headers; if ( this.parameters.dynamicHeaders && @@ -83,7 +83,7 @@ export class FetchTransport implements IExporterTransport { for (const header of resolvedHeaders) { if (header) { - Object.assign(headers, header); + headers.append(...header); } } } diff --git a/packages/telemetry/src/logging/logger-provider.ts b/packages/telemetry/src/logging/logger-provider.ts index 24a626e11a9..cf6a02f22a2 100644 --- a/packages/telemetry/src/logging/logger-provider.ts +++ b/packages/telemetry/src/logging/logger-provider.ts @@ -79,7 +79,7 @@ class OTLPLogExporter JsonLogsSerializer, new FetchTransport({ url: config.url!, - headers: () => ({ + headers: new Headers({ 'Content-Type': 'application/json' }), dynamicHeaders diff --git a/packages/telemetry/src/types.ts b/packages/telemetry/src/types.ts index f1041e5dbc9..95c517148cb 100644 --- a/packages/telemetry/src/types.ts +++ b/packages/telemetry/src/types.ts @@ -15,6 +15,13 @@ * limitations under the License. */ +/** + * A type for HTTP Headers + * + * @internal + */ +export type HttpHeader = [key: string, value: string]; + /** * An interface for classes that provide dynamic headers. * @@ -29,5 +36,5 @@ export interface DynamicHeaderProvider { * @returns A {@link Promise} that resolves to a {@link Record} of header * key-value pairs, or null if no headers are to be added. */ - getHeader(): Promise | null>; + getHeader(): Promise; } From 4c0ebfed56fe777abc9c2741e717f8e849d1adb6 Mon Sep 17 00:00:00 2001 From: alighaznavi Date: Tue, 14 Oct 2025 15:51:12 +0000 Subject: [PATCH 5/5] Revert changes in yarn.lock --- yarn.lock | 31 ++++++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 70c7e806773..e6e4692d51e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -15718,7 +15718,7 @@ string-argv@~0.3.1: resolved "https://registry.npmjs.org/string-argv/-/string-argv-0.3.2.tgz#2b6d0ef24b656274d957d54e0a4bbf6153dc02b6" integrity sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q== -"string-width-cjs@npm:string-width@^4.2.0", "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3: +"string-width-cjs@npm:string-width@^4.2.0": version "4.2.3" resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -15736,6 +15736,15 @@ string-width@^1.0.1, string-width@^1.0.2: is-fullwidth-code-point "^1.0.0" strip-ansi "^3.0.0" +"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3: + version "4.2.3" + resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + string-width@^2.1.1: version "2.1.1" resolved "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" @@ -15799,7 +15808,7 @@ string_decoder@~1.1.1: dependencies: safe-buffer "~5.1.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: +"strip-ansi-cjs@npm:strip-ansi@^6.0.1": version "6.0.1" resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -15820,6 +15829,13 @@ strip-ansi@^4.0.0: dependencies: ansi-regex "^3.0.0" +strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + strip-ansi@^7.0.1: version "7.1.0" resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" @@ -17499,7 +17515,7 @@ workerpool@6.2.0: resolved "https://registry.npmjs.org/workerpool/-/workerpool-6.2.0.tgz#827d93c9ba23ee2019c3ffaff5c27fccea289e8b" integrity sha512-Rsk5qQHJ9eowMH28Jwhe8HEbmdYDX4lwoMWshiCXugjtHqMD9ZbiqSDLxcsfdqsETPzVUtX5s1Z5kStiIM6l4A== -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": version "7.0.0" resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== @@ -17533,6 +17549,15 @@ wrap-ansi@^6.0.1, wrap-ansi@^6.2.0: string-width "^4.1.0" strip-ansi "^6.0.0" +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + wrap-ansi@^8.1.0: version "8.1.0" resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214"