@rudderjs/telescope 0.0.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.
Files changed (72) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +111 -0
  3. package/boost/guidelines.md +38 -0
  4. package/dist/api/routes.d.ts +7 -0
  5. package/dist/api/routes.d.ts.map +1 -0
  6. package/dist/api/routes.js +99 -0
  7. package/dist/api/routes.js.map +1 -0
  8. package/dist/collectors/cache.d.ts +13 -0
  9. package/dist/collectors/cache.d.ts.map +1 -0
  10. package/dist/collectors/cache.js +48 -0
  11. package/dist/collectors/cache.js.map +1 -0
  12. package/dist/collectors/event.d.ts +13 -0
  13. package/dist/collectors/event.d.ts.map +1 -0
  14. package/dist/collectors/event.js +36 -0
  15. package/dist/collectors/event.js.map +1 -0
  16. package/dist/collectors/exception.d.ts +13 -0
  17. package/dist/collectors/exception.d.ts.map +1 -0
  18. package/dist/collectors/exception.js +38 -0
  19. package/dist/collectors/exception.js.map +1 -0
  20. package/dist/collectors/job.d.ts +12 -0
  21. package/dist/collectors/job.d.ts.map +1 -0
  22. package/dist/collectors/job.js +53 -0
  23. package/dist/collectors/job.js.map +1 -0
  24. package/dist/collectors/log.d.ts +13 -0
  25. package/dist/collectors/log.d.ts.map +1 -0
  26. package/dist/collectors/log.js +35 -0
  27. package/dist/collectors/log.js.map +1 -0
  28. package/dist/collectors/mail.d.ts +12 -0
  29. package/dist/collectors/mail.d.ts.map +1 -0
  30. package/dist/collectors/mail.js +38 -0
  31. package/dist/collectors/mail.js.map +1 -0
  32. package/dist/collectors/model.d.ts +15 -0
  33. package/dist/collectors/model.d.ts.map +1 -0
  34. package/dist/collectors/model.js +49 -0
  35. package/dist/collectors/model.js.map +1 -0
  36. package/dist/collectors/notification.d.ts +12 -0
  37. package/dist/collectors/notification.d.ts.map +1 -0
  38. package/dist/collectors/notification.js +41 -0
  39. package/dist/collectors/notification.js.map +1 -0
  40. package/dist/collectors/query.d.ts +13 -0
  41. package/dist/collectors/query.d.ts.map +1 -0
  42. package/dist/collectors/query.js +45 -0
  43. package/dist/collectors/query.js.map +1 -0
  44. package/dist/collectors/request.d.ts +20 -0
  45. package/dist/collectors/request.d.ts.map +1 -0
  46. package/dist/collectors/request.js +73 -0
  47. package/dist/collectors/request.js.map +1 -0
  48. package/dist/collectors/schedule.d.ts +14 -0
  49. package/dist/collectors/schedule.d.ts.map +1 -0
  50. package/dist/collectors/schedule.js +50 -0
  51. package/dist/collectors/schedule.js.map +1 -0
  52. package/dist/index.d.ts +42 -0
  53. package/dist/index.d.ts.map +1 -0
  54. package/dist/index.js +170 -0
  55. package/dist/index.js.map +1 -0
  56. package/dist/storage.d.ts +35 -0
  57. package/dist/storage.d.ts.map +1 -0
  58. package/dist/storage.js +201 -0
  59. package/dist/storage.js.map +1 -0
  60. package/dist/types.d.ts +67 -0
  61. package/dist/types.d.ts.map +1 -0
  62. package/dist/types.js +24 -0
  63. package/dist/types.js.map +1 -0
  64. package/dist/ui/layout.d.ts +11 -0
  65. package/dist/ui/layout.d.ts.map +1 -0
  66. package/dist/ui/layout.js +69 -0
  67. package/dist/ui/layout.js.map +1 -0
  68. package/dist/ui/pages.d.ts +21 -0
  69. package/dist/ui/pages.d.ts.map +1 -0
  70. package/dist/ui/pages.js +225 -0
  71. package/dist/ui/pages.js.map +1 -0
  72. package/package.json +78 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mail.d.ts","sourceRoot":"","sources":["../../src/collectors/mail.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAA;AAG9D;;GAEG;AACH,qBAAa,aAAc,YAAW,SAAS;IAIjC,OAAO,CAAC,QAAQ,CAAC,OAAO;IAHpC,QAAQ,CAAC,IAAI,oBAAmB;IAChC,QAAQ,CAAC,IAAI,EAAG,MAAM,CAAS;gBAEF,OAAO,EAAE,gBAAgB;IAEhD,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;CA8BhC"}
@@ -0,0 +1,38 @@
1
+ import { createEntry } from '../storage.js';
2
+ /**
3
+ * Records mail sends by wrapping the MailRegistry adapter's send method.
4
+ */
5
+ export class MailCollector {
6
+ storage;
7
+ name = 'Mail Collector';
8
+ type = 'mail';
9
+ constructor(storage) {
10
+ this.storage = storage;
11
+ }
12
+ async register() {
13
+ try {
14
+ const mod = await import('@rudderjs/mail');
15
+ const { MailRegistry } = mod;
16
+ const original = MailRegistry.get();
17
+ if (!original)
18
+ return;
19
+ const storage = this.storage;
20
+ const originalSend = original.send.bind(original);
21
+ original['send'] = async function (mailable, options) {
22
+ await originalSend(mailable, options);
23
+ const m = mailable;
24
+ const opt = options;
25
+ storage.store(createEntry('mail', {
26
+ class: m.constructor.name,
27
+ to: opt['to'] ?? [],
28
+ subject: m['subject'] ?? '',
29
+ queued: false,
30
+ }, { tags: [`mail:${m.constructor.name}`] }));
31
+ };
32
+ }
33
+ catch {
34
+ // @rudderjs/mail not installed — skip
35
+ }
36
+ }
37
+ }
38
+ //# sourceMappingURL=mail.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mail.js","sourceRoot":"","sources":["../../src/collectors/mail.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAE3C;;GAEG;AACH,MAAM,OAAO,aAAa;IAIK;IAHpB,IAAI,GAAG,gBAAgB,CAAA;IACvB,IAAI,GAAG,MAAe,CAAA;IAE/B,YAA6B,OAAyB;QAAzB,YAAO,GAAP,OAAO,CAAkB;IAAG,CAAC;IAE1D,KAAK,CAAC,QAAQ;QACZ,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,gBAAgB,CAAC,CAAA;YAC1C,MAAM,EAAE,YAAY,EAAE,GAAG,GAAG,CAAA;YAE5B,MAAM,QAAQ,GAAG,YAAY,CAAC,GAAG,EAAE,CAAA;YACnC,IAAI,CAAC,QAAQ;gBAAE,OAAM;YAErB,MAAM,OAAO,GAAO,IAAI,CAAC,OAAO,CAAA;YAChC,MAAM,YAAY,GAAG,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAGhD;YAAC,QAA+C,CAAC,MAAM,CAAC,GAAG,KAAK,WAC/D,QAAiB,EACjB,OAAgB;gBAEhB,MAAO,YAAsD,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAA;gBAChF,MAAM,CAAC,GAAK,QAAuE,CAAA;gBACnF,MAAM,GAAG,GAAG,OAAkC,CAAA;gBAC9C,OAAO,CAAC,KAAK,CAAC,WAAW,CAAC,MAAM,EAAE;oBAChC,KAAK,EAAI,CAAC,CAAC,WAAW,CAAC,IAAI;oBAC3B,EAAE,EAAO,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE;oBACxB,OAAO,EAAE,CAAC,CAAC,SAAS,CAAC,IAAI,EAAE;oBAC3B,MAAM,EAAG,KAAK;iBACf,EAAE,EAAE,IAAI,EAAE,CAAC,QAAQ,CAAC,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC,CAAA;YAC/C,CAAC,CAAA;QACH,CAAC;QAAC,MAAM,CAAC;YACP,sCAAsC;QACxC,CAAC;IACH,CAAC;CACF"}
@@ -0,0 +1,15 @@
1
+ import type { Collector, TelescopeStorage } from '../types.js';
2
+ /**
3
+ * Records model lifecycle events (created, updated, deleted) via Model.on().
4
+ *
5
+ * Registers on all models discovered through the ModelRegistry.
6
+ */
7
+ export declare class ModelCollector implements Collector {
8
+ private readonly storage;
9
+ readonly name = "Model Collector";
10
+ readonly type: "model";
11
+ constructor(storage: TelescopeStorage);
12
+ register(): Promise<void>;
13
+ private observeModel;
14
+ }
15
+ //# sourceMappingURL=model.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../../src/collectors/model.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAA;AAG9D;;;;GAIG;AACH,qBAAa,cAAe,YAAW,SAAS;IAIlC,OAAO,CAAC,QAAQ,CAAC,OAAO;IAHpC,QAAQ,CAAC,IAAI,qBAAoB;IACjC,QAAQ,CAAC,IAAI,EAAG,OAAO,CAAS;gBAEH,OAAO,EAAE,gBAAgB;IAEhD,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAgB/B,OAAO,CAAC,YAAY;CAyBrB"}
@@ -0,0 +1,49 @@
1
+ import { createEntry } from '../storage.js';
2
+ /**
3
+ * Records model lifecycle events (created, updated, deleted) via Model.on().
4
+ *
5
+ * Registers on all models discovered through the ModelRegistry.
6
+ */
7
+ export class ModelCollector {
8
+ storage;
9
+ name = 'Model Collector';
10
+ type = 'model';
11
+ constructor(storage) {
12
+ this.storage = storage;
13
+ }
14
+ async register() {
15
+ try {
16
+ const orm = await import('@rudderjs/orm');
17
+ const registry = orm.ModelRegistry;
18
+ if (!registry.all)
19
+ return;
20
+ for (const [name, ModelClass] of registry.all()) {
21
+ this.observeModel(name, ModelClass);
22
+ }
23
+ }
24
+ catch {
25
+ // @rudderjs/orm not installed — skip
26
+ }
27
+ }
28
+ observeModel(modelName, ModelClass) {
29
+ const storage = this.storage;
30
+ for (const event of ['created', 'updated', 'deleted']) {
31
+ ModelClass.on(event, (...args) => {
32
+ const content = {
33
+ model: modelName,
34
+ action: event,
35
+ };
36
+ if (event === 'created' || event === 'updated') {
37
+ content['attributes'] = args[0];
38
+ }
39
+ else if (event === 'deleted') {
40
+ content['id'] = args[0];
41
+ }
42
+ storage.store(createEntry('model', content, {
43
+ tags: [`model:${modelName}`, `action:${event}`],
44
+ }));
45
+ });
46
+ }
47
+ }
48
+ }
49
+ //# sourceMappingURL=model.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model.js","sourceRoot":"","sources":["../../src/collectors/model.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAE3C;;;;GAIG;AACH,MAAM,OAAO,cAAc;IAII;IAHpB,IAAI,GAAG,iBAAiB,CAAA;IACxB,IAAI,GAAG,OAAgB,CAAA;IAEhC,YAA6B,OAAyB;QAAzB,YAAO,GAAP,OAAO,CAAkB;IAAG,CAAC;IAE1D,KAAK,CAAC,QAAQ;QACZ,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,eAAe,CAAC,CAAA;YACzC,MAAM,QAAQ,GAAG,GAAG,CAAC,aAEpB,CAAA;YACD,IAAI,CAAC,QAAQ,CAAC,GAAG;gBAAE,OAAM;YAEzB,KAAK,MAAM,CAAC,IAAI,EAAE,UAAU,CAAC,IAAI,QAAQ,CAAC,GAAG,EAAE,EAAE,CAAC;gBAChD,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE,UAAU,CAAC,CAAA;YACrC,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,qCAAqC;QACvC,CAAC;IACH,CAAC;IAEO,YAAY,CAClB,SAAiB,EACjB,UAA8E;QAE9E,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAA;QAE5B,KAAK,MAAM,KAAK,IAAI,CAAC,SAAS,EAAE,SAAS,EAAE,SAAS,CAAU,EAAE,CAAC;YAC/D,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,GAAG,IAAe,EAAE,EAAE;gBAC1C,MAAM,OAAO,GAA4B;oBACvC,KAAK,EAAG,SAAS;oBACjB,MAAM,EAAE,KAAK;iBACd,CAAA;gBAED,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;oBAC/C,OAAO,CAAC,YAAY,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAA;gBACjC,CAAC;qBAAM,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;oBAC/B,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAA;gBACzB,CAAC;gBAED,OAAO,CAAC,KAAK,CAAC,WAAW,CAAC,OAAO,EAAE,OAAO,EAAE;oBAC1C,IAAI,EAAE,CAAC,SAAS,SAAS,EAAE,EAAE,UAAU,KAAK,EAAE,CAAC;iBAChD,CAAC,CAAC,CAAA;YACL,CAAC,CAAC,CAAA;QACJ,CAAC;IACH,CAAC;CACF"}
@@ -0,0 +1,12 @@
1
+ import type { Collector, TelescopeStorage } from '../types.js';
2
+ /**
3
+ * Records notification dispatches by wrapping the ChannelRegistry's get method.
4
+ */
5
+ export declare class NotificationCollector implements Collector {
6
+ private readonly storage;
7
+ readonly name = "Notification Collector";
8
+ readonly type: "notification";
9
+ constructor(storage: TelescopeStorage);
10
+ register(): Promise<void>;
11
+ }
12
+ //# sourceMappingURL=notification.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"notification.d.ts","sourceRoot":"","sources":["../../src/collectors/notification.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAA;AAG9D;;GAEG;AACH,qBAAa,qBAAsB,YAAW,SAAS;IAIzC,OAAO,CAAC,QAAQ,CAAC,OAAO;IAHpC,QAAQ,CAAC,IAAI,4BAA2B;IACxC,QAAQ,CAAC,IAAI,EAAG,cAAc,CAAS;gBAEV,OAAO,EAAE,gBAAgB;IAEhD,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;CA+BhC"}
@@ -0,0 +1,41 @@
1
+ import { createEntry } from '../storage.js';
2
+ /**
3
+ * Records notification dispatches by wrapping the ChannelRegistry's get method.
4
+ */
5
+ export class NotificationCollector {
6
+ storage;
7
+ name = 'Notification Collector';
8
+ type = 'notification';
9
+ constructor(storage) {
10
+ this.storage = storage;
11
+ }
12
+ async register() {
13
+ try {
14
+ const mod = await import('@rudderjs/notification');
15
+ const registry = mod.ChannelRegistry;
16
+ const storage = this.storage;
17
+ const originalGet = registry.get.bind(registry);
18
+ registry.get = (name) => {
19
+ const original = originalGet(name);
20
+ if (!original)
21
+ return original;
22
+ return {
23
+ async send(notifiable, notification) {
24
+ await original.send(notifiable, notification);
25
+ const notif = notification;
26
+ const n = notifiable;
27
+ storage.store(createEntry('notification', {
28
+ class: notif.constructor.name,
29
+ channel: name,
30
+ notifiable: n['id'] ?? notifiable.constructor.name,
31
+ }, { tags: [`notification:${notif.constructor.name}`, `channel:${name}`] }));
32
+ },
33
+ };
34
+ };
35
+ }
36
+ catch {
37
+ // @rudderjs/notification not installed — skip
38
+ }
39
+ }
40
+ }
41
+ //# sourceMappingURL=notification.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"notification.js","sourceRoot":"","sources":["../../src/collectors/notification.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAE3C;;GAEG;AACH,MAAM,OAAO,qBAAqB;IAIH;IAHpB,IAAI,GAAG,wBAAwB,CAAA;IAC/B,IAAI,GAAG,cAAuB,CAAA;IAEvC,YAA6B,OAAyB;QAAzB,YAAO,GAAP,OAAO,CAAkB;IAAG,CAAC;IAE1D,KAAK,CAAC,QAAQ;QACZ,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,wBAAwB,CAAC,CAAA;YAClD,MAAM,QAAQ,GAAG,GAAG,CAAC,eAEpB,CAAA;YAED,MAAM,OAAO,GAAO,IAAI,CAAC,OAAO,CAAA;YAChC,MAAM,WAAW,GAAG,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;YAE/C,QAAQ,CAAC,GAAG,GAAG,CAAC,IAAY,EAAmC,EAAE;gBAC/D,MAAM,QAAQ,GAAG,WAAW,CAAC,IAAI,CAAC,CAAA;gBAClC,IAAI,CAAC,QAAQ;oBAAE,OAAO,QAAQ,CAAA;gBAE9B,OAAO;oBACL,KAAK,CAAC,IAAI,CAAC,UAAmB,EAAE,YAAqB;wBACnD,MAAO,QAAQ,CAAC,IAAsD,CAAC,UAAU,EAAE,YAAY,CAAC,CAAA;wBAChG,MAAM,KAAK,GAAG,YAA2E,CAAA;wBACzF,MAAM,CAAC,GAAO,UAAqC,CAAA;wBACnD,OAAO,CAAC,KAAK,CAAC,WAAW,CAAC,cAAc,EAAE;4BACxC,KAAK,EAAO,KAAK,CAAC,WAAW,CAAC,IAAI;4BAClC,OAAO,EAAK,IAAI;4BAChB,UAAU,EAAE,CAAC,CAAC,IAAI,CAAC,IAAK,UAAgD,CAAC,WAAW,CAAC,IAAI;yBAC1F,EAAE,EAAE,IAAI,EAAE,CAAC,gBAAgB,KAAK,CAAC,WAAW,CAAC,IAAI,EAAE,EAAE,WAAW,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC,CAAA;oBAC9E,CAAC;iBACqB,CAAA;YAC1B,CAAC,CAAA;QACH,CAAC;QAAC,MAAM,CAAC;YACP,8CAA8C;QAChD,CAAC;IACH,CAAC;CACF"}
@@ -0,0 +1,13 @@
1
+ import type { Collector, TelescopeStorage, TelescopeConfig } from '../types.js';
2
+ /**
3
+ * Records database queries by hooking into the ORM's query logging.
4
+ */
5
+ export declare class QueryCollector implements Collector {
6
+ private readonly storage;
7
+ private readonly config;
8
+ readonly name = "Query Collector";
9
+ readonly type: "query";
10
+ constructor(storage: TelescopeStorage, config: TelescopeConfig);
11
+ register(): Promise<void>;
12
+ }
13
+ //# sourceMappingURL=query.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../../src/collectors/query.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AAG/E;;GAEG;AACH,qBAAa,cAAe,YAAW,SAAS;IAK5C,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,MAAM;IALzB,QAAQ,CAAC,IAAI,qBAAoB;IACjC,QAAQ,CAAC,IAAI,EAAG,OAAO,CAAS;gBAGb,OAAO,EAAE,gBAAgB,EACzB,MAAM,EAAG,eAAe;IAGrC,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;CA+BhC"}
@@ -0,0 +1,45 @@
1
+ import { createEntry } from '../storage.js';
2
+ /**
3
+ * Records database queries by hooking into the ORM's query logging.
4
+ */
5
+ export class QueryCollector {
6
+ storage;
7
+ config;
8
+ name = 'Query Collector';
9
+ type = 'query';
10
+ constructor(storage, config) {
11
+ this.storage = storage;
12
+ this.config = config;
13
+ }
14
+ async register() {
15
+ try {
16
+ const orm = await import('@rudderjs/orm');
17
+ const registry = orm.ModelRegistry;
18
+ if (!registry.getAdapter)
19
+ return;
20
+ const adapter = registry.getAdapter();
21
+ if (!adapter?.onQuery)
22
+ return;
23
+ const storage = this.storage;
24
+ const threshold = this.config.slowQueryThreshold ?? 100;
25
+ adapter.onQuery((info) => {
26
+ const tags = [];
27
+ if (info.duration > threshold)
28
+ tags.push('slow');
29
+ if (info.model)
30
+ tags.push(`model:${info.model}`);
31
+ storage.store(createEntry('query', {
32
+ sql: info.sql,
33
+ bindings: info.bindings,
34
+ duration: info.duration,
35
+ connection: info.connection,
36
+ model: info.model,
37
+ }, { tags }));
38
+ });
39
+ }
40
+ catch {
41
+ // @rudderjs/orm not installed or adapter doesn't support onQuery — skip
42
+ }
43
+ }
44
+ }
45
+ //# sourceMappingURL=query.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"query.js","sourceRoot":"","sources":["../../src/collectors/query.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAE3C;;GAEG;AACH,MAAM,OAAO,cAAc;IAKN;IACA;IALV,IAAI,GAAG,iBAAiB,CAAA;IACxB,IAAI,GAAG,OAAgB,CAAA;IAEhC,YACmB,OAAyB,EACzB,MAAwB;QADxB,YAAO,GAAP,OAAO,CAAkB;QACzB,WAAM,GAAN,MAAM,CAAkB;IACxC,CAAC;IAEJ,KAAK,CAAC,QAAQ;QACZ,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,eAAe,CAAC,CAAA;YACzC,MAAM,QAAQ,GAAG,GAAG,CAAC,aAEpB,CAAA;YACD,IAAI,CAAC,QAAQ,CAAC,UAAU;gBAAE,OAAM;YAEhC,MAAM,OAAO,GAAG,QAAQ,CAAC,UAAU,EAAE,CAAA;YACrC,IAAI,CAAC,OAAO,EAAE,OAAO;gBAAE,OAAM;YAE7B,MAAM,OAAO,GAAK,IAAI,CAAC,OAAO,CAAA;YAC9B,MAAM,SAAS,GAAG,IAAI,CAAC,MAAM,CAAC,kBAAkB,IAAI,GAAG,CAAA;YAEvD,OAAO,CAAC,OAAO,CAAC,CAAC,IAAe,EAAE,EAAE;gBAClC,MAAM,IAAI,GAAa,EAAE,CAAA;gBACzB,IAAI,IAAI,CAAC,QAAQ,GAAG,SAAS;oBAAE,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;gBAChD,IAAI,IAAI,CAAC,KAAK;oBAAE,IAAI,CAAC,IAAI,CAAC,SAAS,IAAI,CAAC,KAAK,EAAE,CAAC,CAAA;gBAEhD,OAAO,CAAC,KAAK,CAAC,WAAW,CAAC,OAAO,EAAE;oBACjC,GAAG,EAAS,IAAI,CAAC,GAAG;oBACpB,QAAQ,EAAI,IAAI,CAAC,QAAQ;oBACzB,QAAQ,EAAI,IAAI,CAAC,QAAQ;oBACzB,UAAU,EAAE,IAAI,CAAC,UAAU;oBAC3B,KAAK,EAAO,IAAI,CAAC,KAAK;iBACvB,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAA;YACf,CAAC,CAAC,CAAA;QACJ,CAAC;QAAC,MAAM,CAAC;YACP,wEAAwE;QAC1E,CAAC;IACH,CAAC;CACF"}
@@ -0,0 +1,20 @@
1
+ import type { AppRequest, AppResponse } from '@rudderjs/contracts';
2
+ import type { Collector, TelescopeStorage, TelescopeConfig } from '../types.js';
3
+ /**
4
+ * Records HTTP requests — method, URL, status, duration, headers, payload.
5
+ * Installs as global middleware via the router.
6
+ */
7
+ export declare class RequestCollector implements Collector {
8
+ private readonly storage;
9
+ private readonly config;
10
+ readonly name = "Request Collector";
11
+ readonly type: "request";
12
+ constructor(storage: TelescopeStorage, config: TelescopeConfig);
13
+ register(): void;
14
+ /** Returns a middleware handler that records requests */
15
+ middleware(): (req: AppRequest, res: AppResponse, next: () => Promise<void>) => Promise<void>;
16
+ private shouldIgnore;
17
+ /** True for Vite internals, source files, and static assets */
18
+ private isAsset;
19
+ }
20
+ //# sourceMappingURL=request.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"request.d.ts","sourceRoot":"","sources":["../../src/collectors/request.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAA;AAClE,OAAO,KAAK,EAAE,SAAS,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AAG/E;;;GAGG;AACH,qBAAa,gBAAiB,YAAW,SAAS;IAK9C,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,MAAM;IALzB,QAAQ,CAAC,IAAI,uBAAsB;IACnC,QAAQ,CAAC,IAAI,EAAG,SAAS,CAAS;gBAGf,OAAO,EAAE,gBAAgB,EACzB,MAAM,EAAG,eAAe;IAG3C,QAAQ,IAAI,IAAI;IAIhB,yDAAyD;IACzD,UAAU,KAIM,KAAK,UAAU,EAAE,KAAK,WAAW,EAAE,MAAM,MAAM,OAAO,CAAC,IAAI,CAAC;IAkC5E,OAAO,CAAC,YAAY;IAOpB,+DAA+D;IAC/D,OAAO,CAAC,OAAO;CAShB"}
@@ -0,0 +1,73 @@
1
+ import { createEntry } from '../storage.js';
2
+ /**
3
+ * Records HTTP requests — method, URL, status, duration, headers, payload.
4
+ * Installs as global middleware via the router.
5
+ */
6
+ export class RequestCollector {
7
+ storage;
8
+ config;
9
+ name = 'Request Collector';
10
+ type = 'request';
11
+ constructor(storage, config) {
12
+ this.storage = storage;
13
+ this.config = config;
14
+ }
15
+ register() {
16
+ // Registration handled by the service provider — it adds this.middleware() to the router
17
+ }
18
+ /** Returns a middleware handler that records requests */
19
+ middleware() {
20
+ const storage = this.storage;
21
+ const ignore = this.config.ignoreRequests ?? [];
22
+ return async (req, res, next) => {
23
+ // Skip Vite internals, static assets, and source files
24
+ if (this.isAsset(req.path))
25
+ return next();
26
+ if (this.shouldIgnore(req.path, ignore)) {
27
+ return next();
28
+ }
29
+ const start = Date.now();
30
+ const batchId = crypto.randomUUID();
31
+ req['__telescopeBatchId'] = batchId;
32
+ await next();
33
+ const duration = Date.now() - start;
34
+ const tags = [];
35
+ if (duration > (this.config.slowQueryThreshold ?? 100))
36
+ tags.push('slow');
37
+ const entry = createEntry('request', {
38
+ method: req.method,
39
+ url: req.url,
40
+ path: req.path,
41
+ query: req.query,
42
+ headers: req.headers,
43
+ body: req.body,
44
+ duration,
45
+ params: req.params,
46
+ }, { batchId, tags });
47
+ storage.store(entry);
48
+ };
49
+ }
50
+ shouldIgnore(path, patterns) {
51
+ return patterns.some(p => {
52
+ if (p.endsWith('*'))
53
+ return path.startsWith(p.slice(0, -1));
54
+ return path === p;
55
+ });
56
+ }
57
+ /** True for Vite internals, source files, and static assets */
58
+ isAsset(path) {
59
+ if (path.startsWith('/@'))
60
+ return true; // Vite internals: /@vite, /@react-refresh, /@id, /@fs
61
+ if (path.startsWith('/node_modules'))
62
+ return true;
63
+ if (path.startsWith('/src/'))
64
+ return true; // Vite source modules during dev
65
+ if (path.startsWith('/pages/'))
66
+ return true; // Vike page modules during dev
67
+ if (path.startsWith('/.vite/'))
68
+ return true; // Vite cache
69
+ const segment = path.split('/').pop() ?? '';
70
+ return segment.includes('.'); // any file extension → static asset
71
+ }
72
+ }
73
+ //# sourceMappingURL=request.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"request.js","sourceRoot":"","sources":["../../src/collectors/request.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import type { Collector, TelescopeStorage } from '../types.js';
2
+ /**
3
+ * Records scheduled task executions.
4
+ *
5
+ * Patches the schedule's task runner at boot time to add recording hooks.
6
+ */
7
+ export declare class ScheduleCollector implements Collector {
8
+ private readonly storage;
9
+ readonly name = "Schedule Collector";
10
+ readonly type: "schedule";
11
+ constructor(storage: TelescopeStorage);
12
+ register(): Promise<void>;
13
+ }
14
+ //# sourceMappingURL=schedule.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schedule.d.ts","sourceRoot":"","sources":["../../src/collectors/schedule.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAA;AAG9D;;;;GAIG;AACH,qBAAa,iBAAkB,YAAW,SAAS;IAIrC,OAAO,CAAC,QAAQ,CAAC,OAAO;IAHpC,QAAQ,CAAC,IAAI,wBAAuB;IACpC,QAAQ,CAAC,IAAI,EAAG,UAAU,CAAS;gBAEN,OAAO,EAAE,gBAAgB;IAEhD,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;CAwChC"}
@@ -0,0 +1,50 @@
1
+ import { createEntry } from '../storage.js';
2
+ /**
3
+ * Records scheduled task executions.
4
+ *
5
+ * Patches the schedule's task runner at boot time to add recording hooks.
6
+ */
7
+ export class ScheduleCollector {
8
+ storage;
9
+ name = 'Schedule Collector';
10
+ type = 'schedule';
11
+ constructor(storage) {
12
+ this.storage = storage;
13
+ }
14
+ async register() {
15
+ try {
16
+ const mod = await import('@rudderjs/schedule');
17
+ const sched = mod.schedule;
18
+ const storage = this.storage;
19
+ const originalCall = sched.call.bind(sched);
20
+ sched.call = function (fn, ...args) {
21
+ const task = originalCall(fn, ...args);
22
+ const desc = task['description'] ?? fn.name ?? 'anonymous';
23
+ let start;
24
+ task.before(() => { start = Date.now(); });
25
+ task.onSuccess(() => {
26
+ storage.store(createEntry('schedule', {
27
+ description: desc,
28
+ expression: task['expression'] ?? '',
29
+ status: 'success',
30
+ duration: Date.now() - start,
31
+ }, { tags: ['status:success'] }));
32
+ });
33
+ task.onFailure((error) => {
34
+ storage.store(createEntry('schedule', {
35
+ description: desc,
36
+ expression: task['expression'] ?? '',
37
+ status: 'failed',
38
+ duration: Date.now() - start,
39
+ exception: error instanceof Error ? error.message : String(error),
40
+ }, { tags: ['status:failed'] }));
41
+ });
42
+ return task;
43
+ };
44
+ }
45
+ catch {
46
+ // @rudderjs/schedule not installed — skip
47
+ }
48
+ }
49
+ }
50
+ //# sourceMappingURL=schedule.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schedule.js","sourceRoot":"","sources":["../../src/collectors/schedule.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAE3C;;;;GAIG;AACH,MAAM,OAAO,iBAAiB;IAIC;IAHpB,IAAI,GAAG,oBAAoB,CAAA;IAC3B,IAAI,GAAG,UAAmB,CAAA;IAEnC,YAA6B,OAAyB;QAAzB,YAAO,GAAP,OAAO,CAAkB;IAAG,CAAC;IAE1D,KAAK,CAAC,QAAQ;QACZ,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,oBAAoB,CAAC,CAAA;YAC9C,MAAM,KAAK,GAAG,GAAG,CAAC,QAEjB,CAAA;YAED,MAAM,OAAO,GAAQ,IAAI,CAAC,OAAO,CAAA;YACjC,MAAM,YAAY,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;YAE3C,KAAK,CAAC,IAAI,GAAG,UAAU,EAAiB,EAAE,GAAG,IAAe;gBAC1D,MAAM,IAAI,GAAG,YAAY,CAAC,EAAE,EAAE,GAAG,IAAI,CAAC,CAAA;gBACtC,MAAM,IAAI,GAAI,IAA2C,CAAC,aAAa,CAAC,IAAI,EAAE,CAAC,IAAI,IAAI,WAAW,CAAA;gBAClG,IAAI,KAAa,CAAA;gBAEjB,IAAI,CAAC,MAAM,CAAC,GAAG,EAAE,GAAG,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA,CAAC,CAAC,CAAC,CAAA;gBACzC,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE;oBAClB,OAAO,CAAC,KAAK,CAAC,WAAW,CAAC,UAAU,EAAE;wBACpC,WAAW,EAAE,IAAI;wBACjB,UAAU,EAAI,IAA2C,CAAC,YAAY,CAAC,IAAI,EAAE;wBAC7E,MAAM,EAAO,SAAS;wBACtB,QAAQ,EAAK,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK;qBAChC,EAAE,EAAE,IAAI,EAAE,CAAC,gBAAgB,CAAC,EAAE,CAAC,CAAC,CAAA;gBACnC,CAAC,CAAC,CAAA;gBACF,IAAI,CAAC,SAAS,CAAC,CAAC,KAAc,EAAE,EAAE;oBAChC,OAAO,CAAC,KAAK,CAAC,WAAW,CAAC,UAAU,EAAE;wBACpC,WAAW,EAAE,IAAI;wBACjB,UAAU,EAAI,IAA2C,CAAC,YAAY,CAAC,IAAI,EAAE;wBAC7E,MAAM,EAAO,QAAQ;wBACrB,QAAQ,EAAK,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK;wBAC/B,SAAS,EAAI,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;qBACpE,EAAE,EAAE,IAAI,EAAE,CAAC,eAAe,CAAC,EAAE,CAAC,CAAC,CAAA;gBAClC,CAAC,CAAC,CAAA;gBAEF,OAAO,IAAI,CAAA;YACb,CAAC,CAAA;QACH,CAAC;QAAC,MAAM,CAAC;YACP,0CAA0C;QAC5C,CAAC;IACH,CAAC;CACF"}
@@ -0,0 +1,42 @@
1
+ import { ServiceProvider, type Application } from '@rudderjs/core';
2
+ import { type TelescopeConfig, type TelescopeStorage, type TelescopeEntry, type EntryType, type Collector, type ListOptions } from './types.js';
3
+ export type { TelescopeConfig, TelescopeStorage, TelescopeEntry, EntryType, Collector, ListOptions };
4
+ export { MemoryStorage, SqliteStorage, createEntry } from './storage.js';
5
+ export { RequestCollector } from './collectors/request.js';
6
+ export { QueryCollector } from './collectors/query.js';
7
+ export { JobCollector } from './collectors/job.js';
8
+ export { ExceptionCollector } from './collectors/exception.js';
9
+ export { LogCollector } from './collectors/log.js';
10
+ export { MailCollector } from './collectors/mail.js';
11
+ export { NotificationCollector } from './collectors/notification.js';
12
+ export { EventCollector } from './collectors/event.js';
13
+ export { CacheCollector } from './collectors/cache.js';
14
+ export { ScheduleCollector } from './collectors/schedule.js';
15
+ export { ModelCollector } from './collectors/model.js';
16
+ export declare class TelescopeRegistry {
17
+ private static storage;
18
+ static set(storage: TelescopeStorage): void;
19
+ static get(): TelescopeStorage | null;
20
+ /** @internal — clears the registered storage. Used for testing. */
21
+ static reset(): void;
22
+ }
23
+ export declare class Telescope {
24
+ private static store;
25
+ static list(options?: ListOptions): Promise<TelescopeEntry[]> | TelescopeEntry[];
26
+ static find(id: string): Promise<TelescopeEntry | null> | TelescopeEntry | null;
27
+ static count(type?: EntryType): Promise<number> | number;
28
+ static prune(type?: EntryType): Promise<void> | void;
29
+ static record(entry: TelescopeEntry): Promise<void> | void;
30
+ }
31
+ /**
32
+ * Returns a TelescopeServiceProvider class configured for the given config.
33
+ *
34
+ * Records requests, queries, jobs, exceptions, logs, mail, notifications,
35
+ * events, cache operations, scheduled tasks, and model changes.
36
+ *
37
+ * Usage in bootstrap/providers.ts:
38
+ * import { telescope } from '@rudderjs/telescope'
39
+ * export default [..., telescope(configs.telescope), ...]
40
+ */
41
+ export declare function telescope(config?: TelescopeConfig): new (app: Application) => ServiceProvider;
42
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,KAAK,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAclE,OAAO,EAAiB,KAAK,eAAe,EAAE,KAAK,gBAAgB,EAAE,KAAK,cAAc,EAAE,KAAK,SAAS,EAAE,KAAK,SAAS,EAAE,KAAK,WAAW,EAAE,MAAM,YAAY,CAAA;AAI9J,YAAY,EAAE,eAAe,EAAE,gBAAgB,EAAE,cAAc,EAAE,SAAS,EAAE,SAAS,EAAE,WAAW,EAAE,CAAA;AACpG,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AACxE,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAA;AAC1D,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA;AACtD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAA;AAC9D,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAA;AACpD,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAA;AACpE,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA;AACtD,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAA;AAC5D,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA;AAItD,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,MAAM,CAAC,OAAO,CAAgC;IAEtD,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,gBAAgB,GAAG,IAAI;IAC3C,MAAM,CAAC,GAAG,IAAI,gBAAgB,GAAG,IAAI;IACrC,mEAAmE;IACnE,MAAM,CAAC,KAAK,IAAI,IAAI;CACrB;AAID,qBAAa,SAAS;IACpB,OAAO,CAAC,MAAM,CAAC,KAAK;IAMpB,MAAM,CAAC,IAAI,CAAC,OAAO,GAAE,WAAgB,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC,GAAG,cAAc,EAAE;IAIpF,MAAM,CAAC,IAAI,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,GAAG,cAAc,GAAG,IAAI;IAI/E,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC,GAAG,MAAM;IAIxD,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI;IAIpD,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI;CAG3D;AAID;;;;;;;;;GASG;AACH,wBAAgB,SAAS,CAAC,MAAM,GAAE,eAAoB,GAAG,KAAK,GAAG,EAAE,WAAW,KAAK,eAAe,CAkGjG"}