@engjts/nexus 0.1.8 → 0.1.9
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/package.json +1 -1
- package/BENCHMARK_REPORT.md +0 -343
- package/documentation/01-getting-started.md +0 -240
- package/documentation/02-context.md +0 -335
- package/documentation/03-routing.md +0 -397
- package/documentation/04-middleware.md +0 -483
- package/documentation/05-validation.md +0 -514
- package/documentation/06-error-handling.md +0 -465
- package/documentation/07-performance.md +0 -364
- package/documentation/08-adapters.md +0 -470
- package/documentation/09-api-reference.md +0 -548
- package/documentation/10-examples.md +0 -582
- package/documentation/11-deployment.md +0 -477
- package/documentation/12-sentry.md +0 -620
- package/documentation/13-sentry-data-storage.md +0 -996
- package/documentation/14-sentry-data-reference.md +0 -457
- package/documentation/15-sentry-summary.md +0 -409
- package/documentation/16-alerts-system.md +0 -745
- package/documentation/17-alert-adapters.md +0 -696
- package/documentation/18-alerts-implementation-summary.md +0 -385
- package/documentation/19-class-based-routing.md +0 -840
- package/documentation/20-websocket-realtime.md +0 -813
- package/documentation/21-cache-system.md +0 -510
- package/documentation/22-job-queue.md +0 -772
- package/documentation/23-sentry-plugin.md +0 -551
- package/documentation/24-testing-utilities.md +0 -1287
- package/documentation/25-api-versioning.md +0 -533
- package/documentation/26-context-store.md +0 -607
- package/documentation/27-dependency-injection.md +0 -329
- package/documentation/28-lifecycle-hooks.md +0 -521
- package/documentation/29-package-structure.md +0 -196
- package/documentation/30-plugin-system.md +0 -414
- package/documentation/31-jwt-authentication.md +0 -597
- package/documentation/32-cli.md +0 -268
- package/documentation/ALERTS-COMPLETE-SUMMARY.md +0 -429
- package/documentation/ALERTS-INDEX.md +0 -330
- package/documentation/ALERTS-QUICK-REFERENCE.md +0 -286
- package/documentation/README.md +0 -178
- package/documentation/index.html +0 -34
- package/modern_framework_paper.md +0 -1870
- package/public/css/style.css +0 -87
- package/public/index.html +0 -34
- package/public/js/app.js +0 -27
- package/src/advanced/cache/InMemoryCacheStore.ts +0 -68
- package/src/advanced/cache/MultiTierCache.ts +0 -194
- package/src/advanced/cache/RedisCacheStore.ts +0 -341
- package/src/advanced/cache/index.ts +0 -5
- package/src/advanced/cache/types.ts +0 -40
- package/src/advanced/graphql/SimpleDataLoader.ts +0 -42
- package/src/advanced/graphql/index.ts +0 -22
- package/src/advanced/graphql/server.ts +0 -252
- package/src/advanced/graphql/types.ts +0 -42
- package/src/advanced/jobs/InMemoryQueueStore.ts +0 -68
- package/src/advanced/jobs/JobQueue.ts +0 -556
- package/src/advanced/jobs/RedisQueueStore.ts +0 -367
- package/src/advanced/jobs/index.ts +0 -5
- package/src/advanced/jobs/types.ts +0 -70
- package/src/advanced/observability/APMManager.ts +0 -163
- package/src/advanced/observability/AlertManager.ts +0 -109
- package/src/advanced/observability/MetricRegistry.ts +0 -151
- package/src/advanced/observability/ObservabilityCenter.ts +0 -304
- package/src/advanced/observability/StructuredLogger.ts +0 -154
- package/src/advanced/observability/TracingManager.ts +0 -117
- package/src/advanced/observability/adapters.ts +0 -304
- package/src/advanced/observability/createObservabilityMiddleware.ts +0 -63
- package/src/advanced/observability/index.ts +0 -11
- package/src/advanced/observability/types.ts +0 -174
- package/src/advanced/playground/extractPathParams.ts +0 -6
- package/src/advanced/playground/generateFieldExample.ts +0 -31
- package/src/advanced/playground/generatePlaygroundHTML.ts +0 -1956
- package/src/advanced/playground/generateSummary.ts +0 -19
- package/src/advanced/playground/getTagFromPath.ts +0 -9
- package/src/advanced/playground/index.ts +0 -8
- package/src/advanced/playground/playground.ts +0 -250
- package/src/advanced/playground/types.ts +0 -49
- package/src/advanced/playground/zodToExample.ts +0 -16
- package/src/advanced/playground/zodToParams.ts +0 -15
- package/src/advanced/postman/buildAuth.ts +0 -31
- package/src/advanced/postman/buildBody.ts +0 -15
- package/src/advanced/postman/buildQueryParams.ts +0 -27
- package/src/advanced/postman/buildRequestItem.ts +0 -36
- package/src/advanced/postman/buildResponses.ts +0 -11
- package/src/advanced/postman/buildUrl.ts +0 -33
- package/src/advanced/postman/capitalize.ts +0 -4
- package/src/advanced/postman/generateCollection.ts +0 -59
- package/src/advanced/postman/generateEnvironment.ts +0 -34
- package/src/advanced/postman/generateExampleFromZod.ts +0 -21
- package/src/advanced/postman/generateFieldExample.ts +0 -45
- package/src/advanced/postman/generateName.ts +0 -20
- package/src/advanced/postman/generateUUID.ts +0 -11
- package/src/advanced/postman/getTagFromPath.ts +0 -10
- package/src/advanced/postman/index.ts +0 -28
- package/src/advanced/postman/postman.ts +0 -156
- package/src/advanced/postman/slugify.ts +0 -7
- package/src/advanced/postman/types.ts +0 -140
- package/src/advanced/realtime/index.ts +0 -18
- package/src/advanced/realtime/websocket.ts +0 -231
- package/src/advanced/sentry/index.ts +0 -1236
- package/src/advanced/sentry/types.ts +0 -355
- package/src/advanced/static/generateDirectoryListing.ts +0 -47
- package/src/advanced/static/generateETag.ts +0 -7
- package/src/advanced/static/getMimeType.ts +0 -9
- package/src/advanced/static/index.ts +0 -32
- package/src/advanced/static/isSafePath.ts +0 -13
- package/src/advanced/static/publicDir.ts +0 -21
- package/src/advanced/static/serveStatic.ts +0 -225
- package/src/advanced/static/spa.ts +0 -24
- package/src/advanced/static/types.ts +0 -159
- package/src/advanced/swagger/SwaggerGenerator.ts +0 -66
- package/src/advanced/swagger/buildOperation.ts +0 -61
- package/src/advanced/swagger/buildParameters.ts +0 -61
- package/src/advanced/swagger/buildRequestBody.ts +0 -21
- package/src/advanced/swagger/buildResponses.ts +0 -54
- package/src/advanced/swagger/capitalize.ts +0 -5
- package/src/advanced/swagger/convertPath.ts +0 -9
- package/src/advanced/swagger/createSwagger.ts +0 -12
- package/src/advanced/swagger/generateOperationId.ts +0 -21
- package/src/advanced/swagger/generateSpec.ts +0 -105
- package/src/advanced/swagger/generateSummary.ts +0 -24
- package/src/advanced/swagger/generateSwaggerUI.ts +0 -70
- package/src/advanced/swagger/generateThemeCss.ts +0 -53
- package/src/advanced/swagger/index.ts +0 -25
- package/src/advanced/swagger/swagger.ts +0 -237
- package/src/advanced/swagger/types.ts +0 -206
- package/src/advanced/swagger/zodFieldToOpenAPI.ts +0 -94
- package/src/advanced/swagger/zodSchemaToOpenAPI.ts +0 -50
- package/src/advanced/swagger/zodToOpenAPI.ts +0 -22
- package/src/advanced/testing/factory.ts +0 -509
- package/src/advanced/testing/harness.ts +0 -612
- package/src/advanced/testing/index.ts +0 -430
- package/src/advanced/testing/load-test.ts +0 -618
- package/src/advanced/testing/mock-server.ts +0 -498
- package/src/advanced/testing/mock.ts +0 -670
- package/src/cli/bin.ts +0 -9
- package/src/cli/cli.ts +0 -158
- package/src/cli/commands/add.ts +0 -178
- package/src/cli/commands/build.ts +0 -73
- package/src/cli/commands/create.ts +0 -166
- package/src/cli/commands/dev.ts +0 -85
- package/src/cli/commands/generate.ts +0 -99
- package/src/cli/commands/help.ts +0 -95
- package/src/cli/commands/init.ts +0 -91
- package/src/cli/commands/version.ts +0 -38
- package/src/cli/index.ts +0 -6
- package/src/cli/templates/generators.ts +0 -359
- package/src/cli/templates/index.ts +0 -680
- package/src/cli/utils/exec.ts +0 -52
- package/src/cli/utils/file-system.ts +0 -78
- package/src/cli/utils/logger.ts +0 -111
- package/src/core/adapter.ts +0 -88
- package/src/core/application.ts +0 -1453
- package/src/core/context-pool.ts +0 -79
- package/src/core/context.ts +0 -856
- package/src/core/index.ts +0 -94
- package/src/core/middleware.ts +0 -272
- package/src/core/performance/buffer-pool.ts +0 -108
- package/src/core/performance/middleware-optimizer.ts +0 -162
- package/src/core/plugin/PluginManager.ts +0 -435
- package/src/core/plugin/builder.ts +0 -358
- package/src/core/plugin/index.ts +0 -50
- package/src/core/plugin/types.ts +0 -214
- package/src/core/router/file-router.ts +0 -623
- package/src/core/router/index.ts +0 -260
- package/src/core/router/radix-tree.ts +0 -242
- package/src/core/serializer.ts +0 -397
- package/src/core/store/index.ts +0 -30
- package/src/core/store/registry.ts +0 -178
- package/src/core/store/request-store.ts +0 -240
- package/src/core/store/types.ts +0 -233
- package/src/core/types.ts +0 -616
- package/src/database/adapter.ts +0 -35
- package/src/database/adapters/index.ts +0 -1
- package/src/database/adapters/mysql.ts +0 -669
- package/src/database/database.ts +0 -70
- package/src/database/dialect.ts +0 -388
- package/src/database/index.ts +0 -12
- package/src/database/migrations.ts +0 -86
- package/src/database/optimizer.ts +0 -125
- package/src/database/query-builder.ts +0 -404
- package/src/database/realtime.ts +0 -53
- package/src/database/schema.ts +0 -71
- package/src/database/transactions.ts +0 -56
- package/src/database/types.ts +0 -87
- package/src/deployment/cluster.ts +0 -471
- package/src/deployment/config.ts +0 -454
- package/src/deployment/docker.ts +0 -599
- package/src/deployment/graceful-shutdown.ts +0 -373
- package/src/deployment/index.ts +0 -56
- package/src/index.ts +0 -281
- package/src/security/adapter.ts +0 -318
- package/src/security/auth/JWTPlugin.ts +0 -234
- package/src/security/auth/JWTProvider.ts +0 -316
- package/src/security/auth/adapter.ts +0 -12
- package/src/security/auth/jwt.ts +0 -234
- package/src/security/auth/middleware.ts +0 -188
- package/src/security/csrf.ts +0 -220
- package/src/security/headers.ts +0 -108
- package/src/security/index.ts +0 -60
- package/src/security/rate-limit/adapter.ts +0 -7
- package/src/security/rate-limit/memory.ts +0 -108
- package/src/security/rate-limit/middleware.ts +0 -181
- package/src/security/sanitization.ts +0 -75
- package/src/security/types.ts +0 -240
- package/src/security/utils.ts +0 -52
- package/tsconfig.json +0 -39
|
@@ -1,620 +0,0 @@
|
|
|
1
|
-
# Sentry Integration Guide
|
|
2
|
-
|
|
3
|
-
Nexus Framework menyediakan integrasi Sentry built-in untuk error tracking dan performance monitoring.
|
|
4
|
-
|
|
5
|
-
## Table of Contents
|
|
6
|
-
|
|
7
|
-
1. [Quick Start](#quick-start)
|
|
8
|
-
2. [Configuration](#configuration)
|
|
9
|
-
3. [Error Tracking](#error-tracking)
|
|
10
|
-
4. [Performance Monitoring](#performance-monitoring)
|
|
11
|
-
5. [Breadcrumbs](#breadcrumbs)
|
|
12
|
-
6. [User Context](#user-context)
|
|
13
|
-
7. [Manual Capture](#manual-capture)
|
|
14
|
-
8. [Advanced Usage](#advanced-usage)
|
|
15
|
-
|
|
16
|
-
---
|
|
17
|
-
|
|
18
|
-
## Quick Start
|
|
19
|
-
|
|
20
|
-
### Installation
|
|
21
|
-
|
|
22
|
-
Sentry sudah built-in di Nexus Framework, tidak perlu install package tambahan!
|
|
23
|
-
|
|
24
|
-
### Basic Setup
|
|
25
|
-
|
|
26
|
-
```typescript
|
|
27
|
-
import { createApp } from 'nexus';
|
|
28
|
-
|
|
29
|
-
const app = createApp();
|
|
30
|
-
|
|
31
|
-
// Enable Sentry with one line
|
|
32
|
-
app.sentry({
|
|
33
|
-
dsn: 'https://your-key@your-org.ingest.sentry.io/project-id'
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
app.get('/', (ctx) => ({ message: 'Hello World' }));
|
|
37
|
-
|
|
38
|
-
app.listen(3000);
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
Itu saja! Semua unhandled errors akan otomatis dilaporkan ke Sentry.
|
|
42
|
-
|
|
43
|
-
---
|
|
44
|
-
|
|
45
|
-
## Configuration
|
|
46
|
-
|
|
47
|
-
### Full Options
|
|
48
|
-
|
|
49
|
-
```typescript
|
|
50
|
-
app.sentry({
|
|
51
|
-
// Required: Sentry DSN
|
|
52
|
-
dsn: process.env.SENTRY_DSN!,
|
|
53
|
-
|
|
54
|
-
// Environment (auto-detected from NODE_ENV)
|
|
55
|
-
environment: 'production',
|
|
56
|
-
|
|
57
|
-
// Release version
|
|
58
|
-
release: '1.0.0',
|
|
59
|
-
|
|
60
|
-
// Server name for identification
|
|
61
|
-
serverName: 'api-server-1',
|
|
62
|
-
|
|
63
|
-
// Sample rate for errors (0.0 - 1.0)
|
|
64
|
-
sampleRate: 1.0, // 100% of errors
|
|
65
|
-
|
|
66
|
-
// Sample rate for performance traces (0.0 - 1.0)
|
|
67
|
-
tracesSampleRate: 0.1, // 10% of requests
|
|
68
|
-
|
|
69
|
-
// Enable performance monitoring
|
|
70
|
-
enableTracing: true,
|
|
71
|
-
|
|
72
|
-
// Maximum breadcrumbs to store
|
|
73
|
-
maxBreadcrumbs: 100,
|
|
74
|
-
|
|
75
|
-
// Debug mode (logs Sentry operations)
|
|
76
|
-
debug: false,
|
|
77
|
-
|
|
78
|
-
// Attach stack traces to all messages
|
|
79
|
-
attachStacktrace: true,
|
|
80
|
-
|
|
81
|
-
// Send PII (email, username, IP)
|
|
82
|
-
sendDefaultPii: false,
|
|
83
|
-
|
|
84
|
-
// Global tags for all events
|
|
85
|
-
tags: {
|
|
86
|
-
app: 'my-api',
|
|
87
|
-
version: '1.0.0'
|
|
88
|
-
},
|
|
89
|
-
|
|
90
|
-
// Global extra data
|
|
91
|
-
extra: {
|
|
92
|
-
team: 'backend'
|
|
93
|
-
},
|
|
94
|
-
|
|
95
|
-
// Paths to ignore
|
|
96
|
-
ignorePaths: ['/health', '/metrics'],
|
|
97
|
-
|
|
98
|
-
// Error messages to ignore
|
|
99
|
-
ignoreErrors: [
|
|
100
|
-
'ValidationError',
|
|
101
|
-
/timeout/i
|
|
102
|
-
],
|
|
103
|
-
|
|
104
|
-
// Request timeout
|
|
105
|
-
timeout: 5000,
|
|
106
|
-
|
|
107
|
-
// Integrations
|
|
108
|
-
integrations: {
|
|
109
|
-
http: true,
|
|
110
|
-
console: false,
|
|
111
|
-
unhandledRejection: true,
|
|
112
|
-
uncaughtException: true
|
|
113
|
-
},
|
|
114
|
-
|
|
115
|
-
// Filter events before sending
|
|
116
|
-
beforeSend: (event, hint) => {
|
|
117
|
-
// Drop events from development
|
|
118
|
-
if (event.environment === 'development') {
|
|
119
|
-
return null;
|
|
120
|
-
}
|
|
121
|
-
// Modify event
|
|
122
|
-
event.tags = { ...event.tags, custom: 'value' };
|
|
123
|
-
return event;
|
|
124
|
-
},
|
|
125
|
-
|
|
126
|
-
// Filter transactions before sending
|
|
127
|
-
beforeSendTransaction: (transaction) => {
|
|
128
|
-
// Drop health check transactions
|
|
129
|
-
if (transaction.name.includes('/health')) {
|
|
130
|
-
return null;
|
|
131
|
-
}
|
|
132
|
-
return transaction;
|
|
133
|
-
}
|
|
134
|
-
}, {
|
|
135
|
-
// Middleware options
|
|
136
|
-
includeRequestBody: false,
|
|
137
|
-
includeHeaders: true,
|
|
138
|
-
excludeHeaders: ['authorization', 'cookie'],
|
|
139
|
-
ignorePaths: ['/health', '/metrics'],
|
|
140
|
-
|
|
141
|
-
// Extract user from context
|
|
142
|
-
extractUser: (ctx) => {
|
|
143
|
-
if (ctx.user) {
|
|
144
|
-
return {
|
|
145
|
-
id: ctx.user.id,
|
|
146
|
-
email: ctx.user.email,
|
|
147
|
-
username: ctx.user.name
|
|
148
|
-
};
|
|
149
|
-
}
|
|
150
|
-
return null;
|
|
151
|
-
},
|
|
152
|
-
|
|
153
|
-
// Custom transaction name
|
|
154
|
-
getTransactionName: (ctx) => `${ctx.method} ${ctx.path}`
|
|
155
|
-
});
|
|
156
|
-
```
|
|
157
|
-
|
|
158
|
-
### Environment Variables
|
|
159
|
-
|
|
160
|
-
```bash
|
|
161
|
-
# .env
|
|
162
|
-
SENTRY_DSN=https://xxx@xxx.ingest.sentry.io/xxx
|
|
163
|
-
SENTRY_ENVIRONMENT=production
|
|
164
|
-
SENTRY_RELEASE=1.0.0
|
|
165
|
-
```
|
|
166
|
-
|
|
167
|
-
```typescript
|
|
168
|
-
app.sentry({
|
|
169
|
-
dsn: process.env.SENTRY_DSN!,
|
|
170
|
-
environment: process.env.SENTRY_ENVIRONMENT,
|
|
171
|
-
release: process.env.SENTRY_RELEASE
|
|
172
|
-
});
|
|
173
|
-
```
|
|
174
|
-
|
|
175
|
-
---
|
|
176
|
-
|
|
177
|
-
## Error Tracking
|
|
178
|
-
|
|
179
|
-
### Automatic Error Capture
|
|
180
|
-
|
|
181
|
-
Semua unhandled errors otomatis dilaporkan:
|
|
182
|
-
|
|
183
|
-
```typescript
|
|
184
|
-
app.get('/api/users/:id', async (ctx) => {
|
|
185
|
-
// If this throws, it's automatically captured
|
|
186
|
-
const user = await db.users.find(ctx.params.id);
|
|
187
|
-
|
|
188
|
-
if (!user) {
|
|
189
|
-
throw new Error('User not found'); // Captured!
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
return user;
|
|
193
|
-
});
|
|
194
|
-
```
|
|
195
|
-
|
|
196
|
-
### Manual Error Capture
|
|
197
|
-
|
|
198
|
-
```typescript
|
|
199
|
-
import { captureException } from 'nexus';
|
|
200
|
-
|
|
201
|
-
app.get('/api/risky', async (ctx) => {
|
|
202
|
-
try {
|
|
203
|
-
await riskyOperation();
|
|
204
|
-
} catch (error) {
|
|
205
|
-
// Capture but don't throw
|
|
206
|
-
captureException(error, {
|
|
207
|
-
level: 'warning',
|
|
208
|
-
tags: { operation: 'risky' },
|
|
209
|
-
extra: { userId: ctx.user?.id }
|
|
210
|
-
});
|
|
211
|
-
|
|
212
|
-
return { status: 'fallback' };
|
|
213
|
-
}
|
|
214
|
-
});
|
|
215
|
-
```
|
|
216
|
-
|
|
217
|
-
### Using Sentry Client Directly
|
|
218
|
-
|
|
219
|
-
```typescript
|
|
220
|
-
const sentry = app.getSentryClient();
|
|
221
|
-
|
|
222
|
-
sentry?.captureException(new Error('Something went wrong'), {
|
|
223
|
-
level: 'error',
|
|
224
|
-
tags: { module: 'payments' },
|
|
225
|
-
extra: { orderId: '12345' },
|
|
226
|
-
user: {
|
|
227
|
-
id: 'user-123',
|
|
228
|
-
email: 'user@example.com'
|
|
229
|
-
}
|
|
230
|
-
});
|
|
231
|
-
```
|
|
232
|
-
|
|
233
|
-
---
|
|
234
|
-
|
|
235
|
-
## Performance Monitoring
|
|
236
|
-
|
|
237
|
-
### Automatic Transaction Tracing
|
|
238
|
-
|
|
239
|
-
Setiap HTTP request otomatis di-trace:
|
|
240
|
-
|
|
241
|
-
```
|
|
242
|
-
Transaction: GET /api/users
|
|
243
|
-
├── Span: database.query (SELECT * FROM users)
|
|
244
|
-
├── Span: http.request (external API call)
|
|
245
|
-
└── Span: serialize.json
|
|
246
|
-
```
|
|
247
|
-
|
|
248
|
-
### Custom Spans
|
|
249
|
-
|
|
250
|
-
```typescript
|
|
251
|
-
import { withSpan } from 'nexus';
|
|
252
|
-
|
|
253
|
-
app.get('/api/data', async (ctx) => {
|
|
254
|
-
// Database query span
|
|
255
|
-
const users = await withSpan(ctx, {
|
|
256
|
-
op: 'db.query',
|
|
257
|
-
description: 'Fetch all users'
|
|
258
|
-
}, async () => {
|
|
259
|
-
return await db.users.findAll();
|
|
260
|
-
});
|
|
261
|
-
|
|
262
|
-
// Processing span
|
|
263
|
-
const processed = await withSpan(ctx, {
|
|
264
|
-
op: 'process',
|
|
265
|
-
description: 'Transform user data'
|
|
266
|
-
}, () => {
|
|
267
|
-
return users.map(transformUser);
|
|
268
|
-
});
|
|
269
|
-
|
|
270
|
-
return processed;
|
|
271
|
-
});
|
|
272
|
-
```
|
|
273
|
-
|
|
274
|
-
### Manual Transactions
|
|
275
|
-
|
|
276
|
-
```typescript
|
|
277
|
-
const sentry = app.getSentryClient();
|
|
278
|
-
|
|
279
|
-
// Start transaction
|
|
280
|
-
const transaction = sentry?.startTransaction({
|
|
281
|
-
name: 'Background Job',
|
|
282
|
-
op: 'job.process'
|
|
283
|
-
});
|
|
284
|
-
|
|
285
|
-
if (transaction) {
|
|
286
|
-
// Create child span
|
|
287
|
-
const span = sentry?.startSpan(transaction, {
|
|
288
|
-
op: 'db.query',
|
|
289
|
-
description: 'Fetch pending jobs'
|
|
290
|
-
});
|
|
291
|
-
|
|
292
|
-
await fetchPendingJobs();
|
|
293
|
-
|
|
294
|
-
sentry?.finishSpan(span!, 'ok');
|
|
295
|
-
|
|
296
|
-
// Finish transaction
|
|
297
|
-
sentry?.finishTransaction(transaction, 'ok');
|
|
298
|
-
}
|
|
299
|
-
```
|
|
300
|
-
|
|
301
|
-
---
|
|
302
|
-
|
|
303
|
-
## Breadcrumbs
|
|
304
|
-
|
|
305
|
-
Breadcrumbs adalah jejak aktivitas yang membantu debug:
|
|
306
|
-
|
|
307
|
-
### Automatic Breadcrumbs
|
|
308
|
-
|
|
309
|
-
HTTP requests otomatis menjadi breadcrumbs:
|
|
310
|
-
|
|
311
|
-
```
|
|
312
|
-
[http.request] GET /api/users
|
|
313
|
-
[http.response] GET /api/users - 200
|
|
314
|
-
[http.request] POST /api/orders
|
|
315
|
-
[error] ValidationError: Invalid email
|
|
316
|
-
```
|
|
317
|
-
|
|
318
|
-
### Manual Breadcrumbs
|
|
319
|
-
|
|
320
|
-
```typescript
|
|
321
|
-
import { addBreadcrumb } from 'nexus';
|
|
322
|
-
|
|
323
|
-
app.post('/api/checkout', async (ctx) => {
|
|
324
|
-
addBreadcrumb({
|
|
325
|
-
type: 'info',
|
|
326
|
-
category: 'checkout',
|
|
327
|
-
message: 'Checkout started',
|
|
328
|
-
data: { cartItems: ctx.body.items.length }
|
|
329
|
-
});
|
|
330
|
-
|
|
331
|
-
const order = await processOrder(ctx.body);
|
|
332
|
-
|
|
333
|
-
addBreadcrumb({
|
|
334
|
-
type: 'info',
|
|
335
|
-
category: 'checkout',
|
|
336
|
-
message: 'Order created',
|
|
337
|
-
data: { orderId: order.id }
|
|
338
|
-
});
|
|
339
|
-
|
|
340
|
-
addBreadcrumb({
|
|
341
|
-
type: 'query',
|
|
342
|
-
category: 'payment',
|
|
343
|
-
message: 'Payment initiated',
|
|
344
|
-
data: { amount: order.total }
|
|
345
|
-
});
|
|
346
|
-
|
|
347
|
-
return order;
|
|
348
|
-
});
|
|
349
|
-
```
|
|
350
|
-
|
|
351
|
-
### Breadcrumb Types
|
|
352
|
-
|
|
353
|
-
```typescript
|
|
354
|
-
addBreadcrumb({
|
|
355
|
-
type: 'default', // General events
|
|
356
|
-
// type: 'http', // HTTP requests
|
|
357
|
-
// type: 'navigation', // Route changes
|
|
358
|
-
// type: 'error', // Errors
|
|
359
|
-
// type: 'debug', // Debug info
|
|
360
|
-
// type: 'query', // Database queries
|
|
361
|
-
// type: 'info', // Informational
|
|
362
|
-
|
|
363
|
-
category: 'custom.category',
|
|
364
|
-
message: 'Description',
|
|
365
|
-
level: 'info', // debug, info, warning, error
|
|
366
|
-
data: { key: 'value' }
|
|
367
|
-
});
|
|
368
|
-
```
|
|
369
|
-
|
|
370
|
-
---
|
|
371
|
-
|
|
372
|
-
## User Context
|
|
373
|
-
|
|
374
|
-
### Set User from Auth Middleware
|
|
375
|
-
|
|
376
|
-
```typescript
|
|
377
|
-
// Auth middleware
|
|
378
|
-
const auth: Middleware = async (ctx, next) => {
|
|
379
|
-
const user = await verifyToken(ctx.headers.authorization);
|
|
380
|
-
ctx.user = user;
|
|
381
|
-
return next(ctx);
|
|
382
|
-
};
|
|
383
|
-
|
|
384
|
-
// Sentry config
|
|
385
|
-
app.sentry({
|
|
386
|
-
dsn: process.env.SENTRY_DSN!
|
|
387
|
-
}, {
|
|
388
|
-
extractUser: (ctx) => {
|
|
389
|
-
if (ctx.user) {
|
|
390
|
-
return {
|
|
391
|
-
id: ctx.user.id,
|
|
392
|
-
email: ctx.user.email,
|
|
393
|
-
username: ctx.user.name,
|
|
394
|
-
subscription: ctx.user.plan // Custom data
|
|
395
|
-
};
|
|
396
|
-
}
|
|
397
|
-
return null;
|
|
398
|
-
}
|
|
399
|
-
});
|
|
400
|
-
```
|
|
401
|
-
|
|
402
|
-
### Manual User Context
|
|
403
|
-
|
|
404
|
-
```typescript
|
|
405
|
-
import { setUser } from 'nexus';
|
|
406
|
-
|
|
407
|
-
// Set user
|
|
408
|
-
setUser({
|
|
409
|
-
id: 'user-123',
|
|
410
|
-
email: 'john@example.com',
|
|
411
|
-
username: 'john_doe',
|
|
412
|
-
ip_address: '{{auto}}' // Auto-detect IP
|
|
413
|
-
});
|
|
414
|
-
|
|
415
|
-
// Clear user (on logout)
|
|
416
|
-
setUser(null);
|
|
417
|
-
```
|
|
418
|
-
|
|
419
|
-
---
|
|
420
|
-
|
|
421
|
-
## Manual Capture
|
|
422
|
-
|
|
423
|
-
### Capture Messages
|
|
424
|
-
|
|
425
|
-
```typescript
|
|
426
|
-
import { captureMessage } from 'nexus';
|
|
427
|
-
|
|
428
|
-
// Info level
|
|
429
|
-
captureMessage('User upgraded to premium', {
|
|
430
|
-
level: 'info',
|
|
431
|
-
tags: { plan: 'premium' },
|
|
432
|
-
user: { id: 'user-123' }
|
|
433
|
-
});
|
|
434
|
-
|
|
435
|
-
// Warning level
|
|
436
|
-
captureMessage('Rate limit approaching', {
|
|
437
|
-
level: 'warning',
|
|
438
|
-
extra: { currentRate: 950, limit: 1000 }
|
|
439
|
-
});
|
|
440
|
-
```
|
|
441
|
-
|
|
442
|
-
### Tags and Extra Data
|
|
443
|
-
|
|
444
|
-
```typescript
|
|
445
|
-
import { setTag, setExtra } from 'nexus';
|
|
446
|
-
|
|
447
|
-
// Set global tags (added to all events)
|
|
448
|
-
setTag('app.version', '2.0.0');
|
|
449
|
-
setTag('deployment.region', 'us-east-1');
|
|
450
|
-
|
|
451
|
-
// Set extra context
|
|
452
|
-
setExtra('config', {
|
|
453
|
-
featureFlags: { newUI: true },
|
|
454
|
-
limits: { maxUpload: '10MB' }
|
|
455
|
-
});
|
|
456
|
-
```
|
|
457
|
-
|
|
458
|
-
---
|
|
459
|
-
|
|
460
|
-
## Advanced Usage
|
|
461
|
-
|
|
462
|
-
### Custom Error Handler
|
|
463
|
-
|
|
464
|
-
```typescript
|
|
465
|
-
import { createSentryErrorHandler } from 'nexus';
|
|
466
|
-
|
|
467
|
-
const app = createApp();
|
|
468
|
-
const sentry = new SentryClient({ dsn: '...' });
|
|
469
|
-
|
|
470
|
-
// Use Sentry error handler
|
|
471
|
-
app.onError(createSentryErrorHandler(sentry));
|
|
472
|
-
```
|
|
473
|
-
|
|
474
|
-
### With Graceful Shutdown
|
|
475
|
-
|
|
476
|
-
```typescript
|
|
477
|
-
app.gracefulShutdown({ timeout: 30000 });
|
|
478
|
-
|
|
479
|
-
app.sentry({
|
|
480
|
-
dsn: process.env.SENTRY_DSN!
|
|
481
|
-
});
|
|
482
|
-
|
|
483
|
-
// Sentry flush is automatically added as shutdown hook!
|
|
484
|
-
```
|
|
485
|
-
|
|
486
|
-
### Filtering Events
|
|
487
|
-
|
|
488
|
-
```typescript
|
|
489
|
-
app.sentry({
|
|
490
|
-
dsn: process.env.SENTRY_DSN!,
|
|
491
|
-
|
|
492
|
-
beforeSend: (event, hint) => {
|
|
493
|
-
const error = hint?.originalException;
|
|
494
|
-
|
|
495
|
-
// Don't send validation errors
|
|
496
|
-
if (error?.name === 'ValidationError') {
|
|
497
|
-
return null;
|
|
498
|
-
}
|
|
499
|
-
|
|
500
|
-
// Don't send 404s
|
|
501
|
-
if (event.tags?.['http.status_code'] === '404') {
|
|
502
|
-
return null;
|
|
503
|
-
}
|
|
504
|
-
|
|
505
|
-
// Scrub sensitive data
|
|
506
|
-
if (event.request?.data?.password) {
|
|
507
|
-
event.request.data.password = '[REDACTED]';
|
|
508
|
-
}
|
|
509
|
-
|
|
510
|
-
// Add custom fingerprint for grouping
|
|
511
|
-
if (error?.message.includes('database')) {
|
|
512
|
-
event.fingerprint = ['database-error'];
|
|
513
|
-
}
|
|
514
|
-
|
|
515
|
-
return event;
|
|
516
|
-
}
|
|
517
|
-
});
|
|
518
|
-
```
|
|
519
|
-
|
|
520
|
-
### Multiple Sentry Projects
|
|
521
|
-
|
|
522
|
-
```typescript
|
|
523
|
-
import { SentryClient } from 'nexus';
|
|
524
|
-
|
|
525
|
-
// Main app errors
|
|
526
|
-
const appSentry = new SentryClient({
|
|
527
|
-
dsn: process.env.SENTRY_DSN_APP!,
|
|
528
|
-
environment: 'production'
|
|
529
|
-
});
|
|
530
|
-
|
|
531
|
-
// Payment errors (separate project)
|
|
532
|
-
const paymentSentry = new SentryClient({
|
|
533
|
-
dsn: process.env.SENTRY_DSN_PAYMENTS!,
|
|
534
|
-
environment: 'production',
|
|
535
|
-
tags: { module: 'payments' }
|
|
536
|
-
});
|
|
537
|
-
|
|
538
|
-
// Use different clients for different modules
|
|
539
|
-
app.post('/api/payments', async (ctx) => {
|
|
540
|
-
try {
|
|
541
|
-
return await processPayment(ctx.body);
|
|
542
|
-
} catch (error) {
|
|
543
|
-
paymentSentry.captureException(error);
|
|
544
|
-
throw error;
|
|
545
|
-
}
|
|
546
|
-
});
|
|
547
|
-
```
|
|
548
|
-
|
|
549
|
-
### Testing with Sentry
|
|
550
|
-
|
|
551
|
-
```typescript
|
|
552
|
-
import { SentryClient } from 'nexus';
|
|
553
|
-
|
|
554
|
-
// Mock client for testing
|
|
555
|
-
const mockSentry = new SentryClient({
|
|
556
|
-
dsn: 'https://fake@fake.ingest.sentry.io/123',
|
|
557
|
-
beforeSend: () => null // Drop all events in tests
|
|
558
|
-
});
|
|
559
|
-
|
|
560
|
-
// Or disable entirely
|
|
561
|
-
mockSentry.setEnabled(false);
|
|
562
|
-
```
|
|
563
|
-
|
|
564
|
-
---
|
|
565
|
-
|
|
566
|
-
## Best Practices
|
|
567
|
-
|
|
568
|
-
1. **Always set environment** - Helps filter production vs development errors
|
|
569
|
-
2. **Set release version** - Enables release tracking and source maps
|
|
570
|
-
3. **Use meaningful transaction names** - Makes performance data useful
|
|
571
|
-
4. **Add breadcrumbs at key points** - Helps debug complex flows
|
|
572
|
-
5. **Set user context early** - After authentication
|
|
573
|
-
6. **Use tags for filtering** - team, feature, version, etc.
|
|
574
|
-
7. **Filter sensitive data** - Use beforeSend to scrub PII
|
|
575
|
-
8. **Set appropriate sample rates** - 100% for errors, 10-20% for performance
|
|
576
|
-
9. **Add shutdown hook** - Ensure events are flushed before exit
|
|
577
|
-
10. **Use custom fingerprints** - Group related errors together
|
|
578
|
-
|
|
579
|
-
---
|
|
580
|
-
|
|
581
|
-
## Troubleshooting
|
|
582
|
-
|
|
583
|
-
### Events Not Appearing
|
|
584
|
-
|
|
585
|
-
```typescript
|
|
586
|
-
// Enable debug mode
|
|
587
|
-
app.sentry({
|
|
588
|
-
dsn: process.env.SENTRY_DSN!,
|
|
589
|
-
debug: true // Check console for logs
|
|
590
|
-
});
|
|
591
|
-
```
|
|
592
|
-
|
|
593
|
-
### Check DSN
|
|
594
|
-
|
|
595
|
-
```typescript
|
|
596
|
-
// Validate DSN format
|
|
597
|
-
// Should be: https://<key>@<org>.ingest.sentry.io/<project>
|
|
598
|
-
console.log('DSN:', process.env.SENTRY_DSN);
|
|
599
|
-
```
|
|
600
|
-
|
|
601
|
-
### Check Sample Rate
|
|
602
|
-
|
|
603
|
-
```typescript
|
|
604
|
-
app.sentry({
|
|
605
|
-
dsn: process.env.SENTRY_DSN!,
|
|
606
|
-
sampleRate: 1.0, // 100% for debugging
|
|
607
|
-
tracesSampleRate: 1.0
|
|
608
|
-
});
|
|
609
|
-
```
|
|
610
|
-
|
|
611
|
-
### Force Send Test Event
|
|
612
|
-
|
|
613
|
-
```typescript
|
|
614
|
-
import { captureMessage } from 'nexus';
|
|
615
|
-
|
|
616
|
-
app.get('/sentry-test', (ctx) => {
|
|
617
|
-
captureMessage('Test event from Nexus', { level: 'info' });
|
|
618
|
-
return { status: 'sent' };
|
|
619
|
-
});
|
|
620
|
-
```
|