Files
WeHub Mirror 6bf8bebf51
CI / Test and Build (push) Failing after 1s
CI / Migrate Dev DB (push) Has been skipped
CI / Migrate DB (push) Has been skipped
CodeQL / Analyze actions (push) Has been cancelled
CodeQL / Analyze javascript-typescript (push) Has been cancelled
CI / Detect Version (push) Has been cancelled
CI / Detect Desktop Changes (push) Has been cancelled
CI / Build AMD64 (blacksmith-2vcpu-ubuntu-2404, ./docker/cron.Dockerfile, ubuntu-latest, ghcr.io/simstudioai/cron) (push) Has been cancelled
CI / Build AMD64 (blacksmith-2vcpu-ubuntu-2404, ./docker/db.Dockerfile, ECR_MIGRATIONS, ubuntu-latest, ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Build AMD64 (blacksmith-4vcpu-ubuntu-2404, ./docker/pii.Dockerfile, ECR_PII, ubuntu-latest, ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Build AMD64 (blacksmith-4vcpu-ubuntu-2404, ./docker/realtime.Dockerfile, ECR_REALTIME, ubuntu-latest, ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Build AMD64 (blacksmith-8vcpu-ubuntu-2404, ./docker/app.Dockerfile, ECR_APP, linux-x64-8-core, ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (blacksmith-4vcpu-ubuntu-2404-arm, ./docker/cron.Dockerfile, ubuntu-24.04-arm, ghcr.io/simstudioai/cron) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (blacksmith-4vcpu-ubuntu-2404-arm, ./docker/db.Dockerfile, ubuntu-24.04-arm, ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (blacksmith-4vcpu-ubuntu-2404-arm, ./docker/pii.Dockerfile, ubuntu-24.04-arm, ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (blacksmith-4vcpu-ubuntu-2404-arm, ./docker/realtime.Dockerfile, ubuntu-24.04-arm, ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (blacksmith-8vcpu-ubuntu-2404-arm, ./docker/app.Dockerfile, linux-arm64-8-core, ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Check Docs Changes (push) Has been cancelled
Publish CLI Package / publish-npm (push) Has been cancelled
Publish Python SDK / publish-pypi (push) Has been cancelled
CI / Deploy Trigger.dev (Dev) (push) Has been cancelled
Helm Chart / Lint, test, and validate chart (push) Has been cancelled
Helm Chart / Chart version bumped (push) Has been cancelled
Publish TypeScript SDK / publish-npm (push) Has been cancelled
CI / Build Dev ECR (blacksmith-8vcpu-ubuntu-2404, ./docker/app.Dockerfile, ECR_APP, linux-x64-8-core) (push) Has been cancelled
CI / Promote Images (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/cron) (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 / Build Dev ECR (blacksmith-2vcpu-ubuntu-2404, ./docker/db.Dockerfile, ECR_MIGRATIONS, ubuntu-latest) (push) Has been cancelled
CI / Build Dev ECR (blacksmith-4vcpu-ubuntu-2404, ./docker/pii.Dockerfile, ECR_PII, ubuntu-latest) (push) Has been cancelled
CI / Build Dev ECR (blacksmith-4vcpu-ubuntu-2404, ./docker/realtime.Dockerfile, ECR_REALTIME, ubuntu-latest) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Process Docs (push) Has been cancelled
CI / Create GitHub Release (push) Has been cancelled
CI / Check Desktop Signing Secrets (push) Has been cancelled
CI / Desktop Release (push) Has been cancelled
CI / Create Desktop Prerelease (push) Has been cancelled
CI / Desktop Prerelease Build (push) Has been cancelled
CI / Publish Desktop Prerelease (push) Has been cancelled
CI / Prune Desktop Prereleases (push) Has been cancelled
Helm Chart / Install on kind and run helm test (push) Has been cancelled
WeHub snapshot of cb28d14c6f2c081de7a0d8729a8c816c9adef67a
2026-08-10 11:17:50 +08:00

117 lines
4.9 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// Sim server-side copilot metrics (U17). Sim's MeterProvider is wired in
// instrumentation-node.ts (OTLP → Mimir, 60s) but had no copilot instruments;
// this module is its first consumer. We emit the SAME metric names + label keys
// + histogram bucket boundaries as the Go side (copilot internal/telemetry +
// contracts/metrics_v1.go) so the GoSim union is queryable as one series set
// — e.g. `copilot.tool.duration` split by `tool.executor` (go|client|sim).
//
// Bounded cardinality only: tool.name and gen_ai.agent.name are capped to the
// shared catalogs (else "other"); vfs phase / file-read outcome are bounded
// sets. NEVER a user/chat/request id (those explode Prometheus series).
import { type Counter, type Histogram, metrics } from '@opentelemetry/api'
import { Metric } from '@/lib/copilot/generated/metrics-v1'
import { TOOL_CATALOG } from '@/lib/copilot/generated/tool-catalog-v1'
import { TraceAttr } from '@/lib/copilot/generated/trace-attributes-v1'
// MUST match Go's copilot/internal/telemetry/metrics.go LatencyBucketsMs
// exactly — a histogram_quantile(sum by (le) …) over the GoSim union is only
// valid with identical boundaries. If you change one side, change the other.
const LATENCY_BUCKETS_MS = [
50, 100, 250, 500, 1000, 2000, 5000, 10000, 20000, 30000, 60000, 120000, 300000,
]
// File sizes span KB→tens of MB; a bytes-appropriate bucket set (not latency).
const BYTE_BUCKETS = [1024, 8192, 65536, 262144, 1048576, 4194304, 16777216, 67108864, 268435456]
interface CopilotMeterInstruments {
toolDuration: Histogram
toolCalls: Counter
vfsMaterializeDuration: Histogram
fileReadDuration: Histogram
fileReadBytes: Histogram
}
let cached: CopilotMeterInstruments | undefined
// Lazy init: Turbopack/Next can evaluate this module before the NodeSDK
// installs the real MeterProvider, so resolve instruments on first use (a
// no-op meter before then simply drops records — same pattern as getCopilotTracer).
function instruments(): CopilotMeterInstruments {
if (cached) return cached
const meter = metrics.getMeter('sim-copilot')
cached = {
toolDuration: meter.createHistogram(Metric.CopilotToolDuration, {
unit: 'ms',
advice: { explicitBucketBoundaries: LATENCY_BUCKETS_MS },
}),
toolCalls: meter.createCounter(Metric.CopilotToolCalls),
vfsMaterializeDuration: meter.createHistogram(Metric.CopilotVfsMaterializeDuration, {
unit: 'ms',
advice: { explicitBucketBoundaries: LATENCY_BUCKETS_MS },
}),
fileReadDuration: meter.createHistogram(Metric.CopilotFileReadDuration, {
unit: 'ms',
advice: { explicitBucketBoundaries: LATENCY_BUCKETS_MS },
}),
fileReadBytes: meter.createHistogram(Metric.CopilotFileReadSize, {
unit: 'By',
advice: { explicitBucketBoundaries: BYTE_BUCKETS },
}),
}
return cached
}
// Caps tool.name to the shared catalog (matches Go's cappedToolName): a
// catalog tool keeps its name, everything else (user MCP/custom/unknown)
// collapses to "other" so series count stays finite.
function cappedToolName(name: string): string {
return TOOL_CATALOG[name] ? name : 'other'
}
const REGISTERED_AGENT_IDS = new Set([
'main',
...Object.values(TOOL_CATALOG).flatMap(({ subagentId }) => (subagentId ? [subagentId] : [])),
])
export function normalizeToolAgentId(agentId: string): string {
return REGISTERED_AGENT_IDS.has(agentId) ? agentId : 'other'
}
// recordSimToolMetric emits copilot.tool.calls (+1) and copilot.tool.duration
// for one server-side Sim tool dispatch (executor=sim). outcome is the bounded
// tool outcome (success/error/…). Pure telemetry.
export function recordSimToolMetric(
name: string,
agentId: string,
outcome: string,
durationMs: number
): void {
const { toolDuration, toolCalls } = instruments()
const attrs = {
[TraceAttr.ToolName]: cappedToolName(name),
[TraceAttr.ToolExecutor]: 'sim',
[TraceAttr.ToolOutcome]: outcome,
[TraceAttr.GenAiAgentName]: normalizeToolAgentId(agentId),
}
toolCalls.add(1, attrs)
if (durationMs >= 0) toolDuration.record(durationMs, attrs)
}
// recordVfsMaterialize records VFS materialization time. Call once per phase
// with that phase's duration and once with phase="total" for the whole op, so
// the dashboard can show total + per-phase. phase must be a bounded value.
export function recordVfsMaterialize(phase: string, durationMs: number): void {
if (durationMs < 0) return
instruments().vfsMaterializeDuration.record(durationMs, {
[TraceAttr.CopilotVfsPhase]: phase,
})
}
// recordFileRead records server-side file-read duration + size by outcome.
export function recordFileRead(outcome: string, durationMs: number, bytes: number): void {
const { fileReadDuration, fileReadBytes } = instruments()
const attrs = { [TraceAttr.CopilotVfsReadOutcome]: outcome }
if (durationMs >= 0) fileReadDuration.record(durationMs, attrs)
if (bytes >= 0) fileReadBytes.record(bytes, attrs)
}