@nextsparkjs/plugin-langchain 0.1.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +41 -0
- package/api/observability/metrics/route.ts +110 -0
- package/api/observability/traces/[traceId]/route.ts +398 -0
- package/api/observability/traces/route.ts +205 -0
- package/api/sessions/route.ts +332 -0
- package/components/observability/CollapsibleJson.tsx +71 -0
- package/components/observability/CompactTimeline.tsx +75 -0
- package/components/observability/ConversationFlow.tsx +271 -0
- package/components/observability/DisabledMessage.tsx +21 -0
- package/components/observability/FiltersPanel.tsx +82 -0
- package/components/observability/ObservabilityDashboard.tsx +230 -0
- package/components/observability/SpansList.tsx +210 -0
- package/components/observability/TraceDetail.tsx +335 -0
- package/components/observability/TraceStatusBadge.tsx +39 -0
- package/components/observability/TracesTable.tsx +97 -0
- package/components/observability/index.ts +7 -0
- package/docs/01-getting-started/01-overview.md +196 -0
- package/docs/01-getting-started/02-installation.md +368 -0
- package/docs/01-getting-started/03-configuration.md +794 -0
- package/docs/02-core-concepts/01-architecture.md +566 -0
- package/docs/02-core-concepts/02-agents.md +597 -0
- package/docs/02-core-concepts/03-tools.md +689 -0
- package/docs/03-orchestration/01-graph-orchestrator.md +809 -0
- package/docs/03-orchestration/02-legacy-react.md +650 -0
- package/docs/04-advanced/01-observability.md +645 -0
- package/docs/04-advanced/02-token-tracking.md +469 -0
- package/docs/04-advanced/03-streaming.md +476 -0
- package/docs/04-advanced/04-guardrails.md +597 -0
- package/docs/05-reference/01-api-reference.md +1403 -0
- package/docs/05-reference/02-customization.md +646 -0
- package/docs/05-reference/03-examples.md +881 -0
- package/docs/index.md +85 -0
- package/hooks/observability/useMetrics.ts +31 -0
- package/hooks/observability/useTraceDetail.ts +48 -0
- package/hooks/observability/useTraces.ts +59 -0
- package/lib/agent-factory.ts +354 -0
- package/lib/agent-helpers.ts +201 -0
- package/lib/db-memory-store.ts +417 -0
- package/lib/graph/index.ts +58 -0
- package/lib/graph/nodes/combiner.ts +399 -0
- package/lib/graph/nodes/router.ts +440 -0
- package/lib/graph/orchestrator-graph.ts +386 -0
- package/lib/graph/prompts/combiner.md +131 -0
- package/lib/graph/prompts/router.md +193 -0
- package/lib/graph/types.ts +365 -0
- package/lib/guardrails.ts +230 -0
- package/lib/index.ts +44 -0
- package/lib/logger.ts +70 -0
- package/lib/memory-store.ts +168 -0
- package/lib/message-serializer.ts +110 -0
- package/lib/prompt-renderer.ts +94 -0
- package/lib/providers.ts +226 -0
- package/lib/streaming.ts +232 -0
- package/lib/token-tracker.ts +298 -0
- package/lib/tools-builder.ts +192 -0
- package/lib/tracer-callbacks.ts +342 -0
- package/lib/tracer.ts +350 -0
- package/migrations/001_langchain_memory.sql +83 -0
- package/migrations/002_token_usage.sql +127 -0
- package/migrations/003_observability.sql +257 -0
- package/package.json +28 -0
- package/plugin.config.ts +170 -0
- package/presets/lib/langchain.config.ts.preset +142 -0
- package/presets/templates/sector7/ai-observability/[traceId]/page.tsx +91 -0
- package/presets/templates/sector7/ai-observability/page.tsx +54 -0
- package/types/langchain.types.ts +274 -0
- package/types/observability.types.ts +270 -0
|
@@ -0,0 +1,645 @@
|
|
|
1
|
+
# Observability & Tracing
|
|
2
|
+
|
|
3
|
+
This guide covers the observability system for LangChain agents, including tracing, metrics, and the debugging dashboard.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
The observability system provides **end-to-end visibility** into AI agent execution:
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
User Request → Trace
|
|
11
|
+
├── Router Span (LLM call)
|
|
12
|
+
├── Task Handler Span (tool call)
|
|
13
|
+
├── Customer Handler Span (tool call)
|
|
14
|
+
└── Combiner Span (LLM call)
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
**Key Features**:
|
|
18
|
+
- **Traces**: Track complete agent invocations
|
|
19
|
+
- **Spans**: Track individual operations within traces
|
|
20
|
+
- **Metrics**: Aggregate performance data
|
|
21
|
+
- **Dashboard**: Visual debugging interface
|
|
22
|
+
- **PII Protection**: Mask sensitive data automatically
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## Architecture
|
|
27
|
+
|
|
28
|
+
### Tracing Flow
|
|
29
|
+
|
|
30
|
+
```
|
|
31
|
+
┌─────────────────────────────────────────────────────────────┐
|
|
32
|
+
│ AGENT INVOCATION │
|
|
33
|
+
│ │
|
|
34
|
+
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
|
|
35
|
+
│ │ LLM │ │ Tool │ │ LLM │ │
|
|
36
|
+
│ │ Call │───►│ Call │───►│ Call │ │
|
|
37
|
+
│ └──────────┘ └──────────┘ └──────────┘ │
|
|
38
|
+
│ │ │ │ │
|
|
39
|
+
│ ▼ ▼ ▼ │
|
|
40
|
+
│ ┌──────────────────────────────────────────────┐ │
|
|
41
|
+
│ │ TRACE RECORD │ │
|
|
42
|
+
│ │ ├─ Span: router (llm) │ │
|
|
43
|
+
│ │ ├─ Span: task_handler (tool) │ │
|
|
44
|
+
│ │ └─ Span: combiner (llm) │ │
|
|
45
|
+
│ └──────────────────────────────────────────────┘ │
|
|
46
|
+
│ │ │
|
|
47
|
+
│ ▼ │
|
|
48
|
+
│ ┌─────────────┐ │
|
|
49
|
+
│ │ DATABASE │ │
|
|
50
|
+
│ │ (RLS) │ │
|
|
51
|
+
│ └─────────────┘ │
|
|
52
|
+
└─────────────────────────────────────────────────────────────┘
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### Database Schema
|
|
56
|
+
|
|
57
|
+
Two tables with full Row-Level Security:
|
|
58
|
+
|
|
59
|
+
**`langchain_traces`** - Main trace records
|
|
60
|
+
|
|
61
|
+
| Column | Type | Description |
|
|
62
|
+
|--------|------|-------------|
|
|
63
|
+
| `traceId` | TEXT | Unique identifier |
|
|
64
|
+
| `userId` | TEXT | User who triggered |
|
|
65
|
+
| `teamId` | TEXT | Team context |
|
|
66
|
+
| `sessionId` | TEXT | Session identifier |
|
|
67
|
+
| `agentName` | TEXT | Agent name |
|
|
68
|
+
| `input` | TEXT | User input (truncated) |
|
|
69
|
+
| `output` | TEXT | Agent output (truncated) |
|
|
70
|
+
| `status` | TEXT | running/success/error |
|
|
71
|
+
| `error` | TEXT | Error message |
|
|
72
|
+
| `durationMs` | INTEGER | Execution time |
|
|
73
|
+
| `inputTokens` | INTEGER | Input token count |
|
|
74
|
+
| `outputTokens` | INTEGER | Output token count |
|
|
75
|
+
| `totalCost` | DECIMAL | Cost in USD |
|
|
76
|
+
| `llmCalls` | INTEGER | Number of LLM calls |
|
|
77
|
+
| `toolCalls` | INTEGER | Number of tool calls |
|
|
78
|
+
| `metadata` | JSONB | Additional data |
|
|
79
|
+
| `tags` | TEXT[] | Filtering tags |
|
|
80
|
+
|
|
81
|
+
**`langchain_spans`** - Individual operations
|
|
82
|
+
|
|
83
|
+
| Column | Type | Description |
|
|
84
|
+
|--------|------|-------------|
|
|
85
|
+
| `spanId` | TEXT | Unique identifier |
|
|
86
|
+
| `traceId` | TEXT | Parent trace |
|
|
87
|
+
| `parentSpanId` | TEXT | Parent span (for nesting) |
|
|
88
|
+
| `name` | TEXT | Span name |
|
|
89
|
+
| `type` | TEXT | llm/tool/chain |
|
|
90
|
+
| `provider` | TEXT | LLM provider |
|
|
91
|
+
| `model` | TEXT | Model name |
|
|
92
|
+
| `toolName` | TEXT | Tool name (if tool) |
|
|
93
|
+
| `input` | JSONB | Span input |
|
|
94
|
+
| `output` | JSONB | Span output |
|
|
95
|
+
| `status` | TEXT | running/success/error |
|
|
96
|
+
| `durationMs` | INTEGER | Span duration |
|
|
97
|
+
| `depth` | INTEGER | Nesting depth |
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
## Configuration
|
|
102
|
+
|
|
103
|
+
Configure in `langchain.config.ts`:
|
|
104
|
+
|
|
105
|
+
```typescript
|
|
106
|
+
export const langchainConfig = {
|
|
107
|
+
observability: {
|
|
108
|
+
enabled: true,
|
|
109
|
+
|
|
110
|
+
retention: {
|
|
111
|
+
traces: 30, // Days to keep traces
|
|
112
|
+
},
|
|
113
|
+
|
|
114
|
+
sampling: {
|
|
115
|
+
rate: 1.0, // 1.0 = 100% of requests
|
|
116
|
+
alwaysTraceErrors: true, // Always trace errors
|
|
117
|
+
},
|
|
118
|
+
|
|
119
|
+
pii: {
|
|
120
|
+
maskInputs: false, // Mask PII in inputs
|
|
121
|
+
maskOutputs: true, // Mask PII in outputs
|
|
122
|
+
truncateAt: 10000, // Max content length
|
|
123
|
+
},
|
|
124
|
+
},
|
|
125
|
+
}
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### Configuration Options
|
|
129
|
+
|
|
130
|
+
| Option | Type | Default | Description |
|
|
131
|
+
|--------|------|---------|-------------|
|
|
132
|
+
| `enabled` | boolean | `true` | Enable/disable tracing |
|
|
133
|
+
| `retention.traces` | number | `30` | Days to keep trace data |
|
|
134
|
+
| `sampling.rate` | number | `1.0` | Sample rate (0.0-1.0) |
|
|
135
|
+
| `sampling.alwaysTraceErrors` | boolean | `true` | Always trace errors |
|
|
136
|
+
| `pii.maskInputs` | boolean | `false` | Mask PII in inputs |
|
|
137
|
+
| `pii.maskOutputs` | boolean | `true` | Mask PII in outputs |
|
|
138
|
+
| `pii.truncateAt` | number | `10000` | Max content length |
|
|
139
|
+
|
|
140
|
+
### Sampling
|
|
141
|
+
|
|
142
|
+
Control how many requests are traced:
|
|
143
|
+
|
|
144
|
+
```typescript
|
|
145
|
+
// Development: trace everything
|
|
146
|
+
sampling: { rate: 1.0, alwaysTraceErrors: true }
|
|
147
|
+
|
|
148
|
+
// Production: trace 10% + all errors
|
|
149
|
+
sampling: { rate: 0.1, alwaysTraceErrors: true }
|
|
150
|
+
|
|
151
|
+
// High traffic: trace 1% + errors
|
|
152
|
+
sampling: { rate: 0.01, alwaysTraceErrors: true }
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
---
|
|
156
|
+
|
|
157
|
+
## Tracer Service
|
|
158
|
+
|
|
159
|
+
### Basic Usage
|
|
160
|
+
|
|
161
|
+
```typescript
|
|
162
|
+
import { tracer } from '@/contents/plugins/langchain/lib/tracer'
|
|
163
|
+
|
|
164
|
+
// Start a trace
|
|
165
|
+
const traceContext = await tracer.startTrace(
|
|
166
|
+
{ userId, teamId },
|
|
167
|
+
'orchestrator',
|
|
168
|
+
userMessage,
|
|
169
|
+
{ sessionId, metadata: { source: 'chat' } }
|
|
170
|
+
)
|
|
171
|
+
|
|
172
|
+
try {
|
|
173
|
+
// Your agent logic here
|
|
174
|
+
const result = await processMessage(userMessage)
|
|
175
|
+
|
|
176
|
+
// End trace with success
|
|
177
|
+
await tracer.endTrace(
|
|
178
|
+
{ userId, teamId },
|
|
179
|
+
traceContext.traceId,
|
|
180
|
+
{
|
|
181
|
+
output: result.content,
|
|
182
|
+
tokens: { input: 100, output: 50, total: 150 },
|
|
183
|
+
cost: 0.002,
|
|
184
|
+
llmCalls: 2,
|
|
185
|
+
toolCalls: 1,
|
|
186
|
+
}
|
|
187
|
+
)
|
|
188
|
+
} catch (error) {
|
|
189
|
+
// End trace with error
|
|
190
|
+
await tracer.endTrace(
|
|
191
|
+
{ userId, teamId },
|
|
192
|
+
traceContext.traceId,
|
|
193
|
+
{ error }
|
|
194
|
+
)
|
|
195
|
+
}
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
### Spans
|
|
199
|
+
|
|
200
|
+
Track individual operations within a trace:
|
|
201
|
+
|
|
202
|
+
```typescript
|
|
203
|
+
// Start a span
|
|
204
|
+
const spanContext = await tracer.startSpan(
|
|
205
|
+
{ userId, teamId },
|
|
206
|
+
traceId,
|
|
207
|
+
{
|
|
208
|
+
name: 'router',
|
|
209
|
+
type: 'llm',
|
|
210
|
+
provider: 'anthropic',
|
|
211
|
+
model: 'claude-3-haiku',
|
|
212
|
+
input: { message: userInput },
|
|
213
|
+
}
|
|
214
|
+
)
|
|
215
|
+
|
|
216
|
+
try {
|
|
217
|
+
const result = await routerNode(state)
|
|
218
|
+
|
|
219
|
+
// End span with success
|
|
220
|
+
await tracer.endSpan(
|
|
221
|
+
{ userId, teamId },
|
|
222
|
+
traceId,
|
|
223
|
+
spanContext.spanId,
|
|
224
|
+
{
|
|
225
|
+
output: { intents: result.intents },
|
|
226
|
+
tokens: { input: 50, output: 20 },
|
|
227
|
+
}
|
|
228
|
+
)
|
|
229
|
+
} catch (error) {
|
|
230
|
+
await tracer.endSpan(
|
|
231
|
+
{ userId, teamId },
|
|
232
|
+
traceId,
|
|
233
|
+
spanContext.spanId,
|
|
234
|
+
{ error }
|
|
235
|
+
)
|
|
236
|
+
}
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
### Span Types
|
|
240
|
+
|
|
241
|
+
| Type | Description | Example |
|
|
242
|
+
|------|-------------|---------|
|
|
243
|
+
| `llm` | LLM call | Router, Combiner |
|
|
244
|
+
| `tool` | Tool invocation | TaskHandler, CustomerHandler |
|
|
245
|
+
| `chain` | Chain/workflow | Graph execution |
|
|
246
|
+
| `retriever` | RAG retrieval | Vector search |
|
|
247
|
+
|
|
248
|
+
---
|
|
249
|
+
|
|
250
|
+
## API Endpoints
|
|
251
|
+
|
|
252
|
+
All endpoints require **superadmin** authentication.
|
|
253
|
+
|
|
254
|
+
### List Traces
|
|
255
|
+
|
|
256
|
+
```
|
|
257
|
+
GET /api/v1/theme/default/observability/traces
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
**Query Parameters**:
|
|
261
|
+
- `limit` - Results per page (default: 50)
|
|
262
|
+
- `offset` - Pagination offset
|
|
263
|
+
- `status` - Filter by status (success/error)
|
|
264
|
+
- `agentName` - Filter by agent
|
|
265
|
+
- `teamId` - Filter by team
|
|
266
|
+
- `from` - Start date (ISO)
|
|
267
|
+
- `to` - End date (ISO)
|
|
268
|
+
|
|
269
|
+
**Response**:
|
|
270
|
+
```json
|
|
271
|
+
{
|
|
272
|
+
"success": true,
|
|
273
|
+
"data": {
|
|
274
|
+
"traces": [
|
|
275
|
+
{
|
|
276
|
+
"traceId": "abc-123",
|
|
277
|
+
"agentName": "orchestrator",
|
|
278
|
+
"status": "success",
|
|
279
|
+
"durationMs": 2340,
|
|
280
|
+
"inputTokens": 150,
|
|
281
|
+
"outputTokens": 80,
|
|
282
|
+
"totalCost": 0.002,
|
|
283
|
+
"llmCalls": 2,
|
|
284
|
+
"toolCalls": 1,
|
|
285
|
+
"startedAt": "2024-12-23T10:00:00Z"
|
|
286
|
+
}
|
|
287
|
+
],
|
|
288
|
+
"total": 156,
|
|
289
|
+
"hasMore": true
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
### Get Trace Detail
|
|
295
|
+
|
|
296
|
+
```
|
|
297
|
+
GET /api/v1/theme/default/observability/traces/[traceId]
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
**Response**:
|
|
301
|
+
```json
|
|
302
|
+
{
|
|
303
|
+
"success": true,
|
|
304
|
+
"data": {
|
|
305
|
+
"trace": {
|
|
306
|
+
"traceId": "abc-123",
|
|
307
|
+
"input": "Show my tasks",
|
|
308
|
+
"output": "Found 3 tasks...",
|
|
309
|
+
"status": "success",
|
|
310
|
+
"durationMs": 2340,
|
|
311
|
+
"spans": [
|
|
312
|
+
{
|
|
313
|
+
"spanId": "span-1",
|
|
314
|
+
"name": "router",
|
|
315
|
+
"type": "llm",
|
|
316
|
+
"provider": "anthropic",
|
|
317
|
+
"model": "claude-3-haiku",
|
|
318
|
+
"durationMs": 1200,
|
|
319
|
+
"status": "success"
|
|
320
|
+
},
|
|
321
|
+
{
|
|
322
|
+
"spanId": "span-2",
|
|
323
|
+
"name": "task_handler",
|
|
324
|
+
"type": "tool",
|
|
325
|
+
"durationMs": 340,
|
|
326
|
+
"status": "success"
|
|
327
|
+
}
|
|
328
|
+
]
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
### Get Metrics
|
|
335
|
+
|
|
336
|
+
```
|
|
337
|
+
GET /api/v1/theme/default/observability/metrics
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
**Query Parameters**:
|
|
341
|
+
- `period` - Time period: `1h`, `24h`, `7d`, `30d`
|
|
342
|
+
|
|
343
|
+
**Response**:
|
|
344
|
+
```json
|
|
345
|
+
{
|
|
346
|
+
"success": true,
|
|
347
|
+
"data": {
|
|
348
|
+
"summary": {
|
|
349
|
+
"totalTraces": 1500,
|
|
350
|
+
"successRate": 98.5,
|
|
351
|
+
"avgLatencyMs": 2340,
|
|
352
|
+
"totalCost": 15.23,
|
|
353
|
+
"totalLlmCalls": 2800,
|
|
354
|
+
"totalToolCalls": 1200
|
|
355
|
+
},
|
|
356
|
+
"byAgent": [
|
|
357
|
+
{
|
|
358
|
+
"agentName": "orchestrator",
|
|
359
|
+
"count": 1500,
|
|
360
|
+
"successRate": 98.5,
|
|
361
|
+
"avgLatencyMs": 2340
|
|
362
|
+
}
|
|
363
|
+
],
|
|
364
|
+
"byStatus": {
|
|
365
|
+
"success": 1478,
|
|
366
|
+
"error": 22
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
---
|
|
373
|
+
|
|
374
|
+
## Dashboard
|
|
375
|
+
|
|
376
|
+
The observability dashboard is available at:
|
|
377
|
+
|
|
378
|
+
```
|
|
379
|
+
/sector7/ai-observability
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
> **Note**: This is a superadmin-only page in the Sector7 protected zone.
|
|
383
|
+
|
|
384
|
+
### Features
|
|
385
|
+
|
|
386
|
+
1. **Traces Table**
|
|
387
|
+
- Paginated list of all traces
|
|
388
|
+
- Filter by status, agent, date range
|
|
389
|
+
- Click to view details
|
|
390
|
+
|
|
391
|
+
2. **Trace Detail**
|
|
392
|
+
- Full trace timeline
|
|
393
|
+
- All spans with durations
|
|
394
|
+
- Input/output inspection
|
|
395
|
+
- Error details
|
|
396
|
+
|
|
397
|
+
3. **Metrics Overview**
|
|
398
|
+
- Total traces
|
|
399
|
+
- Success rate
|
|
400
|
+
- Average latency
|
|
401
|
+
- Cost tracking
|
|
402
|
+
|
|
403
|
+
### Components
|
|
404
|
+
|
|
405
|
+
| Component | Purpose |
|
|
406
|
+
|-----------|---------|
|
|
407
|
+
| `ObservabilityDashboard` | Main dashboard container |
|
|
408
|
+
| `TracesTable` | Paginated trace list |
|
|
409
|
+
| `TraceDetail` | Single trace view |
|
|
410
|
+
| `SpansList` | Span timeline |
|
|
411
|
+
| `FiltersPanel` | Filter controls |
|
|
412
|
+
| `TraceStatusBadge` | Status indicator |
|
|
413
|
+
|
|
414
|
+
---
|
|
415
|
+
|
|
416
|
+
## React Hooks
|
|
417
|
+
|
|
418
|
+
### useTraces
|
|
419
|
+
|
|
420
|
+
Fetch paginated trace list:
|
|
421
|
+
|
|
422
|
+
```typescript
|
|
423
|
+
import { useTraces } from '@/contents/plugins/langchain/hooks/observability'
|
|
424
|
+
|
|
425
|
+
function TracesList() {
|
|
426
|
+
const { data, isLoading, error } = useTraces({
|
|
427
|
+
status: 'error',
|
|
428
|
+
agentName: 'orchestrator',
|
|
429
|
+
limit: 20,
|
|
430
|
+
})
|
|
431
|
+
|
|
432
|
+
if (isLoading) return <Loading />
|
|
433
|
+
if (error) return <Error />
|
|
434
|
+
|
|
435
|
+
return (
|
|
436
|
+
<table>
|
|
437
|
+
{data.traces.map(trace => (
|
|
438
|
+
<TraceRow key={trace.traceId} trace={trace} />
|
|
439
|
+
))}
|
|
440
|
+
</table>
|
|
441
|
+
)
|
|
442
|
+
}
|
|
443
|
+
```
|
|
444
|
+
|
|
445
|
+
### useTraceDetail
|
|
446
|
+
|
|
447
|
+
Fetch single trace with spans:
|
|
448
|
+
|
|
449
|
+
```typescript
|
|
450
|
+
import { useTraceDetail } from '@/contents/plugins/langchain/hooks/observability'
|
|
451
|
+
|
|
452
|
+
function TraceView({ traceId }) {
|
|
453
|
+
const { data, isLoading } = useTraceDetail(traceId)
|
|
454
|
+
|
|
455
|
+
if (isLoading) return <Loading />
|
|
456
|
+
|
|
457
|
+
return (
|
|
458
|
+
<div>
|
|
459
|
+
<h2>{data.trace.agentName}</h2>
|
|
460
|
+
<pre>{data.trace.input}</pre>
|
|
461
|
+
<SpanTimeline spans={data.trace.spans} />
|
|
462
|
+
</div>
|
|
463
|
+
)
|
|
464
|
+
}
|
|
465
|
+
```
|
|
466
|
+
|
|
467
|
+
### useMetrics
|
|
468
|
+
|
|
469
|
+
Fetch aggregate metrics:
|
|
470
|
+
|
|
471
|
+
```typescript
|
|
472
|
+
import { useMetrics } from '@/contents/plugins/langchain/hooks/observability'
|
|
473
|
+
|
|
474
|
+
function MetricsDashboard() {
|
|
475
|
+
const { data } = useMetrics({ period: '24h' })
|
|
476
|
+
|
|
477
|
+
return (
|
|
478
|
+
<div>
|
|
479
|
+
<Stat label="Total Traces" value={data.summary.totalTraces} />
|
|
480
|
+
<Stat label="Success Rate" value={`${data.summary.successRate}%`} />
|
|
481
|
+
<Stat label="Avg Latency" value={`${data.summary.avgLatencyMs}ms`} />
|
|
482
|
+
</div>
|
|
483
|
+
)
|
|
484
|
+
}
|
|
485
|
+
```
|
|
486
|
+
|
|
487
|
+
---
|
|
488
|
+
|
|
489
|
+
## PII Protection
|
|
490
|
+
|
|
491
|
+
### Automatic Masking
|
|
492
|
+
|
|
493
|
+
When enabled, the tracer masks common PII patterns:
|
|
494
|
+
|
|
495
|
+
| Pattern | Example | Masked |
|
|
496
|
+
|---------|---------|--------|
|
|
497
|
+
| Email | john@example.com | [EMAIL] |
|
|
498
|
+
| Phone | +1 (555) 123-4567 | [PHONE] |
|
|
499
|
+
| Credit Card | 1234-5678-9012-3456 | [CARD] |
|
|
500
|
+
| SSN | 123-45-6789 | [SSN] |
|
|
501
|
+
|
|
502
|
+
### Configuration
|
|
503
|
+
|
|
504
|
+
```typescript
|
|
505
|
+
pii: {
|
|
506
|
+
maskInputs: false, // Don't mask inputs (for debugging)
|
|
507
|
+
maskOutputs: true, // Mask PII in outputs
|
|
508
|
+
truncateAt: 10000, // Truncate long content
|
|
509
|
+
}
|
|
510
|
+
```
|
|
511
|
+
|
|
512
|
+
### Content Truncation
|
|
513
|
+
|
|
514
|
+
Long content is automatically truncated:
|
|
515
|
+
|
|
516
|
+
```
|
|
517
|
+
Original: "Very long message..." (15000 chars)
|
|
518
|
+
Stored: "Very long message..." (10000 chars) + "[truncated]"
|
|
519
|
+
```
|
|
520
|
+
|
|
521
|
+
---
|
|
522
|
+
|
|
523
|
+
## Integration with Graph Orchestrator
|
|
524
|
+
|
|
525
|
+
The graph orchestrator automatically tracks traces and spans:
|
|
526
|
+
|
|
527
|
+
```typescript
|
|
528
|
+
// In orchestrator.ts
|
|
529
|
+
const traceContext = await tracer.startTrace(
|
|
530
|
+
{ userId: context.userId, teamId: context.teamId },
|
|
531
|
+
'graph-orchestrator',
|
|
532
|
+
message,
|
|
533
|
+
{ sessionId }
|
|
534
|
+
)
|
|
535
|
+
|
|
536
|
+
const result = await invokeOrchestrator(
|
|
537
|
+
message,
|
|
538
|
+
sessionId,
|
|
539
|
+
context,
|
|
540
|
+
history,
|
|
541
|
+
{ traceId: traceContext?.traceId }
|
|
542
|
+
)
|
|
543
|
+
|
|
544
|
+
// Router node creates spans automatically
|
|
545
|
+
// Handler nodes create spans automatically
|
|
546
|
+
// Combiner node creates spans automatically
|
|
547
|
+
|
|
548
|
+
await tracer.endTrace(
|
|
549
|
+
{ userId, teamId },
|
|
550
|
+
traceContext.traceId,
|
|
551
|
+
{
|
|
552
|
+
output: result.finalResponse,
|
|
553
|
+
llmCalls: 2,
|
|
554
|
+
toolCalls: result.completedHandlers.length,
|
|
555
|
+
}
|
|
556
|
+
)
|
|
557
|
+
```
|
|
558
|
+
|
|
559
|
+
---
|
|
560
|
+
|
|
561
|
+
## Best Practices
|
|
562
|
+
|
|
563
|
+
### 1. Use Meaningful Span Names
|
|
564
|
+
|
|
565
|
+
```typescript
|
|
566
|
+
// Good
|
|
567
|
+
{ name: 'router', type: 'llm' }
|
|
568
|
+
{ name: 'task_handler', type: 'tool' }
|
|
569
|
+
|
|
570
|
+
// Bad
|
|
571
|
+
{ name: 'step1', type: 'llm' }
|
|
572
|
+
{ name: 'process', type: 'tool' }
|
|
573
|
+
```
|
|
574
|
+
|
|
575
|
+
### 2. Include Provider/Model Info
|
|
576
|
+
|
|
577
|
+
```typescript
|
|
578
|
+
await tracer.startSpan(context, traceId, {
|
|
579
|
+
name: 'router',
|
|
580
|
+
type: 'llm',
|
|
581
|
+
provider: 'anthropic', // Include this
|
|
582
|
+
model: 'claude-3-haiku', // Include this
|
|
583
|
+
})
|
|
584
|
+
```
|
|
585
|
+
|
|
586
|
+
### 3. Always End Traces
|
|
587
|
+
|
|
588
|
+
```typescript
|
|
589
|
+
try {
|
|
590
|
+
// Logic
|
|
591
|
+
await tracer.endTrace(ctx, traceId, { output })
|
|
592
|
+
} catch (error) {
|
|
593
|
+
await tracer.endTrace(ctx, traceId, { error }) // Always end
|
|
594
|
+
throw error
|
|
595
|
+
}
|
|
596
|
+
```
|
|
597
|
+
|
|
598
|
+
### 4. Use Tags for Filtering
|
|
599
|
+
|
|
600
|
+
```typescript
|
|
601
|
+
await tracer.startTrace(context, agent, input, {
|
|
602
|
+
tags: ['production', 'chat', 'high-priority'],
|
|
603
|
+
})
|
|
604
|
+
```
|
|
605
|
+
|
|
606
|
+
### 5. Sample in Production
|
|
607
|
+
|
|
608
|
+
```typescript
|
|
609
|
+
// Production config
|
|
610
|
+
sampling: {
|
|
611
|
+
rate: 0.1, // Only trace 10%
|
|
612
|
+
alwaysTraceErrors: true, // But always trace errors
|
|
613
|
+
}
|
|
614
|
+
```
|
|
615
|
+
|
|
616
|
+
---
|
|
617
|
+
|
|
618
|
+
## Troubleshooting
|
|
619
|
+
|
|
620
|
+
### Traces Not Appearing
|
|
621
|
+
|
|
622
|
+
1. Check `enabled: true` in config
|
|
623
|
+
2. Verify sampling rate
|
|
624
|
+
3. Check superadmin permissions
|
|
625
|
+
4. Look for console errors
|
|
626
|
+
|
|
627
|
+
### Missing Spans
|
|
628
|
+
|
|
629
|
+
1. Ensure `startSpan` is called before `endSpan`
|
|
630
|
+
2. Check traceId is passed correctly
|
|
631
|
+
3. Verify RLS policies allow insert
|
|
632
|
+
|
|
633
|
+
### High Storage Usage
|
|
634
|
+
|
|
635
|
+
1. Reduce `retention.traces`
|
|
636
|
+
2. Lower `pii.truncateAt`
|
|
637
|
+
3. Reduce `sampling.rate`
|
|
638
|
+
|
|
639
|
+
---
|
|
640
|
+
|
|
641
|
+
## Related Documentation
|
|
642
|
+
|
|
643
|
+
- [Graph Orchestrator](../03-orchestration/01-graph-orchestrator.md) - How tracing integrates with the graph
|
|
644
|
+
- [Token Tracking](./02-token-tracking.md) - Cost and usage tracking
|
|
645
|
+
- [Configuration](../01-getting-started/03-configuration.md) - Full configuration reference
|