nestjs-profiler 1.0.14 → 1.0.16
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 +25 -20
- package/collectors/cache-collector.d.ts +18 -0
- package/collectors/cache-collector.js +175 -0
- package/collectors/cache-collector.js.map +1 -0
- package/collectors/log-collector.d.ts +12 -0
- package/collectors/log-collector.js +66 -0
- package/collectors/log-collector.js.map +1 -0
- package/collectors/mongo-collector.d.ts +19 -0
- package/collectors/mongo-collector.js +200 -0
- package/collectors/mongo-collector.js.map +1 -0
- package/collectors/mysql-collector.d.ts +12 -0
- package/collectors/mysql-collector.js +128 -0
- package/collectors/mysql-collector.js.map +1 -0
- package/collectors/postgres-collector.d.ts +15 -0
- package/collectors/postgres-collector.js +201 -0
- package/collectors/postgres-collector.js.map +1 -0
- package/common/profiler-options.interface.d.ts +20 -0
- package/common/profiler-options.interface.js +3 -0
- package/common/profiler-options.interface.js.map +1 -0
- package/common/profiler.model.d.ts +67 -0
- package/common/profiler.model.js +3 -0
- package/common/profiler.model.js.map +1 -0
- package/interceptors/request-profiler.interceptor.d.ts +11 -0
- package/interceptors/request-profiler.interceptor.js +103 -0
- package/interceptors/request-profiler.interceptor.js.map +1 -0
- package/middleware/profiler.middleware.d.ts +4 -0
- package/middleware/profiler.middleware.js +21 -0
- package/middleware/profiler.middleware.js.map +1 -0
- package/package.json +8 -3
- package/storage/in-memory-profiler-storage.d.ts +9 -0
- package/storage/in-memory-profiler-storage.js +29 -0
- package/storage/in-memory-profiler-storage.js.map +1 -0
- package/storage/profiler-storage.interface.d.ts +6 -0
- package/storage/profiler-storage.interface.js +3 -0
- package/storage/profiler-storage.interface.js.map +1 -0
- package/views/entities.html +35 -36
package/README.md
CHANGED
|
@@ -1,18 +1,22 @@
|
|
|
1
1
|
# nestjs-profiler
|
|
2
2
|
|
|
3
|
+
<p align="center">
|
|
4
|
+
<img src="https://raw.githubusercontent.com/MohammedRaslan/Nest-JS-Profiler/refs/heads/main/libs/nestjs-profiler/src/assets/logo.png" width="400" alt="Dashboard Preview">
|
|
5
|
+
</p>
|
|
6
|
+
|
|
3
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.
|
|
4
8
|
|
|
5
9
|
## Features
|
|
6
10
|
|
|
7
|
-
-
|
|
8
|
-
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
-
|
|
13
|
-
-
|
|
14
|
-
-
|
|
15
|
-
-
|
|
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.
|
|
16
20
|
|
|
17
21
|
## Installation
|
|
18
22
|
|
|
@@ -56,27 +60,27 @@ import { ProfilerModule } from 'nestjs-profiler';
|
|
|
56
60
|
collectQueries: true,
|
|
57
61
|
explain: {
|
|
58
62
|
enabled: true,
|
|
59
|
-
thresholdMs: 50,
|
|
60
|
-
analyze: false,
|
|
63
|
+
thresholdMs: 50, // Only explain queries taking > 50ms
|
|
64
|
+
analyze: false, // If true, runs EXPLAIN ANALYZE (execution!)
|
|
61
65
|
},
|
|
62
66
|
// Add pgDriver
|
|
63
67
|
pgDriver: pg,
|
|
64
|
-
|
|
68
|
+
|
|
65
69
|
// MongoDB Profiling (default: true)
|
|
66
70
|
collectMongo: true,
|
|
67
|
-
|
|
71
|
+
|
|
68
72
|
// MySQL Profiling (default: true)
|
|
69
73
|
collectMysql: true,
|
|
70
|
-
|
|
74
|
+
|
|
71
75
|
// Cache Profiling (default: true)
|
|
72
76
|
collectCache: true,
|
|
73
|
-
|
|
77
|
+
|
|
74
78
|
// Log Profiling (default: true)
|
|
75
79
|
collectLogs: true,
|
|
76
80
|
|
|
77
81
|
// Storage backend (default: InMemory)
|
|
78
82
|
// You can implement custom storage by passing an object implementing ProfilerStorage
|
|
79
|
-
storage: 'memory',
|
|
83
|
+
storage: 'memory',
|
|
80
84
|
}),
|
|
81
85
|
],
|
|
82
86
|
})
|
|
@@ -97,10 +101,10 @@ import { ProfilerModule } from 'nestjs-profiler';
|
|
|
97
101
|
|
|
98
102
|
async function bootstrap() {
|
|
99
103
|
const app = await NestFactory.create(AppModule);
|
|
100
|
-
|
|
104
|
+
|
|
101
105
|
// Initialize Profiler Explorers
|
|
102
106
|
ProfilerModule.initialize(app);
|
|
103
|
-
|
|
107
|
+
|
|
104
108
|
await app.listen(3000);
|
|
105
109
|
}
|
|
106
110
|
bootstrap();
|
|
@@ -115,8 +119,9 @@ Navigate to `http://localhost:3000/__profiler` (or your app's port).
|
|
|
115
119
|
### 3. JSON API
|
|
116
120
|
|
|
117
121
|
You can also retrieve profile data programmatically:
|
|
118
|
-
|
|
119
|
-
-
|
|
122
|
+
|
|
123
|
+
- `GET /__profiler/json` - List recent requests
|
|
124
|
+
- `GET /__profiler/:id/json` - Get details for a specific request
|
|
120
125
|
|
|
121
126
|
## License
|
|
122
127
|
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { OnModuleInit } from '@nestjs/common';
|
|
2
|
+
import { ProfilerService } from '../services/profiler.service';
|
|
3
|
+
import type { ProfilerOptions } from '../common/profiler-options.interface';
|
|
4
|
+
import type { Cache } from 'cache-manager';
|
|
5
|
+
export declare class CacheCollector implements OnModuleInit {
|
|
6
|
+
private readonly profiler;
|
|
7
|
+
private readonly options;
|
|
8
|
+
private readonly cacheManager;
|
|
9
|
+
private readonly logger;
|
|
10
|
+
constructor(profiler: ProfilerService, options: ProfilerOptions, cacheManager: Cache);
|
|
11
|
+
onModuleInit(): void;
|
|
12
|
+
private wrapCacheManager;
|
|
13
|
+
private wrapGet;
|
|
14
|
+
private wrapSet;
|
|
15
|
+
private wrapDel;
|
|
16
|
+
private wrapReset;
|
|
17
|
+
private captureOperation;
|
|
18
|
+
}
|
|
@@ -0,0 +1,175 @@
|
|
|
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 CacheCollector_1;
|
|
15
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
|
+
exports.CacheCollector = void 0;
|
|
17
|
+
const common_1 = require("@nestjs/common");
|
|
18
|
+
const profiler_service_1 = require("../services/profiler.service");
|
|
19
|
+
let CacheCollector = CacheCollector_1 = class CacheCollector {
|
|
20
|
+
constructor(profiler, options, cacheManager) {
|
|
21
|
+
this.profiler = profiler;
|
|
22
|
+
this.options = options;
|
|
23
|
+
this.cacheManager = cacheManager;
|
|
24
|
+
this.logger = new common_1.Logger(CacheCollector_1.name);
|
|
25
|
+
}
|
|
26
|
+
onModuleInit() {
|
|
27
|
+
if (this.options.collectCache === false) {
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
if (!this.cacheManager) {
|
|
31
|
+
this.logger.warn('No CACHE_MANAGER found, skipping Cache profiling. Ensure CacheModule is imported globally or available to ProfilerModule.');
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
this.logger.log('CacheCollector initialized: Wrapping CACHE_MANAGER');
|
|
35
|
+
this.wrapCacheManager();
|
|
36
|
+
}
|
|
37
|
+
wrapCacheManager() {
|
|
38
|
+
const cm = this.cacheManager;
|
|
39
|
+
this.logger.log(`CacheCollector: Inspecting CacheManager keys: ${Object.keys(cm)}`);
|
|
40
|
+
if (cm.store && cm.store.get) {
|
|
41
|
+
this.logger.log('CacheCollector: Underlying store found: ' + (cm.store.name || cm.store.constructor?.name));
|
|
42
|
+
}
|
|
43
|
+
this.wrapGet(cm);
|
|
44
|
+
this.wrapSet(cm);
|
|
45
|
+
this.wrapDel(cm);
|
|
46
|
+
this.wrapReset(cm);
|
|
47
|
+
}
|
|
48
|
+
wrapGet(cm) {
|
|
49
|
+
const self = this;
|
|
50
|
+
const originalGet = cm.get;
|
|
51
|
+
if (originalGet) {
|
|
52
|
+
this.logger.log('CacheCollector: Wrapping "get" method');
|
|
53
|
+
cm.get = async function (...args) {
|
|
54
|
+
const startTime = Date.now();
|
|
55
|
+
const key = args[0];
|
|
56
|
+
try {
|
|
57
|
+
const result = await originalGet.apply(this, args);
|
|
58
|
+
const endTime = Date.now();
|
|
59
|
+
self.captureOperation('get', key, result !== undefined && result !== null ? 'hit' : 'miss', startTime, endTime);
|
|
60
|
+
return result;
|
|
61
|
+
}
|
|
62
|
+
catch (error) {
|
|
63
|
+
const endTime = Date.now();
|
|
64
|
+
self.captureOperation('get', key, 'fail', startTime, endTime);
|
|
65
|
+
throw error;
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
this.logger.warn('CacheCollector: "get" method not found on CacheManager');
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
wrapSet(cm) {
|
|
74
|
+
const self = this;
|
|
75
|
+
const originalSet = cm.set;
|
|
76
|
+
if (originalSet) {
|
|
77
|
+
this.logger.log('CacheCollector: Wrapping "set" method');
|
|
78
|
+
cm.set = async function (...args) {
|
|
79
|
+
const startTime = Date.now();
|
|
80
|
+
const key = args[0];
|
|
81
|
+
const ttl = args[2];
|
|
82
|
+
try {
|
|
83
|
+
const result = await originalSet.apply(this, args);
|
|
84
|
+
const endTime = Date.now();
|
|
85
|
+
self.captureOperation('set', key, 'success', startTime, endTime, ttl);
|
|
86
|
+
return result;
|
|
87
|
+
}
|
|
88
|
+
catch (error) {
|
|
89
|
+
const endTime = Date.now();
|
|
90
|
+
self.captureOperation('set', key, 'fail', startTime, endTime);
|
|
91
|
+
throw error;
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
else {
|
|
96
|
+
this.logger.warn('CacheCollector: "set" method not found on CacheManager');
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
wrapDel(cm) {
|
|
100
|
+
const self = this;
|
|
101
|
+
const originalDel = cm.del;
|
|
102
|
+
if (originalDel) {
|
|
103
|
+
cm.del = async function (...args) {
|
|
104
|
+
const startTime = Date.now();
|
|
105
|
+
const key = args[0];
|
|
106
|
+
try {
|
|
107
|
+
const result = await originalDel.apply(this, args);
|
|
108
|
+
const endTime = Date.now();
|
|
109
|
+
self.captureOperation('del', key, 'success', startTime, endTime);
|
|
110
|
+
return result;
|
|
111
|
+
}
|
|
112
|
+
catch (error) {
|
|
113
|
+
const endTime = Date.now();
|
|
114
|
+
self.captureOperation('del', key, 'fail', startTime, endTime);
|
|
115
|
+
throw error;
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
wrapReset(cm) {
|
|
121
|
+
const self = this;
|
|
122
|
+
const originalReset = cm.reset;
|
|
123
|
+
if (originalReset) {
|
|
124
|
+
cm.reset = async function (...args) {
|
|
125
|
+
const startTime = Date.now();
|
|
126
|
+
try {
|
|
127
|
+
const result = await originalReset.apply(this, args);
|
|
128
|
+
const endTime = Date.now();
|
|
129
|
+
self.captureOperation('reset', '*', 'success', startTime, endTime);
|
|
130
|
+
return result;
|
|
131
|
+
}
|
|
132
|
+
catch (error) {
|
|
133
|
+
const endTime = Date.now();
|
|
134
|
+
self.captureOperation('reset', '*', 'fail', startTime, endTime);
|
|
135
|
+
throw error;
|
|
136
|
+
}
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
captureOperation(operation, key, result, startTime, endTime, ttl) {
|
|
141
|
+
try {
|
|
142
|
+
let storeName = 'unknown';
|
|
143
|
+
const cm = this.cacheManager;
|
|
144
|
+
if (cm.store) {
|
|
145
|
+
if (cm.store.name)
|
|
146
|
+
storeName = cm.store.name;
|
|
147
|
+
else if (cm.store.constructor && cm.store.constructor.name)
|
|
148
|
+
storeName = cm.store.constructor.name;
|
|
149
|
+
}
|
|
150
|
+
const profile = {
|
|
151
|
+
key: String(key),
|
|
152
|
+
store: storeName,
|
|
153
|
+
operation,
|
|
154
|
+
result,
|
|
155
|
+
ttl,
|
|
156
|
+
duration: endTime - startTime,
|
|
157
|
+
startTime,
|
|
158
|
+
};
|
|
159
|
+
this.logger.debug(`CacheCollector: Captured ${operation} on ${key}. Duration: ${profile.duration}ms`);
|
|
160
|
+
this.profiler.addCache(profile);
|
|
161
|
+
}
|
|
162
|
+
catch (e) {
|
|
163
|
+
this.logger.error('Error capturing cache operation', e);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
};
|
|
167
|
+
exports.CacheCollector = CacheCollector;
|
|
168
|
+
exports.CacheCollector = CacheCollector = CacheCollector_1 = __decorate([
|
|
169
|
+
(0, common_1.Injectable)(),
|
|
170
|
+
__param(1, (0, common_1.Inject)('PROFILER_OPTIONS')),
|
|
171
|
+
__param(2, (0, common_1.Optional)()),
|
|
172
|
+
__param(2, (0, common_1.Inject)('CACHE_MANAGER')),
|
|
173
|
+
__metadata("design:paramtypes", [profiler_service_1.ProfilerService, Object, Object])
|
|
174
|
+
], CacheCollector);
|
|
175
|
+
//# sourceMappingURL=cache-collector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache-collector.js","sourceRoot":"","sources":["../../../libs/nestjs-profiler/src/collectors/cache-collector.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { OnModuleInit } from '@nestjs/common';
|
|
2
|
+
import { ProfilerService } from '../services/profiler.service';
|
|
3
|
+
import type { ProfilerOptions } from '../common/profiler-options.interface';
|
|
4
|
+
export declare class LogCollector implements OnModuleInit {
|
|
5
|
+
private profiler;
|
|
6
|
+
private options;
|
|
7
|
+
private logger;
|
|
8
|
+
constructor(profiler: ProfilerService, options: ProfilerOptions);
|
|
9
|
+
onModuleInit(): void;
|
|
10
|
+
private patchProcessStream;
|
|
11
|
+
private capture;
|
|
12
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
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 LogCollector_1;
|
|
15
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
|
+
exports.LogCollector = void 0;
|
|
17
|
+
const common_1 = require("@nestjs/common");
|
|
18
|
+
const profiler_service_1 = require("../services/profiler.service");
|
|
19
|
+
let LogCollector = LogCollector_1 = class LogCollector {
|
|
20
|
+
constructor(profiler, options) {
|
|
21
|
+
this.profiler = profiler;
|
|
22
|
+
this.options = options;
|
|
23
|
+
this.logger = new common_1.Logger(LogCollector_1.name);
|
|
24
|
+
}
|
|
25
|
+
onModuleInit() {
|
|
26
|
+
if (this.options.collectLogs === false) {
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
this.patchProcessStream('stdout');
|
|
30
|
+
this.patchProcessStream('stderr');
|
|
31
|
+
this.logger.log('LogCollector initialized: Patching process.stdout/stderr');
|
|
32
|
+
}
|
|
33
|
+
patchProcessStream(streamName) {
|
|
34
|
+
const stream = process[streamName];
|
|
35
|
+
const originalWrite = stream.write;
|
|
36
|
+
const self = this;
|
|
37
|
+
stream.write = function (chunk, encodingOrCb, cb) {
|
|
38
|
+
const result = originalWrite.apply(this, arguments);
|
|
39
|
+
try {
|
|
40
|
+
const msg = chunk.toString();
|
|
41
|
+
if (msg.includes('[LogCollector]'))
|
|
42
|
+
return result;
|
|
43
|
+
self.capture(streamName === 'stderr' ? 'error' : 'log', msg);
|
|
44
|
+
}
|
|
45
|
+
catch (e) {
|
|
46
|
+
}
|
|
47
|
+
return result;
|
|
48
|
+
};
|
|
49
|
+
}
|
|
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
|
+
};
|
|
60
|
+
exports.LogCollector = LogCollector;
|
|
61
|
+
exports.LogCollector = LogCollector = LogCollector_1 = __decorate([
|
|
62
|
+
(0, common_1.Injectable)(),
|
|
63
|
+
__param(1, (0, common_1.Inject)('PROFILER_OPTIONS')),
|
|
64
|
+
__metadata("design:paramtypes", [profiler_service_1.ProfilerService, Object])
|
|
65
|
+
], LogCollector);
|
|
66
|
+
//# sourceMappingURL=log-collector.js.map
|
|
@@ -0,0 +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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { OnModuleInit } from '@nestjs/common';
|
|
2
|
+
import { ProfilerService } from '../services/profiler.service';
|
|
3
|
+
import type { ProfilerOptions } from '../common/profiler-options.interface';
|
|
4
|
+
export declare class MongoCollector implements OnModuleInit {
|
|
5
|
+
private profiler;
|
|
6
|
+
private options;
|
|
7
|
+
private logger;
|
|
8
|
+
private mongodb;
|
|
9
|
+
constructor(profiler: ProfilerService, options: ProfilerOptions);
|
|
10
|
+
onModuleInit(): void;
|
|
11
|
+
private patchMongo;
|
|
12
|
+
private handleQueryOperation;
|
|
13
|
+
private handleInsertOperation;
|
|
14
|
+
private handleAggregateOperation;
|
|
15
|
+
private buildFilter;
|
|
16
|
+
private captureQuery;
|
|
17
|
+
private rowCountResolvers;
|
|
18
|
+
private getRowCount;
|
|
19
|
+
}
|
|
@@ -0,0 +1,200 @@
|
|
|
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 MongoCollector_1;
|
|
15
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
|
+
exports.MongoCollector = void 0;
|
|
17
|
+
const common_1 = require("@nestjs/common");
|
|
18
|
+
const profiler_service_1 = require("../services/profiler.service");
|
|
19
|
+
let MongoCollector = MongoCollector_1 = class MongoCollector {
|
|
20
|
+
constructor(profiler, options) {
|
|
21
|
+
this.profiler = profiler;
|
|
22
|
+
this.options = options;
|
|
23
|
+
this.logger = new common_1.Logger(MongoCollector_1.name);
|
|
24
|
+
this.rowCountResolvers = [
|
|
25
|
+
(r) => (typeof r === 'number' ? r : null),
|
|
26
|
+
(r) => (Array.isArray(r.docs) ? r.docs.length : null),
|
|
27
|
+
(r) => r.insertedCount ?? null,
|
|
28
|
+
(r) => r.modifiedCount ?? null,
|
|
29
|
+
(r) => r.deletedCount ?? null,
|
|
30
|
+
];
|
|
31
|
+
}
|
|
32
|
+
onModuleInit() {
|
|
33
|
+
if (this.options.collectMongo === false) {
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
try {
|
|
37
|
+
this.mongodb = this.options.mongoDriver || require('mongodb');
|
|
38
|
+
this.patchMongo();
|
|
39
|
+
this.logger.log('MongoCollector initialized: Patching mongodb driver');
|
|
40
|
+
}
|
|
41
|
+
catch (e) {
|
|
42
|
+
if (e.code === 'MODULE_NOT_FOUND') {
|
|
43
|
+
this.logger.debug('mongodb driver not found, skipping MongoDB profiling');
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
this.logger.error('Failed to initialize MongoCollector', e);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
patchMongo() {
|
|
51
|
+
if (!this.mongodb) {
|
|
52
|
+
this.logger.warn('MongoDB driver is undefined provided to MongoCollector');
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
if (!this.mongodb.Collection) {
|
|
56
|
+
this.logger.warn(`mongodb.Collection not found on provided driver. Keys: ${Object.keys(this.mongodb).join(', ')}`);
|
|
57
|
+
this.logger.warn('If you are using Mongoose, ensure you are passing the "mongodb" driver instance, not Mongoose itself.');
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
const self = this;
|
|
61
|
+
const collection = this.mongodb.Collection;
|
|
62
|
+
const operations = [
|
|
63
|
+
'find', 'findOne', 'insertOne', 'insertMany',
|
|
64
|
+
'updateOne', 'updateMany', 'deleteOne', 'deleteMany',
|
|
65
|
+
'aggregate', 'countDocuments', 'replaceOne'
|
|
66
|
+
];
|
|
67
|
+
this.logger.debug(`Patching MongoDB Collection methods: ${operations.join(', ')}`);
|
|
68
|
+
operations.forEach(opName => {
|
|
69
|
+
const originalMethod = collection.prototype[opName];
|
|
70
|
+
if (!originalMethod) {
|
|
71
|
+
this.logger.warn(`Could not find method ${opName} on Collection.prototype`);
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
collection.prototype[opName] = function (...args) {
|
|
75
|
+
if (process.env.PROFILER_DEBUG) {
|
|
76
|
+
self.logger.debug(`Mongo Intercepted: ${opName}`);
|
|
77
|
+
}
|
|
78
|
+
const startTime = Date.now();
|
|
79
|
+
const collectionName = this.collectionName || 'unknown';
|
|
80
|
+
const dbName = this.s?.db?.databaseName || this.dbName || 'unknown';
|
|
81
|
+
const client = this.s?.db?.s?.client;
|
|
82
|
+
const host = client?.s?.options?.hosts?.[0] || 'localhost:27017';
|
|
83
|
+
const connectionName = `${dbName}@${host}`;
|
|
84
|
+
let filter = {};
|
|
85
|
+
let operation = opName;
|
|
86
|
+
filter = self.buildFilter(opName, args);
|
|
87
|
+
const result = originalMethod.apply(this, args);
|
|
88
|
+
if (result && typeof result.then === 'function') {
|
|
89
|
+
return result.then((res) => {
|
|
90
|
+
const endTime = Date.now();
|
|
91
|
+
self.captureQuery(operation, collectionName, filter, startTime, endTime, connectionName, res);
|
|
92
|
+
return res;
|
|
93
|
+
}).catch((err) => {
|
|
94
|
+
const endTime = Date.now();
|
|
95
|
+
self.captureQuery(operation, collectionName, filter, startTime, endTime, connectionName, null, err);
|
|
96
|
+
throw err;
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
if (result && result.toArray) {
|
|
100
|
+
const originalToArray = result.toArray;
|
|
101
|
+
result.toArray = function () {
|
|
102
|
+
const arrayPromise = originalToArray.apply(this, arguments);
|
|
103
|
+
return arrayPromise.then((docs) => {
|
|
104
|
+
const endTime = Date.now();
|
|
105
|
+
self.captureQuery(operation, collectionName, filter, startTime, endTime, connectionName, { docs });
|
|
106
|
+
return docs;
|
|
107
|
+
}).catch((err) => {
|
|
108
|
+
const endTime = Date.now();
|
|
109
|
+
self.captureQuery(operation, collectionName, filter, startTime, endTime, connectionName, null, err);
|
|
110
|
+
throw err;
|
|
111
|
+
});
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
return result;
|
|
115
|
+
};
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
handleQueryOperation(opName, args) {
|
|
119
|
+
const operations = [
|
|
120
|
+
'find',
|
|
121
|
+
'findOne',
|
|
122
|
+
'deleteOne',
|
|
123
|
+
'deleteMany',
|
|
124
|
+
'countDocuments',
|
|
125
|
+
'updateOne',
|
|
126
|
+
'updateMany',
|
|
127
|
+
'replaceOne',
|
|
128
|
+
];
|
|
129
|
+
if (!operations.includes(opName)) {
|
|
130
|
+
return null;
|
|
131
|
+
}
|
|
132
|
+
return args[0] || {};
|
|
133
|
+
}
|
|
134
|
+
handleInsertOperation(opName, args) {
|
|
135
|
+
if (!['insertOne', 'insertMany'].includes(opName)) {
|
|
136
|
+
return null;
|
|
137
|
+
}
|
|
138
|
+
return {
|
|
139
|
+
document: args[0],
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
handleAggregateOperation(opName, args) {
|
|
143
|
+
if (opName !== 'aggregate') {
|
|
144
|
+
return null;
|
|
145
|
+
}
|
|
146
|
+
return {
|
|
147
|
+
pipeline: args[0] || [],
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
buildFilter(opName, args) {
|
|
151
|
+
return (this.handleQueryOperation(opName, args) ??
|
|
152
|
+
this.handleInsertOperation(opName, args) ??
|
|
153
|
+
this.handleAggregateOperation(opName, args) ??
|
|
154
|
+
{});
|
|
155
|
+
}
|
|
156
|
+
captureQuery(operation, collection, filter, startTime, endTime, connectionName, result, error) {
|
|
157
|
+
try {
|
|
158
|
+
const queryText = JSON.stringify({
|
|
159
|
+
collection,
|
|
160
|
+
operation,
|
|
161
|
+
filter
|
|
162
|
+
}, null, 2);
|
|
163
|
+
const rowCount = this.getRowCount(result);
|
|
164
|
+
const queryProfile = {
|
|
165
|
+
sql: queryText,
|
|
166
|
+
query: queryText,
|
|
167
|
+
database: 'mongodb',
|
|
168
|
+
operation,
|
|
169
|
+
filter,
|
|
170
|
+
duration: endTime - startTime,
|
|
171
|
+
startTime,
|
|
172
|
+
rowCount,
|
|
173
|
+
connection: connectionName,
|
|
174
|
+
error: error ? String(error) : undefined,
|
|
175
|
+
};
|
|
176
|
+
this.profiler.addQuery(queryProfile);
|
|
177
|
+
}
|
|
178
|
+
catch (e) {
|
|
179
|
+
if (process.env.PROFILER_DEBUG) {
|
|
180
|
+
this.logger.error('Failed to capture MongoDB query', e);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
getRowCount(result) {
|
|
185
|
+
for (const resolver of this.rowCountResolvers) {
|
|
186
|
+
const value = resolver(result);
|
|
187
|
+
if (value !== null && value !== undefined) {
|
|
188
|
+
return value;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
return 0;
|
|
192
|
+
}
|
|
193
|
+
};
|
|
194
|
+
exports.MongoCollector = MongoCollector;
|
|
195
|
+
exports.MongoCollector = MongoCollector = MongoCollector_1 = __decorate([
|
|
196
|
+
(0, common_1.Injectable)(),
|
|
197
|
+
__param(1, (0, common_1.Inject)('PROFILER_OPTIONS')),
|
|
198
|
+
__metadata("design:paramtypes", [profiler_service_1.ProfilerService, Object])
|
|
199
|
+
], MongoCollector);
|
|
200
|
+
//# sourceMappingURL=mongo-collector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mongo-collector.js","sourceRoot":"","sources":["../../../libs/nestjs-profiler/src/collectors/mongo-collector.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { OnModuleInit } from '@nestjs/common';
|
|
2
|
+
import { ProfilerService } from '../services/profiler.service';
|
|
3
|
+
import type { ProfilerOptions } from '../common/profiler-options.interface';
|
|
4
|
+
export declare class MysqlCollector implements OnModuleInit {
|
|
5
|
+
private profiler;
|
|
6
|
+
private options;
|
|
7
|
+
private logger;
|
|
8
|
+
private mysql;
|
|
9
|
+
constructor(profiler: ProfilerService, options: ProfilerOptions);
|
|
10
|
+
onModuleInit(): void;
|
|
11
|
+
private patchMysql;
|
|
12
|
+
}
|