@senzops/apm-node 1.1.8 → 1.1.11

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.
@@ -0,0 +1,41 @@
1
+ import type { SenzorClient } from '../core/client';
2
+ import { hookRequire } from './hook';
3
+
4
+ export const instrumentNodeCron = (client: SenzorClient, debug: boolean) => {
5
+ hookRequire('node-cron', (cronExports) => {
6
+
7
+ // Abstracted patcher so we can apply it to both the root and the .default export
8
+ const patchSchedule = (target: any) => {
9
+ if (!target || typeof target.schedule !== 'function' || target.__senzorPatched) return;
10
+
11
+ const originalSchedule = target.schedule;
12
+
13
+ target.schedule = function (expression: string, func: (...args: any[]) => any, options: any) {
14
+ // Handle node-cron's dynamic options argument (can be string or object)
15
+ const optsObj = typeof options === 'object' ? options : { timezone: options };
16
+ const taskName = optsObj?.name || `cron: ${expression}`;
17
+
18
+ const wrappedFunc = client.wrapTask(
19
+ taskName,
20
+ 'cron',
21
+ { metadata: optsObj },
22
+ func
23
+ );
24
+
25
+ return originalSchedule.call(this, expression, wrappedFunc, options);
26
+ };
27
+
28
+ // Safely mark as patched to prevent infinite loops
29
+ Object.defineProperty(target, '__senzorPatched', { value: true, enumerable: false, writable: true });
30
+ if (debug) console.log('[Senzor] Node-Cron successfully instrumented');
31
+ };
32
+
33
+ // Apply patch to root (for const cron = require('node-cron'))
34
+ patchSchedule(cronExports);
35
+
36
+ // Apply patch to default (for import cron from 'node-cron')
37
+ if (cronExports.default) {
38
+ patchSchedule(cronExports.default);
39
+ }
40
+ });
41
+ };
@@ -0,0 +1,24 @@
1
+ import Module from 'module';
2
+
3
+ export const hookRequire = (moduleName: string, onRequire: (exports: any) => void) => {
4
+ // 1. If it was already loaded (e.g., imported at the top of the file before init)
5
+ try {
6
+ const resolvedPath = require.resolve(moduleName);
7
+ const cached = require.cache[resolvedPath];
8
+ if (cached && cached.exports) {
9
+ onRequire(cached.exports);
10
+ }
11
+ } catch (e) {
12
+ // Silently ignore if module is not installed
13
+ }
14
+
15
+ // 2. Intercept future requires
16
+ const originalLoad = (Module as any)._load;
17
+ (Module as any)._load = function (request: string, parent: any, isMain: boolean) {
18
+ const exports = originalLoad.apply(this, arguments);
19
+ if (request === moduleName && exports) {
20
+ onRequire(exports);
21
+ }
22
+ return exports;
23
+ };
24
+ };