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
129 lines
3.8 KiB
TypeScript
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 }
|