From b11af342fe4dd9a664491158eef260f4ac8cc810 Mon Sep 17 00:00:00 2001 From: Tianyi Cui <53024+tianyicui@users.noreply.github.com> Date: Wed, 7 Oct 2026 23:25:35 +0800 Subject: [PATCH] fix(telemetry): expose only supported exporter options --- docs/config-catalog.md | 10 +++++---- docs/config-catalog.zh.md | 10 +++++---- .../extensions/tool-cordis/src/api-catalog.ts | 12 ++++++++-- .../session-telemetry-otel/README.i18n.yaml | 4 ++-- .../session/session-telemetry-otel/README.md | 2 +- .../session-telemetry-otel/README.zh.md | 2 +- .../session-telemetry-otel/package.json | 2 -- .../session-telemetry-otel/src/index.ts | 13 ++++++----- packages/telemetry/otel/README.i18n.yaml | 4 ++-- packages/telemetry/otel/README.md | 2 +- packages/telemetry/otel/README.zh.md | 2 +- packages/telemetry/otel/src/event-log.ts | 3 ++- .../telemetry/otel/src/event-transport.ts | 6 ++--- packages/telemetry/otel/src/index.ts | 3 ++- packages/telemetry/otel/src/session-log.ts | 22 +++++++++++-------- packages/telemetry/otel/src/transport.ts | 15 +++++++++++-- .../telemetry/otel/tests/session-log.spec.ts | 15 ++++++++++++- pnpm-lock.yaml | 6 ----- 18 files changed, 84 insertions(+), 49 deletions(-) diff --git a/docs/config-catalog.md b/docs/config-catalog.md index df7b35de77..3fc95a8805 100644 --- a/docs/config-catalog.md +++ b/docs/config-catalog.md @@ -2830,8 +2830,8 @@ export interface Config { ## `@deepseek-ai/dsh-session-telemetry-otel` - `inject`: `sessions` · `otel` -- `refs`: `BatchLogRecordProcessorOptions` (`@opentelemetry/sdk-logs`) · `OTLPExporterNodeConfigBase` (`@opentelemetry/otlp-exporter-base`) -- `source`: [`packages/session/session-telemetry-otel/src/index.ts:87`](../packages/session/session-telemetry-otel/src/index.ts) +- `refs`: [`LogExporterOptions`](../packages/telemetry/otel/src/index.ts) · [`SessionLogProcessorOptions`](../packages/telemetry/otel/src/index.ts) +- `source`: [`packages/session/session-telemetry-otel/src/index.ts:85`](../packages/session/session-telemetry-otel/src/index.ts) ```ts config-catalog /** @@ -2845,16 +2845,18 @@ export interface Config { /** * Explicit SDK HTTP transport settings, including optional routing headers. * Ambient credentials are not inherited. URL is required while uploading. + * Exporter self-observability metering is not supported. */ - exporter?: OTLPExporterNodeConfigBase & { + exporter?: Omit & { /** Full logs endpoint (e.g. `https://collector.example.com/v1/logs`). Required outside `DISABLED`; validated at load. */ url?: string } /** * Count, queue, cadence, and per-request watchdog settings for the byte-bounded * processor. A watchdog warning never releases an unsettled transport slot. + * SDK processor self-observability metering is not supported. */ - processor?: Omit + processor?: SessionLogProcessorOptions /** Maximum time spent awaiting the SDK provider's complete shutdown path. */ shutdownTimeoutMillis?: number /** Uncompressed OTLP request byte limit, at most 4,000,000. */ diff --git a/docs/config-catalog.zh.md b/docs/config-catalog.zh.md index e2b5b5c7f8..fc87a3d753 100644 --- a/docs/config-catalog.zh.md +++ b/docs/config-catalog.zh.md @@ -2832,8 +2832,8 @@ export interface Config { ## `@deepseek-ai/dsh-session-telemetry-otel` - `inject`: `sessions` · `otel` -- `refs`: `BatchLogRecordProcessorOptions` (`@opentelemetry/sdk-logs`) · `OTLPExporterNodeConfigBase` (`@opentelemetry/otlp-exporter-base`) -- `source`: [`packages/session/session-telemetry-otel/src/index.ts:87`](../packages/session/session-telemetry-otel/src/index.ts) +- `refs`: [`LogExporterOptions`](../packages/telemetry/otel/src/index.ts) · [`SessionLogProcessorOptions`](../packages/telemetry/otel/src/index.ts) +- `source`: [`packages/session/session-telemetry-otel/src/index.ts:85`](../packages/session/session-telemetry-otel/src/index.ts) ```ts config-catalog /** @@ -2847,16 +2847,18 @@ export interface Config { /** * Explicit SDK HTTP transport settings, including optional routing headers. * Ambient credentials are not inherited. URL is required while uploading. + * Exporter self-observability metering is not supported. */ - exporter?: OTLPExporterNodeConfigBase & { + exporter?: Omit & { /** Full logs endpoint (e.g. `https://collector.example.com/v1/logs`). Required outside `DISABLED`; validated at load. */ url?: string } /** * Count, queue, cadence, and per-request watchdog settings for the byte-bounded * processor. A watchdog warning never releases an unsettled transport slot. + * SDK processor self-observability metering is not supported. */ - processor?: Omit + processor?: SessionLogProcessorOptions /** Maximum time spent awaiting the SDK provider's complete shutdown path. */ shutdownTimeoutMillis?: number /** Uncompressed OTLP request byte limit, at most 4,000,000. */ diff --git a/packages/extensions/tool-cordis/src/api-catalog.ts b/packages/extensions/tool-cordis/src/api-catalog.ts index c763a74b06..6535d0856e 100644 --- a/packages/extensions/tool-cordis/src/api-catalog.ts +++ b/packages/extensions/tool-cordis/src/api-catalog.ts @@ -5334,7 +5334,7 @@ export const TYPE_API: readonly TypeApiEntry[] = [ }, { name: 'EventLogOptions', - declaration: 'export interface EventLogOptions {\n exporter: SessionLogOptions[\'exporter\'];\n resourceAttributes: Attributes;\n scope: {\n name: string;\n version?: string;\n };\n processor: Omit;\n onFailure: SessionLogOptions[\'onFailure\'];\n}', + declaration: 'export interface EventLogOptions {\n exporter: LogExporterOptions;\n resourceAttributes: Attributes;\n scope: {\n name: string;\n version?: string;\n };\n processor: Omit;\n onFailure: SessionLogOptions[\'onFailure\'];\n}', }, { name: 'EventLogReporter', @@ -5844,6 +5844,10 @@ export const TYPE_API: readonly TypeApiEntry[] = [ name: 'LocalizedText', declaration: 'export type LocalizedText = string | {\n readonly en: string;\n readonly [locale: string]: string;\n};', }, + { + name: 'LogExporterOptions', + declaration: 'export type LogExporterOptions = Omit & {\n url: string;\n};', + }, { name: 'LspHover', declaration: 'export interface LspHover {\n readonly contents: string;\n readonly range?: LspRange;\n}', @@ -6950,7 +6954,11 @@ export const TYPE_API: readonly TypeApiEntry[] = [ }, { name: 'SessionLogOptions', - declaration: 'export interface SessionLogOptions {\n exporter: OTLPExporterNodeConfigBase & {\n url: string;\n };\n processor?: Omit;\n maxRequestBytes?: number;\n scope: {\n name: string;\n version?: string;\n };\n resourceAttributes: Attributes;\n onFailure: (message: string, error?: Error) => void;\n}', + declaration: 'export interface SessionLogOptions {\n exporter: LogExporterOptions;\n processor?: SessionLogProcessorOptions;\n maxRequestBytes?: number;\n scope: {\n name: string;\n version?: string;\n };\n resourceAttributes: Attributes;\n onFailure: (message: string, error?: Error) => void;\n}', + }, + { + name: 'SessionLogProcessorOptions', + declaration: 'export type SessionLogProcessorOptions = Omit;', }, { name: 'SessionLogRecord', diff --git a/packages/session/session-telemetry-otel/README.i18n.yaml b/packages/session/session-telemetry-otel/README.i18n.yaml index 2262216071..e1c2d0763c 100644 --- a/packages/session/session-telemetry-otel/README.i18n.yaml +++ b/packages/session/session-telemetry-otel/README.i18n.yaml @@ -54,8 +54,8 @@ en: 7593cf5d0d2cedd6 zh: f57cc48a1b5cbfa9 /deepseek-ai-dsh-session-telemetry-otel/known-limitations-and-deferred-work: - en: e43087aea7af4c9e - zh: f8b529e2012b4c63 + en: 5d0b88f8256bd782 + zh: 36b8d64645ed6c2e /deepseek-ai-dsh-session-telemetry-otel/known-limitations-and-deferred-work/dev-note: en: e67f633dc6fe7773 zh: 3bb0c20c93f16f98 diff --git a/packages/session/session-telemetry-otel/README.md b/packages/session/session-telemetry-otel/README.md index 818406c6d1..633110b236 100644 --- a/packages/session/session-telemetry-otel/README.md +++ b/packages/session/session-telemetry-otel/README.md @@ -137,7 +137,7 @@ None; the package neither assembles nor sends a provider request. These limits define where SDK behavior governs and where export guarantees end. They are current package constraints. -- **Upstream experimental tree** — `@opentelemetry/sdk-logs` is published from the upstream experimental tree; SDK API churn lands here and only here, while the seam contract does not move. +- **Upstream experimental tree** — `@opentelemetry/sdk-logs` is published from the upstream experimental tree; SDK API churn lands in the [shared OTel plugin](../../telemetry/otel/README.md), while the seam contract does not move. - **Live-collector behavior belongs to the SDK exporter** — authentication, TLS, throttling, and other real OTLP deployment behavior follow the upstream SDK rather than a package-owned compatibility layer. - **Best-effort handoff** — new cold snapshots and a new feedback submission after restart can repeat prefixes; receivers deduplicate by Session id, format version, and event seq. There is no durable outbox, delivery watermark, automatic retry promise, or collector-acceptance guarantee. OTel and the opt-in DeepSeek API path can overlap. Withdrawal exports a deletion event, not remote erasure. diff --git a/packages/session/session-telemetry-otel/README.zh.md b/packages/session/session-telemetry-otel/README.zh.md index f4c663a4c0..5855a8643e 100644 --- a/packages/session/session-telemetry-otel/README.zh.md +++ b/packages/session/session-telemetry-otel/README.zh.md @@ -137,7 +137,7 @@ kind: "package-reference" 这些限制说明 SDK 行为在何处起主导作用、导出保证止于何处。它们是当前包约束。 -- **上游实验性源码树**——`@opentelemetry/sdk-logs` 从上游实验性源码树发布;SDK API 的变动只会落在本包,也仅落在本包,而 seam 约定不动。 +- **上游实验性源码树**——`@opentelemetry/sdk-logs` 从上游实验性源码树发布;SDK API 的变动落在[共享 OTel 插件](../../telemetry/otel/README.zh.md),而 seam 约定不动。 - **真实 collector 行为属于 SDK 导出器**——身份验证、TLS、限流及其他真实 OTLP 部署行为遵循上游 SDK,不由本包自有兼容层处理。 - **尽力交接**——新冷快照以及重启后的新反馈提交可能重复前缀;接收方按 Session id、格式版本和事件 seq 去重。没有持久化 outbox、投递水位、自动重试承诺或采集端接受保证。OTel 与需显式启用的 DeepSeek API 路径可能重叠。撤回导出删除事件,不是远端擦除。 diff --git a/packages/session/session-telemetry-otel/package.json b/packages/session/session-telemetry-otel/package.json index b13f94f961..879c434958 100644 --- a/packages/session/session-telemetry-otel/package.json +++ b/packages/session/session-telemetry-otel/package.json @@ -28,8 +28,6 @@ "license": "MIT", "dependencies": { "@opentelemetry/api-logs": "^0.222.0", - "@opentelemetry/otlp-exporter-base": "^0.222.0", - "@opentelemetry/sdk-logs": "^0.222.0", "@deepseek-ai/schemastery": "workspace:~" }, "peerDependencies": { diff --git a/packages/session/session-telemetry-otel/src/index.ts b/packages/session/session-telemetry-otel/src/index.ts index 6d351a585f..1e5dc258b8 100644 --- a/packages/session/session-telemetry-otel/src/index.ts +++ b/packages/session/session-telemetry-otel/src/index.ts @@ -24,9 +24,7 @@ import { } from '@deepseek-ai/dsh-session-telemetry' import { APP_IDENTITY } from '@deepseek-ai/dsh-llm' import { getOrCreateAnonymousUserId } from '@deepseek-ai/dsh-anonymous-user-id' -import type { SessionLogReporter } from '@deepseek-ai/dsh-otel' -import type { BatchLogRecordProcessorOptions } from '@opentelemetry/sdk-logs' -import type { OTLPExporterNodeConfigBase } from '@opentelemetry/otlp-exporter-base' +import type { LogExporterOptions, SessionLogProcessorOptions, SessionLogReporter } from '@deepseek-ai/dsh-otel' import { SeverityNumber } from '@opentelemetry/api-logs' /** Session-sharing policy selected by {@link Config.mode}. */ @@ -90,16 +88,18 @@ export interface Config { /** * Explicit SDK HTTP transport settings, including optional routing headers. * Ambient credentials are not inherited. URL is required while uploading. + * Exporter self-observability metering is not supported. */ - exporter?: OTLPExporterNodeConfigBase & { + exporter?: Omit & { /** Full logs endpoint (e.g. `https://collector.example.com/v1/logs`). Required outside `DISABLED`; validated at load. */ url?: string } /** * Count, queue, cadence, and per-request watchdog settings for the byte-bounded * processor. A watchdog warning never releases an unsettled transport slot. + * SDK processor self-observability metering is not supported. */ - processor?: Omit + processor?: SessionLogProcessorOptions /** Maximum time spent awaiting the SDK provider's complete shutdown path. */ shutdownTimeoutMillis?: number /** Uncompressed OTLP request byte limit, at most 4,000,000. */ @@ -110,7 +110,8 @@ export interface Config { * Schemastery validator for {@link Config}; cordis runs it before the plugin * starts. The constructor validates endpoint and shutdown requirements; the * reporter validates Session byte and queue limits. SDK transport and - * processor settings retain their upstream types. + * processor settings use the reporter's accepted option types, which exclude + * self-observability metering. */ export const Config: z = z.object({ mode: z.union(Object.values(SessionTelemetryMode)).default(DEFAULT_TELEMETRY_MODE), diff --git a/packages/telemetry/otel/README.i18n.yaml b/packages/telemetry/otel/README.i18n.yaml index 1528a60b0b..92d25cbcbb 100644 --- a/packages/telemetry/otel/README.i18n.yaml +++ b/packages/telemetry/otel/README.i18n.yaml @@ -18,8 +18,8 @@ en: f141a9d909c555d8 zh: e4f5b690ccb1337c /deepseek-ai-dsh-otel/understand-the-implementation: - en: d1b6f8f2b25ea252 - zh: 73d6147bae811ce0 + en: db3709ac9594b0de + zh: 8e5c84967d1eafbb /deepseek-ai-dsh-otel/further-exploration: en: ee17b991de098cc0 zh: f90257e411921f2b diff --git a/packages/telemetry/otel/README.md b/packages/telemetry/otel/README.md index 3b0730da04..d70e961cc2 100644 --- a/packages/telemetry/otel/README.md +++ b/packages/telemetry/otel/README.md @@ -34,7 +34,7 @@ Headers are explicit. The service does not add a channel header or inherit ambie ## Understand the implementation -`src/index.ts` registers the service; `event-log.ts` owns ordinary SDK batching; `session-log.ts` owns byte/count scheduling; `transport.ts` supplies the Session SDK JSON HTTP delegate; `event-transport.ts` uses Got for cancellable ordinary-event HTTP requests and retry waits with SDK serialization and export accounting. No global OTel provider is installed. The Session processor measures each record once, groups conservative sizes, and waits for the SDK concurrency queue to clear after every callback before sending another request. +`src/index.ts` registers the service; `event-log.ts` owns ordinary SDK batching; `session-log.ts` owns byte/count scheduling; `transport.ts` supplies the Session SDK JSON HTTP delegate and owns the shared exporter metrics recorder, which receives no meter provider and records nothing; `event-transport.ts` uses Got for cancellable ordinary-event HTTP requests and retry waits with SDK serialization and export accounting. No global OTel provider is installed; the accepted exporter options exclude the upstream `selfObsMeterProvider`, and the Session processor accepts only the batching fields it implements, so exporter and Session-processor self-observability metrics stay unrecorded. The Session processor measures each record once, groups conservative sizes, and waits for the SDK concurrency queue to clear after every callback before sending another request. Composition tests exercise independent channels and service removal; adapter tests cover dependent-fiber cleanup and feedback authorization. diff --git a/packages/telemetry/otel/README.zh.md b/packages/telemetry/otel/README.zh.md index 74d29f7eaf..200e747a7c 100644 --- a/packages/telemetry/otel/README.zh.md +++ b/packages/telemetry/otel/README.zh.md @@ -34,7 +34,7 @@ Header 显式提供。服务不会附加 channel header,也不继承环境中 ## 理解实现 -`src/index.ts` 注册服务;`event-log.ts` 负责普通事件的 SDK 聚合;`session-log.ts` 负责字节和条数调度;`transport.ts` 提供 Session 的 SDK JSON HTTP delegate;`event-transport.ts` 使用 Got 实现可取消的普通事件 HTTP 请求和重试等待,序列化与导出计数仍由 SDK 负责。不安装全局 OTel provider。Session processor 对每条记录只计量一次,按保守大小组包,并在每次回调后等待 SDK 并发队列清理完成才发送下一请求。 +`src/index.ts` 注册服务;`event-log.ts` 负责普通事件的 SDK 聚合;`session-log.ts` 负责字节和条数调度;`transport.ts` 提供 Session 的 SDK JSON HTTP delegate,并持有共享的 exporter 指标记录器(不接收 meter provider,不记录任何指标);`event-transport.ts` 使用 Got 实现可取消的普通事件 HTTP 请求和重试等待,序列化与导出计数仍由 SDK 负责。不安装全局 OTel provider;接受的 exporter 选项排除上游的 `selfObsMeterProvider`,Session processor 也只接受它实现的聚合字段,因此 exporter 和 Session processor 的自观测指标都不会被记录。Session processor 对每条记录只计量一次,按保守大小组包,并在每次回调后等待 SDK 并发队列清理完成才发送下一请求。 组合测试覆盖独立通道和服务移除;适配器测试覆盖依赖 fiber 清理与反馈授权。 diff --git a/packages/telemetry/otel/src/event-log.ts b/packages/telemetry/otel/src/event-log.ts index e86518eb9b..feb01de458 100644 --- a/packages/telemetry/otel/src/event-log.ts +++ b/packages/telemetry/otel/src/event-log.ts @@ -8,6 +8,7 @@ import { BatchLogRecordProcessor, LoggerProvider } from '@opentelemetry/sdk-logs import type { BatchLogRecordProcessorOptions, LogRecordExporter } from '@opentelemetry/sdk-logs' import type { SessionLogOptions } from './session-log.ts' import { createEventLogExporter } from './event-transport.ts' +import type { LogExporterOptions } from './transport.ts' /** Scalar values accepted by the collector's Arrow attributes map. */ export type OTelEventScalar = string | number | boolean @@ -28,7 +29,7 @@ export interface OTelEventRecord { /** Ordinary-event transport, resource, scope, and count-batching options. */ export interface EventLogOptions { - exporter: SessionLogOptions['exporter'] + exporter: LogExporterOptions resourceAttributes: Attributes scope: { name: string; version?: string } processor: Omit diff --git a/packages/telemetry/otel/src/event-transport.ts b/packages/telemetry/otel/src/event-transport.ts index bc55814f19..74b4ebd134 100644 --- a/packages/telemetry/otel/src/event-transport.ts +++ b/packages/telemetry/otel/src/event-transport.ts @@ -2,10 +2,10 @@ import type { Agent as HttpsAgent } from 'node:https' import { gzipSync } from 'node:zlib' import got from 'got' -import { createOtlpNetworkExportDelegate, OTLPExporterBase, type OTLPExporterNodeConfigBase } from '@opentelemetry/otlp-exporter-base' +import { createOtlpNetworkExportDelegate, OTLPExporterBase } from '@opentelemetry/otlp-exporter-base' import { JsonLogsSerializer } from '@opentelemetry/otlp-transformer' import type { LogRecordExporter } from '@opentelemetry/sdk-logs' -import { createLogExporterMetrics, logTransportOptions } from './transport.ts' +import { createLogExporterMetrics, type LogExporterOptions, logTransportOptions } from './transport.ts' /** * Create a channel-owned exporter whose cancellation releases requests and retry timers. @@ -13,7 +13,7 @@ import { createLogExporterMetrics, logTransportOptions } from './transport.ts' * @param signal - channel cancellation, shared by current and future batch exports. * @returns the SDK exporter; shutdown also destroys its owned HTTP agent. */ -export function createEventLogExporter(options: OTLPExporterNodeConfigBase & { url: string }, signal: AbortSignal): LogRecordExporter { +export function createEventLogExporter(options: LogExporterOptions, signal: AbortSignal): LogRecordExporter { const config = logTransportOptions(options) let agent: ReturnType | undefined const exporter = new OTLPExporterBase(createOtlpNetworkExportDelegate(config, JsonLogsSerializer, createLogExporterMetrics(config.url), { diff --git a/packages/telemetry/otel/src/index.ts b/packages/telemetry/otel/src/index.ts index 607b0c2908..0bf71f9bdf 100644 --- a/packages/telemetry/otel/src/index.ts +++ b/packages/telemetry/otel/src/index.ts @@ -31,4 +31,5 @@ export default class OTel extends Service { } export type { EventLogOptions, OTelEventRecord, OTelEventScalar, EventLogReporter } from './event-log.ts' -export type { SessionLogRecord, SessionLogOptions, SessionLogReporter } from './session-log.ts' +export type { SessionLogProcessorOptions, SessionLogRecord, SessionLogOptions, SessionLogReporter } from './session-log.ts' +export type { LogExporterOptions } from './transport.ts' diff --git a/packages/telemetry/otel/src/session-log.ts b/packages/telemetry/otel/src/session-log.ts index 59ee612d29..81e8b90d53 100644 --- a/packages/telemetry/otel/src/session-log.ts +++ b/packages/telemetry/otel/src/session-log.ts @@ -3,11 +3,10 @@ import type { SessionEvent, SessionId } from '@deepseek-ai/dsh-session' import type { Attributes } from '@opentelemetry/api' import { SeverityNumber } from '@opentelemetry/api-logs' import { ExportResultCode } from '@opentelemetry/core' -import type { OTLPExporterNodeConfigBase } from '@opentelemetry/otlp-exporter-base' import { JsonLogsSerializer } from '@opentelemetry/otlp-transformer' import { resourceFromAttributes } from '@opentelemetry/resources' import { LoggerProvider, type BatchLogRecordProcessorOptions, type LogRecordExporter, type ReadableLogRecord, type LogRecordProcessor } from '@opentelemetry/sdk-logs' -import { createLogExporter } from './transport.ts' +import { createLogExporter, type LogExporterOptions } from './transport.ts' /** Collector request ceiling in uncompressed UTF-8 bytes, including the OTLP envelope. */ export const SESSION_LOG_MAX_REQUEST_BYTES = 4_000_000 @@ -23,15 +22,20 @@ export interface SessionLogRecord { severityNumber?: SeverityNumber } +/** + * Byte and count batching fields implemented by {@link SessionLogProcessor}. + * + * `exporter` belongs to the owning channel, and `selfObsMeterProvider` is + * excluded because this processor implements no self-observability metering. + */ +export type SessionLogProcessorOptions = Omit + /** Session-log transport and byte/count queue settings. */ export interface SessionLogOptions { - /** Explicit destination and SDK transport options. */ - exporter: OTLPExporterNodeConfigBase & { - /** Full HTTP(S) logs destination. */ - url: string - } + /** Explicit destination and SDK transport settings; exporter self-observability metering is not supported. */ + exporter: LogExporterOptions /** Session-only queue settings, independent of product-event aggregation. */ - processor?: Omit + processor?: SessionLogProcessorOptions /** May lower, but never exceed, the collector's 4,000,000-byte limit. */ maxRequestBytes?: number /** Instrumentation scope supplied by the business owner. */ @@ -76,7 +80,7 @@ class SessionLogProcessor implements LogRecordProcessor { constructor( private readonly exporter: LogRecordExporter, private readonly limit: number, - private readonly config: Required>, + private readonly config: Required>, private readonly warn: SessionLogOptions['onFailure'], ) {} diff --git a/packages/telemetry/otel/src/transport.ts b/packages/telemetry/otel/src/transport.ts index 965de9859f..769d3e8e15 100644 --- a/packages/telemetry/otel/src/transport.ts +++ b/packages/telemetry/otel/src/transport.ts @@ -7,12 +7,23 @@ import type { LogRecordExporter, ReadableLogRecord } from '@opentelemetry/sdk-lo /** `otel.component.type` reported by OTLP HTTP log exporter self-observability metrics. */ const OTLP_HTTP_LOG_EXPORTER_COMPONENT_TYPE = 'otlp_http_log_exporter' +/** + * Collector and SDK HTTP settings accepted by this package's log exporters. + * + * `OTLPExporterConfigBase.selfObsMeterProvider` is excluded: every channel here + * passes no meter provider to the exporter metrics recorder, which stays noop. + */ +export type LogExporterOptions = Omit & { + /** Full HTTP(S) logs destination. */ + url: string +} + /** * Create an SDK JSON exporter without inheriting another collector's headers or TLS identity. * @param options - explicit endpoint, headers, agent, and SDK transport settings. * @returns the exporter owned by one independent log pipeline. */ -export function createLogExporter(options: OTLPExporterNodeConfigBase & { url: string }): LogRecordExporter { +export function createLogExporter(options: LogExporterOptions): LogRecordExporter { return new OTLPExporterBase(createOtlpHttpExportDelegate( logTransportOptions(options), JsonLogsSerializer, OTLP_HTTP_LOG_EXPORTER_COMPONENT_TYPE, LogsExporterMetricsHelper, undefined)) } @@ -32,7 +43,7 @@ export function createLogExporterMetrics(url: string): ExporterMetrics[0] { const shared = mergeOtlpSharedConfigurationWithDefaults(options, getSharedConfigurationFromEnvironment('LOGS'), getSharedConfigurationDefaults()) return { diff --git a/packages/telemetry/otel/tests/session-log.spec.ts b/packages/telemetry/otel/tests/session-log.spec.ts index 10299d95e8..d2d9e07a8d 100644 --- a/packages/telemetry/otel/tests/session-log.spec.ts +++ b/packages/telemetry/otel/tests/session-log.spec.ts @@ -5,10 +5,23 @@ import { Agent, createServer, type IncomingHttpHeaders } from 'node:http' import { once } from 'node:events' import { gunzipSync } from 'node:zlib' import { afterEach, beforeEach, expect, it, vi } from 'vitest' +import type { MeterProvider } from '@opentelemetry/api' import { CompressionAlgorithm } from '@opentelemetry/otlp-exporter-base' import { JsonLogsSerializer } from '@opentelemetry/otlp-transformer' import { SessionId, SessionSeq } from '@deepseek-ai/dsh-session' -import { SESSION_LOG_MAX_REQUEST_BYTES, type SessionLogRecord, type SessionLogOptions } from '../src/session-log.ts' +import { SESSION_LOG_MAX_REQUEST_BYTES, type SessionLogProcessorOptions, type SessionLogRecord, type SessionLogOptions } from '../src/session-log.ts' +import type { LogExporterOptions } from '../src/transport.ts' + +/** Type-only probe: accepted channel options exclude SDK self-observability metering. */ +function meteringOptionsAreExcluded(url: string, meterProvider: MeterProvider): void { + // @ts-expect-error -- exporter self-observability metering is not accepted. + const exporter: LogExporterOptions = { url, selfObsMeterProvider: meterProvider } + // @ts-expect-error -- this processor implements no self-observability metering. + const processor: SessionLogProcessorOptions = { selfObsMeterProvider: meterProvider } + void exporter + void processor +} +void meteringOptionsAreExcluded interface Capture { bytes: number diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 25fb9da66c..e7e1abe63a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -12137,12 +12137,6 @@ importers: '@opentelemetry/api-logs': specifier: ^0.222.0 version: 0.222.0 - '@opentelemetry/otlp-exporter-base': - specifier: ^0.222.0 - version: 0.222.0(@opentelemetry/api@1.9.1) - '@opentelemetry/sdk-logs': - specifier: ^0.222.0 - version: 0.222.0(@opentelemetry/api@1.9.1) devDependencies: '@deepseek-ai/cordis': specifier: workspace:~