@engjts/nexus 0.1.8 → 0.1.10
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/dist/advanced/playground/playground.js.map +1 -1
- package/dist/advanced/static/generateDirectoryListing.d.ts +1 -1
- package/dist/advanced/static/generateDirectoryListing.d.ts.map +1 -1
- package/dist/advanced/static/generateDirectoryListing.js +12 -6
- package/dist/advanced/static/generateDirectoryListing.js.map +1 -1
- package/dist/advanced/static/index.d.ts +2 -0
- package/dist/advanced/static/index.d.ts.map +1 -1
- package/dist/advanced/static/index.js +4 -1
- package/dist/advanced/static/index.js.map +1 -1
- package/dist/advanced/static/serveStatic.d.ts.map +1 -1
- package/dist/advanced/static/serveStatic.js +7 -1
- package/dist/advanced/static/serveStatic.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- 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,996 +0,0 @@
|
|
|
1
|
-
# Sentry Data Storage & Scope Analysis
|
|
2
|
-
|
|
3
|
-
Dokumentasi lengkap tentang data apa saja yang dikirim ke Sentry dan bagaimana scope-nya dalam Nexus Framework.
|
|
4
|
-
|
|
5
|
-
## Table of Contents
|
|
6
|
-
|
|
7
|
-
1. [Event Structure](#event-structure)
|
|
8
|
-
2. [Data Categories](#data-categories)
|
|
9
|
-
3. [Scope Hierarchy](#scope-hierarchy)
|
|
10
|
-
4. [Security & Privacy](#security--privacy)
|
|
11
|
-
5. [Storage & Retention](#storage--retention)
|
|
12
|
-
6. [Data Flow Diagram](#data-flow-diagram)
|
|
13
|
-
|
|
14
|
-
---
|
|
15
|
-
|
|
16
|
-
## Event Structure
|
|
17
|
-
|
|
18
|
-
Setiap event yang dikirim ke Sentry memiliki struktur lengkap:
|
|
19
|
-
|
|
20
|
-
```json
|
|
21
|
-
{
|
|
22
|
-
"event_id": "a1b2c3d4e5f6g7h8",
|
|
23
|
-
"timestamp": 1701619200,
|
|
24
|
-
"platform": "node",
|
|
25
|
-
"level": "error",
|
|
26
|
-
"logger": "nexus",
|
|
27
|
-
"server_name": "api-server-1",
|
|
28
|
-
"release": "1.0.0",
|
|
29
|
-
"environment": "production",
|
|
30
|
-
|
|
31
|
-
"message": "Database connection failed",
|
|
32
|
-
|
|
33
|
-
"exception": {
|
|
34
|
-
"values": [
|
|
35
|
-
{
|
|
36
|
-
"type": "DatabaseError",
|
|
37
|
-
"value": "Connection timeout after 5000ms",
|
|
38
|
-
"stacktrace": { /* stack frames */ },
|
|
39
|
-
"mechanism": {
|
|
40
|
-
"type": "generic",
|
|
41
|
-
"handled": true
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
]
|
|
45
|
-
},
|
|
46
|
-
|
|
47
|
-
"user": { /* user data */ },
|
|
48
|
-
"tags": { /* tags */ },
|
|
49
|
-
"extra": { /* extra context */ },
|
|
50
|
-
"contexts": { /* system context */ },
|
|
51
|
-
"breadcrumbs": [ /* activity trail */ ],
|
|
52
|
-
"request": { /* HTTP request info */ },
|
|
53
|
-
"fingerprint": [ /* grouping */ ]
|
|
54
|
-
}
|
|
55
|
-
```
|
|
56
|
-
|
|
57
|
-
---
|
|
58
|
-
|
|
59
|
-
## Data Categories
|
|
60
|
-
|
|
61
|
-
### 1. Event Metadata
|
|
62
|
-
|
|
63
|
-
**Apa yang disimpan:**
|
|
64
|
-
```typescript
|
|
65
|
-
{
|
|
66
|
-
event_id: string; // Unique identifier
|
|
67
|
-
timestamp: number; // When error occurred (Unix timestamp)
|
|
68
|
-
platform: 'node'; // Platform type
|
|
69
|
-
level: 'error' | 'warning'; // Severity level
|
|
70
|
-
logger: 'nexus'; // Which logger
|
|
71
|
-
message?: string; // Error message
|
|
72
|
-
fingerprint?: string[]; // Grouping key
|
|
73
|
-
}
|
|
74
|
-
```
|
|
75
|
-
|
|
76
|
-
**Scope**: **GLOBAL** - Semua error akan punya metadata ini
|
|
77
|
-
|
|
78
|
-
**Contoh**:
|
|
79
|
-
```json
|
|
80
|
-
{
|
|
81
|
-
"event_id": "a1b2c3d4e5f6g7h8",
|
|
82
|
-
"timestamp": 1701619200,
|
|
83
|
-
"platform": "node",
|
|
84
|
-
"level": "error",
|
|
85
|
-
"message": "User validation failed"
|
|
86
|
-
}
|
|
87
|
-
```
|
|
88
|
-
|
|
89
|
-
---
|
|
90
|
-
|
|
91
|
-
### 2. Error/Exception Data
|
|
92
|
-
|
|
93
|
-
**Apa yang disimpan:**
|
|
94
|
-
```typescript
|
|
95
|
-
{
|
|
96
|
-
type: string; // Error class name (e.g., "ValidationError")
|
|
97
|
-
value: string; // Error message
|
|
98
|
-
stacktrace: {
|
|
99
|
-
frames: [
|
|
100
|
-
{
|
|
101
|
-
filename: string; // File path
|
|
102
|
-
function: string; // Function name
|
|
103
|
-
lineno: number; // Line number
|
|
104
|
-
colno: number; // Column number
|
|
105
|
-
abs_path: string; // Absolute path
|
|
106
|
-
in_app: boolean; // Is this our code?
|
|
107
|
-
context_line?: string; // Line of code
|
|
108
|
-
pre_context?: string[]; // Lines before
|
|
109
|
-
post_context?: string[]; // Lines after
|
|
110
|
-
}
|
|
111
|
-
]
|
|
112
|
-
};
|
|
113
|
-
mechanism: {
|
|
114
|
-
type: 'generic' | 'unhandledRejection' | 'uncaughtException';
|
|
115
|
-
handled: boolean;
|
|
116
|
-
};
|
|
117
|
-
}
|
|
118
|
-
```
|
|
119
|
-
|
|
120
|
-
**Scope**: **ERROR-SPECIFIC** - Hanya pada error events
|
|
121
|
-
|
|
122
|
-
**Contoh Stack Trace**:
|
|
123
|
-
```json
|
|
124
|
-
{
|
|
125
|
-
"exception": {
|
|
126
|
-
"values": [{
|
|
127
|
-
"type": "TypeError",
|
|
128
|
-
"value": "Cannot read property 'email' of undefined",
|
|
129
|
-
"stacktrace": {
|
|
130
|
-
"frames": [
|
|
131
|
-
{
|
|
132
|
-
"filename": "/app/src/handlers/user.ts",
|
|
133
|
-
"function": "createUser",
|
|
134
|
-
"lineno": 42,
|
|
135
|
-
"colno": 15,
|
|
136
|
-
"abs_path": "/app/src/handlers/user.ts",
|
|
137
|
-
"in_app": true,
|
|
138
|
-
"context_line": "const email = user.email.toLowerCase();",
|
|
139
|
-
"pre_context": ["async function createUser(user) {", " // Validate user"],
|
|
140
|
-
"post_context": [" return email;", "}"]
|
|
141
|
-
},
|
|
142
|
-
{
|
|
143
|
-
"filename": "/app/node_modules/express/index.js",
|
|
144
|
-
"function": "handler",
|
|
145
|
-
"in_app": false
|
|
146
|
-
}
|
|
147
|
-
]
|
|
148
|
-
}
|
|
149
|
-
}]
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
```
|
|
153
|
-
|
|
154
|
-
---
|
|
155
|
-
|
|
156
|
-
### 3. Server Context
|
|
157
|
-
|
|
158
|
-
**Apa yang disimpan:**
|
|
159
|
-
```typescript
|
|
160
|
-
{
|
|
161
|
-
server_name: string; // Server hostname
|
|
162
|
-
release: string; // App version (e.g., "1.0.0")
|
|
163
|
-
environment: string; // 'production' | 'staging' | 'development'
|
|
164
|
-
contexts: {
|
|
165
|
-
runtime: {
|
|
166
|
-
name: 'node';
|
|
167
|
-
version: string; // Node.js version (e.g., "v20.10.0")
|
|
168
|
-
};
|
|
169
|
-
os: {
|
|
170
|
-
name: string; // Platform (e.g., 'linux', 'darwin')
|
|
171
|
-
version: string; // Architecture (e.g., 'x64')
|
|
172
|
-
};
|
|
173
|
-
};
|
|
174
|
-
}
|
|
175
|
-
```
|
|
176
|
-
|
|
177
|
-
**Scope**: **GLOBAL** - Ada di setiap event
|
|
178
|
-
|
|
179
|
-
**Contoh**:
|
|
180
|
-
```json
|
|
181
|
-
{
|
|
182
|
-
"server_name": "api-server-1",
|
|
183
|
-
"release": "1.0.0",
|
|
184
|
-
"environment": "production",
|
|
185
|
-
"contexts": {
|
|
186
|
-
"runtime": {
|
|
187
|
-
"name": "node",
|
|
188
|
-
"version": "v20.10.0"
|
|
189
|
-
},
|
|
190
|
-
"os": {
|
|
191
|
-
"name": "linux",
|
|
192
|
-
"version": "x64"
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
```
|
|
197
|
-
|
|
198
|
-
---
|
|
199
|
-
|
|
200
|
-
### 4. User Context
|
|
201
|
-
|
|
202
|
-
**Apa yang disimpan:**
|
|
203
|
-
```typescript
|
|
204
|
-
{
|
|
205
|
-
id?: string; // User ID (e.g., "user-123")
|
|
206
|
-
email?: string; // User email
|
|
207
|
-
username?: string; // Username
|
|
208
|
-
ip_address?: string; // User's IP address
|
|
209
|
-
[key: string]: any; // Custom user data
|
|
210
|
-
}
|
|
211
|
-
```
|
|
212
|
-
|
|
213
|
-
**Scope**: **CONDITIONAL** - Hanya jika middleware `extractUser` mengembalikan data
|
|
214
|
-
|
|
215
|
-
**Contoh**:
|
|
216
|
-
```json
|
|
217
|
-
{
|
|
218
|
-
"user": {
|
|
219
|
-
"id": "user-12345",
|
|
220
|
-
"email": "john@example.com",
|
|
221
|
-
"username": "john_doe",
|
|
222
|
-
"ip_address": "192.168.1.1",
|
|
223
|
-
"subscription": "premium",
|
|
224
|
-
"country": "US"
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
```
|
|
228
|
-
|
|
229
|
-
**Cara Data Dikumpulkan**:
|
|
230
|
-
```typescript
|
|
231
|
-
app.sentry({
|
|
232
|
-
dsn: process.env.SENTRY_DSN!
|
|
233
|
-
}, {
|
|
234
|
-
extractUser: (ctx) => {
|
|
235
|
-
if (ctx.user) {
|
|
236
|
-
return {
|
|
237
|
-
id: ctx.user.id,
|
|
238
|
-
email: ctx.user.email,
|
|
239
|
-
username: ctx.user.name,
|
|
240
|
-
subscription: ctx.user.plan,
|
|
241
|
-
country: ctx.user.country
|
|
242
|
-
};
|
|
243
|
-
}
|
|
244
|
-
return null;
|
|
245
|
-
}
|
|
246
|
-
});
|
|
247
|
-
```
|
|
248
|
-
|
|
249
|
-
---
|
|
250
|
-
|
|
251
|
-
### 5. HTTP Request Context
|
|
252
|
-
|
|
253
|
-
**Apa yang disimpan:**
|
|
254
|
-
```typescript
|
|
255
|
-
{
|
|
256
|
-
request: {
|
|
257
|
-
url?: string; // Full URL
|
|
258
|
-
method?: string; // HTTP method (GET, POST, etc.)
|
|
259
|
-
headers?: {
|
|
260
|
-
[key: string]: string;
|
|
261
|
-
};
|
|
262
|
-
query_string?: string; // Query params (from URL)
|
|
263
|
-
data?: any; // Request body (optional)
|
|
264
|
-
cookies?: string; // Cookie header
|
|
265
|
-
};
|
|
266
|
-
}
|
|
267
|
-
```
|
|
268
|
-
|
|
269
|
-
**Scope**: **REQUEST-BASED** - Dikumpulkan dari middleware
|
|
270
|
-
|
|
271
|
-
**Contoh Lengkap**:
|
|
272
|
-
```json
|
|
273
|
-
{
|
|
274
|
-
"request": {
|
|
275
|
-
"url": "https://api.example.com/api/users/123?sort=name",
|
|
276
|
-
"method": "POST",
|
|
277
|
-
"query_string": "sort=name",
|
|
278
|
-
"headers": {
|
|
279
|
-
"user-agent": "Mozilla/5.0...",
|
|
280
|
-
"content-type": "application/json",
|
|
281
|
-
"accept": "application/json"
|
|
282
|
-
},
|
|
283
|
-
"data": {
|
|
284
|
-
"name": "John Doe",
|
|
285
|
-
"email": "john@example.com"
|
|
286
|
-
},
|
|
287
|
-
"cookies": "session=abc123; theme=dark"
|
|
288
|
-
}
|
|
289
|
-
}
|
|
290
|
-
```
|
|
291
|
-
|
|
292
|
-
**Kontrol Data yang Dikirim**:
|
|
293
|
-
```typescript
|
|
294
|
-
app.sentry({
|
|
295
|
-
dsn: process.env.SENTRY_DSN!
|
|
296
|
-
}, {
|
|
297
|
-
// Include request body in error reports
|
|
298
|
-
includeRequestBody: true,
|
|
299
|
-
|
|
300
|
-
// Include request headers
|
|
301
|
-
includeHeaders: true,
|
|
302
|
-
|
|
303
|
-
// Headers to exclude (sensitive data)
|
|
304
|
-
excludeHeaders: [
|
|
305
|
-
'authorization',
|
|
306
|
-
'cookie',
|
|
307
|
-
'x-api-key',
|
|
308
|
-
'x-auth-token'
|
|
309
|
-
]
|
|
310
|
-
});
|
|
311
|
-
```
|
|
312
|
-
|
|
313
|
-
---
|
|
314
|
-
|
|
315
|
-
### 6. Tags
|
|
316
|
-
|
|
317
|
-
**Apa yang disimpan:**
|
|
318
|
-
```typescript
|
|
319
|
-
{
|
|
320
|
-
tags: {
|
|
321
|
-
[key: string]: string; // Simple key-value for filtering
|
|
322
|
-
}
|
|
323
|
-
}
|
|
324
|
-
```
|
|
325
|
-
|
|
326
|
-
**Scope**: **FLEXIBLE** - Global + per-event
|
|
327
|
-
|
|
328
|
-
**Contoh**:
|
|
329
|
-
```json
|
|
330
|
-
{
|
|
331
|
-
"tags": {
|
|
332
|
-
"http.method": "POST",
|
|
333
|
-
"http.url": "/api/users",
|
|
334
|
-
"http.status_code": "500",
|
|
335
|
-
"environment": "production",
|
|
336
|
-
"version": "1.0.0",
|
|
337
|
-
"region": "us-east-1",
|
|
338
|
-
"team": "backend",
|
|
339
|
-
"module": "payments"
|
|
340
|
-
}
|
|
341
|
-
}
|
|
342
|
-
```
|
|
343
|
-
|
|
344
|
-
**Penggunaan**:
|
|
345
|
-
```typescript
|
|
346
|
-
// Global tags (di semua event)
|
|
347
|
-
app.sentry({
|
|
348
|
-
tags: {
|
|
349
|
-
app: 'my-api',
|
|
350
|
-
version: '1.0.0',
|
|
351
|
-
team: 'backend'
|
|
352
|
-
}
|
|
353
|
-
});
|
|
354
|
-
|
|
355
|
-
// Per-event tags
|
|
356
|
-
captureException(error, {
|
|
357
|
-
tags: {
|
|
358
|
-
module: 'payments',
|
|
359
|
-
operation: 'charge'
|
|
360
|
-
}
|
|
361
|
-
});
|
|
362
|
-
|
|
363
|
-
// Manually set tags
|
|
364
|
-
setTag('feature_flag.new_checkout', 'enabled');
|
|
365
|
-
```
|
|
366
|
-
|
|
367
|
-
---
|
|
368
|
-
|
|
369
|
-
### 7. Extra Context
|
|
370
|
-
|
|
371
|
-
**Apa yang disimpan:**
|
|
372
|
-
```typescript
|
|
373
|
-
{
|
|
374
|
-
extra: {
|
|
375
|
-
[key: string]: any; // Any data (objects, arrays, etc.)
|
|
376
|
-
}
|
|
377
|
-
}
|
|
378
|
-
```
|
|
379
|
-
|
|
380
|
-
**Scope**: **FLEXIBLE** - Global + per-event
|
|
381
|
-
|
|
382
|
-
**Contoh**:
|
|
383
|
-
```json
|
|
384
|
-
{
|
|
385
|
-
"extra": {
|
|
386
|
-
"user_id": "user-123",
|
|
387
|
-
"order_id": "order-456",
|
|
388
|
-
"payment_method": "credit_card",
|
|
389
|
-
"amount": 99.99,
|
|
390
|
-
"cart_items": [
|
|
391
|
-
{ "sku": "PROD-001", "qty": 2 },
|
|
392
|
-
{ "sku": "PROD-002", "qty": 1 }
|
|
393
|
-
],
|
|
394
|
-
"feature_flags": {
|
|
395
|
-
"new_checkout": true,
|
|
396
|
-
"ai_recommendations": false
|
|
397
|
-
},
|
|
398
|
-
"trace_id": "xyz-789",
|
|
399
|
-
"db_query_time_ms": 245
|
|
400
|
-
}
|
|
401
|
-
}
|
|
402
|
-
```
|
|
403
|
-
|
|
404
|
-
**Penggunaan**:
|
|
405
|
-
```typescript
|
|
406
|
-
// Global extra
|
|
407
|
-
app.sentry({
|
|
408
|
-
extra: {
|
|
409
|
-
api_version: 'v2',
|
|
410
|
-
database: 'postgres'
|
|
411
|
-
}
|
|
412
|
-
});
|
|
413
|
-
|
|
414
|
-
// Per-event extra
|
|
415
|
-
captureException(error, {
|
|
416
|
-
extra: {
|
|
417
|
-
user_id: ctx.user?.id,
|
|
418
|
-
order_id: ctx.params.orderId,
|
|
419
|
-
database_query: dbQuery
|
|
420
|
-
}
|
|
421
|
-
});
|
|
422
|
-
|
|
423
|
-
// Set extra manually
|
|
424
|
-
setExtra('current_feature_flags', {
|
|
425
|
-
ai_search: true,
|
|
426
|
-
dark_mode: false
|
|
427
|
-
});
|
|
428
|
-
```
|
|
429
|
-
|
|
430
|
-
---
|
|
431
|
-
|
|
432
|
-
### 8. Breadcrumbs
|
|
433
|
-
|
|
434
|
-
**Apa yang disimpan:**
|
|
435
|
-
```typescript
|
|
436
|
-
[
|
|
437
|
-
{
|
|
438
|
-
type: 'http' | 'default' | 'navigation' | 'error' | 'debug' | 'query' | 'info';
|
|
439
|
-
category?: string;
|
|
440
|
-
message?: string;
|
|
441
|
-
level?: 'debug' | 'info' | 'warning' | 'error';
|
|
442
|
-
timestamp?: number;
|
|
443
|
-
data?: Record<string, any>;
|
|
444
|
-
}
|
|
445
|
-
]
|
|
446
|
-
```
|
|
447
|
-
|
|
448
|
-
**Scope**: **REQUEST-BASED** - Per transaction (max 100)
|
|
449
|
-
|
|
450
|
-
**Contoh Breadcrumb Trail**:
|
|
451
|
-
```json
|
|
452
|
-
{
|
|
453
|
-
"breadcrumbs": [
|
|
454
|
-
{
|
|
455
|
-
"type": "info",
|
|
456
|
-
"category": "auth",
|
|
457
|
-
"message": "User login",
|
|
458
|
-
"level": "info",
|
|
459
|
-
"timestamp": 1701619100,
|
|
460
|
-
"data": { "user_id": "user-123" }
|
|
461
|
-
},
|
|
462
|
-
{
|
|
463
|
-
"type": "http",
|
|
464
|
-
"category": "http.request",
|
|
465
|
-
"message": "GET /api/cart",
|
|
466
|
-
"level": "info",
|
|
467
|
-
"timestamp": 1701619150,
|
|
468
|
-
"data": {
|
|
469
|
-
"method": "GET",
|
|
470
|
-
"url": "/api/cart",
|
|
471
|
-
"status_code": 200,
|
|
472
|
-
"duration_ms": 45
|
|
473
|
-
}
|
|
474
|
-
},
|
|
475
|
-
{
|
|
476
|
-
"type": "query",
|
|
477
|
-
"category": "database",
|
|
478
|
-
"message": "SELECT * FROM orders WHERE user_id = ?",
|
|
479
|
-
"level": "info",
|
|
480
|
-
"timestamp": 1701619160,
|
|
481
|
-
"data": {
|
|
482
|
-
"duration_ms": 32,
|
|
483
|
-
"rows_affected": 5
|
|
484
|
-
}
|
|
485
|
-
},
|
|
486
|
-
{
|
|
487
|
-
"type": "default",
|
|
488
|
-
"category": "payment",
|
|
489
|
-
"message": "Processing payment",
|
|
490
|
-
"level": "info",
|
|
491
|
-
"timestamp": 1701619170,
|
|
492
|
-
"data": { "amount": 99.99, "method": "stripe" }
|
|
493
|
-
},
|
|
494
|
-
{
|
|
495
|
-
"type": "error",
|
|
496
|
-
"category": "payment",
|
|
497
|
-
"message": "Payment declined",
|
|
498
|
-
"level": "error",
|
|
499
|
-
"timestamp": 1701619175,
|
|
500
|
-
"data": { "code": "card_declined", "retry_count": 2 }
|
|
501
|
-
}
|
|
502
|
-
]
|
|
503
|
-
}
|
|
504
|
-
```
|
|
505
|
-
|
|
506
|
-
**Penggunaan**:
|
|
507
|
-
```typescript
|
|
508
|
-
addBreadcrumb({
|
|
509
|
-
type: 'http',
|
|
510
|
-
category: 'api.call',
|
|
511
|
-
message: 'Calling external API',
|
|
512
|
-
level: 'info',
|
|
513
|
-
data: {
|
|
514
|
-
endpoint: 'https://api.stripe.com/charges',
|
|
515
|
-
method: 'POST',
|
|
516
|
-
timeout: 5000
|
|
517
|
-
}
|
|
518
|
-
});
|
|
519
|
-
```
|
|
520
|
-
|
|
521
|
-
---
|
|
522
|
-
|
|
523
|
-
### 9. Performance Tracing
|
|
524
|
-
|
|
525
|
-
**Apa yang disimpan**:
|
|
526
|
-
```typescript
|
|
527
|
-
{
|
|
528
|
-
trace_id: string; // Unique trace ID
|
|
529
|
-
span_id: string; // This span's ID
|
|
530
|
-
parent_span_id?: string; // Parent span (if nested)
|
|
531
|
-
name: string; // Span name
|
|
532
|
-
op: string; // Operation type
|
|
533
|
-
status: string; // 'ok' | 'error'
|
|
534
|
-
start_timestamp: number; // Start time (Unix seconds)
|
|
535
|
-
timestamp: number; // End time
|
|
536
|
-
tags?: Record<string, string>;
|
|
537
|
-
data?: Record<string, any>;
|
|
538
|
-
spans?: Span[]; // Child spans
|
|
539
|
-
}
|
|
540
|
-
```
|
|
541
|
-
|
|
542
|
-
**Scope**: **CONDITIONAL** - Hanya jika `enableTracing: true`
|
|
543
|
-
|
|
544
|
-
**Contoh Transaction dengan Spans**:
|
|
545
|
-
```json
|
|
546
|
-
{
|
|
547
|
-
"trace_id": "a1b2c3d4e5f6g7h8i9j0",
|
|
548
|
-
"span_id": "k1l2m3n4o5p6q7r8",
|
|
549
|
-
"name": "POST /api/orders",
|
|
550
|
-
"op": "http.server",
|
|
551
|
-
"status": "ok",
|
|
552
|
-
"start_timestamp": 1701619200.123,
|
|
553
|
-
"timestamp": 1701619200.456,
|
|
554
|
-
"tags": {
|
|
555
|
-
"http.method": "POST",
|
|
556
|
-
"http.status_code": "201"
|
|
557
|
-
},
|
|
558
|
-
"data": {
|
|
559
|
-
"http.response_time_ms": 333
|
|
560
|
-
},
|
|
561
|
-
"spans": [
|
|
562
|
-
{
|
|
563
|
-
"span_id": "r8s9t0u1v2w3x4y5",
|
|
564
|
-
"parent_span_id": "k1l2m3n4o5p6q7r8",
|
|
565
|
-
"op": "db.query",
|
|
566
|
-
"description": "SELECT * FROM users WHERE id = ?",
|
|
567
|
-
"status": "ok",
|
|
568
|
-
"start_timestamp": 1701619200.150,
|
|
569
|
-
"timestamp": 1701619200.180,
|
|
570
|
-
"data": {
|
|
571
|
-
"duration_ms": 30,
|
|
572
|
-
"rows": 1
|
|
573
|
-
}
|
|
574
|
-
},
|
|
575
|
-
{
|
|
576
|
-
"span_id": "z1a2b3c4d5e6f7g8",
|
|
577
|
-
"parent_span_id": "k1l2m3n4o5p6q7r8",
|
|
578
|
-
"op": "http.request",
|
|
579
|
-
"description": "POST https://api.stripe.com/charges",
|
|
580
|
-
"status": "ok",
|
|
581
|
-
"start_timestamp": 1701619200.200,
|
|
582
|
-
"timestamp": 1701619200.350,
|
|
583
|
-
"data": {
|
|
584
|
-
"duration_ms": 150,
|
|
585
|
-
"status_code": 200
|
|
586
|
-
}
|
|
587
|
-
}
|
|
588
|
-
]
|
|
589
|
-
}
|
|
590
|
-
```
|
|
591
|
-
|
|
592
|
-
---
|
|
593
|
-
|
|
594
|
-
## Scope Hierarchy
|
|
595
|
-
|
|
596
|
-
Bagaimana data dikumpulkan pada berbagai tingkat:
|
|
597
|
-
|
|
598
|
-
```
|
|
599
|
-
┌─────────────────────────────────────────────────────────┐
|
|
600
|
-
│ Application Scope (Initialization) │
|
|
601
|
-
│ - environment │
|
|
602
|
-
│ - release │
|
|
603
|
-
│ - serverName │
|
|
604
|
-
│ - sampleRate │
|
|
605
|
-
│ - Global tags │
|
|
606
|
-
│ - Global extra │
|
|
607
|
-
└──────────────┬──────────────────────────────────────────┘
|
|
608
|
-
│
|
|
609
|
-
┌──────────────┴──────────────────────────────────────────┐
|
|
610
|
-
│ Request Scope (Each HTTP Request) │
|
|
611
|
-
│ - user (from extractUser middleware) │
|
|
612
|
-
│ - correlationId │
|
|
613
|
-
│ - timestamp │
|
|
614
|
-
│ - HTTP request context │
|
|
615
|
-
│ - URL, method, headers, body │
|
|
616
|
-
│ - Breadcrumbs (per request, max 100) │
|
|
617
|
-
└──────────────┬──────────────────────────────────────────┘
|
|
618
|
-
│
|
|
619
|
-
┌──────────────┴──────────────────────────────────────────┐
|
|
620
|
-
│ Transaction Scope (Performance Tracing) │
|
|
621
|
-
│ - trace_id, span_id │
|
|
622
|
-
│ - op (operation type) │
|
|
623
|
-
│ - Child spans (db queries, API calls, etc.) │
|
|
624
|
-
│ - tags (http.method, http.status_code, etc.) │
|
|
625
|
-
│ - data (duration_ms, response_time, etc.) │
|
|
626
|
-
└──────────────┬──────────────────────────────────────────┘
|
|
627
|
-
│
|
|
628
|
-
┌──────────────┴──────────────────────────────────────────┐
|
|
629
|
-
│ Event Scope (Error/Message Capture) │
|
|
630
|
-
│ - event_id │
|
|
631
|
-
│ - level (error, warning, info, etc.) │
|
|
632
|
-
│ - exception/message │
|
|
633
|
-
│ - fingerprint (for grouping) │
|
|
634
|
-
│ - Per-event tags & extra │
|
|
635
|
-
└─────────────────────────────────────────────────────────┘
|
|
636
|
-
```
|
|
637
|
-
|
|
638
|
-
---
|
|
639
|
-
|
|
640
|
-
## Security & Privacy
|
|
641
|
-
|
|
642
|
-
### Data Yang TIDAK Dikirim (Secara Default):
|
|
643
|
-
|
|
644
|
-
1. **Passwords & Secrets**
|
|
645
|
-
```typescript
|
|
646
|
-
// TIDAK dikirim:
|
|
647
|
-
password, token, secret, apiKey, auth, authorization
|
|
648
|
-
```
|
|
649
|
-
|
|
650
|
-
2. **Personal Information (PII)**
|
|
651
|
-
```typescript
|
|
652
|
-
// Kontrol dengan flag:
|
|
653
|
-
app.sentry({
|
|
654
|
-
sendDefaultPii: false // Default
|
|
655
|
-
});
|
|
656
|
-
```
|
|
657
|
-
|
|
658
|
-
3. **Sensitive Headers**
|
|
659
|
-
```typescript
|
|
660
|
-
app.sentry({}, {
|
|
661
|
-
excludeHeaders: [
|
|
662
|
-
'authorization',
|
|
663
|
-
'cookie',
|
|
664
|
-
'x-api-key',
|
|
665
|
-
'x-auth-token',
|
|
666
|
-
'x-csrf-token'
|
|
667
|
-
]
|
|
668
|
-
});
|
|
669
|
-
```
|
|
670
|
-
|
|
671
|
-
### Data Filtering & Scrubbing:
|
|
672
|
-
|
|
673
|
-
```typescript
|
|
674
|
-
app.sentry({
|
|
675
|
-
dsn: process.env.SENTRY_DSN!,
|
|
676
|
-
|
|
677
|
-
beforeSend: (event, hint) => {
|
|
678
|
-
// Redact credit card numbers
|
|
679
|
-
if (event.request?.data?.card_number) {
|
|
680
|
-
event.request.data.card_number = '[REDACTED]';
|
|
681
|
-
}
|
|
682
|
-
|
|
683
|
-
// Remove sensitive query params
|
|
684
|
-
if (event.request?.query_string) {
|
|
685
|
-
event.request.query_string = event.request.query_string
|
|
686
|
-
.replace(/token=[^&]*/g, 'token=[REDACTED]');
|
|
687
|
-
}
|
|
688
|
-
|
|
689
|
-
// Scrub emails in some cases
|
|
690
|
-
if (process.env.NODE_ENV === 'production') {
|
|
691
|
-
if (event.user?.email) {
|
|
692
|
-
const parts = event.user.email.split('@');
|
|
693
|
-
event.user.email = parts[0].substring(0, 2) + '***@' + parts[1];
|
|
694
|
-
}
|
|
695
|
-
}
|
|
696
|
-
|
|
697
|
-
return event;
|
|
698
|
-
}
|
|
699
|
-
});
|
|
700
|
-
```
|
|
701
|
-
|
|
702
|
-
### Compliance:
|
|
703
|
-
|
|
704
|
-
- **GDPR**: Datas disimpan di Sentry server (pastikan punya DPA)
|
|
705
|
-
- **CCPA**: User punya hak untuk request/delete data
|
|
706
|
-
- **Data Retention**: Set retention policy di Sentry dashboard
|
|
707
|
-
|
|
708
|
-
---
|
|
709
|
-
|
|
710
|
-
## Storage & Retention
|
|
711
|
-
|
|
712
|
-
### Di Mana Data Disimpan:
|
|
713
|
-
|
|
714
|
-
1. **Sentry Cloud** (default)
|
|
715
|
-
```typescript
|
|
716
|
-
app.sentry({
|
|
717
|
-
dsn: 'https://key@org.ingest.sentry.io/project'
|
|
718
|
-
// Data dikirim ke Sentry cloud servers
|
|
719
|
-
});
|
|
720
|
-
```
|
|
721
|
-
|
|
722
|
-
2. **Self-Hosted Sentry**
|
|
723
|
-
```typescript
|
|
724
|
-
app.sentry({
|
|
725
|
-
dsn: 'https://key@sentry.example.com/project'
|
|
726
|
-
// Data dikirim ke server Anda sendiri
|
|
727
|
-
});
|
|
728
|
-
```
|
|
729
|
-
|
|
730
|
-
### Retention Policy (default):
|
|
731
|
-
|
|
732
|
-
- **Errors**: 30 hari
|
|
733
|
-
- **Transactions**: 30 hari (bisa dikurangi)
|
|
734
|
-
- **Attachments**: 7 hari
|
|
735
|
-
|
|
736
|
-
### Quota:
|
|
737
|
-
|
|
738
|
-
Default free tier:
|
|
739
|
-
- 5,000 errors/bulan
|
|
740
|
-
- 10,000 transactions/bulan
|
|
741
|
-
- Bisa ditingkatkan dengan paid plan
|
|
742
|
-
|
|
743
|
-
---
|
|
744
|
-
|
|
745
|
-
## Data Flow Diagram
|
|
746
|
-
|
|
747
|
-
```
|
|
748
|
-
┌────────────────────────────┐
|
|
749
|
-
│ Application Starts │
|
|
750
|
-
│ - app.sentry({dsn:...}) │
|
|
751
|
-
└──────────────┬─────────────┘
|
|
752
|
-
│
|
|
753
|
-
┌──────────────┴──────────────┐
|
|
754
|
-
│ HTTP Request Comes In │
|
|
755
|
-
│ middleware: createSentry() │
|
|
756
|
-
└──────────────┬──────────────┘
|
|
757
|
-
│
|
|
758
|
-
┌────────┴────────┐
|
|
759
|
-
│ │
|
|
760
|
-
┌──┴──┐ ┌────┴───┐
|
|
761
|
-
│ OK │ │ ERROR │
|
|
762
|
-
└──┬──┘ └────┬───┘
|
|
763
|
-
│ │
|
|
764
|
-
│ ┌───────┴─────────┐
|
|
765
|
-
│ │ │
|
|
766
|
-
│ captureException() captureMessage()
|
|
767
|
-
│ (automatic or manual) (manual)
|
|
768
|
-
│ │ │
|
|
769
|
-
│ └────────┬────────┘
|
|
770
|
-
│ │
|
|
771
|
-
│ ┌────────┴────────────────┐
|
|
772
|
-
│ │ │
|
|
773
|
-
│ beforeSend() filter? beforeSend() filter?
|
|
774
|
-
│ Drop? Drop?
|
|
775
|
-
│ │ │
|
|
776
|
-
│ └────────┬────────────────┘
|
|
777
|
-
│ │
|
|
778
|
-
│ Build Envelope:
|
|
779
|
-
│ - Event metadata
|
|
780
|
-
│ - Exception/message
|
|
781
|
-
│ - User context
|
|
782
|
-
│ - Request context
|
|
783
|
-
│ - Tags & extra
|
|
784
|
-
│ - Breadcrumbs
|
|
785
|
-
│ - Tracing data
|
|
786
|
-
│ │
|
|
787
|
-
│ ┌────────┴──────────┐
|
|
788
|
-
│ │ │
|
|
789
|
-
│ HTTP POST to Sentry (Optional)
|
|
790
|
-
│ async (non-blocking) Store locally
|
|
791
|
-
│ │
|
|
792
|
-
│ │
|
|
793
|
-
│ Sentry receives event
|
|
794
|
-
│ - Processes & deduplicates
|
|
795
|
-
│ - Creates issue group
|
|
796
|
-
│ - Stores in database
|
|
797
|
-
│ - Updates dashboard
|
|
798
|
-
│ - Triggers alerts (if configured)
|
|
799
|
-
│
|
|
800
|
-
┌──┴──┐
|
|
801
|
-
│Done │
|
|
802
|
-
└─────┘
|
|
803
|
-
```
|
|
804
|
-
|
|
805
|
-
---
|
|
806
|
-
|
|
807
|
-
## Contoh Lengkap Data Sentry Event
|
|
808
|
-
|
|
809
|
-
```typescript
|
|
810
|
-
// Scenario: User tries to checkout dengan credit card yang declined
|
|
811
|
-
|
|
812
|
-
app.post('/api/checkout', async (ctx) => {
|
|
813
|
-
// Data yang dikumpulkan oleh Sentry:
|
|
814
|
-
});
|
|
815
|
-
```
|
|
816
|
-
|
|
817
|
-
**Event Lengkap yang Dikirim ke Sentry**:
|
|
818
|
-
|
|
819
|
-
```json
|
|
820
|
-
{
|
|
821
|
-
"event_id": "a1b2c3d4e5f6g7h8",
|
|
822
|
-
"timestamp": 1701619200.123,
|
|
823
|
-
"platform": "node",
|
|
824
|
-
"level": "error",
|
|
825
|
-
"logger": "nexus",
|
|
826
|
-
"message": "Payment declined",
|
|
827
|
-
|
|
828
|
-
"exception": {
|
|
829
|
-
"values": [{
|
|
830
|
-
"type": "PaymentError",
|
|
831
|
-
"value": "Card declined: insufficient_funds",
|
|
832
|
-
"stacktrace": {
|
|
833
|
-
"frames": [
|
|
834
|
-
{
|
|
835
|
-
"filename": "/app/src/handlers/checkout.ts",
|
|
836
|
-
"function": "processPayment",
|
|
837
|
-
"lineno": 45,
|
|
838
|
-
"in_app": true
|
|
839
|
-
}
|
|
840
|
-
]
|
|
841
|
-
}
|
|
842
|
-
}]
|
|
843
|
-
},
|
|
844
|
-
|
|
845
|
-
"user": {
|
|
846
|
-
"id": "user-123",
|
|
847
|
-
"email": "john@example.com",
|
|
848
|
-
"ip_address": "192.168.1.1",
|
|
849
|
-
"subscription_tier": "free"
|
|
850
|
-
},
|
|
851
|
-
|
|
852
|
-
"request": {
|
|
853
|
-
"url": "https://api.example.com/api/checkout",
|
|
854
|
-
"method": "POST",
|
|
855
|
-
"headers": {
|
|
856
|
-
"user-agent": "Mozilla/5.0...",
|
|
857
|
-
"content-type": "application/json"
|
|
858
|
-
},
|
|
859
|
-
"data": {
|
|
860
|
-
"amount": 99.99,
|
|
861
|
-
"currency": "USD",
|
|
862
|
-
"card_last_four": "4242"
|
|
863
|
-
}
|
|
864
|
-
},
|
|
865
|
-
|
|
866
|
-
"tags": {
|
|
867
|
-
"http.method": "POST",
|
|
868
|
-
"http.url": "/api/checkout",
|
|
869
|
-
"http.status_code": "402",
|
|
870
|
-
"feature": "checkout",
|
|
871
|
-
"payment_method": "credit_card",
|
|
872
|
-
"card_brand": "visa",
|
|
873
|
-
"error_code": "insufficient_funds"
|
|
874
|
-
},
|
|
875
|
-
|
|
876
|
-
"extra": {
|
|
877
|
-
"order_id": "order-456",
|
|
878
|
-
"user_tier": "free",
|
|
879
|
-
"cart_total": 99.99,
|
|
880
|
-
"retry_count": 2,
|
|
881
|
-
"payment_processor": "stripe",
|
|
882
|
-
"processor_response_time_ms": 1200
|
|
883
|
-
},
|
|
884
|
-
|
|
885
|
-
"breadcrumbs": [
|
|
886
|
-
{
|
|
887
|
-
"type": "info",
|
|
888
|
-
"category": "checkout",
|
|
889
|
-
"message": "Checkout page loaded",
|
|
890
|
-
"timestamp": 1701619100
|
|
891
|
-
},
|
|
892
|
-
{
|
|
893
|
-
"type": "info",
|
|
894
|
-
"category": "cart",
|
|
895
|
-
"message": "Cart validated",
|
|
896
|
-
"data": { "items": 3, "total": 99.99 },
|
|
897
|
-
"timestamp": 1701619110
|
|
898
|
-
},
|
|
899
|
-
{
|
|
900
|
-
"type": "http",
|
|
901
|
-
"category": "http.request",
|
|
902
|
-
"message": "POST /api/checkout",
|
|
903
|
-
"timestamp": 1701619190
|
|
904
|
-
},
|
|
905
|
-
{
|
|
906
|
-
"type": "query",
|
|
907
|
-
"category": "database",
|
|
908
|
-
"message": "SELECT user_payment_methods WHERE user_id = ?",
|
|
909
|
-
"data": { "duration_ms": 15 },
|
|
910
|
-
"timestamp": 1701619195
|
|
911
|
-
},
|
|
912
|
-
{
|
|
913
|
-
"type": "http",
|
|
914
|
-
"category": "payment",
|
|
915
|
-
"message": "Calling Stripe API",
|
|
916
|
-
"data": { "endpoint": "/v1/charges", "amount": 9999 },
|
|
917
|
-
"timestamp": 1701619198
|
|
918
|
-
}
|
|
919
|
-
],
|
|
920
|
-
|
|
921
|
-
"contexts": {
|
|
922
|
-
"runtime": {
|
|
923
|
-
"name": "node",
|
|
924
|
-
"version": "v20.10.0"
|
|
925
|
-
},
|
|
926
|
-
"os": {
|
|
927
|
-
"name": "linux",
|
|
928
|
-
"version": "x64"
|
|
929
|
-
}
|
|
930
|
-
},
|
|
931
|
-
|
|
932
|
-
"server_name": "api-server-1",
|
|
933
|
-
"release": "1.0.0",
|
|
934
|
-
"environment": "production"
|
|
935
|
-
}
|
|
936
|
-
```
|
|
937
|
-
|
|
938
|
-
---
|
|
939
|
-
|
|
940
|
-
## Best Practices Pengumpulan Data
|
|
941
|
-
|
|
942
|
-
1. **Jangan kirim password/token**
|
|
943
|
-
```typescript
|
|
944
|
-
beforeSend: (event) => {
|
|
945
|
-
if (event.request?.data?.password) {
|
|
946
|
-
delete event.request.data.password;
|
|
947
|
-
}
|
|
948
|
-
return event;
|
|
949
|
-
}
|
|
950
|
-
```
|
|
951
|
-
|
|
952
|
-
2. **Exclude sensitive headers**
|
|
953
|
-
```typescript
|
|
954
|
-
app.sentry({}, {
|
|
955
|
-
excludeHeaders: ['authorization', 'cookie', 'x-api-key']
|
|
956
|
-
});
|
|
957
|
-
```
|
|
958
|
-
|
|
959
|
-
3. **Gunakan tags untuk filtering**
|
|
960
|
-
```typescript
|
|
961
|
-
captureException(error, {
|
|
962
|
-
tags: {
|
|
963
|
-
feature: 'payments',
|
|
964
|
-
severity: 'high'
|
|
965
|
-
}
|
|
966
|
-
});
|
|
967
|
-
```
|
|
968
|
-
|
|
969
|
-
4. **Samping breadcrumbs saja yang penting**
|
|
970
|
-
```typescript
|
|
971
|
-
addBreadcrumb({
|
|
972
|
-
category: 'payment',
|
|
973
|
-
message: 'Payment attempt',
|
|
974
|
-
data: { amount: 99.99 } // Good
|
|
975
|
-
// JANGAN: data: { all: bigData } // Bad
|
|
976
|
-
});
|
|
977
|
-
```
|
|
978
|
-
|
|
979
|
-
5. **Set user context setelah auth**
|
|
980
|
-
```typescript
|
|
981
|
-
app.sentry({}, {
|
|
982
|
-
extractUser: (ctx) => {
|
|
983
|
-
return ctx.user ? {
|
|
984
|
-
id: ctx.user.id,
|
|
985
|
-
email: ctx.user.email
|
|
986
|
-
} : null;
|
|
987
|
-
}
|
|
988
|
-
});
|
|
989
|
-
```
|
|
990
|
-
|
|
991
|
-
6. **Fingerprint untuk grouping yang smart**
|
|
992
|
-
```typescript
|
|
993
|
-
captureException(error, {
|
|
994
|
-
fingerprint: ['payment-declined', error.code]
|
|
995
|
-
});
|
|
996
|
-
```
|