Skip to content

Commit c2d9dd9

Browse files
committed
Otel
1 parent a54470e commit c2d9dd9

34 files changed

Lines changed: 2197 additions & 577 deletions

File tree

apps/sim/app/api/billing/update-cost/route.ts

Lines changed: 23 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { type NextRequest, NextResponse } from 'next/server'
44
import { z } from 'zod'
55
import { recordUsage } from '@/lib/billing/core/usage-log'
66
import { checkAndBillOverageThreshold } from '@/lib/billing/threshold-billing'
7+
import { TraceAttr } from '@/lib/copilot/generated/trace-attributes-v1'
78
import { TraceSpan } from '@/lib/copilot/generated/trace-spans-v1'
89
import { checkInternalApiKey } from '@/lib/copilot/request/http'
910
import { withIncomingGoSpan } from '@/lib/copilot/request/otel'
@@ -59,8 +60,8 @@ async function updateCostInner(
5960
logger.info(`[${requestId}] Update cost request started`)
6061

6162
if (!isBillingEnabled) {
62-
span.setAttribute('billing.outcome', 'billing_disabled')
63-
span.setAttribute('http.status_code', 200)
63+
span.setAttribute(TraceAttr.BillingOutcome, 'billing_disabled')
64+
span.setAttribute(TraceAttr.HttpStatusCode, 200)
6465
return NextResponse.json({
6566
success: true,
6667
message: 'Billing disabled, cost update skipped',
@@ -76,8 +77,8 @@ async function updateCostInner(
7677
const authResult = checkInternalApiKey(req)
7778
if (!authResult.success) {
7879
logger.warn(`[${requestId}] Authentication failed: ${authResult.error}`)
79-
span.setAttribute('billing.outcome', 'auth_failed')
80-
span.setAttribute('http.status_code', 401)
80+
span.setAttribute(TraceAttr.BillingOutcome, 'auth_failed')
81+
span.setAttribute(TraceAttr.HttpStatusCode, 401)
8182
return NextResponse.json(
8283
{
8384
success: false,
@@ -95,8 +96,8 @@ async function updateCostInner(
9596
errors: validation.error.issues,
9697
body,
9798
})
98-
span.setAttribute('billing.outcome', 'invalid_body')
99-
span.setAttribute('http.status_code', 400)
99+
span.setAttribute(TraceAttr.BillingOutcome, 'invalid_body')
100+
span.setAttribute(TraceAttr.HttpStatusCode, 400)
100101
return NextResponse.json(
101102
{
102103
success: false,
@@ -112,14 +113,14 @@ async function updateCostInner(
112113
const isMcp = source === 'mcp_copilot'
113114

114115
span.setAttributes({
115-
'user.id': userId,
116-
'gen_ai.request.model': model,
117-
'billing.source': source,
118-
'billing.cost_usd': cost,
119-
'gen_ai.usage.input_tokens': inputTokens,
120-
'gen_ai.usage.output_tokens': outputTokens,
121-
'billing.is_mcp': isMcp,
122-
...(idempotencyKey ? { 'billing.idempotency_key': idempotencyKey } : {}),
116+
[TraceAttr.UserId]: userId,
117+
[TraceAttr.GenAiRequestModel]: model,
118+
[TraceAttr.BillingSource]: source,
119+
[TraceAttr.BillingCostUsd]: cost,
120+
[TraceAttr.GenAiUsageInputTokens]: inputTokens,
121+
[TraceAttr.GenAiUsageOutputTokens]: outputTokens,
122+
[TraceAttr.BillingIsMcp]: isMcp,
123+
...(idempotencyKey ? { [TraceAttr.BillingIdempotencyKey]: idempotencyKey } : {}),
123124
})
124125

125126
claim = idempotencyKey
@@ -132,8 +133,8 @@ async function updateCostInner(
132133
userId,
133134
source,
134135
})
135-
span.setAttribute('billing.outcome', 'duplicate_idempotency_key')
136-
span.setAttribute('http.status_code', 409)
136+
span.setAttribute(TraceAttr.BillingOutcome, 'duplicate_idempotency_key')
137+
span.setAttribute(TraceAttr.HttpStatusCode, 409)
137138
return NextResponse.json(
138139
{
139140
success: false,
@@ -198,9 +199,9 @@ async function updateCostInner(
198199
cost,
199200
})
200201

201-
span.setAttribute('billing.outcome', 'billed')
202-
span.setAttribute('http.status_code', 200)
203-
span.setAttribute('billing.duration_ms', duration)
202+
span.setAttribute(TraceAttr.BillingOutcome, 'billed')
203+
span.setAttribute(TraceAttr.HttpStatusCode, 200)
204+
span.setAttribute(TraceAttr.BillingDurationMs, duration)
204205
return NextResponse.json({
205206
success: true,
206207
data: {
@@ -235,9 +236,9 @@ async function updateCostInner(
235236
)
236237
}
237238

238-
span.setAttribute('billing.outcome', 'internal_error')
239-
span.setAttribute('http.status_code', 500)
240-
span.setAttribute('billing.duration_ms', duration)
239+
span.setAttribute(TraceAttr.BillingOutcome, 'internal_error')
240+
span.setAttribute(TraceAttr.HttpStatusCode, 500)
241+
span.setAttribute(TraceAttr.BillingDurationMs, duration)
241242
return NextResponse.json(
242243
{
243244
success: false,

apps/sim/app/api/copilot/api-keys/generate/route.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { type NextRequest, NextResponse } from 'next/server'
22
import { z } from 'zod'
33
import { getSession } from '@/lib/auth'
44
import { SIM_AGENT_API_URL } from '@/lib/copilot/constants'
5+
import { TraceAttr } from '@/lib/copilot/generated/trace-attributes-v1'
56
import { fetchGo } from '@/lib/copilot/request/go/fetch'
67
import { env } from '@/lib/core/config/env'
78

@@ -42,7 +43,7 @@ export async function POST(req: NextRequest) {
4243
body: JSON.stringify({ userId, name }),
4344
spanName: 'sim → go /api/validate-key/generate',
4445
operation: 'generate_api_key',
45-
attributes: { 'user.id': userId },
46+
attributes: { [TraceAttr.UserId]: userId },
4647
})
4748

4849
if (!res.ok) {

apps/sim/app/api/copilot/api-keys/route.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { type NextRequest, NextResponse } from 'next/server'
22
import { getSession } from '@/lib/auth'
33
import { SIM_AGENT_API_URL } from '@/lib/copilot/constants'
4+
import { TraceAttr } from '@/lib/copilot/generated/trace-attributes-v1'
45
import { fetchGo } from '@/lib/copilot/request/go/fetch'
56
import { env } from '@/lib/core/config/env'
67

@@ -22,7 +23,7 @@ export async function GET(request: NextRequest) {
2223
body: JSON.stringify({ userId }),
2324
spanName: 'sim → go /api/validate-key/get-api-keys',
2425
operation: 'get_api_keys',
25-
attributes: { 'user.id': userId },
26+
attributes: { [TraceAttr.UserId]: userId },
2627
})
2728

2829
if (!res.ok) {
@@ -79,7 +80,7 @@ export async function DELETE(request: NextRequest) {
7980
body: JSON.stringify({ userId, apiKeyId: id }),
8081
spanName: 'sim → go /api/validate-key/delete',
8182
operation: 'delete_api_key',
82-
attributes: { 'user.id': userId, 'api_key.id': id },
83+
attributes: { [TraceAttr.UserId]: userId, [TraceAttr.ApiKeyId]: id },
8384
})
8485

8586
if (!res.ok) {

apps/sim/app/api/copilot/api-keys/validate/route.ts

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { eq } from 'drizzle-orm'
55
import { type NextRequest, NextResponse } from 'next/server'
66
import { z } from 'zod'
77
import { checkServerSideUsageLimits } from '@/lib/billing/calculations/usage-monitor'
8+
import { TraceAttr } from '@/lib/copilot/generated/trace-attributes-v1'
89
import { TraceSpan } from '@/lib/copilot/generated/trace-spans-v1'
910
import { checkInternalApiKey } from '@/lib/copilot/request/http'
1011
import { withIncomingGoSpan } from '@/lib/copilot/request/otel'
@@ -31,17 +32,17 @@ export async function POST(req: NextRequest) {
3132
try {
3233
const auth = checkInternalApiKey(req)
3334
if (!auth.success) {
34-
span.setAttribute('copilot.validate.outcome', 'internal_auth_failed')
35-
span.setAttribute('http.status_code', 401)
35+
span.setAttribute(TraceAttr.CopilotValidateOutcome, 'internal_auth_failed')
36+
span.setAttribute(TraceAttr.HttpStatusCode, 401)
3637
return new NextResponse(null, { status: 401 })
3738
}
3839

3940
const body = await req.json().catch(() => null)
4041
const validationResult = ValidateApiKeySchema.safeParse(body)
4142
if (!validationResult.success) {
4243
logger.warn('Invalid validation request', { errors: validationResult.error.errors })
43-
span.setAttribute('copilot.validate.outcome', 'invalid_body')
44-
span.setAttribute('http.status_code', 400)
44+
span.setAttribute(TraceAttr.CopilotValidateOutcome, 'invalid_body')
45+
span.setAttribute(TraceAttr.HttpStatusCode, 400)
4546
return NextResponse.json(
4647
{
4748
error: 'userId is required',
@@ -52,22 +53,22 @@ export async function POST(req: NextRequest) {
5253
}
5354

5455
const { userId } = validationResult.data
55-
span.setAttribute('user.id', userId)
56+
span.setAttribute(TraceAttr.UserId, userId)
5657

5758
const [existingUser] = await db.select().from(user).where(eq(user.id, userId)).limit(1)
5859
if (!existingUser) {
5960
logger.warn('[API VALIDATION] userId does not exist', { userId })
60-
span.setAttribute('copilot.validate.outcome', 'user_not_found')
61-
span.setAttribute('http.status_code', 403)
61+
span.setAttribute(TraceAttr.CopilotValidateOutcome, 'user_not_found')
62+
span.setAttribute(TraceAttr.HttpStatusCode, 403)
6263
return NextResponse.json({ error: 'User not found' }, { status: 403 })
6364
}
6465

6566
logger.info('[API VALIDATION] Validating usage limit', { userId })
6667
const { isExceeded, currentUsage, limit } = await checkServerSideUsageLimits(userId)
6768
span.setAttributes({
68-
'billing.usage.current': currentUsage,
69-
'billing.usage.limit': limit,
70-
'billing.usage.exceeded': isExceeded,
69+
[TraceAttr.BillingUsageCurrent]: currentUsage,
70+
[TraceAttr.BillingUsageLimit]: limit,
71+
[TraceAttr.BillingUsageExceeded]: isExceeded,
7172
})
7273

7374
logger.info('[API VALIDATION] Usage limit validated', {
@@ -79,18 +80,18 @@ export async function POST(req: NextRequest) {
7980

8081
if (isExceeded) {
8182
logger.info('[API VALIDATION] Usage exceeded', { userId, currentUsage, limit })
82-
span.setAttribute('copilot.validate.outcome', 'usage_exceeded')
83-
span.setAttribute('http.status_code', 402)
83+
span.setAttribute(TraceAttr.CopilotValidateOutcome, 'usage_exceeded')
84+
span.setAttribute(TraceAttr.HttpStatusCode, 402)
8485
return new NextResponse(null, { status: 402 })
8586
}
8687

87-
span.setAttribute('copilot.validate.outcome', 'ok')
88-
span.setAttribute('http.status_code', 200)
88+
span.setAttribute(TraceAttr.CopilotValidateOutcome, 'ok')
89+
span.setAttribute(TraceAttr.HttpStatusCode, 200)
8990
return new NextResponse(null, { status: 200 })
9091
} catch (error) {
9192
logger.error('Error validating usage limit', { error })
92-
span.setAttribute('copilot.validate.outcome', 'internal_error')
93-
span.setAttribute('http.status_code', 500)
93+
span.setAttribute(TraceAttr.CopilotValidateOutcome, 'internal_error')
94+
span.setAttribute(TraceAttr.HttpStatusCode, 500)
9495
return NextResponse.json({ error: 'Failed to validate usage' }, { status: 500 })
9596
}
9697
}

apps/sim/app/api/copilot/auto-allowed-tools/route.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { createLogger } from '@sim/logger'
22
import { type NextRequest, NextResponse } from 'next/server'
33
import { getSession } from '@/lib/auth'
44
import { SIM_AGENT_API_URL } from '@/lib/copilot/constants'
5+
import { TraceAttr } from '@/lib/copilot/generated/trace-attributes-v1'
56
import { fetchGo } from '@/lib/copilot/request/go/fetch'
67
import { env } from '@/lib/core/config/env'
78

@@ -38,7 +39,7 @@ export async function GET() {
3839
headers: copilotHeaders(),
3940
spanName: 'sim → go /api/tool-preferences/auto-allowed',
4041
operation: 'list_auto_allowed_tools',
41-
attributes: { 'user.id': userId },
42+
attributes: { [TraceAttr.UserId]: userId },
4243
}
4344
)
4445

@@ -79,7 +80,7 @@ export async function POST(request: NextRequest) {
7980
body: JSON.stringify({ userId, toolId: body.toolId }),
8081
spanName: 'sim → go /api/tool-preferences/auto-allowed',
8182
operation: 'add_auto_allowed_tool',
82-
attributes: { 'user.id': userId, 'tool.id': body.toolId },
83+
attributes: { [TraceAttr.UserId]: userId, [TraceAttr.ToolId]: body.toolId },
8384
})
8485

8586
if (!res.ok) {
@@ -124,7 +125,7 @@ export async function DELETE(request: NextRequest) {
124125
headers: copilotHeaders(),
125126
spanName: 'sim → go /api/tool-preferences/auto-allowed',
126127
operation: 'remove_auto_allowed_tool',
127-
attributes: { 'user.id': userId, 'tool.id': toolId },
128+
attributes: { [TraceAttr.UserId]: userId, [TraceAttr.ToolId]: toolId },
128129
}
129130
)
130131

0 commit comments

Comments
 (0)