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

@@ -9,7 +9,6 @@ import { isEnvTruthy } from '../../utils/envUtils.js';
import { getLastAssistantMessage } from '../../utils/messages.js';
import { getMainLoopModel } from '../../utils/model/model.js';
import { getInitialSettings } from '../../utils/settings/settings.js';
import { logOTelEvent } from '../../utils/telemetry/events.js';
import { submitTranscriptShare, type TranscriptShareTrigger } from './submitTranscriptShare.js';
import type { TranscriptShareResponse } from './TranscriptSharePrompt.js';
import { useSurveyState } from './useSurveyState.js';
@@ -99,11 +98,6 @@ export function useFeedbackSurvey(messages: Message[], isLoading: boolean, submi
last_assistant_message_id: lastAssistantMessageIdRef.current as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS,
survey_type: surveyType as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS
});
void logOTelEvent('feedback_survey', {
event_type: 'appeared',
appearance_id: appearanceId,
survey_type: surveyType
});
}, [updateLastShownTime, surveyType]);
const onSelect = useCallback((appearanceId_0: string, selected: FeedbackSurveyResponse) => {
updateLastShownTime(Date.now(), submitCountRef.current);
@@ -114,12 +108,6 @@ export function useFeedbackSurvey(messages: Message[], isLoading: boolean, submi
last_assistant_message_id: lastAssistantMessageIdRef.current as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS,
survey_type: surveyType as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS
});
void logOTelEvent('feedback_survey', {
event_type: 'responded',
appearance_id: appearanceId_0,
response: selected,
survey_type: surveyType
});
}, [updateLastShownTime, surveyType]);
const shouldShowTranscriptPrompt = useCallback((selected_0: FeedbackSurveyResponse) => {
// Only bad and good ratings trigger the transcript ask
@@ -150,11 +138,6 @@ export function useFeedbackSurvey(messages: Message[], isLoading: boolean, submi
survey_type: surveyType as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS,
trigger: trigger as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS
});
void logOTelEvent('feedback_survey', {
event_type: 'transcript_prompt_appeared',
appearance_id: appearanceId_1,
survey_type: surveyType
});
}, [surveyType]);
const onTranscriptSelect = useCallback(async (appearanceId_2: string, selected_1: TranscriptShareResponse, surveyResponse_0: FeedbackSurveyResponse | null): Promise<boolean> => {
const trigger_0: TranscriptShareTrigger = surveyResponse_0 === 'good' ? 'good_feedback_survey' : 'bad_feedback_survey';

View File

@@ -10,7 +10,6 @@ import { getGlobalConfig, saveGlobalConfig } from '../../utils/config.js';
import { isEnvTruthy } from '../../utils/envUtils.js';
import { isAutoManagedMemoryFile } from '../../utils/memoryFileDetection.js';
import { extractTextContent, getLastAssistantMessage } from '../../utils/messages.js';
import { logOTelEvent } from '../../utils/telemetry/events.js';
import { submitTranscriptShare } from './submitTranscriptShare.js';
import type { TranscriptShareResponse } from './TranscriptSharePrompt.js';
import { useSurveyState } from './useSurveyState.js';
@@ -67,11 +66,6 @@ export function useMemorySurvey(messages: Message[], isLoading: boolean, hasActi
event_type: 'appeared' as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS,
appearance_id: appearanceId as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS
});
void logOTelEvent('feedback_survey', {
event_type: 'appeared',
appearance_id: appearanceId,
survey_type: 'memory'
});
}, []);
const onSelect = useCallback((appearanceId_0: string, selected: FeedbackSurveyResponse) => {
logEvent(MEMORY_SURVEY_EVENT, {
@@ -79,12 +73,6 @@ export function useMemorySurvey(messages: Message[], isLoading: boolean, hasActi
appearance_id: appearanceId_0 as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS,
response: selected as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS
});
void logOTelEvent('feedback_survey', {
event_type: 'responded',
appearance_id: appearanceId_0,
response: selected,
survey_type: 'memory'
});
}, []);
const shouldShowTranscriptPrompt = useCallback((selected_0: FeedbackSurveyResponse) => {
if ("external" !== 'ant') {
@@ -107,11 +95,6 @@ export function useMemorySurvey(messages: Message[], isLoading: boolean, hasActi
appearance_id: appearanceId_1 as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS,
trigger: TRANSCRIPT_SHARE_TRIGGER as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS
});
void logOTelEvent('feedback_survey', {
event_type: 'transcript_prompt_appeared',
appearance_id: appearanceId_1,
survey_type: 'memory'
});
}, []);
const onTranscriptSelect = useCallback(async (appearanceId_2: string, selected_1: TranscriptShareResponse): Promise<boolean> => {
logEvent(MEMORY_SURVEY_EVENT, {

File diff suppressed because one or more lines are too long

View File

@@ -1,6 +1,6 @@
// Centralized analytics/telemetry logging for tool permission decisions.
// All permission approve/reject events flow through logPermissionDecision(),
// which fans out to Statsig analytics, OTel telemetry, and code-edit metrics.
// which fans out to analytics compatibility calls and code-edit metrics.
import { feature } from 'bun:bundle'
import {
type AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS,
@@ -11,7 +11,6 @@ import { getCodeEditToolDecisionCounter } from '../../bootstrap/state.js'
import type { Tool as ToolType, ToolUseContext } from '../../Tool.js'
import { getLanguageName } from '../../utils/cliHighlight.js'
import { SandboxManager } from '../../utils/sandbox/sandbox-adapter.js'
import { logOTelEvent } from '../../utils/telemetry/events.js'
import type {
PermissionApprovalSource,
PermissionRejectionSource,
@@ -227,11 +226,6 @@ function logPermissionDecision(
timestamp: Date.now(),
})
void logOTelEvent('tool_decision', {
decision,
source: sourceString,
tool_name: sanitizeToolNameForAnalytics(tool.name),
})
}
export { isCodeEditingTool, buildCodeEditToolAttributes, logPermissionDecision }

View File

@@ -22,7 +22,6 @@ import { logError } from 'src/utils/log.js'
import { getAPIProviderForStatsig } from 'src/utils/model/providers.js'
import type { PermissionMode } from 'src/utils/permissions/PermissionMode.js'
import { jsonStringify } from 'src/utils/slowOperations.js'
import { logOTelEvent } from 'src/utils/telemetry/events.js'
import {
endLLMRequestSpan,
isBetaTracingEnabled,
@@ -364,16 +363,6 @@ export function logAPIError({
...getAnthropicEnvMetadata(),
})
// Log API error event for OTLP
void logOTelEvent('api_error', {
model: model,
error: errStr,
status_code: String(status),
duration_ms: String(durationMs),
attempt: String(attempt),
speed: fastMode ? 'fast' : 'normal',
})
// Pass the span to correctly match responses to requests when beta tracing is enabled
endLLMRequestSpan(llmSpan, {
success: false,
@@ -714,18 +703,6 @@ export function logAPISuccessAndDuration({
previousRequestId,
betas,
})
// Log API request event for OTLP
void logOTelEvent('api_request', {
model,
input_tokens: String(usage.input_tokens),
output_tokens: String(usage.output_tokens),
cache_read_tokens: String(usage.cache_read_input_tokens),
cache_creation_tokens: String(usage.cache_creation_input_tokens),
cost_usd: String(costUSD),
duration_ms: String(durationMs),
speed: fastMode ? 'fast' : 'normal',
})
// Extract model output, thinking output, and tool call flag when beta tracing is enabled
let modelOutput: string | undefined
let thinkingOutput: string | undefined

View File

@@ -87,7 +87,6 @@ import {
} from '../../utils/sessionActivity.js'
import { jsonStringify } from '../../utils/slowOperations.js'
import { Stream } from '../../utils/stream.js'
import { logOTelEvent } from '../../utils/telemetry/events.js'
import {
addToolContentEvent,
endToolBlockedOnUserSpan,
@@ -945,28 +944,18 @@ async function checkPermissionsAndCallTool(
)
}
// Emit tool_decision OTel event and code-edit counter if the interactive
// permission path didn't already log it (headless mode bypasses permission
// logging, so we need to emit both the generic event and the code-edit
// counter here)
// Increment the code-edit counter here when the interactive permission path
// did not already log a decision (headless mode bypasses permission logging).
if (
permissionDecision.behavior !== 'ask' &&
!toolUseContext.toolDecisions?.has(toolUseID)
) {
const decision =
permissionDecision.behavior === 'allow' ? 'accept' : 'reject'
// Increment code-edit tool decision counter for headless mode
if (isCodeEditingTool(tool.name)) {
const source = decisionReasonToOTelSource(
permissionDecision.decisionReason,
permissionDecision.behavior,
)
void logOTelEvent('tool_decision', {
decision,
source,
tool_name: sanitizeToolNameForAnalytics(tool.name),
})
// Increment code-edit tool decision counter for headless mode
if (isCodeEditingTool(tool.name)) {
void buildCodeEditToolAttributes(
tool,
processedInput,
@@ -1373,27 +1362,10 @@ async function checkPermissionsAndCallTool(
}
}
// Log tool result event for OTLP with tool parameters and decision context
const mcpServerScope = isMcpTool(tool)
? getMcpServerScopeFromToolName(tool.name)
: null
void logOTelEvent('tool_result', {
tool_name: sanitizeToolNameForAnalytics(tool.name),
success: 'true',
duration_ms: String(durationMs),
...(Object.keys(toolParameters).length > 0 && {
tool_parameters: jsonStringify(toolParameters),
}),
...(telemetryToolInput && { tool_input: telemetryToolInput }),
tool_result_size_bytes: String(toolResultSizeBytes),
...(decisionInfo && {
decision_source: decisionInfo.source,
decision_type: decisionInfo.decision,
}),
...(mcpServerScope && { mcp_server_scope: mcpServerScope }),
})
// Run PostToolUse hooks
let toolOutput = result.data
const hookResults = []
@@ -1666,27 +1638,9 @@ async function checkPermissionsAndCallTool(
mcpServerBaseUrl,
),
})
// Log tool result error event for OTLP with tool parameters and decision context
const mcpServerScope = isMcpTool(tool)
? getMcpServerScopeFromToolName(tool.name)
: null
void logOTelEvent('tool_result', {
tool_name: sanitizeToolNameForAnalytics(tool.name),
use_id: toolUseID,
success: 'false',
duration_ms: String(durationMs),
error: errorMessage(error),
...(Object.keys(toolParameters).length > 0 && {
tool_parameters: jsonStringify(toolParameters),
}),
...(telemetryToolInput && { tool_input: telemetryToolInput }),
...(decisionInfo && {
decision_source: decisionInfo.source,
decision_type: decisionInfo.decision,
}),
...(mcpServerScope && { mcp_server_scope: mcpServerScope }),
})
}
const content = formatError(error)

View File

@@ -1,223 +0,0 @@
// Code generated by protoc-gen-ts_proto. DO NOT EDIT.
// versions:
// protoc-gen-ts_proto v2.6.1
// protoc unknown
// source: events_mono/growthbook/v1/growthbook_experiment_event.proto
/* eslint-disable */
import { Timestamp } from '../../../google/protobuf/timestamp.js'
import { PublicApiAuth } from '../../common/v1/auth.js'
/**
* GrowthBook experiment assignment event
* This event tracks when a user is exposed to an experiment variant
* See: https://docs.growthbook.io/guide/bigquery
*/
export interface GrowthbookExperimentEvent {
/** Unique event identifier (for deduplication) */
event_id?: string | undefined
/** When user was exposed to experiment (maps to GrowthBook's timestamp column) */
timestamp?: Date | undefined
/** Experiment tracking key (maps to GrowthBook's experiment_id column) */
experiment_id?: string | undefined
/** Variation index: 0=control, 1+=variants (maps to GrowthBook's variation_id column) */
variation_id?: number | undefined
/** Environment where assignment occurred */
environment?: string | undefined
/** User attributes at time of assignment */
user_attributes?: string | undefined
/** Experiment metadata */
experiment_metadata?: string | undefined
/** Device identifier for the client */
device_id?: string | undefined
/** Authentication context automatically injected by the API */
auth?: PublicApiAuth | undefined
/** Session identifier for tracking user sessions */
session_id?: string | undefined
/** Anonymous identifier for unauthenticated users */
anonymous_id?: string | undefined
/** Event metadata variables (automatically populated by internal-tools-common event_logging library) */
event_metadata_vars?: string | undefined
}
function createBaseGrowthbookExperimentEvent(): GrowthbookExperimentEvent {
return {
event_id: '',
timestamp: undefined,
experiment_id: '',
variation_id: 0,
environment: '',
user_attributes: '',
experiment_metadata: '',
device_id: '',
auth: undefined,
session_id: '',
anonymous_id: '',
event_metadata_vars: '',
}
}
export const GrowthbookExperimentEvent: MessageFns<GrowthbookExperimentEvent> =
{
fromJSON(object: any): GrowthbookExperimentEvent {
return {
event_id: isSet(object.event_id)
? globalThis.String(object.event_id)
: '',
timestamp: isSet(object.timestamp)
? fromJsonTimestamp(object.timestamp)
: undefined,
experiment_id: isSet(object.experiment_id)
? globalThis.String(object.experiment_id)
: '',
variation_id: isSet(object.variation_id)
? globalThis.Number(object.variation_id)
: 0,
environment: isSet(object.environment)
? globalThis.String(object.environment)
: '',
user_attributes: isSet(object.user_attributes)
? globalThis.String(object.user_attributes)
: '',
experiment_metadata: isSet(object.experiment_metadata)
? globalThis.String(object.experiment_metadata)
: '',
device_id: isSet(object.device_id)
? globalThis.String(object.device_id)
: '',
auth: isSet(object.auth)
? PublicApiAuth.fromJSON(object.auth)
: undefined,
session_id: isSet(object.session_id)
? globalThis.String(object.session_id)
: '',
anonymous_id: isSet(object.anonymous_id)
? globalThis.String(object.anonymous_id)
: '',
event_metadata_vars: isSet(object.event_metadata_vars)
? globalThis.String(object.event_metadata_vars)
: '',
}
},
toJSON(message: GrowthbookExperimentEvent): unknown {
const obj: any = {}
if (message.event_id !== undefined) {
obj.event_id = message.event_id
}
if (message.timestamp !== undefined) {
obj.timestamp = message.timestamp.toISOString()
}
if (message.experiment_id !== undefined) {
obj.experiment_id = message.experiment_id
}
if (message.variation_id !== undefined) {
obj.variation_id = Math.round(message.variation_id)
}
if (message.environment !== undefined) {
obj.environment = message.environment
}
if (message.user_attributes !== undefined) {
obj.user_attributes = message.user_attributes
}
if (message.experiment_metadata !== undefined) {
obj.experiment_metadata = message.experiment_metadata
}
if (message.device_id !== undefined) {
obj.device_id = message.device_id
}
if (message.auth !== undefined) {
obj.auth = PublicApiAuth.toJSON(message.auth)
}
if (message.session_id !== undefined) {
obj.session_id = message.session_id
}
if (message.anonymous_id !== undefined) {
obj.anonymous_id = message.anonymous_id
}
if (message.event_metadata_vars !== undefined) {
obj.event_metadata_vars = message.event_metadata_vars
}
return obj
},
create<I extends Exact<DeepPartial<GrowthbookExperimentEvent>, I>>(
base?: I,
): GrowthbookExperimentEvent {
return GrowthbookExperimentEvent.fromPartial(base ?? ({} as any))
},
fromPartial<I extends Exact<DeepPartial<GrowthbookExperimentEvent>, I>>(
object: I,
): GrowthbookExperimentEvent {
const message = createBaseGrowthbookExperimentEvent()
message.event_id = object.event_id ?? ''
message.timestamp = object.timestamp ?? undefined
message.experiment_id = object.experiment_id ?? ''
message.variation_id = object.variation_id ?? 0
message.environment = object.environment ?? ''
message.user_attributes = object.user_attributes ?? ''
message.experiment_metadata = object.experiment_metadata ?? ''
message.device_id = object.device_id ?? ''
message.auth =
object.auth !== undefined && object.auth !== null
? PublicApiAuth.fromPartial(object.auth)
: undefined
message.session_id = object.session_id ?? ''
message.anonymous_id = object.anonymous_id ?? ''
message.event_metadata_vars = object.event_metadata_vars ?? ''
return message
},
}
type Builtin =
| Date
| Function
| Uint8Array
| string
| number
| boolean
| undefined
type DeepPartial<T> = T extends Builtin
? T
: T extends globalThis.Array<infer U>
? globalThis.Array<DeepPartial<U>>
: T extends ReadonlyArray<infer U>
? ReadonlyArray<DeepPartial<U>>
: T extends {}
? { [K in keyof T]?: DeepPartial<T[K]> }
: Partial<T>
type KeysOfUnion<T> = T extends T ? keyof T : never
type Exact<P, I extends P> = P extends Builtin
? P
: P & { [K in keyof P]: Exact<P[K], I[K]> } & {
[K in Exclude<keyof I, KeysOfUnion<P>>]: never
}
function fromTimestamp(t: Timestamp): Date {
let millis = (t.seconds || 0) * 1_000
millis += (t.nanos || 0) / 1_000_000
return new globalThis.Date(millis)
}
function fromJsonTimestamp(o: any): Date {
if (o instanceof globalThis.Date) {
return o
} else if (typeof o === 'string') {
return new globalThis.Date(o)
} else {
return fromTimestamp(Timestamp.fromJSON(o))
}
}
function isSet(value: any): boolean {
return value !== null && value !== undefined
}
interface MessageFns<T> {
fromJSON(object: any): T
toJSON(message: T): unknown
create<I extends Exact<DeepPartial<T>, I>>(base?: I): T
fromPartial<I extends Exact<DeepPartial<T>, I>>(object: I): T
}

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,

View File

@@ -40,7 +40,6 @@ import { isRestrictedToPluginOnly, isSourceAdminTrusted } from '../settings/plug
import { parseSlashCommand } from '../slashCommandParsing.js';
import { sleep } from '../sleep.js';
import { recordSkillUsage } from '../suggestions/skillUsageTracking.js';
import { logOTelEvent, redactIfDisabled } from '../telemetry/events.js';
import { buildPluginCommandTelemetryFields } from '../telemetry/pluginTelemetry.js';
import { getAssistantMessageContentLength } from '../tokens.js';
import { createAgentId } from '../uuid.js';
@@ -362,12 +361,6 @@ export async function processSlashCommand(inputString: string, precedingInputBlo
const promptId = randomUUID();
setPromptId(promptId);
logEvent('tengu_input_prompt', {});
// Log user prompt event for OTLP
void logOTelEvent('user_prompt', {
prompt_length: String(inputString.length),
prompt: redactIfDisabled(inputString),
'prompt.id': promptId
});
return {
messages: [createUserMessage({
content: prepareUserContent({

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
}