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:
@@ -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';
|
||||
|
||||
@@ -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
@@ -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 }
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -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,
|
||||
|
||||
@@ -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({
|
||||
|
||||
@@ -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', {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
Reference in New Issue
Block a user