Files
simstudioai--sim/apps/sim/lib/copilot/request/trace.ts
T
wehub-resource-sync d25d482dc2
Publish CLI Package / publish-npm (push) Waiting to run
Publish Python SDK / publish-pypi (push) Waiting to run
Publish TypeScript SDK / publish-npm (push) Waiting to run
CI / Migrate Dev DB (push) Has been skipped
CI / Detect Version (push) Has been cancelled
CI / Migrate DB (push) Has been cancelled
CI / Build Dev ECR (./docker/app.Dockerfile, ECR_APP) (push) Has been cancelled
CI / Build Dev ECR (./docker/db.Dockerfile, ECR_MIGRATIONS) (push) Has been cancelled
CI / Build Dev ECR (./docker/pii.Dockerfile, ECR_PII) (push) Has been cancelled
CI / Build Dev ECR (./docker/realtime.Dockerfile, ECR_REALTIME) (push) Has been cancelled
CI / Deploy Trigger.dev (Dev) (push) Has been cancelled
CI / Build AMD64 (./docker/app.Dockerfile, ECR_APP, ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Build AMD64 (./docker/db.Dockerfile, ECR_MIGRATIONS, ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Build AMD64 (./docker/pii.Dockerfile, ECR_PII, ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Build AMD64 (./docker/realtime.Dockerfile, ECR_REALTIME, ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/app.Dockerfile, ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/db.Dockerfile, ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/pii.Dockerfile, ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/realtime.Dockerfile, ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Check Docs Changes (push) Has been cancelled
CI / Process Docs (push) Has been cancelled
CI / Create GitHub Release (push) Has been cancelled
CI / Test and Build (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:20:55 +08:00

129 lines
3.8 KiB
TypeScript

import {
type RequestTraceV1CostSummary,
RequestTraceV1Outcome,
type RequestTraceV1SimReport,
type RequestTraceV1Span,
RequestTraceV1SpanSource,
RequestTraceV1SpanStatus,
type RequestTraceV1UsageSummary,
} from '@/lib/copilot/generated/request-trace-v1'
export class TraceCollector {
private readonly spans: RequestTraceV1Span[] = []
private readonly startMs = Date.now()
private goTraceId?: string
private activeSpan?: RequestTraceV1Span
startSpan(
name: string,
kind: string,
attributes?: Record<string, unknown>,
parent?: RequestTraceV1Span
): RequestTraceV1Span {
const startMs = Date.now()
const span: RequestTraceV1Span = {
name,
kind,
startMs,
endMs: startMs,
durationMs: 0,
status: RequestTraceV1SpanStatus.ok,
source: RequestTraceV1SpanSource.sim,
...(parent
? { parentName: parent.name }
: this.activeSpan
? { parentName: this.activeSpan.name }
: {}),
...(attributes && Object.keys(attributes).length > 0 ? { attributes } : {}),
}
this.spans.push(span)
return span
}
endSpan(
span: RequestTraceV1Span,
status: RequestTraceV1SpanStatus | string = RequestTraceV1SpanStatus.ok
): void {
span.endMs = Date.now()
span.durationMs = span.endMs - span.startMs
span.status = status as RequestTraceV1SpanStatus
}
setActiveSpan(span: RequestTraceV1Span | undefined): void {
this.activeSpan = span
}
setGoTraceId(id: string): void {
if (!this.goTraceId && id) {
this.goTraceId = id
}
}
build(params: {
outcome: RequestTraceV1Outcome
simRequestId: string
streamId?: string
chatId?: string
runId?: string
executionId?: string
// Original user prompt, surfaced on the `request_traces.message`
// column at row-insert time so it's queryable from the DB without
// going through Tempo. Sim already has this at chat-POST time; it's
// threaded through here to the trace report so the row is complete
// the moment it's first written instead of waiting on the late
// analytics UPDATE.
userMessage?: string
usage?: {
prompt: number
completion: number
cacheAttemptedRequests?: number
cacheHitRequests?: number
cacheWriteRequests?: number
cacheReadTokens?: number
cacheWriteTokens?: number
cacheSavingsRate?: number
}
cost?: { input: number; output: number; total: number }
}): RequestTraceV1SimReport {
const endMs = Date.now()
const usage: RequestTraceV1UsageSummary | undefined = params.usage
? {
inputTokens: params.usage.prompt,
outputTokens: params.usage.completion,
cacheAttemptedRequests: params.usage.cacheAttemptedRequests ?? 0,
cacheHitRequests: params.usage.cacheHitRequests ?? 0,
cacheWriteRequests: params.usage.cacheWriteRequests ?? 0,
cacheReadTokens: params.usage.cacheReadTokens ?? 0,
cacheWriteTokens: params.usage.cacheWriteTokens ?? 0,
cacheSavingsRate: params.usage.cacheSavingsRate ?? 0,
}
: undefined
const cost: RequestTraceV1CostSummary | undefined = params.cost
? {
rawTotalCost: params.cost.total,
billedTotalCost: params.cost.total,
}
: undefined
return {
simRequestId: params.simRequestId,
goTraceId: this.goTraceId,
streamId: params.streamId,
chatId: params.chatId,
runId: params.runId,
executionId: params.executionId,
...(params.userMessage ? { userMessage: params.userMessage } : {}),
startMs: this.startMs,
endMs,
durationMs: endMs - this.startMs,
outcome: params.outcome,
usage,
cost,
spans: this.spans,
}
}
}
export { RequestTraceV1Outcome, RequestTraceV1SpanStatus }