@odvi/create-dtt-framework 0.1.3 → 0.1.6
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/commands/create.d.ts.map +1 -1
- package/dist/commands/create.js +16 -13
- package/dist/commands/create.js.map +1 -1
- package/package.json +3 -2
- package/template/.env.example +106 -0
- package/template/components.json +22 -0
- package/template/docs/framework/01-overview.md +289 -0
- package/template/docs/framework/02-techstack.md +503 -0
- package/template/docs/framework/api-layer.md +681 -0
- package/template/docs/framework/clerk-authentication.md +649 -0
- package/template/docs/framework/cli-installation.md +564 -0
- package/template/docs/framework/deployment/ci-cd.md +907 -0
- package/template/docs/framework/deployment/digitalocean.md +991 -0
- package/template/docs/framework/deployment/domain-setup.md +972 -0
- package/template/docs/framework/deployment/environment-variables.md +862 -0
- package/template/docs/framework/deployment/monitoring.md +927 -0
- package/template/docs/framework/deployment/production-checklist.md +649 -0
- package/template/docs/framework/deployment/vercel.md +791 -0
- package/template/docs/framework/environment-variables.md +646 -0
- package/template/docs/framework/health-check-system.md +583 -0
- package/template/docs/framework/implementation.md +559 -0
- package/template/docs/framework/snowflake-integration.md +594 -0
- package/template/docs/framework/state-management.md +615 -0
- package/template/docs/framework/supabase-integration.md +582 -0
- package/template/docs/framework/testing-guide.md +544 -0
- package/template/docs/framework/what-did-i-miss.md +526 -0
- package/template/drizzle.config.ts +11 -0
- package/template/next.config.js +21 -0
- package/template/postcss.config.js +5 -0
- package/template/prettier.config.js +4 -0
- package/template/public/favicon.ico +0 -0
- package/template/src/app/(auth)/layout.tsx +4 -0
- package/template/src/app/(auth)/sign-in/[[...sign-in]]/page.tsx +10 -0
- package/template/src/app/(auth)/sign-up/[[...sign-up]]/page.tsx +10 -0
- package/template/src/app/(dashboard)/dashboard/page.tsx +8 -0
- package/template/src/app/(dashboard)/health/page.tsx +16 -0
- package/template/src/app/(dashboard)/layout.tsx +17 -0
- package/template/src/app/api/[[...route]]/route.ts +11 -0
- package/template/src/app/api/debug-files/route.ts +33 -0
- package/template/src/app/api/webhooks/clerk/route.ts +112 -0
- package/template/src/app/layout.tsx +28 -0
- package/template/src/app/page.tsx +12 -0
- package/template/src/app/providers.tsx +20 -0
- package/template/src/components/layouts/navbar.tsx +14 -0
- package/template/src/components/shared/loading-spinner.tsx +6 -0
- package/template/src/components/ui/badge.tsx +46 -0
- package/template/src/components/ui/button.tsx +62 -0
- package/template/src/components/ui/card.tsx +92 -0
- package/template/src/components/ui/collapsible.tsx +33 -0
- package/template/src/components/ui/scroll-area.tsx +58 -0
- package/template/src/components/ui/sheet.tsx +139 -0
- package/template/src/config/__tests__/env.test.ts +164 -0
- package/template/src/config/__tests__/site.test.ts +46 -0
- package/template/src/config/env.ts +36 -0
- package/template/src/config/site.ts +10 -0
- package/template/src/env.js +44 -0
- package/template/src/features/__tests__/health-check-config.test.ts +142 -0
- package/template/src/features/__tests__/health-check-types.test.ts +201 -0
- package/template/src/features/documentation/components/doc-sidebar.tsx +109 -0
- package/template/src/features/documentation/components/doc-viewer.tsx +70 -0
- package/template/src/features/documentation/index.tsx +92 -0
- package/template/src/features/documentation/utils/doc-loader.ts +177 -0
- package/template/src/features/health-check/components/health-dashboard.tsx +374 -0
- package/template/src/features/health-check/config.ts +71 -0
- package/template/src/features/health-check/index.ts +4 -0
- package/template/src/features/health-check/stores/health-store.ts +14 -0
- package/template/src/features/health-check/types.ts +18 -0
- package/template/src/hooks/__tests__/use-debounce.test.tsx +28 -0
- package/template/src/hooks/queries/use-health-checks.ts +16 -0
- package/template/src/hooks/utils/use-debounce.ts +20 -0
- package/template/src/lib/__tests__/utils.test.ts +52 -0
- package/template/src/lib/__tests__/validators.test.ts +114 -0
- package/template/src/lib/nextbank/client.ts +67 -0
- package/template/src/lib/snowflake/client.ts +102 -0
- package/template/src/lib/supabase/admin.ts +7 -0
- package/template/src/lib/supabase/client.ts +7 -0
- package/template/src/lib/supabase/server.ts +23 -0
- package/template/src/lib/utils.ts +6 -0
- package/template/src/lib/validators.ts +9 -0
- package/template/src/middleware.ts +22 -0
- package/template/src/server/api/index.ts +22 -0
- package/template/src/server/api/middleware/auth.ts +19 -0
- package/template/src/server/api/middleware/logger.ts +4 -0
- package/template/src/server/api/routes/health/clerk.ts +214 -0
- package/template/src/server/api/routes/health/database.ts +141 -0
- package/template/src/server/api/routes/health/edge-functions.ts +107 -0
- package/template/src/server/api/routes/health/framework.ts +48 -0
- package/template/src/server/api/routes/health/index.ts +102 -0
- package/template/src/server/api/routes/health/nextbank.ts +46 -0
- package/template/src/server/api/routes/health/snowflake.ts +83 -0
- package/template/src/server/api/routes/health/storage.ts +177 -0
- package/template/src/server/api/routes/users.ts +79 -0
- package/template/src/server/db/index.ts +17 -0
- package/template/src/server/db/queries/users.ts +8 -0
- package/template/src/server/db/schema/__tests__/health-checks.test.ts +31 -0
- package/template/src/server/db/schema/__tests__/users.test.ts +46 -0
- package/template/src/server/db/schema/health-checks.ts +11 -0
- package/template/src/server/db/schema/index.ts +2 -0
- package/template/src/server/db/schema/users.ts +16 -0
- package/template/src/server/db/schema.ts +1 -0
- package/template/src/stores/__tests__/ui-store.test.ts +87 -0
- package/template/src/stores/ui-store.ts +14 -0
- package/template/src/styles/globals.css +129 -0
- package/template/src/test/mocks/clerk.ts +35 -0
- package/template/src/test/mocks/snowflake.ts +28 -0
- package/template/src/test/mocks/supabase.ts +37 -0
- package/template/src/test/setup.ts +69 -0
- package/template/src/test/utils/test-helpers.ts +158 -0
- package/template/src/types/index.ts +14 -0
- package/template/tsconfig.json +43 -0
- package/template/vitest.config.ts +44 -0
|
@@ -0,0 +1,927 @@
|
|
|
1
|
+
# DTT Framework - Monitoring and Alerting Guide
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
This guide provides comprehensive instructions for setting up monitoring, health checks, error tracking, performance monitoring, and uptime monitoring for the DTT Framework.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Table of Contents
|
|
10
|
+
|
|
11
|
+
1. [Setting Up Monitoring](#setting-up-monitoring)
|
|
12
|
+
2. [Health Check Monitoring](#health-check-monitoring)
|
|
13
|
+
3. [Error Tracking](#error-tracking)
|
|
14
|
+
4. [Performance Monitoring](#performance-monitoring)
|
|
15
|
+
5. [Uptime Monitoring](#uptime-monitoring)
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## Setting Up Monitoring
|
|
20
|
+
|
|
21
|
+
### Overview of Monitoring Stack
|
|
22
|
+
|
|
23
|
+
A comprehensive monitoring stack includes:
|
|
24
|
+
|
|
25
|
+
| Component | Purpose | Tools |
|
|
26
|
+
|-----------|---------|-------|
|
|
27
|
+
| **Application Monitoring** | Track application health | Vercel Analytics, Datadog |
|
|
28
|
+
| **Error Tracking** | Capture and analyze errors | Sentry, Rollbar |
|
|
29
|
+
| **Performance Monitoring** | Measure performance metrics | Lighthouse, Web Vitals |
|
|
30
|
+
| **Uptime Monitoring** | Monitor service availability | UptimeRobot, Pingdom |
|
|
31
|
+
| **Log Management** | Aggregate and search logs | Logtail, Papertrail |
|
|
32
|
+
| **Database Monitoring** | Track database performance | Supabase Dashboard |
|
|
33
|
+
|
|
34
|
+
### Monitoring Architecture
|
|
35
|
+
|
|
36
|
+
```
|
|
37
|
+
┌─────────────────────────────────────────────────────────────┐
|
|
38
|
+
│ Application Layer │
|
|
39
|
+
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
|
|
40
|
+
│ │ Next.js App │ │ API Routes │ │ Edge Functions│ │
|
|
41
|
+
│ └──────────────┘ └──────────────┘ └──────────────┘ │
|
|
42
|
+
└─────────────────────────────────────────────────────────────┘
|
|
43
|
+
│
|
|
44
|
+
┌────────────────┼────────────────┐
|
|
45
|
+
▼ ▼ ▼
|
|
46
|
+
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
|
|
47
|
+
│ Analytics │ │ Error Track │ │ Health │
|
|
48
|
+
│ (Vercel) │ │ (Sentry) │ │ Checks │
|
|
49
|
+
└──────────────┘ └──────────────┘ └──────────────┘
|
|
50
|
+
│ │ │
|
|
51
|
+
└────────────────┼────────────────┘
|
|
52
|
+
▼
|
|
53
|
+
┌──────────────────────┐
|
|
54
|
+
│ Monitoring Dashboard │
|
|
55
|
+
└──────────────────────┘
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
## Health Check Monitoring
|
|
61
|
+
|
|
62
|
+
### Built-in Health Check Endpoint
|
|
63
|
+
|
|
64
|
+
The framework includes a health check endpoint at `/api/health`:
|
|
65
|
+
|
|
66
|
+
```typescript
|
|
67
|
+
// src/app/api/health/route.ts
|
|
68
|
+
export async function GET() {
|
|
69
|
+
const checks = await Promise.allSettled([
|
|
70
|
+
checkDatabase(),
|
|
71
|
+
checkClerk(),
|
|
72
|
+
checkSupabase(),
|
|
73
|
+
checkSnowflake(),
|
|
74
|
+
])
|
|
75
|
+
|
|
76
|
+
const status = checks.every(c => c.status === 'fulfilled') ? 'ok' : 'degraded'
|
|
77
|
+
|
|
78
|
+
return Response.json({
|
|
79
|
+
status,
|
|
80
|
+
timestamp: new Date().toISOString(),
|
|
81
|
+
services: {
|
|
82
|
+
database: formatCheck(checks[0]),
|
|
83
|
+
clerk: formatCheck(checks[1]),
|
|
84
|
+
supabase: formatCheck(checks[2]),
|
|
85
|
+
snowflake: formatCheck(checks[3]),
|
|
86
|
+
},
|
|
87
|
+
})
|
|
88
|
+
}
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### Health Check Response Format
|
|
92
|
+
|
|
93
|
+
```json
|
|
94
|
+
{
|
|
95
|
+
"status": "ok",
|
|
96
|
+
"timestamp": "2024-01-01T00:00:00.000Z",
|
|
97
|
+
"services": {
|
|
98
|
+
"database": {
|
|
99
|
+
"status": "ok",
|
|
100
|
+
"responseTime": 45,
|
|
101
|
+
"message": "Connected successfully"
|
|
102
|
+
},
|
|
103
|
+
"clerk": {
|
|
104
|
+
"status": "ok",
|
|
105
|
+
"responseTime": 32,
|
|
106
|
+
"message": "API accessible"
|
|
107
|
+
},
|
|
108
|
+
"supabase": {
|
|
109
|
+
"status": "ok",
|
|
110
|
+
"responseTime": 28,
|
|
111
|
+
"message": "Service operational"
|
|
112
|
+
},
|
|
113
|
+
"snowflake": {
|
|
114
|
+
"status": "ok",
|
|
115
|
+
"responseTime": 156,
|
|
116
|
+
"message": "Warehouse accessible"
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### Configuring Health Checks in Vercel
|
|
123
|
+
|
|
124
|
+
#### Via Dashboard
|
|
125
|
+
|
|
126
|
+
1. Go to **Settings** → **Health Checks**
|
|
127
|
+
2. Add health check:
|
|
128
|
+
- **Path**: `/api/health`
|
|
129
|
+
- **Interval**: 30 seconds
|
|
130
|
+
- **Timeout**: 5 seconds
|
|
131
|
+
- **Threshold**: 3 failures
|
|
132
|
+
|
|
133
|
+
#### Via vercel.json
|
|
134
|
+
|
|
135
|
+
```json
|
|
136
|
+
{
|
|
137
|
+
"healthChecks": [
|
|
138
|
+
{
|
|
139
|
+
"path": "/api/health",
|
|
140
|
+
"interval": 30000,
|
|
141
|
+
"timeout": 5000,
|
|
142
|
+
"threshold": 3
|
|
143
|
+
}
|
|
144
|
+
]
|
|
145
|
+
}
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
### Configuring Health Checks in DigitalOcean
|
|
149
|
+
|
|
150
|
+
#### App Platform
|
|
151
|
+
|
|
152
|
+
```yaml
|
|
153
|
+
# .do/app.yaml
|
|
154
|
+
health_check:
|
|
155
|
+
http_path: /api/health
|
|
156
|
+
initial_delay_seconds: 60
|
|
157
|
+
period_seconds: 30
|
|
158
|
+
timeout_seconds: 5
|
|
159
|
+
success_threshold: 1
|
|
160
|
+
failure_threshold: 3
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
#### Droplet (Nginx)
|
|
164
|
+
|
|
165
|
+
```nginx
|
|
166
|
+
# Add to Nginx configuration
|
|
167
|
+
location /api/health {
|
|
168
|
+
access_log off;
|
|
169
|
+
proxy_pass http://localhost:3000;
|
|
170
|
+
proxy_set_header Host $host;
|
|
171
|
+
}
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
### Custom Health Checks
|
|
175
|
+
|
|
176
|
+
Create custom health checks for specific services:
|
|
177
|
+
|
|
178
|
+
```typescript
|
|
179
|
+
// src/lib/health-checks/database.ts
|
|
180
|
+
export async function checkDatabase() {
|
|
181
|
+
const start = Date.now()
|
|
182
|
+
try {
|
|
183
|
+
await db.select().from(users).limit(1)
|
|
184
|
+
return {
|
|
185
|
+
status: 'ok',
|
|
186
|
+
responseTime: Date.now() - start,
|
|
187
|
+
message: 'Database connection successful',
|
|
188
|
+
}
|
|
189
|
+
} catch (error) {
|
|
190
|
+
return {
|
|
191
|
+
status: 'error',
|
|
192
|
+
responseTime: Date.now() - start,
|
|
193
|
+
message: error instanceof Error ? error.message : 'Unknown error',
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// src/lib/health-checks/clerk.ts
|
|
199
|
+
export async function checkClerk() {
|
|
200
|
+
const start = Date.now()
|
|
201
|
+
try {
|
|
202
|
+
await clerkClient.users.getUserList({ limit: 1 })
|
|
203
|
+
return {
|
|
204
|
+
status: 'ok',
|
|
205
|
+
responseTime: Date.now() - start,
|
|
206
|
+
message: 'Clerk API accessible',
|
|
207
|
+
}
|
|
208
|
+
} catch (error) {
|
|
209
|
+
return {
|
|
210
|
+
status: 'error',
|
|
211
|
+
responseTime: Date.now() - start,
|
|
212
|
+
message: error instanceof Error ? error.message : 'Unknown error',
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
### Health Check Best Practices
|
|
219
|
+
|
|
220
|
+
| Practice | Description |
|
|
221
|
+
|-----------|-------------|
|
|
222
|
+
| **Fast Response** | Health checks should complete in <100ms |
|
|
223
|
+
| **No Side Effects** | Health checks should not modify data |
|
|
224
|
+
| **Consistent** | Same response format for all checks |
|
|
225
|
+
| **Comprehensive** | Check all critical services |
|
|
226
|
+
| **Actionable** | Provide clear error messages |
|
|
227
|
+
|
|
228
|
+
---
|
|
229
|
+
|
|
230
|
+
## Error Tracking
|
|
231
|
+
|
|
232
|
+
### Setting Up Sentry
|
|
233
|
+
|
|
234
|
+
#### Step 1: Install Sentry SDK
|
|
235
|
+
|
|
236
|
+
```bash
|
|
237
|
+
# Install Sentry SDK
|
|
238
|
+
pnpm add @sentry/nextjs
|
|
239
|
+
|
|
240
|
+
# Initialize Sentry
|
|
241
|
+
npx @sentry/wizard@latest -i nextjs
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
#### Step 2: Configure Sentry
|
|
245
|
+
|
|
246
|
+
Create `sentry.client.config.ts`:
|
|
247
|
+
|
|
248
|
+
```typescript
|
|
249
|
+
import * as Sentry from '@sentry/nextjs'
|
|
250
|
+
|
|
251
|
+
Sentry.init({
|
|
252
|
+
dsn: process.env.NEXT_PUBLIC_SENTRY_DSN,
|
|
253
|
+
tracesSampleRate: 1.0,
|
|
254
|
+
environment: process.env.NODE_ENV,
|
|
255
|
+
})
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
Create `sentry.server.config.ts`:
|
|
259
|
+
|
|
260
|
+
```typescript
|
|
261
|
+
import * as Sentry from '@sentry/nextjs'
|
|
262
|
+
|
|
263
|
+
Sentry.init({
|
|
264
|
+
dsn: process.env.SENTRY_DSN,
|
|
265
|
+
tracesSampleRate: 1.0,
|
|
266
|
+
environment: process.env.NODE_ENV,
|
|
267
|
+
})
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
#### Step 3: Add Environment Variables
|
|
271
|
+
|
|
272
|
+
```bash
|
|
273
|
+
# Add to .env or platform secrets
|
|
274
|
+
NEXT_PUBLIC_SENTRY_DSN=https://xxx@sentry.io/xxx
|
|
275
|
+
SENTRY_DSN=https://xxx@sentry.io/xxx
|
|
276
|
+
SENTRY_AUTH_TOKEN=sntrys_xxx
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
#### Step 4: Configure Source Maps
|
|
280
|
+
|
|
281
|
+
```javascript
|
|
282
|
+
// next.config.js
|
|
283
|
+
const { withSentryConfig } = require('@sentry/nextjs')
|
|
284
|
+
|
|
285
|
+
module.exports = withSentryConfig(
|
|
286
|
+
{
|
|
287
|
+
// Your Next.js config
|
|
288
|
+
},
|
|
289
|
+
{
|
|
290
|
+
silent: true,
|
|
291
|
+
org: 'your-org',
|
|
292
|
+
project: 'your-project',
|
|
293
|
+
}
|
|
294
|
+
)
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
### Error Types to Track
|
|
298
|
+
|
|
299
|
+
| Error Type | Severity | Action Required |
|
|
300
|
+
|------------|----------|-----------------|
|
|
301
|
+
| **JavaScript Errors** | High | Immediate investigation |
|
|
302
|
+
| **API Errors (5xx)** | Critical | Immediate investigation |
|
|
303
|
+
| **API Errors (4xx)** | Medium | Monitor and investigate |
|
|
304
|
+
| **Database Errors** | Critical | Immediate investigation |
|
|
305
|
+
| **Authentication Errors** | High | Investigate and fix |
|
|
306
|
+
|
|
307
|
+
### Error Alerting
|
|
308
|
+
|
|
309
|
+
Configure alerts in Sentry:
|
|
310
|
+
|
|
311
|
+
1. Go to **Settings** → **Alerts**
|
|
312
|
+
2. Create new alert:
|
|
313
|
+
- **Condition**: Error rate >1% for 5 minutes
|
|
314
|
+
- **Notification**: Email, Slack, PagerDuty
|
|
315
|
+
- **Severity**: Critical
|
|
316
|
+
|
|
317
|
+
### Custom Error Context
|
|
318
|
+
|
|
319
|
+
Add custom context to errors:
|
|
320
|
+
|
|
321
|
+
```typescript
|
|
322
|
+
try {
|
|
323
|
+
// Your code
|
|
324
|
+
} catch (error) {
|
|
325
|
+
Sentry.captureException(error, {
|
|
326
|
+
tags: {
|
|
327
|
+
feature: 'user-authentication',
|
|
328
|
+
action: 'sign-in',
|
|
329
|
+
},
|
|
330
|
+
extra: {
|
|
331
|
+
userId: 'user-123',
|
|
332
|
+
timestamp: new Date().toISOString(),
|
|
333
|
+
},
|
|
334
|
+
})
|
|
335
|
+
}
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
### Error Tracking Best Practices
|
|
339
|
+
|
|
340
|
+
| Practice | Description |
|
|
341
|
+
|-----------|-------------|
|
|
342
|
+
| **Capture Context** | Include user and request context |
|
|
343
|
+
| **Group Errors** | Group similar errors together |
|
|
344
|
+
| **Set Severity** | Prioritize errors by severity |
|
|
345
|
+
| **Filter Noise** | Ignore expected errors |
|
|
346
|
+
| **Review Regularly** | Review errors daily |
|
|
347
|
+
|
|
348
|
+
---
|
|
349
|
+
|
|
350
|
+
## Performance Monitoring
|
|
351
|
+
|
|
352
|
+
### Vercel Analytics
|
|
353
|
+
|
|
354
|
+
#### Installation
|
|
355
|
+
|
|
356
|
+
```bash
|
|
357
|
+
# Install Vercel Analytics
|
|
358
|
+
pnpm add @vercel/analytics
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
#### Integration
|
|
362
|
+
|
|
363
|
+
```typescript
|
|
364
|
+
// src/app/layout.tsx
|
|
365
|
+
import { Analytics } from '@vercel/analytics/react'
|
|
366
|
+
|
|
367
|
+
export default function RootLayout({ children }) {
|
|
368
|
+
return (
|
|
369
|
+
<html>
|
|
370
|
+
<body>
|
|
371
|
+
{children}
|
|
372
|
+
<Analytics />
|
|
373
|
+
</body>
|
|
374
|
+
</html>
|
|
375
|
+
)
|
|
376
|
+
}
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
#### Custom Events
|
|
380
|
+
|
|
381
|
+
```typescript
|
|
382
|
+
import { Analytics } from '@vercel/analytics/react'
|
|
383
|
+
|
|
384
|
+
// Track custom events
|
|
385
|
+
Analytics.track('user_sign_in', {
|
|
386
|
+
method: 'email',
|
|
387
|
+
plan: 'premium',
|
|
388
|
+
})
|
|
389
|
+
```
|
|
390
|
+
|
|
391
|
+
### Web Vitals Monitoring
|
|
392
|
+
|
|
393
|
+
#### Core Web Vitals
|
|
394
|
+
|
|
395
|
+
| Metric | Good | Needs Improvement | Poor |
|
|
396
|
+
|--------|------|------------------|-------|
|
|
397
|
+
| **LCP** | <2.5s | 2.5s-4s | >4s |
|
|
398
|
+
| **FID** | <100ms | 100ms-300ms | >300ms |
|
|
399
|
+
| **CLS** | <0.1 | 0.1-0.25 | >0.25 |
|
|
400
|
+
|
|
401
|
+
#### Monitoring Web Vitals
|
|
402
|
+
|
|
403
|
+
```typescript
|
|
404
|
+
// src/app/layout.tsx
|
|
405
|
+
'use client'
|
|
406
|
+
|
|
407
|
+
import { useReportWebVitals } from 'next/web-vitals'
|
|
408
|
+
|
|
409
|
+
export function WebVitals() {
|
|
410
|
+
useReportWebVitals((metric) => {
|
|
411
|
+
// Send to analytics
|
|
412
|
+
fetch('/api/analytics', {
|
|
413
|
+
method: 'POST',
|
|
414
|
+
body: JSON.stringify(metric),
|
|
415
|
+
})
|
|
416
|
+
})
|
|
417
|
+
|
|
418
|
+
return null
|
|
419
|
+
}
|
|
420
|
+
```
|
|
421
|
+
|
|
422
|
+
### Database Performance Monitoring
|
|
423
|
+
|
|
424
|
+
#### Supabase Dashboard
|
|
425
|
+
|
|
426
|
+
1. Go to **Supabase Dashboard** → **Reports**
|
|
427
|
+
2. Monitor:
|
|
428
|
+
- Query performance
|
|
429
|
+
- Connection pool usage
|
|
430
|
+
- Database size
|
|
431
|
+
- Storage usage
|
|
432
|
+
|
|
433
|
+
#### Slow Query Monitoring
|
|
434
|
+
|
|
435
|
+
```sql
|
|
436
|
+
-- Enable slow query logging
|
|
437
|
+
ALTER DATABASE postgres SET log_min_duration_statement = 1000;
|
|
438
|
+
|
|
439
|
+
-- View slow queries
|
|
440
|
+
SELECT * FROM pg_stat_statements
|
|
441
|
+
ORDER BY mean_exec_time DESC
|
|
442
|
+
LIMIT 10;
|
|
443
|
+
```
|
|
444
|
+
|
|
445
|
+
### API Performance Monitoring
|
|
446
|
+
|
|
447
|
+
#### Track API Response Times
|
|
448
|
+
|
|
449
|
+
```typescript
|
|
450
|
+
// Middleware to track API performance
|
|
451
|
+
export async function middleware(request: NextRequest) {
|
|
452
|
+
const start = Date.now()
|
|
453
|
+
|
|
454
|
+
const response = await NextResponse.next()
|
|
455
|
+
|
|
456
|
+
const duration = Date.now() - start
|
|
457
|
+
|
|
458
|
+
// Log slow requests
|
|
459
|
+
if (duration > 1000) {
|
|
460
|
+
console.warn(`Slow request: ${request.url} took ${duration}ms`)
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
response.headers.set('x-response-time', `${duration}ms`)
|
|
464
|
+
|
|
465
|
+
return response
|
|
466
|
+
}
|
|
467
|
+
```
|
|
468
|
+
|
|
469
|
+
### Performance Budgets
|
|
470
|
+
|
|
471
|
+
#### Define Budgets
|
|
472
|
+
|
|
473
|
+
```javascript
|
|
474
|
+
// next.config.js
|
|
475
|
+
module.exports = {
|
|
476
|
+
experimental: {
|
|
477
|
+
optimizeCss: true,
|
|
478
|
+
},
|
|
479
|
+
images: {
|
|
480
|
+
formats: ['image/avif', 'image/webp'],
|
|
481
|
+
},
|
|
482
|
+
}
|
|
483
|
+
```
|
|
484
|
+
|
|
485
|
+
#### Monitor Budgets
|
|
486
|
+
|
|
487
|
+
Use tools like:
|
|
488
|
+
- **Lighthouse CI**: Automated performance testing
|
|
489
|
+
- **Bundlephobia**: Analyze bundle size
|
|
490
|
+
- **Webpack Bundle Analyzer**: Visualize bundle size
|
|
491
|
+
|
|
492
|
+
### Performance Monitoring Tools
|
|
493
|
+
|
|
494
|
+
| Tool | Purpose | Cost |
|
|
495
|
+
|------|---------|------|
|
|
496
|
+
| **Vercel Analytics** | Web vitals, traffic | Free |
|
|
497
|
+
| **Lighthouse** | Page performance | Free |
|
|
498
|
+
| **WebPageTest** | Detailed performance | Free |
|
|
499
|
+
| **GTmetrix** | Performance analysis | Free/Paid |
|
|
500
|
+
| **SpeedCurve** | Performance monitoring | Paid |
|
|
501
|
+
| **Datadog** | APM | Paid |
|
|
502
|
+
|
|
503
|
+
---
|
|
504
|
+
|
|
505
|
+
## Uptime Monitoring
|
|
506
|
+
|
|
507
|
+
### UptimeRobot Setup
|
|
508
|
+
|
|
509
|
+
#### Step 1: Create Account
|
|
510
|
+
|
|
511
|
+
1. Sign up at [uptimerobot.com](https://uptimerobot.com)
|
|
512
|
+
2. Verify your email
|
|
513
|
+
|
|
514
|
+
#### Step 2: Add Monitor
|
|
515
|
+
|
|
516
|
+
1. Click **"Add New Monitor"**
|
|
517
|
+
2. Configure:
|
|
518
|
+
- **Monitor Type**: HTTP(s)
|
|
519
|
+
- **Friendly Name**: DTT Framework Production
|
|
520
|
+
- **URL**: `https://your-app.com/api/health`
|
|
521
|
+
- **Monitoring Interval**: 5 minutes
|
|
522
|
+
- **Alert Contacts**: Add your email
|
|
523
|
+
|
|
524
|
+
#### Step 3: Configure Alerts
|
|
525
|
+
|
|
526
|
+
1. Go to **My Settings** → **Alert Contacts**
|
|
527
|
+
2. Add contacts:
|
|
528
|
+
- Email
|
|
529
|
+
- Slack
|
|
530
|
+
- SMS (paid)
|
|
531
|
+
- Webhook
|
|
532
|
+
|
|
533
|
+
### Pingdom Setup
|
|
534
|
+
|
|
535
|
+
#### Step 1: Create Account
|
|
536
|
+
|
|
537
|
+
1. Sign up at [pingdom.com](https://pingdom.com)
|
|
538
|
+
2. Choose a plan
|
|
539
|
+
|
|
540
|
+
#### Step 2: Add Uptime Check
|
|
541
|
+
|
|
542
|
+
1. Go to **Uptime** → **Add New**
|
|
543
|
+
2. Configure:
|
|
544
|
+
- **Name**: DTT Framework Production
|
|
545
|
+
- **URL**: `https://your-app.com/api/health`
|
|
546
|
+
- **Check Interval**: 1 minute
|
|
547
|
+
- **Alerts**: Configure alert contacts
|
|
548
|
+
|
|
549
|
+
### Status Page Setup
|
|
550
|
+
|
|
551
|
+
Create a public status page:
|
|
552
|
+
|
|
553
|
+
```typescript
|
|
554
|
+
// src/app/status/page.tsx
|
|
555
|
+
export default async function StatusPage() {
|
|
556
|
+
const health = await fetch('https://your-app.com/api/health').then(r => r.json())
|
|
557
|
+
|
|
558
|
+
return (
|
|
559
|
+
<div className="p-8">
|
|
560
|
+
<h1 className="text-2xl font-bold mb-4">System Status</h1>
|
|
561
|
+
<div className="space-y-4">
|
|
562
|
+
<div className="flex items-center gap-2">
|
|
563
|
+
<div className={`w-3 h-3 rounded-full ${health.status === 'ok' ? 'bg-green-500' : 'bg-red-500'}`} />
|
|
564
|
+
<span>Overall: {health.status}</span>
|
|
565
|
+
</div>
|
|
566
|
+
{Object.entries(health.services).map(([service, status]: [string, any]) => (
|
|
567
|
+
<div key={service} className="flex items-center gap-2">
|
|
568
|
+
<div className={`w-3 h-3 rounded-full ${status.status === 'ok' ? 'bg-green-500' : 'bg-red-500'}`} />
|
|
569
|
+
<span>{service}: {status.status} ({status.responseTime}ms)</span>
|
|
570
|
+
</div>
|
|
571
|
+
))}
|
|
572
|
+
</div>
|
|
573
|
+
</div>
|
|
574
|
+
)
|
|
575
|
+
}
|
|
576
|
+
```
|
|
577
|
+
|
|
578
|
+
### Synthetic Monitoring
|
|
579
|
+
|
|
580
|
+
Set up synthetic monitoring to test user flows:
|
|
581
|
+
|
|
582
|
+
```typescript
|
|
583
|
+
// Example: Test authentication flow
|
|
584
|
+
async function testAuthentication() {
|
|
585
|
+
const startTime = Date.now()
|
|
586
|
+
|
|
587
|
+
try {
|
|
588
|
+
// 1. Navigate to sign-in page
|
|
589
|
+
const signInPage = await fetch('https://your-app.com/sign-in')
|
|
590
|
+
if (!signInPage.ok) throw new Error('Sign-in page failed')
|
|
591
|
+
|
|
592
|
+
// 2. Submit credentials
|
|
593
|
+
const response = await fetch('https://your-app.com/api/sign-in', {
|
|
594
|
+
method: 'POST',
|
|
595
|
+
body: JSON.stringify({ email: 'test@example.com', password: 'password' }),
|
|
596
|
+
})
|
|
597
|
+
|
|
598
|
+
if (!response.ok) throw new Error('Authentication failed')
|
|
599
|
+
|
|
600
|
+
const duration = Date.now() - startTime
|
|
601
|
+
return { status: 'ok', duration }
|
|
602
|
+
} catch (error) {
|
|
603
|
+
return { status: 'error', error: error instanceof Error ? error.message : 'Unknown error' }
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
```
|
|
607
|
+
|
|
608
|
+
---
|
|
609
|
+
|
|
610
|
+
## Log Management
|
|
611
|
+
|
|
612
|
+
### Vercel Logs
|
|
613
|
+
|
|
614
|
+
#### Access Logs
|
|
615
|
+
|
|
616
|
+
```bash
|
|
617
|
+
# View recent logs
|
|
618
|
+
vercel logs
|
|
619
|
+
|
|
620
|
+
# View logs for specific deployment
|
|
621
|
+
vercel logs <deployment-url>
|
|
622
|
+
|
|
623
|
+
# Follow logs in real-time
|
|
624
|
+
vercel logs --follow
|
|
625
|
+
|
|
626
|
+
# Filter logs
|
|
627
|
+
vercel logs --filter="error"
|
|
628
|
+
```
|
|
629
|
+
|
|
630
|
+
#### Log Levels
|
|
631
|
+
|
|
632
|
+
| Level | Description | Use Case |
|
|
633
|
+
|-------|-------------|----------|
|
|
634
|
+
| **Error** | Error conditions | Critical issues |
|
|
635
|
+
| **Warn** | Warning conditions | Potential issues |
|
|
636
|
+
| **Info** | Informational messages | General information |
|
|
637
|
+
| **Debug** | Debugging messages | Development |
|
|
638
|
+
|
|
639
|
+
### DigitalOcean Droplet Logs
|
|
640
|
+
|
|
641
|
+
#### Application Logs (PM2)
|
|
642
|
+
|
|
643
|
+
```bash
|
|
644
|
+
# View PM2 logs
|
|
645
|
+
pm2 logs
|
|
646
|
+
|
|
647
|
+
# View specific application logs
|
|
648
|
+
pm2 logs dtt-framework
|
|
649
|
+
|
|
650
|
+
# View error logs only
|
|
651
|
+
pm2 logs dtt-framework --err
|
|
652
|
+
|
|
653
|
+
# Clear logs
|
|
654
|
+
pm2 flush
|
|
655
|
+
```
|
|
656
|
+
|
|
657
|
+
#### Nginx Logs
|
|
658
|
+
|
|
659
|
+
```bash
|
|
660
|
+
# View access logs
|
|
661
|
+
tail -f /var/log/nginx/access.log
|
|
662
|
+
|
|
663
|
+
# View error logs
|
|
664
|
+
tail -f /var/log/nginx/error.log
|
|
665
|
+
|
|
666
|
+
# Search for specific patterns
|
|
667
|
+
grep "error" /var/log/nginx/error.log
|
|
668
|
+
```
|
|
669
|
+
|
|
670
|
+
#### System Logs
|
|
671
|
+
|
|
672
|
+
```bash
|
|
673
|
+
# View system logs
|
|
674
|
+
journalctl -f
|
|
675
|
+
|
|
676
|
+
# View specific service logs
|
|
677
|
+
journalctl -u nginx -f
|
|
678
|
+
|
|
679
|
+
# View logs from last hour
|
|
680
|
+
journalctl --since "1 hour ago"
|
|
681
|
+
```
|
|
682
|
+
|
|
683
|
+
### Log Aggregation
|
|
684
|
+
|
|
685
|
+
#### Logtail
|
|
686
|
+
|
|
687
|
+
```bash
|
|
688
|
+
# Install Logtail
|
|
689
|
+
curl -sSL https://logs.betterstack.com/install.sh | bash
|
|
690
|
+
|
|
691
|
+
# Configure
|
|
692
|
+
logtail install --source dtt-framework
|
|
693
|
+
|
|
694
|
+
# View logs
|
|
695
|
+
logtail tail
|
|
696
|
+
```
|
|
697
|
+
|
|
698
|
+
#### Papertrail
|
|
699
|
+
|
|
700
|
+
```bash
|
|
701
|
+
# Install remote_syslog2
|
|
702
|
+
wget https://github.com/papertrail/remote_syslog2/releases/download/v0.20/remote_syslog_linux_amd64.tar.gz
|
|
703
|
+
|
|
704
|
+
# Configure
|
|
705
|
+
cat > /etc/log_files.yml <<EOF
|
|
706
|
+
files:
|
|
707
|
+
- /var/log/nginx/access.log
|
|
708
|
+
- /var/log/nginx/error.log
|
|
709
|
+
destination:
|
|
710
|
+
host: logsXX.papertrailapp.com
|
|
711
|
+
port: XXXXX
|
|
712
|
+
protocol: tls
|
|
713
|
+
EOF
|
|
714
|
+
|
|
715
|
+
# Start service
|
|
716
|
+
remote_syslog
|
|
717
|
+
```
|
|
718
|
+
|
|
719
|
+
---
|
|
720
|
+
|
|
721
|
+
## Alerting
|
|
722
|
+
|
|
723
|
+
### Alert Configuration
|
|
724
|
+
|
|
725
|
+
#### Critical Alerts
|
|
726
|
+
|
|
727
|
+
| Condition | Threshold | Action |
|
|
728
|
+
|-----------|-----------|--------|
|
|
729
|
+
| **Application Down** | Health check fails 3 times | Page team immediately |
|
|
730
|
+
| **Error Rate** | >1% for 5 minutes | Email team |
|
|
731
|
+
| **Response Time** | >5s for 5 minutes | Email team |
|
|
732
|
+
| **Database Down** | Connection fails 3 times | Page team immediately |
|
|
733
|
+
|
|
734
|
+
#### Warning Alerts
|
|
735
|
+
|
|
736
|
+
| Condition | Threshold | Action |
|
|
737
|
+
|-----------|-----------|--------|
|
|
738
|
+
| **High Error Rate** | >0.5% for 10 minutes | Email team |
|
|
739
|
+
| **Slow Response** | >2s for 10 minutes | Email team |
|
|
740
|
+
| **High Memory** | >80% for 15 minutes | Email team |
|
|
741
|
+
| **High CPU** | >80% for 15 minutes | Email team |
|
|
742
|
+
|
|
743
|
+
### Alert Channels
|
|
744
|
+
|
|
745
|
+
#### Email Alerts
|
|
746
|
+
|
|
747
|
+
Configure email alerts in your monitoring tool.
|
|
748
|
+
|
|
749
|
+
#### Slack Alerts
|
|
750
|
+
|
|
751
|
+
Create Slack webhook:
|
|
752
|
+
|
|
753
|
+
```bash
|
|
754
|
+
# Create Slack app
|
|
755
|
+
# https://api.slack.com/apps
|
|
756
|
+
|
|
757
|
+
# Add Incoming Webhook
|
|
758
|
+
# Copy webhook URL
|
|
759
|
+
|
|
760
|
+
# Add to monitoring tool
|
|
761
|
+
```
|
|
762
|
+
|
|
763
|
+
#### PagerDuty Integration
|
|
764
|
+
|
|
765
|
+
```bash
|
|
766
|
+
# Create PagerDuty service
|
|
767
|
+
# Add integration
|
|
768
|
+
# Copy integration key
|
|
769
|
+
|
|
770
|
+
# Add to monitoring tool
|
|
771
|
+
```
|
|
772
|
+
|
|
773
|
+
### Alert Escalation Policy
|
|
774
|
+
|
|
775
|
+
```
|
|
776
|
+
Level 1: Email team (5 minutes)
|
|
777
|
+
↓
|
|
778
|
+
Level 2: Slack channel (10 minutes)
|
|
779
|
+
↓
|
|
780
|
+
Level 3: SMS/Call (15 minutes)
|
|
781
|
+
↓
|
|
782
|
+
Level 4: Manager notification (30 minutes)
|
|
783
|
+
```
|
|
784
|
+
|
|
785
|
+
---
|
|
786
|
+
|
|
787
|
+
## Monitoring Dashboard
|
|
788
|
+
|
|
789
|
+
### Creating a Dashboard
|
|
790
|
+
|
|
791
|
+
Use tools like:
|
|
792
|
+
- **Grafana**: Open-source dashboard
|
|
793
|
+
- **Datadog**: SaaS dashboard
|
|
794
|
+
- **New Relic**: SaaS dashboard
|
|
795
|
+
- **Vercel Dashboard**: Built-in
|
|
796
|
+
|
|
797
|
+
### Dashboard Metrics
|
|
798
|
+
|
|
799
|
+
Include these metrics on your dashboard:
|
|
800
|
+
|
|
801
|
+
| Category | Metrics |
|
|
802
|
+
|----------|---------|
|
|
803
|
+
| **Application** | Request rate, error rate, response time |
|
|
804
|
+
| **Infrastructure** | CPU, memory, disk usage |
|
|
805
|
+
| **Database** | Query time, connection pool, slow queries |
|
|
806
|
+
| **External Services** | API latency, success rate |
|
|
807
|
+
| **Business** | Active users, sign-ups, conversions |
|
|
808
|
+
|
|
809
|
+
---
|
|
810
|
+
|
|
811
|
+
## Monitoring Best Practices
|
|
812
|
+
|
|
813
|
+
### 1. Monitor Everything
|
|
814
|
+
|
|
815
|
+
- Application metrics
|
|
816
|
+
- Infrastructure metrics
|
|
817
|
+
- Business metrics
|
|
818
|
+
- User experience metrics
|
|
819
|
+
|
|
820
|
+
### 2. Set Meaningful Alerts
|
|
821
|
+
|
|
822
|
+
- Alert on actionable issues
|
|
823
|
+
- Avoid alert fatigue
|
|
824
|
+
- Use severity levels
|
|
825
|
+
- Configure escalation
|
|
826
|
+
|
|
827
|
+
### 3. Review Regularly
|
|
828
|
+
|
|
829
|
+
- Daily: Check error rates
|
|
830
|
+
- Weekly: Review performance trends
|
|
831
|
+
- Monthly: Optimize based on data
|
|
832
|
+
|
|
833
|
+
### 4. Document Incidents
|
|
834
|
+
|
|
835
|
+
- Document every incident
|
|
836
|
+
- Track root causes
|
|
837
|
+
- Share learnings
|
|
838
|
+
- Improve processes
|
|
839
|
+
|
|
840
|
+
### 5. Continuous Improvement
|
|
841
|
+
|
|
842
|
+
- Adjust thresholds based on data
|
|
843
|
+
- Add new metrics as needed
|
|
844
|
+
- Remove unused alerts
|
|
845
|
+
- Update dashboards regularly
|
|
846
|
+
|
|
847
|
+
---
|
|
848
|
+
|
|
849
|
+
## Troubleshooting
|
|
850
|
+
|
|
851
|
+
### Issue: Health Check Failing
|
|
852
|
+
|
|
853
|
+
**Symptoms:**
|
|
854
|
+
- Health check returns error
|
|
855
|
+
- Monitoring shows service down
|
|
856
|
+
|
|
857
|
+
**Solutions:**
|
|
858
|
+
|
|
859
|
+
```bash
|
|
860
|
+
# Check health endpoint manually
|
|
861
|
+
curl https://your-app.com/api/health
|
|
862
|
+
|
|
863
|
+
# Check application logs
|
|
864
|
+
vercel logs
|
|
865
|
+
|
|
866
|
+
# Check database connection
|
|
867
|
+
psql $DATABASE_URL -c "SELECT 1"
|
|
868
|
+
|
|
869
|
+
# Restart application
|
|
870
|
+
pm2 restart dtt-framework
|
|
871
|
+
```
|
|
872
|
+
|
|
873
|
+
### Issue: High Error Rate
|
|
874
|
+
|
|
875
|
+
**Symptoms:**
|
|
876
|
+
- Error rate spike
|
|
877
|
+
- Many user complaints
|
|
878
|
+
|
|
879
|
+
**Solutions:**
|
|
880
|
+
|
|
881
|
+
```bash
|
|
882
|
+
# Check error logs
|
|
883
|
+
vercel logs --filter="error"
|
|
884
|
+
|
|
885
|
+
# Check Sentry for recent errors
|
|
886
|
+
# Go to Sentry dashboard
|
|
887
|
+
|
|
888
|
+
# Identify common errors
|
|
889
|
+
# Look for patterns
|
|
890
|
+
|
|
891
|
+
# Fix critical errors first
|
|
892
|
+
# Deploy hotfix if needed
|
|
893
|
+
```
|
|
894
|
+
|
|
895
|
+
### Issue: Slow Response Times
|
|
896
|
+
|
|
897
|
+
**Symptoms:**
|
|
898
|
+
- Pages loading slowly
|
|
899
|
+
- API responses slow
|
|
900
|
+
|
|
901
|
+
**Solutions:**
|
|
902
|
+
|
|
903
|
+
```bash
|
|
904
|
+
# Check response times
|
|
905
|
+
curl -w "@curl-format.txt" https://your-app.com
|
|
906
|
+
|
|
907
|
+
# Check database queries
|
|
908
|
+
# Review slow query logs
|
|
909
|
+
|
|
910
|
+
# Check CDN caching
|
|
911
|
+
# Verify cache headers
|
|
912
|
+
|
|
913
|
+
# Optimize images
|
|
914
|
+
# Use next/image
|
|
915
|
+
```
|
|
916
|
+
|
|
917
|
+
---
|
|
918
|
+
|
|
919
|
+
## Related Documentation
|
|
920
|
+
|
|
921
|
+
- [Vercel Deployment](./vercel.md) - Vercel deployment guide
|
|
922
|
+
- [DigitalOcean Deployment](./digitalocean.md) - DigitalOcean deployment guide
|
|
923
|
+
- [Environment Variables](./environment-variables.md) - Complete variable reference
|
|
924
|
+
- [CI/CD Setup](./ci-cd.md) - Automated deployments
|
|
925
|
+
- [Production Checklist](./production-checklist.md) - Pre-deployment checklist
|
|
926
|
+
- [Domain Setup](./domain-setup.md) - Custom domain configuration
|
|
927
|
+
- [Health Check System](../health-check-system.md) - Built-in health check features
|