@ngn-net/nestjs-telescope 0.1.1
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 +110 -0
- package/dist/constants.d.ts +3 -0
- package/dist/constants.js +7 -0
- package/dist/controllers/telescope.controller.d.ts +17 -0
- package/dist/controllers/telescope.controller.js +126 -0
- package/dist/enums/entry-type.enum.d.ts +14 -0
- package/dist/enums/entry-type.enum.js +19 -0
- package/dist/guards/telescope-jwt.guard.d.ts +7 -0
- package/dist/guards/telescope-jwt.guard.js +44 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +25 -0
- package/dist/interfaces/entry.interface.d.ts +10 -0
- package/dist/interfaces/entry.interface.js +2 -0
- package/dist/interfaces/telescope-options.interface.d.ts +13 -0
- package/dist/interfaces/telescope-options.interface.js +2 -0
- package/dist/storage/entities/telescope-entry.entity.d.ts +10 -0
- package/dist/storage/entities/telescope-entry.entity.js +56 -0
- package/dist/storage/telescope-repository.service.d.ts +18 -0
- package/dist/storage/telescope-repository.service.js +77 -0
- package/dist/telescope.module.d.ts +4 -0
- package/dist/telescope.module.js +84 -0
- package/dist/telescope.service.d.ts +13 -0
- package/dist/telescope.service.js +62 -0
- package/dist/watchers/cache.watcher.d.ts +7 -0
- package/dist/watchers/cache.watcher.js +62 -0
- package/dist/watchers/event.watcher.d.ts +13 -0
- package/dist/watchers/event.watcher.js +51 -0
- package/dist/watchers/exception.watcher.d.ts +8 -0
- package/dist/watchers/exception.watcher.js +44 -0
- package/dist/watchers/http-request.watcher.d.ts +8 -0
- package/dist/watchers/http-request.watcher.js +52 -0
- package/dist/watchers/log.watcher.d.ts +7 -0
- package/dist/watchers/log.watcher.js +63 -0
- package/dist/watchers/mail.watcher.d.ts +12 -0
- package/dist/watchers/mail.watcher.js +90 -0
- package/dist/watchers/query.watcher.d.ts +10 -0
- package/dist/watchers/query.watcher.js +52 -0
- package/dist/watchers/queue.watcher.d.ts +10 -0
- package/dist/watchers/queue.watcher.js +66 -0
- package/dist/watchers/redis.watcher.d.ts +7 -0
- package/dist/watchers/redis.watcher.js +74 -0
- package/dist/watchers/schedule.watcher.d.ts +9 -0
- package/dist/watchers/schedule.watcher.js +92 -0
- package/package.json +49 -0
- package/ui/index.html +1268 -0
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { OnModuleInit } from '@nestjs/common';
|
|
2
|
+
import { Queue } from 'bullmq';
|
|
3
|
+
import { TelescopeService } from '../telescope.service';
|
|
4
|
+
export declare class QueueWatcher implements OnModuleInit {
|
|
5
|
+
private readonly queue;
|
|
6
|
+
private readonly telescope;
|
|
7
|
+
private queueEvents;
|
|
8
|
+
constructor(queue: Queue, telescope: TelescopeService);
|
|
9
|
+
onModuleInit(): void;
|
|
10
|
+
}
|
|
@@ -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
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.QueueWatcher = void 0;
|
|
16
|
+
// src/watchers/queue.watcher.ts
|
|
17
|
+
const common_1 = require("@nestjs/common");
|
|
18
|
+
const bullmq_1 = require("@nestjs/bullmq");
|
|
19
|
+
const bullmq_2 = require("bullmq");
|
|
20
|
+
const telescope_service_1 = require("../telescope.service");
|
|
21
|
+
const entry_type_enum_1 = require("../enums/entry-type.enum");
|
|
22
|
+
let QueueWatcher = class QueueWatcher {
|
|
23
|
+
queue;
|
|
24
|
+
telescope;
|
|
25
|
+
queueEvents;
|
|
26
|
+
constructor(queue, telescope) {
|
|
27
|
+
this.queue = queue;
|
|
28
|
+
this.telescope = telescope;
|
|
29
|
+
}
|
|
30
|
+
onModuleInit() {
|
|
31
|
+
this.queueEvents = new bullmq_2.QueueEvents(this.queue.name, {
|
|
32
|
+
connection: this.queue.opts?.connection,
|
|
33
|
+
});
|
|
34
|
+
this.queueEvents.on('completed', ({ jobId, returnvalue }) => {
|
|
35
|
+
this.telescope.record({
|
|
36
|
+
type: entry_type_enum_1.EntryType.JOB,
|
|
37
|
+
content: { jobId, status: 'completed', returnvalue },
|
|
38
|
+
});
|
|
39
|
+
});
|
|
40
|
+
this.queueEvents.on('failed', ({ jobId, failedReason }) => {
|
|
41
|
+
this.telescope.record({
|
|
42
|
+
type: entry_type_enum_1.EntryType.JOB,
|
|
43
|
+
content: { jobId, status: 'failed', failedReason },
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
this.queueEvents.on('active', ({ jobId, prev }) => {
|
|
47
|
+
this.telescope.record({
|
|
48
|
+
type: entry_type_enum_1.EntryType.JOB,
|
|
49
|
+
content: { jobId, status: 'active', prev },
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
this.queueEvents.on('stalled', ({ jobId }) => {
|
|
53
|
+
this.telescope.record({
|
|
54
|
+
type: entry_type_enum_1.EntryType.JOB,
|
|
55
|
+
content: { jobId, status: 'stalled' },
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
exports.QueueWatcher = QueueWatcher;
|
|
61
|
+
exports.QueueWatcher = QueueWatcher = __decorate([
|
|
62
|
+
(0, common_1.Injectable)(),
|
|
63
|
+
__param(0, (0, bullmq_1.InjectQueue)('telescope-queue')),
|
|
64
|
+
__metadata("design:paramtypes", [bullmq_2.Queue,
|
|
65
|
+
telescope_service_1.TelescopeService])
|
|
66
|
+
], QueueWatcher);
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { OnModuleInit } from '@nestjs/common';
|
|
2
|
+
import { TelescopeService } from '../telescope.service';
|
|
3
|
+
export declare class RedisWatcher implements OnModuleInit {
|
|
4
|
+
private readonly telescope;
|
|
5
|
+
constructor(telescope: TelescopeService);
|
|
6
|
+
onModuleInit(): void;
|
|
7
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
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
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.RedisWatcher = void 0;
|
|
13
|
+
// src/watchers/redis.watcher.ts
|
|
14
|
+
const common_1 = require("@nestjs/common");
|
|
15
|
+
const telescope_service_1 = require("../telescope.service");
|
|
16
|
+
const entry_type_enum_1 = require("../enums/entry-type.enum");
|
|
17
|
+
let RedisWatcher = class RedisWatcher {
|
|
18
|
+
telescope;
|
|
19
|
+
constructor(telescope) {
|
|
20
|
+
this.telescope = telescope;
|
|
21
|
+
}
|
|
22
|
+
onModuleInit() {
|
|
23
|
+
try {
|
|
24
|
+
// Dynamically hook into ioredis if it is present in the workspace/runtime
|
|
25
|
+
// This prevents runtime failures if the project does not use Redis
|
|
26
|
+
const ioredis = require('ioredis');
|
|
27
|
+
if (ioredis && ioredis.prototype && ioredis.prototype.sendCommand) {
|
|
28
|
+
const originalSendCommand = ioredis.prototype.sendCommand;
|
|
29
|
+
const self = this;
|
|
30
|
+
ioredis.prototype.sendCommand = function (command, ...args) {
|
|
31
|
+
const start = Date.now();
|
|
32
|
+
const name = command?.name || 'unknown';
|
|
33
|
+
const commandArgs = command?.args || [];
|
|
34
|
+
const result = originalSendCommand.call(this, command, ...args);
|
|
35
|
+
if (result && typeof result.then === 'function') {
|
|
36
|
+
result.then((res) => {
|
|
37
|
+
const duration = Date.now() - start;
|
|
38
|
+
self.telescope.record({
|
|
39
|
+
type: entry_type_enum_1.EntryType.REDIS,
|
|
40
|
+
content: {
|
|
41
|
+
command: name,
|
|
42
|
+
arguments: commandArgs,
|
|
43
|
+
duration,
|
|
44
|
+
status: 'success',
|
|
45
|
+
},
|
|
46
|
+
});
|
|
47
|
+
}, (err) => {
|
|
48
|
+
const duration = Date.now() - start;
|
|
49
|
+
self.telescope.record({
|
|
50
|
+
type: entry_type_enum_1.EntryType.REDIS,
|
|
51
|
+
content: {
|
|
52
|
+
command: name,
|
|
53
|
+
arguments: commandArgs,
|
|
54
|
+
duration,
|
|
55
|
+
status: 'failed',
|
|
56
|
+
error: err.message || String(err),
|
|
57
|
+
},
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
return result;
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
catch (e) {
|
|
66
|
+
// ioredis is not loaded or available, skip hooking
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
exports.RedisWatcher = RedisWatcher;
|
|
71
|
+
exports.RedisWatcher = RedisWatcher = __decorate([
|
|
72
|
+
(0, common_1.Injectable)(),
|
|
73
|
+
__metadata("design:paramtypes", [telescope_service_1.TelescopeService])
|
|
74
|
+
], RedisWatcher);
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { OnApplicationBootstrap } from '@nestjs/common';
|
|
2
|
+
import { SchedulerRegistry } from '@nestjs/schedule';
|
|
3
|
+
import { TelescopeService } from '../telescope.service';
|
|
4
|
+
export declare class ScheduleWatcher implements OnApplicationBootstrap {
|
|
5
|
+
private readonly telescope;
|
|
6
|
+
private readonly schedulerRegistry?;
|
|
7
|
+
constructor(telescope: TelescopeService, schedulerRegistry?: SchedulerRegistry | undefined);
|
|
8
|
+
onApplicationBootstrap(): void;
|
|
9
|
+
}
|
|
@@ -0,0 +1,92 @@
|
|
|
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
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.ScheduleWatcher = void 0;
|
|
16
|
+
// src/watchers/schedule.watcher.ts
|
|
17
|
+
const common_1 = require("@nestjs/common");
|
|
18
|
+
const schedule_1 = require("@nestjs/schedule");
|
|
19
|
+
const telescope_service_1 = require("../telescope.service");
|
|
20
|
+
const entry_type_enum_1 = require("../enums/entry-type.enum");
|
|
21
|
+
let ScheduleWatcher = class ScheduleWatcher {
|
|
22
|
+
telescope;
|
|
23
|
+
schedulerRegistry;
|
|
24
|
+
constructor(telescope, schedulerRegistry) {
|
|
25
|
+
this.telescope = telescope;
|
|
26
|
+
this.schedulerRegistry = schedulerRegistry;
|
|
27
|
+
}
|
|
28
|
+
onApplicationBootstrap() {
|
|
29
|
+
if (!this.schedulerRegistry)
|
|
30
|
+
return;
|
|
31
|
+
try {
|
|
32
|
+
const cronJobs = this.schedulerRegistry.getCronJobs();
|
|
33
|
+
cronJobs.forEach((job, name) => {
|
|
34
|
+
// Intercept cron job execution callbacks
|
|
35
|
+
const originalCallbacks = job.callbacks || [];
|
|
36
|
+
if (originalCallbacks.length > 0) {
|
|
37
|
+
job.callbacks = originalCallbacks.map((cb) => {
|
|
38
|
+
return async (...args) => {
|
|
39
|
+
const start = Date.now();
|
|
40
|
+
this.telescope.record({
|
|
41
|
+
type: entry_type_enum_1.EntryType.SCHEDULED_TASK,
|
|
42
|
+
content: {
|
|
43
|
+
name,
|
|
44
|
+
status: 'running',
|
|
45
|
+
cronTime: job.cronTime?.toString(),
|
|
46
|
+
},
|
|
47
|
+
});
|
|
48
|
+
try {
|
|
49
|
+
const res = await cb(...args);
|
|
50
|
+
const duration = Date.now() - start;
|
|
51
|
+
this.telescope.record({
|
|
52
|
+
type: entry_type_enum_1.EntryType.SCHEDULED_TASK,
|
|
53
|
+
content: {
|
|
54
|
+
name,
|
|
55
|
+
status: 'completed',
|
|
56
|
+
duration,
|
|
57
|
+
cronTime: job.cronTime?.toString(),
|
|
58
|
+
},
|
|
59
|
+
});
|
|
60
|
+
return res;
|
|
61
|
+
}
|
|
62
|
+
catch (err) {
|
|
63
|
+
const duration = Date.now() - start;
|
|
64
|
+
this.telescope.record({
|
|
65
|
+
type: entry_type_enum_1.EntryType.SCHEDULED_TASK,
|
|
66
|
+
content: {
|
|
67
|
+
name,
|
|
68
|
+
status: 'failed',
|
|
69
|
+
duration,
|
|
70
|
+
error: err.message || String(err),
|
|
71
|
+
cronTime: job.cronTime?.toString(),
|
|
72
|
+
},
|
|
73
|
+
});
|
|
74
|
+
throw err;
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
catch (e) {
|
|
82
|
+
// Ignore if schedule registry lookup fails
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
exports.ScheduleWatcher = ScheduleWatcher;
|
|
87
|
+
exports.ScheduleWatcher = ScheduleWatcher = __decorate([
|
|
88
|
+
(0, common_1.Injectable)(),
|
|
89
|
+
__param(1, (0, common_1.Optional)()),
|
|
90
|
+
__metadata("design:paramtypes", [telescope_service_1.TelescopeService,
|
|
91
|
+
schedule_1.SchedulerRegistry])
|
|
92
|
+
], ScheduleWatcher);
|
package/package.json
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@ngn-net/nestjs-telescope",
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"publishConfig": {
|
|
5
|
+
"access": "public"
|
|
6
|
+
},
|
|
7
|
+
"description": "Full‑featured monitoring package for NestJS (inspired by Laravel Telescope)",
|
|
8
|
+
"author": "Generated by Antigravity",
|
|
9
|
+
"license": "MIT",
|
|
10
|
+
"main": "dist/index.js",
|
|
11
|
+
"types": "dist/index.d.ts",
|
|
12
|
+
"scripts": {
|
|
13
|
+
"build": "npm run clean && tsc -p tsconfig.build.json",
|
|
14
|
+
"clean": "rimraf dist",
|
|
15
|
+
"test": "jest",
|
|
16
|
+
"prepare": "npm run build"
|
|
17
|
+
},
|
|
18
|
+
"dependencies": {
|
|
19
|
+
"@nestjs/common": "^10",
|
|
20
|
+
"@nestjs/core": "^10",
|
|
21
|
+
"@nestjs/typeorm": "^10",
|
|
22
|
+
"@nestjs/bullmq": "^10",
|
|
23
|
+
"@nestjs/config": "^3",
|
|
24
|
+
"@nestjs/jwt": "^10",
|
|
25
|
+
"@nestjs/passport": "^10",
|
|
26
|
+
"@nestjs/cache-manager": "^2",
|
|
27
|
+
"@nestjs/event-emitter": "^2",
|
|
28
|
+
"@nestjs/schedule": "^4",
|
|
29
|
+
"typeorm": "^0.3",
|
|
30
|
+
"bullmq": "^5",
|
|
31
|
+
"nodemailer": "^6",
|
|
32
|
+
"cache-manager": "^5",
|
|
33
|
+
"class-transformer": "^0.5",
|
|
34
|
+
"class-validator": "^0.14",
|
|
35
|
+
"reflect-metadata": "^0.2",
|
|
36
|
+
"passport-jwt": "^4"
|
|
37
|
+
},
|
|
38
|
+
"devDependencies": {
|
|
39
|
+
"typescript": "^5",
|
|
40
|
+
"ts-node": "^10",
|
|
41
|
+
"rimraf": "^5",
|
|
42
|
+
"jest": "^29",
|
|
43
|
+
"ts-jest": "^29",
|
|
44
|
+
"@types/jest": "^29",
|
|
45
|
+
"@types/node": "^20",
|
|
46
|
+
"@types/express": "^4.17.21",
|
|
47
|
+
"@types/nodemailer": "^6.4.15"
|
|
48
|
+
}
|
|
49
|
+
}
|