nestjs-profiler 1.0.25 → 1.0.27
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/README.md +254 -147
- package/collectors/event-collector.d.ts +18 -0
- package/collectors/event-collector.js +254 -0
- package/collectors/event-collector.js.map +1 -0
- package/common/profiler-options.interface.d.ts +8 -0
- package/common/profiler.model.d.ts +25 -0
- package/controllers/profiler.controller.d.ts +17 -1
- package/controllers/profiler.controller.js +129 -17
- package/controllers/profiler.controller.js.map +1 -1
- package/middleware/profiler-auth.middleware.d.ts +10 -0
- package/middleware/profiler-auth.middleware.js +110 -0
- package/middleware/profiler-auth.middleware.js.map +1 -0
- package/package.json +2 -2
- package/profiler.module.js +103 -1
- package/profiler.module.js.map +1 -1
- package/services/cron-explorer.service.d.ts +48 -0
- package/services/cron-explorer.service.js +260 -0
- package/services/cron-explorer.service.js.map +1 -0
- package/services/entity-explorer.service.d.ts +1 -1
- package/services/entity-explorer.service.js +7 -7
- package/services/entity-explorer.service.js.map +1 -1
- package/services/health.service.js +23 -8
- package/services/health.service.js.map +1 -1
- package/services/profiler.service.d.ts +10 -1
- package/services/profiler.service.js +103 -35
- package/services/profiler.service.js.map +1 -1
- package/services/route-explorer.service.d.ts +23 -1
- package/services/route-explorer.service.js +136 -10
- package/services/route-explorer.service.js.map +1 -1
- package/services/template-builder.service.d.ts +1 -0
- package/services/template-builder.service.js +184 -83
- package/services/template-builder.service.js.map +1 -1
- package/services/view.service.d.ts +1 -1
- package/services/view.service.js +32 -23
- package/services/view.service.js.map +1 -1
- package/views/cron-jobs.html +635 -0
- package/views/events.html +763 -0
- package/views/layout.html +40 -9
- package/views/login.html +277 -0
- package/views/routes.html +405 -37
package/README.md
CHANGED
|
@@ -4,253 +4,360 @@
|
|
|
4
4
|
<img src="https://raw.githubusercontent.com/MohammedRaslan/Nest-JS-Profiler/refs/heads/main/libs/nestjs-profiler/src/assets/logo.png" width="400" alt="NestJS Profiler Logo" />
|
|
5
5
|
</p>
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
<p align="center">
|
|
8
|
+
<a href="https://www.npmjs.com/package/nestjs-profiler"><img src="https://img.shields.io/npm/v/nestjs-profiler.svg" alt="npm version" /></a>
|
|
9
|
+
<a href="https://www.npmjs.com/package/nestjs-profiler"><img src="https://img.shields.io/npm/dm/nestjs-profiler.svg" alt="npm downloads" /></a>
|
|
10
|
+
<img src="https://img.shields.io/badge/node-%3E%3D16-brightgreen" alt="node version" />
|
|
11
|
+
<img src="https://img.shields.io/badge/license-MIT-blue" alt="license" />
|
|
12
|
+
</p>
|
|
8
13
|
|
|
9
|
-
|
|
14
|
+
> A drop-in debugging dashboard for NestJS. Inspect HTTP requests, database queries, outbound calls, logs, events, scheduled jobs, and code health — all from one browser tab, with zero instrumentation required.
|
|
10
15
|
|
|
11
|
-
|
|
12
|
-
- **Database Profiling**
|
|
13
|
-
- **PostgreSQL** — Captures all queries via `pg` (compatible with TypeORM, MikroORM, raw pg). Supports **Auto-Explain** to run `EXPLAIN` or `EXPLAIN ANALYZE` on slow queries automatically.
|
|
14
|
-
- **MongoDB** — Profiles MongoDB commands and queries.
|
|
15
|
-
- **MySQL** — Profiles MySQL queries.
|
|
16
|
-
- **N+1 Detection** — Automatically flags repeated identical queries within the same request.
|
|
17
|
-
- **Slow Query Tagging** — Tags queries exceeding 100ms.
|
|
18
|
-
- **Sequential Scan Detection** — Tags queries using a Seq Scan from the explain plan.
|
|
19
|
-
- **Outbound HTTP Tracking** — Captures every outbound `http`/`https` call made during a request: URL, method, status code, duration, and headers. Works automatically with axios, node-fetch, and any library built on Node's `http`/`https` modules. Enabled by default — no configuration required.
|
|
20
|
-
- **Cache Profiling** — Tracks cache operations (get, set, del, reset) and hit/miss ratio when using `@nestjs/cache-manager`.
|
|
21
|
-
- **Log Profiling** — Captures application logs associated with each request context.
|
|
22
|
-
- **Live Logs Terminal** — Real-time streaming log viewer at `/__profiler/view/logs/live` via Server-Sent Events. Supports level filtering, search, pause/resume, and auto-scroll.
|
|
23
|
-
- **Summary Dashboard** — Aggregate statistics: avg/p95 duration, error rate, cache hit rate, top slow endpoints, top slow queries, and recent errors.
|
|
24
|
-
- **Entity Explorer** — Lists all registered TypeORM/MikroORM entities and their columns.
|
|
25
|
-
- **Route Explorer** — Lists all registered routes with their controllers and handlers.
|
|
26
|
-
- **Package Health** — Runs `npm audit` and `npm outdated` to surface known vulnerabilities and stale dependencies. Results are cached for 5 minutes. Works with npm, yarn, and pnpm. If the registry is unreachable, outdated packages are still shown with an inline warning.
|
|
27
|
-
- **Code Quality** — Runs ESLint and TypeScript compiler checks (`tsc --noEmit`) against your source code. Issues are displayed grouped by file or by rule, with direct links to ESLint rule docs and TypeScript error references. Auto-fixable issues are flagged. File paths are copyable with one click.
|
|
28
|
-
- **Web UI** — Built-in dashboard at `/__profiler` with no external dependencies.
|
|
29
|
-
- **Zero Hard Dependencies** — Core functionality works out of the box; database drivers are optional peer dependencies.
|
|
16
|
+
---
|
|
30
17
|
|
|
31
|
-
|
|
18
|
+
> ⚠️ **Development use only.** The profiler adds request overhead and exposes internal application data. Always set `enabled: process.env.NODE_ENV !== 'production'`.
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## Quick Start
|
|
23
|
+
|
|
24
|
+
**1. Install**
|
|
32
25
|
|
|
33
26
|
```bash
|
|
34
27
|
npm install nestjs-profiler
|
|
35
28
|
```
|
|
36
29
|
|
|
37
|
-
|
|
30
|
+
**2. Register in your AppModule**
|
|
31
|
+
|
|
32
|
+
```typescript
|
|
33
|
+
import { ProfilerModule } from 'nestjs-profiler';
|
|
34
|
+
|
|
35
|
+
@Module({
|
|
36
|
+
imports: [
|
|
37
|
+
ProfilerModule.forRoot({
|
|
38
|
+
enabled: process.env.NODE_ENV !== 'production',
|
|
39
|
+
}),
|
|
40
|
+
],
|
|
41
|
+
})
|
|
42
|
+
export class AppModule {}
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
**3. Initialize in main.ts**
|
|
46
|
+
|
|
47
|
+
```typescript
|
|
48
|
+
import { ProfilerModule } from 'nestjs-profiler';
|
|
49
|
+
|
|
50
|
+
async function bootstrap() {
|
|
51
|
+
const app = await NestFactory.create(AppModule);
|
|
52
|
+
ProfilerModule.initialize(app); // enables Route Explorer, Entity Explorer, Scheduled Jobs
|
|
53
|
+
await app.listen(3000);
|
|
54
|
+
}
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
### Global Prefix (Required if you use global route prefix)
|
|
60
|
+
|
|
61
|
+
If your app uses a global route prefix, exclude the profiler:
|
|
62
|
+
|
|
63
|
+
```typescript
|
|
64
|
+
app.setGlobalPrefix('api', {
|
|
65
|
+
exclude: [{ path: '__profiler/(.*)', method: RequestMethod.ALL }],
|
|
66
|
+
});
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Open `http://localhost:3000/__profiler` — the dashboard is live.
|
|
38
70
|
|
|
39
|
-
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
## Features
|
|
74
|
+
|
|
75
|
+
### Request Profiling
|
|
76
|
+
- Traces every HTTP request: method, URL, handler, status code, duration, headers, and body
|
|
77
|
+
- Summary dashboard with avg/p95 duration, error rate, cache hit rate, top slow endpoints, and recent errors
|
|
78
|
+
- Full detail view per request including all associated queries, cache ops, logs, and outbound calls
|
|
79
|
+
|
|
80
|
+
### Database
|
|
81
|
+
- **PostgreSQL** — captures all queries via `pg`, compatible with TypeORM, MikroORM, and raw pg
|
|
82
|
+
- **MongoDB** — profiles all MongoDB commands
|
|
83
|
+
- **MySQL** — profiles MySQL queries via `mysql2`
|
|
84
|
+
- **N+1 Detection** — flags repeated identical queries within the same request
|
|
85
|
+
- **Slow Query Tagging** — highlights queries over 100ms
|
|
86
|
+
- **Sequential Scan Detection** — flags full table scans from the query explain plan
|
|
87
|
+
- **Auto-Explain** — automatically runs `EXPLAIN` or `EXPLAIN ANALYZE` on slow queries (opt-in)
|
|
88
|
+
|
|
89
|
+
### Outbound HTTP
|
|
90
|
+
Automatically captures every `http`/`https` call your app makes — including axios, node-fetch, and any library built on Node's core modules. Records method, URL, status code, duration, headers (with Authorization and Cookie values redacted), and errors. No configuration required.
|
|
91
|
+
|
|
92
|
+
### Cache
|
|
93
|
+
Tracks `get`, `set`, `del`, and `reset` operations with hit/miss ratio when using `@nestjs/cache-manager`.
|
|
94
|
+
|
|
95
|
+
### Logs
|
|
96
|
+
- Captures application logs per request context
|
|
97
|
+
- **Live Logs Terminal** — real-time streaming viewer via Server-Sent Events, with level filtering, search, pause/resume, and auto-scroll
|
|
98
|
+
|
|
99
|
+
### Code Analysis
|
|
100
|
+
- **Package Health** — runs `npm audit` and `npm outdated` to surface vulnerabilities and stale dependencies, sorted by severity
|
|
101
|
+
- **Code Quality** — runs ESLint and `tsc --noEmit` against your source. Issues shown by file or by rule, with links to rule docs and TypeScript error references. Auto-fixable issues are flagged
|
|
102
|
+
|
|
103
|
+
### Application Intelligence
|
|
104
|
+
- **Route Explorer** — every registered route grouped by controller, with path/query/header params, body DTOs, property types, and source file paths
|
|
105
|
+
- **Entity Explorer** — all registered TypeORM/MikroORM entities with their columns
|
|
106
|
+
- **Event Tracking** — intercepts every `EventEmitter2` emission and renders a cascading tree: which service fired it, which listeners handled it, individual timings, child events, and errors. Requires `@nestjs/event-emitter`
|
|
107
|
+
- **Scheduled Jobs** — live view of all `@Cron`, `@Interval`, and `@Timeout` jobs from `@nestjs/schedule`, with countdowns, last run times, cycle progress, and handler details. Requires `@nestjs/schedule`
|
|
108
|
+
|
|
109
|
+
### Security
|
|
110
|
+
- **Dashboard Authentication** — optional login wall with HMAC-SHA256 tokens stored in `localStorage`, 24-hour TTL. No separate auth server needed
|
|
111
|
+
|
|
112
|
+
---
|
|
113
|
+
|
|
114
|
+
## Installation
|
|
40
115
|
|
|
41
116
|
```bash
|
|
42
|
-
|
|
43
|
-
|
|
117
|
+
npm install nestjs-profiler
|
|
118
|
+
```
|
|
44
119
|
|
|
45
|
-
|
|
46
|
-
npm install mongodb
|
|
120
|
+
### Optional Peer Dependencies
|
|
47
121
|
|
|
48
|
-
|
|
49
|
-
npm install mysql2
|
|
122
|
+
Install only what your project uses:
|
|
50
123
|
|
|
51
|
-
|
|
52
|
-
npm install
|
|
124
|
+
```bash
|
|
125
|
+
npm install pg # PostgreSQL
|
|
126
|
+
npm install mongodb # MongoDB
|
|
127
|
+
npm install mysql2 # MySQL
|
|
128
|
+
npm install @nestjs/cache-manager cache-manager # Cache profiling
|
|
129
|
+
npm install @nestjs/event-emitter # Event tracking
|
|
130
|
+
npm install @nestjs/schedule # Scheduled jobs
|
|
53
131
|
```
|
|
54
132
|
|
|
133
|
+
---
|
|
134
|
+
|
|
55
135
|
## Configuration
|
|
56
136
|
|
|
57
|
-
|
|
137
|
+
All options are passed to `ProfilerModule.forRoot()`. Only `enabled` is required — everything else is opt-in.
|
|
58
138
|
|
|
59
139
|
```typescript
|
|
60
|
-
import { Module } from '@nestjs/common';
|
|
61
140
|
import { ProfilerModule } from 'nestjs-profiler';
|
|
62
141
|
import * as pg from 'pg';
|
|
63
142
|
|
|
64
143
|
@Module({
|
|
65
144
|
imports: [
|
|
66
145
|
ProfilerModule.forRoot({
|
|
67
|
-
// Global enable/disable (default: true)
|
|
68
|
-
// Recommended: disable in production
|
|
69
146
|
enabled: process.env.NODE_ENV !== 'production',
|
|
70
147
|
|
|
71
|
-
//
|
|
72
|
-
// PostgreSQL — pass the pg driver instance
|
|
148
|
+
// PostgreSQL
|
|
73
149
|
pgDriver: pg,
|
|
74
150
|
collectQueries: true,
|
|
75
|
-
|
|
76
|
-
// Auto-Explain for slow queries
|
|
77
151
|
explain: {
|
|
78
152
|
enabled: true,
|
|
79
|
-
thresholdMs:
|
|
80
|
-
analyze: false, // true = EXPLAIN ANALYZE (
|
|
153
|
+
thresholdMs: 100, // explain queries slower than this
|
|
154
|
+
analyze: false, // true = EXPLAIN ANALYZE (executes the query!)
|
|
81
155
|
},
|
|
82
156
|
|
|
83
|
-
// MongoDB
|
|
157
|
+
// MongoDB
|
|
84
158
|
mongoDriver: require('mongodb'),
|
|
85
159
|
collectMongo: true,
|
|
86
160
|
|
|
87
|
-
// MySQL
|
|
161
|
+
// MySQL
|
|
88
162
|
mysqlDriver: require('mysql2'),
|
|
89
163
|
collectMysql: true,
|
|
90
164
|
|
|
91
|
-
//
|
|
92
|
-
// Tracks all outbound http/https calls made during each request.
|
|
93
|
-
// Enabled by default — set false to disable.
|
|
165
|
+
// Outbound HTTP (on by default)
|
|
94
166
|
collectHttp: true,
|
|
95
167
|
|
|
96
|
-
//
|
|
97
|
-
collectCache: true,
|
|
168
|
+
// Cache
|
|
169
|
+
collectCache: true,
|
|
98
170
|
|
|
99
|
-
//
|
|
171
|
+
// Logs
|
|
100
172
|
collectLogs: true,
|
|
101
173
|
|
|
102
|
-
//
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
174
|
+
// Auth (off by default)
|
|
175
|
+
auth: {
|
|
176
|
+
enabled: true,
|
|
177
|
+
username: 'admin',
|
|
178
|
+
password: 'supersecret',
|
|
179
|
+
},
|
|
106
180
|
}),
|
|
107
181
|
],
|
|
108
182
|
})
|
|
109
183
|
export class AppModule {}
|
|
110
184
|
```
|
|
111
185
|
|
|
112
|
-
###
|
|
186
|
+
### Options Reference
|
|
113
187
|
|
|
114
|
-
| Option | Default |
|
|
188
|
+
| Option | Default | Description |
|
|
115
189
|
|---|---|---|
|
|
116
|
-
| `enabled` | `true` |
|
|
117
|
-
| `collectHttp` | `true` |
|
|
118
|
-
| `collectLogs` | `true` | |
|
|
119
|
-
| `collectQueries` | `true` | Requires
|
|
120
|
-
| `collectCache` | `true` | Requires `@nestjs/cache-manager` |
|
|
121
|
-
| `explain.enabled` | `false` |
|
|
122
|
-
|
|
123
|
-
|
|
190
|
+
| `enabled` | `true` | Master switch. Tie to `NODE_ENV` in production |
|
|
191
|
+
| `collectHttp` | `true` | Outbound HTTP tracking (patches `http`/`https`) |
|
|
192
|
+
| `collectLogs` | `true` | Log capture per request |
|
|
193
|
+
| `collectQueries` | `true` | DB query capture. Requires a driver to be passed |
|
|
194
|
+
| `collectCache` | `true` | Cache op tracking. Requires `@nestjs/cache-manager` |
|
|
195
|
+
| `explain.enabled` | `false` | Auto-Explain for slow queries |
|
|
196
|
+
| `explain.thresholdMs` | `100` | Minimum query duration to trigger explain |
|
|
197
|
+
| `explain.analyze` | `false` | Run `EXPLAIN ANALYZE` instead of `EXPLAIN` |
|
|
198
|
+
| `auth.enabled` | `false` | Enable login wall. `username` and `password` required when `true` |
|
|
199
|
+
| Event Tracking | automatic | Activates when `@nestjs/event-emitter` is detected |
|
|
200
|
+
| Scheduled Jobs | automatic | Activates when `@nestjs/schedule` is detected |
|
|
124
201
|
|
|
125
|
-
|
|
202
|
+
---
|
|
126
203
|
|
|
127
|
-
|
|
204
|
+
## Dashboard
|
|
128
205
|
|
|
129
|
-
|
|
130
|
-
import { NestFactory } from '@nestjs/core';
|
|
131
|
-
import { AppModule } from './app.module';
|
|
132
|
-
import { ProfilerModule } from 'nestjs-profiler';
|
|
206
|
+
Navigate to `/__profiler` after starting your app.
|
|
133
207
|
|
|
134
|
-
|
|
135
|
-
const app = await NestFactory.create(AppModule);
|
|
136
|
-
|
|
137
|
-
ProfilerModule.initialize(app);
|
|
138
|
-
|
|
139
|
-
await app.listen(3000);
|
|
140
|
-
}
|
|
141
|
-
bootstrap();
|
|
142
|
-
```
|
|
143
|
-
|
|
144
|
-
### 2. Accessing the Dashboard
|
|
145
|
-
|
|
146
|
-
Once configured, start your application. The profiler automatically intercepts all requests.
|
|
147
|
-
|
|
148
|
-
Navigate to `http://localhost:3000/__profiler`.
|
|
149
|
-
|
|
150
|
-
#### Dashboard Pages
|
|
151
|
-
|
|
152
|
-
| Path | Description |
|
|
208
|
+
| Page | Description |
|
|
153
209
|
|---|---|
|
|
154
|
-
| `/__profiler` | Redirects to Summary (default landing page) |
|
|
155
210
|
| `/__profiler/view/summary` | Aggregate stats: avg/p95 duration, error rate, top slow endpoints |
|
|
156
|
-
| `/__profiler/view/requests` | All captured requests |
|
|
157
|
-
| `/__profiler/view/queries` | All
|
|
158
|
-
| `/__profiler/view/http-calls` | All outbound HTTP calls
|
|
211
|
+
| `/__profiler/view/requests` | All captured requests with status, duration, and method |
|
|
212
|
+
| `/__profiler/view/queries` | All DB queries across requests, sortable by duration |
|
|
213
|
+
| `/__profiler/view/http-calls` | All outbound HTTP calls, sortable by duration |
|
|
159
214
|
| `/__profiler/view/logs` | Paginated application logs |
|
|
160
|
-
| `/__profiler/view/logs/live` |
|
|
215
|
+
| `/__profiler/view/logs/live` | Real-time streaming log terminal |
|
|
161
216
|
| `/__profiler/view/cache` | Cache operations with hit/miss breakdown |
|
|
162
|
-
| `/__profiler/view/entities` | Registered database entities |
|
|
163
|
-
| `/__profiler/view/routes` | All registered
|
|
217
|
+
| `/__profiler/view/entities` | Registered database entities and their columns |
|
|
218
|
+
| `/__profiler/view/routes` | All registered routes with DTOs and parameter types |
|
|
164
219
|
| `/__profiler/view/health` | Package vulnerabilities and outdated dependency report |
|
|
165
|
-
| `/__profiler/view/code-quality` | ESLint and TypeScript static analysis
|
|
220
|
+
| `/__profiler/view/code-quality` | ESLint and TypeScript static analysis |
|
|
221
|
+
| `/__profiler/view/events` | Event cascade tree for `EventEmitter2` emissions |
|
|
222
|
+
| `/__profiler/view/cron-jobs` | Live scheduled job monitor — cron, intervals, and timeouts |
|
|
166
223
|
| `/__profiler/:id` | Full detail view for a single request |
|
|
167
224
|
|
|
168
|
-
###
|
|
225
|
+
### JSON API
|
|
169
226
|
|
|
170
|
-
|
|
227
|
+
All data is also available as JSON for programmatic use:
|
|
171
228
|
|
|
172
|
-
|
|
229
|
+
```
|
|
230
|
+
GET /__profiler/json # all captured requests
|
|
231
|
+
GET /__profiler/:id/json # single request detail
|
|
232
|
+
GET /__profiler/api/health # package health (5 min cache)
|
|
233
|
+
GET /__profiler/api/health?force=true
|
|
234
|
+
GET /__profiler/api/code-quality # static analysis (5 min cache)
|
|
235
|
+
GET /__profiler/api/code-quality?force=true
|
|
236
|
+
GET /__profiler/api/events # event log (live, not cached)
|
|
237
|
+
GET /__profiler/api/cron-jobs # scheduled job state (live, not cached)
|
|
238
|
+
```
|
|
173
239
|
|
|
174
|
-
|
|
175
|
-
- HTTP vs HTTPS protocol
|
|
176
|
-
- Response status code
|
|
177
|
-
- Duration in ms
|
|
178
|
-
- Request and response headers (Authorization/Cookie values are automatically redacted)
|
|
179
|
-
- Error message if the call failed
|
|
240
|
+
---
|
|
180
241
|
|
|
181
|
-
|
|
242
|
+
## Feature Guides
|
|
182
243
|
|
|
183
|
-
|
|
244
|
+
### Dashboard Authentication
|
|
184
245
|
|
|
185
246
|
```typescript
|
|
186
|
-
ProfilerModule.forRoot({
|
|
247
|
+
ProfilerModule.forRoot({
|
|
248
|
+
auth: {
|
|
249
|
+
enabled: true,
|
|
250
|
+
username: 'admin',
|
|
251
|
+
password: 'supersecret',
|
|
252
|
+
},
|
|
253
|
+
})
|
|
187
254
|
```
|
|
188
255
|
|
|
189
|
-
|
|
256
|
+
When enabled, all `/__profiler` pages check for a valid token in `localStorage` before rendering. If none is found, the browser redirects to the login page. Tokens use HMAC-SHA256 keyed on the password and expire after 24 hours — changing the password invalidates all active sessions automatically.
|
|
190
257
|
|
|
191
|
-
|
|
258
|
+
TypeScript enforces that `username` and `password` are present when `enabled: true`. Omitting either is a compile-time error.
|
|
192
259
|
|
|
193
|
-
|
|
194
|
-
- **Outdated packages** — shows current, wanted, and latest versions with major-update warnings.
|
|
195
|
-
- Results are **cached for 5 minutes** server-side. Navigating back to the tab shows the cached result instantly without re-running. Click **Re-run audit** to force a fresh scan.
|
|
196
|
-
- If `npm audit` cannot reach the registry (e.g. VPN or proxy), the outdated packages section still renders with an inline warning for the unavailable audit.
|
|
197
|
-
- No configuration required — works automatically for npm, yarn, and pnpm projects.
|
|
260
|
+
> Auth is enforced client-side. It prevents casual access on shared dev/staging environments but is not a security boundary for sensitive data.
|
|
198
261
|
|
|
199
|
-
|
|
262
|
+
| Route | Purpose |
|
|
263
|
+
|---|---|
|
|
264
|
+
| `GET /__profiler/login` | Login page |
|
|
265
|
+
| `POST /__profiler/api/login` | Validates credentials, returns a session token |
|
|
266
|
+
| `GET /__profiler/logout` | Clears the token and redirects to login |
|
|
200
267
|
|
|
201
|
-
|
|
202
|
-
GET /__profiler/api/health # cached result (5 min TTL)
|
|
203
|
-
GET /__profiler/api/health?force=true # force fresh scan
|
|
204
|
-
```
|
|
268
|
+
---
|
|
205
269
|
|
|
206
|
-
###
|
|
270
|
+
### Event Tracking
|
|
207
271
|
|
|
208
|
-
|
|
272
|
+
Requires `@nestjs/event-emitter`:
|
|
209
273
|
|
|
210
|
-
|
|
274
|
+
```typescript
|
|
275
|
+
import { EventEmitterModule } from '@nestjs/event-emitter';
|
|
211
276
|
|
|
212
|
-
|
|
213
|
-
|
|
277
|
+
@Module({
|
|
278
|
+
imports: [EventEmitterModule.forRoot()],
|
|
279
|
+
})
|
|
280
|
+
export class AppModule {}
|
|
281
|
+
```
|
|
214
282
|
|
|
215
|
-
|
|
283
|
+
The profiler intercepts every `emit` and `emitAsync` call automatically. No decorators or instrumentation needed. The dashboard renders a full cascade tree showing the emitter, all listeners with timings, child events, and any listener errors.
|
|
216
284
|
|
|
217
|
-
**
|
|
285
|
+
**Example — what you see in the dashboard:**
|
|
218
286
|
|
|
219
|
-
|
|
287
|
+
```
|
|
288
|
+
🔔 order.created (async) ⬆ OrderService.createOrder 145ms
|
|
289
|
+
✓ onOrderCreated [InventoryListener] 45ms
|
|
290
|
+
✓ onOrderCreated [InvoiceListener] 80ms
|
|
291
|
+
✓ onOrderCreated [AuditListener] 5ms
|
|
292
|
+
└── 🔔 inventory.reserved ⬆ InventoryListener 23ms
|
|
293
|
+
✓ onInventoryReserved [NotificationListener] 20ms
|
|
294
|
+
└── 🔔 invoice.created ⬆ InvoiceListener 4ms
|
|
295
|
+
✓ onInvoiceCreated [AuditListener] 3ms
|
|
296
|
+
```
|
|
220
297
|
|
|
221
|
-
|
|
298
|
+
---
|
|
222
299
|
|
|
223
|
-
|
|
300
|
+
### Scheduled Jobs
|
|
224
301
|
|
|
225
|
-
|
|
302
|
+
Requires `@nestjs/schedule`:
|
|
226
303
|
|
|
304
|
+
```bash
|
|
305
|
+
npm install @nestjs/schedule
|
|
227
306
|
```
|
|
228
|
-
|
|
229
|
-
|
|
307
|
+
|
|
308
|
+
```typescript
|
|
309
|
+
import { ScheduleModule } from '@nestjs/schedule';
|
|
310
|
+
|
|
311
|
+
@Module({
|
|
312
|
+
imports: [ScheduleModule.forRoot()],
|
|
313
|
+
})
|
|
314
|
+
export class AppModule {}
|
|
230
315
|
```
|
|
231
316
|
|
|
232
|
-
|
|
317
|
+
The profiler detects `SchedulerRegistry` at startup via `ProfilerModule.initialize(app)` — no additional configuration needed. The dashboard has three tabs:
|
|
233
318
|
|
|
234
|
-
|
|
319
|
+
**Cron Jobs** — one card per `@Cron()` method showing the expression with a plain-English translation (e.g. `0 */5 * * * *` → *Every 5 minutes*), a live next-run countdown, last run time, cycle progress bar, handler name, and source file path. An *Upcoming — next 3 hours* strip at the top plots all jobs on a shared timeline.
|
|
235
320
|
|
|
236
|
-
|
|
237
|
-
- `GET /__profiler/:id/json` — Details for a specific request
|
|
321
|
+
**Intervals** — one card per `@Interval()` method with an animated frequency ring, the repeat period displayed prominently (e.g. *Every 30s*), and fires-per-minute count.
|
|
238
322
|
|
|
239
|
-
|
|
323
|
+
**Timeouts** — one card per `@Timeout()` method. Pending jobs show a live countdown in amber; fired jobs turn grey with a *Fired* badge. Both show the configured delay and the handler that will run.
|
|
240
324
|
|
|
241
|
-
|
|
325
|
+
All tabs auto-refresh every 15 seconds. If `@nestjs/schedule` is not installed, the page shows an install prompt instead of an error.
|
|
326
|
+
|
|
327
|
+
**Example:**
|
|
242
328
|
|
|
243
329
|
```typescript
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
330
|
+
import { Cron, CronExpression, Interval, Timeout } from '@nestjs/schedule';
|
|
331
|
+
|
|
332
|
+
@Injectable()
|
|
333
|
+
export class TasksService {
|
|
334
|
+
|
|
335
|
+
@Cron(CronExpression.EVERY_MINUTE, { name: 'health-ping' })
|
|
336
|
+
handleHealthPing() { /* ... */ }
|
|
337
|
+
|
|
338
|
+
@Cron('0 0 * * *', { name: 'nightly-cleanup' })
|
|
339
|
+
handleNightlyCleanup() { /* ... */ }
|
|
340
|
+
|
|
341
|
+
@Interval('metrics-flush', 30_000)
|
|
342
|
+
handleMetricsFlush() { /* ... */ }
|
|
343
|
+
|
|
344
|
+
@Timeout('deferred-init', 10_000)
|
|
345
|
+
handleDeferredInit() { /* ... */ }
|
|
346
|
+
}
|
|
247
347
|
```
|
|
248
348
|
|
|
249
|
-
|
|
349
|
+
---
|
|
350
|
+
|
|
351
|
+
### Route Explorer
|
|
352
|
+
|
|
353
|
+
Populated by `ProfilerModule.initialize(app)`. Lists every route grouped by controller in an expandable accordion. Each route surfaces:
|
|
354
|
+
|
|
355
|
+
- HTTP method and full path (including global prefix)
|
|
356
|
+
- Path parameters, query parameters, and headers with their TypeScript types
|
|
357
|
+
- Body DTO — class name, all decorated properties and types (discovered via `reflect-metadata`)
|
|
358
|
+
- Source file path with a one-click copy button
|
|
250
359
|
|
|
251
|
-
|
|
252
|
-
- The default in-memory storage holds the last 100 requests. Older profiles are evicted automatically.
|
|
253
|
-
- Outbound HTTP tracking patches `http`/`https` at the Node.js module level. The patch is applied once on module init and is safe for hot-reload (double-patch is guarded).
|
|
360
|
+
Works with `emitDecoratorMetadata: true` (standard in NestJS). No OpenAPI/Swagger required.
|
|
254
361
|
|
|
255
362
|
## License
|
|
256
363
|
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { OnModuleInit } from '@nestjs/common';
|
|
2
|
+
import { ProfilerService } from '../services/profiler.service';
|
|
3
|
+
export declare class EventCollector implements OnModuleInit {
|
|
4
|
+
private readonly profilerService;
|
|
5
|
+
private readonly eventEmitter?;
|
|
6
|
+
private resolvedListenerNames;
|
|
7
|
+
private readonly listenerRegistrationCounters;
|
|
8
|
+
constructor(profilerService: ProfilerService, eventEmitter?: any | undefined);
|
|
9
|
+
setListenerNames(map: Map<string, Array<{
|
|
10
|
+
name: string;
|
|
11
|
+
file: string;
|
|
12
|
+
}>>): void;
|
|
13
|
+
onModuleInit(): void;
|
|
14
|
+
private patchEmitter;
|
|
15
|
+
private buildProfile;
|
|
16
|
+
private serializePayload;
|
|
17
|
+
private getCallerLocation;
|
|
18
|
+
}
|