Strip dead OTel event noise from telemetry compatibility paths

The open build no longer exports OpenTelemetry events, but several user-prompt, tool, hook, API, and survey paths were still constructing and calling a no-op logOTelEvent helper. This removes those dead calls, drops the now-unused helper module, and deletes an unreferenced GrowthBook experiment event artifact so the remaining compatibility layer is less distracting during future audits.

Constraint: Keep the local logEvent and tracing compatibility surfaces untouched where they still structure control flow
Constraint: Avoid touching unrelated bridge and session changes already present in the worktree
Rejected: Remove sessionTracing compatibility entirely | Call surface is still broad and intertwined with non-telemetry control flow
Rejected: Leave no-op OTel event calls in place | They add audit noise without preserving behavior
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Continue treating remaining telemetry-named helpers as removable only when their call sites are proven behavior-free
Tested: bun test src/services/analytics/index.test.ts src/components/FeedbackSurvey/submitTranscriptShare.test.ts
Tested: bun run ./scripts/build.ts
Not-tested: bun x tsc --noEmit (repository has pre-existing unrelated type errors)
This commit is contained in:
2026-04-09 14:01:41 +08:00
parent 2264aea591
commit 523b8c0a4a
11 changed files with 11 additions and 428 deletions

View File

@@ -55,7 +55,6 @@ import {
logEvent,
type AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS,
} from 'src/services/analytics/index.js'
import { logOTelEvent } from './telemetry/events.js'
import { ALLOWED_OFFICIAL_MARKETPLACE_NAMES } from './plugins/schemas.js'
import {
startHookSpan,
@@ -2071,18 +2070,6 @@ async function* executeHooks({
? jsonStringify(getHookDefinitionsForTelemetry(matchingHooks))
: '[]'
// Log hook execution start to OTEL (only for beta tracing)
if (isBetaTracingEnabled()) {
void logOTelEvent('hook_execution_start', {
hook_event: hookEvent,
hook_name: hookName,
num_hooks: String(matchingHooks.length),
managed_only: String(shouldAllowManagedHooksOnly()),
hook_definitions: hookDefinitionsJson,
hook_source: shouldAllowManagedHooksOnly() ? 'policySettings' : 'merged',
})
}
// Start hook span for beta tracing
const hookSpan = startHookSpan(
hookEvent,
@@ -2943,25 +2930,6 @@ async function* executeHooks({
totalDurationMs,
})
// Log hook execution completion to OTEL (only for beta tracing)
if (isBetaTracingEnabled()) {
const hookDefinitionsComplete =
getHookDefinitionsForTelemetry(matchingHooks)
void logOTelEvent('hook_execution_complete', {
hook_event: hookEvent,
hook_name: hookName,
num_hooks: String(matchingHooks.length),
num_success: String(outcomes.success),
num_blocking: String(outcomes.blocking),
num_non_blocking_error: String(outcomes.non_blocking_error),
num_cancelled: String(outcomes.cancelled),
managed_only: String(shouldAllowManagedHooksOnly()),
hook_definitions: jsonStringify(hookDefinitionsComplete),
hook_source: shouldAllowManagedHooksOnly() ? 'policySettings' : 'merged',
})
}
// End hook span for beta tracing
endHookSpan(hookSpan, {
numSuccess: outcomes.success,

File diff suppressed because one or more lines are too long

View File

@@ -9,7 +9,6 @@ import type {
import { logEvent } from '../../services/analytics/index.js'
import type { PermissionMode } from '../../types/permissions.js'
import { createUserMessage } from '../messages.js'
import { logOTelEvent, redactIfDisabled } from '../telemetry/events.js'
import { startInteractionSpan } from '../telemetry/sessionTracing.js'
import {
matchesKeepGoingKeyword,
@@ -37,25 +36,6 @@ export function processTextPrompt(
: input.find(block => block.type === 'text')?.text || ''
startInteractionSpan(userPromptText)
// Emit user_prompt OTEL event for both string (CLI) and array (SDK/VS Code)
// input shapes. Previously gated on `typeof input === 'string'`, so VS Code
// sessions never emitted user_prompt (anthropics/claude-code#33301).
// For array input, use the LAST text block: createUserContent pushes the
// user's message last (after any <ide_selection>/attachment context blocks),
// so .findLast gets the actual prompt. userPromptText (first block) is kept
// unchanged for startInteractionSpan to preserve existing span attributes.
const otelPromptText =
typeof input === 'string'
? input
: input.findLast(block => block.type === 'text')?.text || ''
if (otelPromptText) {
void logOTelEvent('user_prompt', {
prompt_length: String(otelPromptText.length),
prompt: redactIfDisabled(otelPromptText),
'prompt.id': promptId,
})
}
const isNegative = matchesNegativeKeyword(userPromptText)
const isKeepGoing = matchesKeepGoingKeyword(userPromptText)
logEvent('tengu_input_prompt', {

View File

@@ -1,14 +0,0 @@
/**
* OpenTelemetry event egress is disabled in this build.
*/
export function redactIfDisabled(_content: string): string {
return '<REDACTED>'
}
export async function logOTelEvent(
_eventName: string,
_metadata: { [key: string]: string | undefined } = {},
): Promise<void> {
return
}