nestjs-profiler 1.0.21 → 1.0.24

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 CHANGED
@@ -4,19 +4,27 @@
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
- A NestJS module for profiling HTTP requests, database queries, and cache operations. Inspired by Symfony Profiler, it provides a web-based dashboard to inspect request duration, executed queries, log messages, and explain plans for slow queries.
7
+ A NestJS module for profiling HTTP requests, database queries, cache operations, outbound HTTP calls, and application logs. Inspired by Symfony Profiler, it provides a web-based dashboard to inspect everything that happens inside a request from DB queries to downstream API calls in real time.
8
8
 
9
9
  ## Features
10
10
 
11
- - **HTTP Request Tracing**: Tracks method, URL, controller handler, duration, and status code.
12
- - **Database Profiling**:
13
- - **PostgreSQL**: Captures queries executed via `pg` (compatible with TypeORM, MikroORM, raw pg). Supports **Auto-Explain** to running `EXPLAIN` or `EXPLAIN ANALYZE` on slow queries.
14
- - **MongoDB**: Profiles MongoDB commands and queries.
15
- - **MySQL**: Profiles MySQL queries.
16
- - **Cache Profiling**: Tracks cache operations (get, set, del) when using `@nestjs/cache-manager`.
17
- - **Logger Profiling**: Captures application logs associated with the request context.
18
- - **Web UI**: Built-in lightweight dashboard at `/__profiler` to view traces.
19
- - **Zero Hard Dependencies**: Core functionality works out of the box; database drivers are optional peer dependencies.
11
+ - **HTTP Request Tracing** Tracks method, URL, controller handler, duration, status code, headers, and request body.
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
+ - **Web UI** — Built-in dashboard at `/__profiler` with no external dependencies.
27
+ - **Zero Hard Dependencies** — Core functionality works out of the box; database drivers are optional peer dependencies.
20
28
 
21
29
  ## Installation
22
30
 
@@ -26,7 +34,7 @@ npm install nestjs-profiler
26
34
 
27
35
  ### Peer Dependencies (Optional)
28
36
 
29
- Install the dependencies relevant to your project:
37
+ Install only the dependencies relevant to your project:
30
38
 
31
39
  ```bash
32
40
  # For PostgreSQL
@@ -44,48 +52,54 @@ npm install @nestjs/cache-manager cache-manager
44
52
 
45
53
  ## Configuration
46
54
 
47
- Import `ProfilerModule` in your root `AppModule`.
55
+ Import `ProfilerModule` in your root `AppModule`:
48
56
 
49
57
  ```typescript
50
58
  import { Module } from '@nestjs/common';
51
59
  import { ProfilerModule } from 'nestjs-profiler';
60
+ import * as pg from 'pg';
52
61
 
53
62
  @Module({
54
63
  imports: [
55
64
  ProfilerModule.forRoot({
56
65
  // Global enable/disable (default: true)
66
+ // Recommended: disable in production
57
67
  enabled: process.env.NODE_ENV !== 'production',
58
68
 
59
- // PostgreSQL Profiling
69
+ // ── Database ─────────────────────────────────────────────────
70
+ // PostgreSQL — pass the pg driver instance
71
+ pgDriver: pg,
60
72
  collectQueries: true,
73
+
74
+ // Auto-Explain for slow queries
61
75
  explain: {
62
76
  enabled: true,
63
- thresholdMs: 50, // Only explain queries taking > 50ms
64
- analyze: false, // If true, runs EXPLAIN ANALYZE (execution!)
77
+ thresholdMs: 50, // Only explain queries taking > 50ms
78
+ analyze: false, // true = EXPLAIN ANALYZE (actually executes!)
65
79
  },
66
- // Add pgDriver
67
- pgDriver: pg,
68
-
69
- // Add mysql2 driver for MySQL profiling
70
- mysqlDriver: mysql2,
71
80
 
72
- // Add mongodb driver for MongoDB profiling
73
- mongoDriver: mongodb,
74
-
75
- // MongoDB Profiling (default: true)
81
+ // MongoDB — pass the mongodb driver instance
82
+ mongoDriver: require('mongodb'),
76
83
  collectMongo: true,
77
84
 
78
- // MySQL Profiling (default: true)
85
+ // MySQL pass the mysql2 driver instance
86
+ mysqlDriver: require('mysql2'),
79
87
  collectMysql: true,
80
88
 
81
- // Cache Profiling (default: true)
82
- collectCache: true,
89
+ // ── Outbound HTTP ─────────────────────────────────────────────
90
+ // Tracks all outbound http/https calls made during each request.
91
+ // Enabled by default — set false to disable.
92
+ collectHttp: true,
93
+
94
+ // ── Cache ─────────────────────────────────────────────────────
95
+ collectCache: true, // requires @nestjs/cache-manager
83
96
 
84
- // Log Profiling (default: true)
97
+ // ── Logs ──────────────────────────────────────────────────────
85
98
  collectLogs: true,
86
99
 
87
- // Storage backend (default: InMemory)
88
- // You can implement custom storage by passing an object implementing ProfilerStorage
100
+ // ── Storage ───────────────────────────────────────────────────
101
+ // Default: in-memory (last 100 requests).
102
+ // Pass a custom object implementing ProfilerStorage for persistence.
89
103
  storage: 'memory',
90
104
  }),
91
105
  ],
@@ -93,14 +107,24 @@ import { ProfilerModule } from 'nestjs-profiler';
93
107
  export class AppModule {}
94
108
  ```
95
109
 
110
+ ### Default behaviour
111
+
112
+ | Option | Default | Notes |
113
+ |---|---|---|
114
+ | `enabled` | `true` | Set `false` or tie to `NODE_ENV` |
115
+ | `collectHttp` | `true` | Patches `http`/`https` automatically |
116
+ | `collectLogs` | `true` | |
117
+ | `collectQueries` | `true` | Requires `pgDriver` / `mongoDriver` / `mysqlDriver` |
118
+ | `collectCache` | `true` | Requires `@nestjs/cache-manager` |
119
+ | `explain.enabled` | `false` | Opt-in only |
120
+
96
121
  ## Usage
97
122
 
98
123
  ### 1. Initialize Explorers (Optional but Recommended)
99
124
 
100
- To enable the **Entity Explorer** and **Route Explorer** features in the dashboard, initialize the profiler in your `main.ts` file right after creating the application.
125
+ To enable the **Entity Explorer** and **Route Explorer**, call `initialize` in `main.ts` after creating the app:
101
126
 
102
127
  ```typescript
103
- // main.ts
104
128
  import { NestFactory } from '@nestjs/core';
105
129
  import { AppModule } from './app.module';
106
130
  import { ProfilerModule } from 'nestjs-profiler';
@@ -108,7 +132,6 @@ import { ProfilerModule } from 'nestjs-profiler';
108
132
  async function bootstrap() {
109
133
  const app = await NestFactory.create(AppModule);
110
134
 
111
- // Initialize Profiler Explorers
112
135
  ProfilerModule.initialize(app);
113
136
 
114
137
  await app.listen(3000);
@@ -118,16 +141,68 @@ bootstrap();
118
141
 
119
142
  ### 2. Accessing the Dashboard
120
143
 
121
- Once configured, start your application. The profiler automatically intercepts requests and queries.
144
+ Once configured, start your application. The profiler automatically intercepts all requests.
145
+
146
+ Navigate to `http://localhost:3000/__profiler`.
147
+
148
+ #### Dashboard Pages
149
+
150
+ | Path | Description |
151
+ |---|---|
152
+ | `/__profiler` | Request list — all captured requests |
153
+ | `/__profiler/view/summary` | Aggregate stats: avg/p95 duration, error rate, top slow endpoints |
154
+ | `/__profiler/view/queries` | All database queries across requests, sorted by duration |
155
+ | `/__profiler/view/http-calls` | All outbound HTTP calls across requests, sorted by duration |
156
+ | `/__profiler/view/logs` | Paginated application logs |
157
+ | `/__profiler/view/logs/live` | Live streaming terminal — real-time log output |
158
+ | `/__profiler/view/cache` | Cache operations with hit/miss breakdown |
159
+ | `/__profiler/view/entities` | Registered database entities |
160
+ | `/__profiler/view/routes` | All registered application routes |
161
+ | `/__profiler/:id` | Full detail view for a single request |
162
+
163
+ ### 3. Outbound HTTP Tracking
164
+
165
+ Outbound HTTP tracking is **enabled by default**. Any `http.request`, `https.request`, `http.get`, or `https.get` call made during a request is automatically captured — including calls made via axios, node-fetch, and similar libraries.
122
166
 
123
- Navigate to `http://localhost:3000/__profiler` (or your app's port).
167
+ Each captured call records:
124
168
 
125
- ### 3. JSON API
169
+ - Method and full URL
170
+ - HTTP vs HTTPS protocol
171
+ - Response status code
172
+ - Duration in ms
173
+ - Request and response headers (Authorization/Cookie values are automatically redacted)
174
+ - Error message if the call failed
175
+
176
+ You can view outbound calls for a specific request in the request detail view, or browse all calls across all requests at `/__profiler/view/http-calls`.
177
+
178
+ To disable:
179
+
180
+ ```typescript
181
+ ProfilerModule.forRoot({ collectHttp: false })
182
+ ```
183
+
184
+ ### 4. JSON API
185
+
186
+ Retrieve profile data programmatically:
187
+
188
+ - `GET /__profiler/json` — List all captured requests
189
+ - `GET /__profiler/:id/json` — Details for a specific request
190
+
191
+ ## Global Prefix
192
+
193
+ If your app uses a global prefix (e.g. `/api`), exclude the profiler routes:
194
+
195
+ ```typescript
196
+ app.setGlobalPrefix('api', {
197
+ exclude: [{ path: '__profiler/(.*)', method: RequestMethod.ALL }],
198
+ });
199
+ ```
126
200
 
127
- You can also retrieve profile data programmatically:
201
+ ## Important Notes
128
202
 
129
- - `GET /__profiler/json` - List recent requests
130
- - `GET /__profiler/:id/json` - Get details for a specific request
203
+ - The profiler is designed for **development and debugging only**. Do not enable in production — it adds request overhead and exposes internal application data.
204
+ - The default in-memory storage holds the last 100 requests. Older profiles are evicted automatically.
205
+ - 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).
131
206
 
132
207
  ## License
133
208
 
@@ -0,0 +1,12 @@
1
+ import { OnModuleInit } from '@nestjs/common';
2
+ import type { ProfilerOptions } from '../common/profiler-options.interface';
3
+ import { ProfilerService } from '../services/profiler.service';
4
+ export declare class HttpCollector implements OnModuleInit {
5
+ private readonly profiler;
6
+ private readonly options;
7
+ private readonly logger;
8
+ constructor(profiler: ProfilerService, options: ProfilerOptions);
9
+ onModuleInit(): void;
10
+ private patchModule;
11
+ private sanitiseHeaders;
12
+ }
@@ -0,0 +1,132 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
12
+ return function (target, key) { decorator(target, key, paramIndex); }
13
+ };
14
+ var HttpCollector_1;
15
+ Object.defineProperty(exports, "__esModule", { value: true });
16
+ exports.HttpCollector = void 0;
17
+ const common_1 = require("@nestjs/common");
18
+ const profiler_service_1 = require("../services/profiler.service");
19
+ const PROFILER_INTERNAL_HEADER = 'x-profiler-internal';
20
+ let HttpCollector = HttpCollector_1 = class HttpCollector {
21
+ constructor(profiler, options) {
22
+ this.profiler = profiler;
23
+ this.options = options;
24
+ this.logger = new common_1.Logger(HttpCollector_1.name);
25
+ }
26
+ onModuleInit() {
27
+ if (this.options.collectHttp === false)
28
+ return;
29
+ const httpMod = require('http');
30
+ const httpsMod = require('https');
31
+ this.patchModule(httpMod, 'http');
32
+ this.patchModule(httpsMod, 'https');
33
+ this.logger.log('HTTP/HTTPS outbound request tracking enabled');
34
+ }
35
+ patchModule(mod, protocol) {
36
+ if (mod.__profilerPatched)
37
+ return;
38
+ mod.__profilerPatched = true;
39
+ const self = this;
40
+ const originalRequest = mod.request.bind(mod);
41
+ const originalGet = mod.get.bind(mod);
42
+ mod.request = function (...args) {
43
+ const startTime = Date.now();
44
+ let method = 'GET';
45
+ let host = '';
46
+ let path = '/';
47
+ let fullUrl = '';
48
+ let reqHeaders = {};
49
+ try {
50
+ const first = args[0];
51
+ if (typeof first === 'string' || first instanceof URL) {
52
+ const u = typeof first === 'string' ? new URL(first) : first;
53
+ host = u.hostname + (u.port ? `:${u.port}` : '');
54
+ path = u.pathname + u.search;
55
+ fullUrl = u.toString();
56
+ const opts = (args[1] && typeof args[1] === 'object' && typeof args[1] !== 'function') ? args[1] : {};
57
+ method = (opts?.method || 'GET').toUpperCase();
58
+ reqHeaders = opts?.headers || {};
59
+ }
60
+ else if (first && typeof first === 'object') {
61
+ method = (first.method || 'GET').toUpperCase();
62
+ host = first.hostname || first.host || 'localhost';
63
+ if (first.port && !String(host).includes(':'))
64
+ host += `:${first.port}`;
65
+ path = first.path || '/';
66
+ const defaultPort = protocol === 'https' ? 443 : 80;
67
+ const portStr = first.port && first.port !== defaultPort ? `:${first.port}` : '';
68
+ fullUrl = `${protocol}://${first.hostname || first.host || 'localhost'}${portStr}${path}`;
69
+ reqHeaders = first.headers || {};
70
+ }
71
+ }
72
+ catch (_) { }
73
+ if (reqHeaders[PROFILER_INTERNAL_HEADER] || fullUrl.includes('/__profiler')) {
74
+ return originalRequest(...args);
75
+ }
76
+ const profile = self.profiler.getCurrentProfile();
77
+ const req = originalRequest(...args);
78
+ if (profile) {
79
+ const httpCall = {
80
+ method,
81
+ url: fullUrl,
82
+ host,
83
+ path,
84
+ protocol,
85
+ startTime,
86
+ duration: 0,
87
+ requestHeaders: self.sanitiseHeaders(reqHeaders),
88
+ };
89
+ req.on('response', (res) => {
90
+ httpCall.statusCode = res.statusCode;
91
+ httpCall.responseHeaders = self.sanitiseHeaders(res.headers);
92
+ res.on('end', () => {
93
+ httpCall.duration = Date.now() - startTime;
94
+ self.profiler.addHttpCall(httpCall);
95
+ });
96
+ res.resume();
97
+ });
98
+ req.on('error', (err) => {
99
+ httpCall.duration = Date.now() - startTime;
100
+ httpCall.error = err.message;
101
+ self.profiler.addHttpCall(httpCall);
102
+ });
103
+ }
104
+ return req;
105
+ };
106
+ mod.get = function (...args) {
107
+ const req = mod.request(...args);
108
+ req.end();
109
+ return req;
110
+ };
111
+ }
112
+ sanitiseHeaders(headers) {
113
+ const result = {};
114
+ for (const [k, v] of Object.entries(headers || {})) {
115
+ const lower = k.toLowerCase();
116
+ if (lower === 'authorization' || lower === 'cookie' || lower === 'set-cookie') {
117
+ result[k] = '[redacted]';
118
+ }
119
+ else {
120
+ result[k] = Array.isArray(v) ? v.join(', ') : String(v ?? '');
121
+ }
122
+ }
123
+ return result;
124
+ }
125
+ };
126
+ exports.HttpCollector = HttpCollector;
127
+ exports.HttpCollector = HttpCollector = HttpCollector_1 = __decorate([
128
+ (0, common_1.Injectable)(),
129
+ __param(1, (0, common_1.Inject)('PROFILER_OPTIONS')),
130
+ __metadata("design:paramtypes", [profiler_service_1.ProfilerService, Object])
131
+ ], HttpCollector);
132
+ //# sourceMappingURL=http-collector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http-collector.js","sourceRoot":"","sources":["../../../libs/nestjs-profiler/src/collectors/http-collector.ts"],"names":[],"mappings":"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"}
@@ -7,6 +7,8 @@ export declare class LogCollector implements OnModuleInit {
7
7
  private logger;
8
8
  constructor(profiler: ProfilerService, options: ProfilerOptions);
9
9
  onModuleInit(): void;
10
+ private stripAnsi;
11
+ private detectLevel;
12
+ private parseNestLog;
10
13
  private patchProcessStream;
11
- private capture;
12
14
  }
@@ -30,6 +30,29 @@ let LogCollector = LogCollector_1 = class LogCollector {
30
30
  this.patchProcessStream('stderr');
31
31
  this.logger.log('LogCollector initialized: Patching process.stdout/stderr');
32
32
  }
33
+ stripAnsi(str) {
34
+ return str.replace(/\x1b\[[0-9;]*m/g, '').replace(/\x1b\[[0-9;]*[A-Za-z]/g, '');
35
+ }
36
+ detectLevel(raw, fallback) {
37
+ if (raw.includes('\x1b[31m'))
38
+ return 'error';
39
+ if (raw.includes('\x1b[33m'))
40
+ return 'warn';
41
+ if (raw.includes('\x1b[95m'))
42
+ return 'debug';
43
+ if (raw.includes('\x1b[96m'))
44
+ return 'verbose';
45
+ if (raw.includes('\x1b[32m'))
46
+ return 'log';
47
+ return fallback;
48
+ }
49
+ parseNestLog(clean) {
50
+ const match = clean.match(/^\[Nest\]\s+\d+\s+-\s+[\d/,: APM]+\s+\w+\s+\[([^\]]+)\]\s+(.+)$/s);
51
+ if (match)
52
+ return { context: match[1], message: match[2].trim() };
53
+ const prefixStripped = clean.replace(/^\[Nest\]\s+\d+\s+-\s+[\d/,: APM]+\s+\w+\s+/, '').trim();
54
+ return { message: prefixStripped || clean };
55
+ }
33
56
  patchProcessStream(streamName) {
34
57
  const stream = process[streamName];
35
58
  const originalWrite = stream.write;
@@ -37,25 +60,23 @@ let LogCollector = LogCollector_1 = class LogCollector {
37
60
  stream.write = function (chunk, encodingOrCb, cb) {
38
61
  const result = originalWrite.apply(this, arguments);
39
62
  try {
40
- const msg = chunk.toString();
41
- if (msg.includes('[LogCollector]'))
63
+ const raw = chunk.toString();
64
+ if (raw.includes('[LogCollector]'))
65
+ return result;
66
+ const level = self.detectLevel(raw, streamName === 'stderr' ? 'error' : 'log');
67
+ const clean = self.stripAnsi(raw).trim();
68
+ if (!clean)
42
69
  return result;
43
- self.capture(streamName === 'stderr' ? 'error' : 'log', msg);
70
+ const { context, message } = self.parseNestLog(clean);
71
+ if (!message)
72
+ return result;
73
+ self.profiler.addLog({ level, message, context, timestamp: Date.now() });
44
74
  }
45
75
  catch (e) {
46
76
  }
47
77
  return result;
48
78
  };
49
79
  }
50
- capture(level, message) {
51
- if (!message.trim())
52
- return;
53
- this.profiler.addLog({
54
- level,
55
- message: message.trim(),
56
- timestamp: Date.now()
57
- });
58
- }
59
80
  };
60
81
  exports.LogCollector = LogCollector;
61
82
  exports.LogCollector = LogCollector = LogCollector_1 = __decorate([
@@ -1 +1 @@
1
- {"version":3,"file":"log-collector.js","sourceRoot":"","sources":["../../../libs/nestjs-profiler/src/collectors/log-collector.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,2CAAyF;AACzF,mEAA+D;AAIxD,IAAM,YAAY,oBAAlB,MAAM,YAAY;IAGrB,YACY,QAAyB,EACL,OAAgC;QADpD,aAAQ,GAAR,QAAQ,CAAiB;QACG,YAAO,GAAP,OAAO,CAAiB;QAJxD,WAAM,GAAG,IAAI,eAAM,CAAC,cAAY,CAAC,IAAI,CAAC,CAAC;IAK3C,CAAC;IAEL,YAAY;QACR,IAAI,IAAI,CAAC,OAAO,CAAC,WAAW,KAAK,KAAK,EAAE,CAAC;YACrC,OAAO;QACX,CAAC;QAED,IAAI,CAAC,kBAAkB,CAAC,QAAQ,CAAC,CAAC;QAClC,IAAI,CAAC,kBAAkB,CAAC,QAAQ,CAAC,CAAC;QAClC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,0DAA0D,CAAC,CAAC;IAChF,CAAC;IAEO,kBAAkB,CAAC,UAA+B;QACtD,MAAM,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;QACnC,MAAM,aAAa,GAAG,MAAM,CAAC,KAAK,CAAC;QACnC,MAAM,IAAI,GAAG,IAAI,CAAC;QAElB,MAAM,CAAC,KAAK,GAAG,UACX,KAA0B,EAC1B,YAAuD,EACvD,EAA0B;YAE1B,MAAM,MAAM,GAAG,aAAa,CAAC,KAAK,CAAC,IAAI,EAAE,SAAgB,CAAC,CAAC;YAE3D,IAAI,CAAC;gBACD,MAAM,GAAG,GAAG,KAAK,CAAC,QAAQ,EAAE,CAAC;gBAC7B,IAAI,GAAG,CAAC,QAAQ,CAAC,gBAAgB,CAAC;oBAAE,OAAO,MAAM,CAAC;gBAElD,IAAI,CAAC,OAAO,CAAC,UAAU,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;YACjE,CAAC;YAAC,OAAO,CAAC,EAAE,CAAC;YACb,CAAC;YAED,OAAO,MAAM,CAAC;QAClB,CAAC,CAAC;IACN,CAAC;IAEO,OAAO,CAAC,KAAa,EAAE,OAAe;QAC1C,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE;YAAE,OAAO;QAE5B,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC;YACjB,KAAK;YACL,OAAO,EAAE,OAAO,CAAC,IAAI,EAAE;YACvB,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;SACxB,CAAC,CAAC;IACP,CAAC;CACJ,CAAA;AAnDY,oCAAY;uBAAZ,YAAY;IADxB,IAAA,mBAAU,GAAE;IAMJ,WAAA,IAAA,eAAM,EAAC,kBAAkB,CAAC,CAAA;qCADT,kCAAe;GAJ5B,YAAY,CAmDxB"}
1
+ {"version":3,"file":"log-collector.js","sourceRoot":"","sources":["../../../libs/nestjs-profiler/src/collectors/log-collector.ts"],"names":[],"mappings":"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"}
@@ -16,5 +16,6 @@ export interface ProfilerOptions {
16
16
  collectMongo?: boolean;
17
17
  collectCache?: boolean;
18
18
  collectMysql?: boolean;
19
+ collectHttp?: boolean;
19
20
  explain?: ProfilerExplainOptions;
20
21
  }
@@ -31,6 +31,19 @@ export interface CacheProfile {
31
31
  startTime: number;
32
32
  value?: any;
33
33
  }
34
+ export interface HttpCallProfile {
35
+ method: string;
36
+ url: string;
37
+ host: string;
38
+ path: string;
39
+ statusCode?: number;
40
+ duration: number;
41
+ startTime: number;
42
+ requestHeaders?: Record<string, string>;
43
+ responseHeaders?: Record<string, string>;
44
+ error?: string;
45
+ protocol: 'http' | 'https';
46
+ }
34
47
  export interface RequestProfile {
35
48
  id: string;
36
49
  method: string;
@@ -52,6 +65,7 @@ export interface RequestProfile {
52
65
  queries: QueryProfile[];
53
66
  logs: LogProfile[];
54
67
  cache?: CacheProfile[];
68
+ httpCalls?: HttpCallProfile[];
55
69
  timestamp: number;
56
70
  requestHeaders?: Record<string, any>;
57
71
  requestBody?: any;
@@ -24,11 +24,15 @@ export declare class ProfilerController {
24
24
  }>;
25
25
  detail(id: string, res: Response): Promise<void>;
26
26
  detailJson(id: string): Promise<import("..").RequestProfile>;
27
+ summary(res: Response): Promise<void>;
27
28
  listQueries(res: Response): Promise<void>;
28
29
  listLogs(res: Response, page?: number): Promise<void>;
29
30
  listEntities(res: Response): Promise<void>;
30
31
  listRoutes(res: Response): Promise<void>;
31
32
  listCache(res: Response): Promise<void>;
33
+ listHttpCalls(res: Response): Promise<void>;
34
+ liveLogsPage(res: Response): Promise<void>;
35
+ liveLogsStream(res: Response): void;
32
36
  serveAsset(file: string, res: Response): Promise<void>;
33
37
  serveJs(file: string, res: Response): Promise<void>;
34
38
  }
@@ -80,6 +80,13 @@ let ProfilerController = class ProfilerController {
80
80
  throw new common_1.NotFoundException('Profile not found');
81
81
  return profile;
82
82
  }
83
+ async summary(res) {
84
+ const stats = await this.profilerService.getSummaryStats();
85
+ const content = this.templateBuilder.buildSummaryPage(stats);
86
+ const html = this.viewService.renderWithLayout('Summary', content, 'summary');
87
+ res.header('Content-Type', 'text/html');
88
+ res.send(html);
89
+ }
83
90
  async listQueries(res) {
84
91
  const queries = await this.profilerService.getQueriesList();
85
92
  const content = this.templateBuilder.buildQueriesList(queries);
@@ -115,6 +122,57 @@ let ProfilerController = class ProfilerController {
115
122
  res.header('Content-Type', 'text/html');
116
123
  res.send(html);
117
124
  }
125
+ async listHttpCalls(res) {
126
+ const calls = await this.profilerService.getHttpCallsList();
127
+ const content = this.templateBuilder.buildHttpCallsList(calls);
128
+ const html = this.viewService.renderWithLayout('Outbound HTTP', content, 'http-calls');
129
+ res.header('Content-Type', 'text/html');
130
+ res.send(html);
131
+ }
132
+ async liveLogsPage(res) {
133
+ const html = this.viewService.renderWithLayout('Live Logs', this.templateBuilder.buildLiveLogsPage(), 'live-logs');
134
+ res.header('Content-Type', 'text/html');
135
+ res.send(html);
136
+ }
137
+ liveLogsStream(res) {
138
+ res.setHeader('Content-Type', 'text/event-stream');
139
+ res.setHeader('Cache-Control', 'no-cache');
140
+ res.setHeader('Connection', 'keep-alive');
141
+ res.setHeader('X-Accel-Buffering', 'no');
142
+ res.flushHeaders();
143
+ this.profilerService.logEmitter.setMaxListeners(this.profilerService.logEmitter.getMaxListeners() + 1);
144
+ res.write(`data: ${JSON.stringify({ level: 'system', message: 'Stream connected', timestamp: Date.now() })}\n\n`);
145
+ let batch = [];
146
+ let batchTimer = null;
147
+ const flush = () => {
148
+ batchTimer = null;
149
+ if (batch.length === 0 || res.writableEnded)
150
+ return;
151
+ const payload = batch.splice(0);
152
+ res.write(`data: ${JSON.stringify(payload)}\n\n`);
153
+ if (typeof res.flush === 'function')
154
+ res.flush();
155
+ };
156
+ const onLog = (log) => {
157
+ if (res.writableEnded)
158
+ return;
159
+ batch.push(log);
160
+ if (!batchTimer)
161
+ batchTimer = setTimeout(flush, 50);
162
+ };
163
+ const heartbeat = setInterval(() => {
164
+ if (!res.writableEnded)
165
+ res.write(': heartbeat\n\n');
166
+ }, 15_000);
167
+ this.profilerService.logEmitter.on('log', onLog);
168
+ res.on('close', () => {
169
+ clearInterval(heartbeat);
170
+ if (batchTimer)
171
+ clearTimeout(batchTimer);
172
+ this.profilerService.logEmitter.off('log', onLog);
173
+ this.profilerService.logEmitter.setMaxListeners(Math.max(1, this.profilerService.logEmitter.getMaxListeners() - 1));
174
+ });
175
+ }
118
176
  async serveAsset(file, res) {
119
177
  const fs = require('fs');
120
178
  const path = require('path');
@@ -191,6 +249,13 @@ __decorate([
191
249
  __metadata("design:paramtypes", [String]),
192
250
  __metadata("design:returntype", Promise)
193
251
  ], ProfilerController.prototype, "detailJson", null);
252
+ __decorate([
253
+ (0, common_1.Get)('view/summary'),
254
+ __param(0, (0, common_1.Res)()),
255
+ __metadata("design:type", Function),
256
+ __metadata("design:paramtypes", [Object]),
257
+ __metadata("design:returntype", Promise)
258
+ ], ProfilerController.prototype, "summary", null);
194
259
  __decorate([
195
260
  (0, common_1.Get)('view/queries'),
196
261
  __param(0, (0, common_1.Res)()),
@@ -227,6 +292,27 @@ __decorate([
227
292
  __metadata("design:paramtypes", [Object]),
228
293
  __metadata("design:returntype", Promise)
229
294
  ], ProfilerController.prototype, "listCache", null);
295
+ __decorate([
296
+ (0, common_1.Get)('view/http-calls'),
297
+ __param(0, (0, common_1.Res)()),
298
+ __metadata("design:type", Function),
299
+ __metadata("design:paramtypes", [Object]),
300
+ __metadata("design:returntype", Promise)
301
+ ], ProfilerController.prototype, "listHttpCalls", null);
302
+ __decorate([
303
+ (0, common_1.Get)('view/logs/live'),
304
+ __param(0, (0, common_1.Res)()),
305
+ __metadata("design:type", Function),
306
+ __metadata("design:paramtypes", [Object]),
307
+ __metadata("design:returntype", Promise)
308
+ ], ProfilerController.prototype, "liveLogsPage", null);
309
+ __decorate([
310
+ (0, common_1.Get)('logs/stream'),
311
+ __param(0, (0, common_1.Res)()),
312
+ __metadata("design:type", Function),
313
+ __metadata("design:paramtypes", [Object]),
314
+ __metadata("design:returntype", void 0)
315
+ ], ProfilerController.prototype, "liveLogsStream", null);
230
316
  __decorate([
231
317
  (0, common_1.Get)('assets/:file'),
232
318
  __param(0, (0, common_1.Param)('file')),