@senzops/apm-node 1.1.12 → 1.1.15

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.
@@ -1,24 +1,247 @@
1
1
  import Module from 'module';
2
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)
3
+ const SENZOR_PATCHED =
4
+ Symbol.for('senzor.require.patched');
5
+
6
+ const SENZOR_HOOKS =
7
+ Symbol.for('senzor.require.hooks');
8
+
9
+ type HookFn =
10
+ (exports: unknown) => void;
11
+
12
+ type HookMap =
13
+ Map<string, HookFn[]>;
14
+
15
+ function getHookRegistry(): HookMap {
16
+
17
+ const mod =
18
+ Module as unknown as Record<
19
+ symbol,
20
+ HookMap
21
+ >;
22
+
23
+ if (!mod[SENZOR_HOOKS]) {
24
+
25
+ Object.defineProperty(
26
+ mod,
27
+ SENZOR_HOOKS,
28
+ {
29
+ value: new Map(),
30
+ enumerable: false
31
+ }
32
+ );
33
+
34
+ }
35
+
36
+ return mod[SENZOR_HOOKS];
37
+
38
+ }
39
+
40
+ function runHooks(
41
+ moduleName: string,
42
+ exports: unknown
43
+ ) {
44
+
45
+ const registry =
46
+ (Module as unknown as Record<
47
+ symbol,
48
+ HookMap
49
+ >)[SENZOR_HOOKS];
50
+
51
+ if (!registry) return;
52
+
53
+ const hooks =
54
+ registry.get(moduleName);
55
+
56
+ if (!hooks?.length) return;
57
+
58
+ for (const hook of hooks) {
59
+
60
+ try {
61
+ hook(exports);
62
+ }
63
+ catch (err) {
64
+
65
+ console.error(
66
+ `[Senzor] instrumentation failed for ${moduleName}`,
67
+ err
68
+ );
69
+
70
+ }
71
+
72
+ }
73
+
74
+ }
75
+
76
+ function patchLoaderOnce() {
77
+
78
+ const mod =
79
+ Module as unknown as any;
80
+
81
+ if (mod[SENZOR_PATCHED]) {
82
+ return;
83
+ }
84
+
85
+ const previousLoad =
86
+ mod._load;
87
+
88
+ mod._load =
89
+ function patchedLoad(
90
+ request: string,
91
+ parent: unknown,
92
+ isMain: boolean
93
+ ) {
94
+
95
+ const exports =
96
+ previousLoad.apply(
97
+ this,
98
+ arguments
99
+ );
100
+
101
+ runHooks(
102
+ request,
103
+ exports
104
+ );
105
+
106
+ return exports;
107
+
108
+ };
109
+
110
+ Object.defineProperty(
111
+ mod,
112
+ SENZOR_PATCHED,
113
+ {
114
+ value: true,
115
+ enumerable: false
116
+ }
117
+ );
118
+
119
+ }
120
+
121
+ function patchCached(
122
+ moduleName: string,
123
+ hook: HookFn
124
+ ) {
125
+
5
126
  try {
6
- const resolvedPath = require.resolve(moduleName);
7
- const cached = require.cache[resolvedPath];
8
- if (cached && cached.exports) {
9
- onRequire(cached.exports);
127
+
128
+ const resolved =
129
+ require.resolve(
130
+ moduleName
131
+ );
132
+
133
+ const cached =
134
+ require.cache?.[
135
+ resolved
136
+ ];
137
+
138
+ if (cached?.exports) {
139
+
140
+ hook(
141
+ cached.exports
142
+ );
143
+
144
+ }
145
+
146
+ }
147
+ catch { }
148
+
149
+ }
150
+
151
+ function tryRequire(
152
+ moduleName: string,
153
+ hook: HookFn
154
+ ) {
155
+
156
+ try {
157
+
158
+ const mod =
159
+ require(moduleName);
160
+
161
+ if (mod) {
162
+ hook(mod);
10
163
  }
11
- } catch (e) {
12
- // Silently ignore if module is not installed
164
+
13
165
  }
166
+ catch { }
167
+
168
+ }
169
+
170
+ function retryPatch(
171
+ moduleName: string,
172
+ hook: HookFn
173
+ ) {
174
+
175
+ let attempts = 0;
176
+
177
+ const max = 5;
178
+
179
+ const timer =
180
+ setInterval(() => {
181
+
182
+ attempts++;
183
+
184
+ try {
185
+
186
+ const mod =
187
+ require(moduleName);
188
+
189
+ if (mod) {
190
+
191
+ hook(mod);
192
+
193
+ clearInterval(timer);
194
+
195
+ }
196
+
197
+ }
198
+ catch { }
199
+
200
+ if (attempts >= max) {
201
+ clearInterval(timer);
202
+ }
203
+
204
+ }, 200);
205
+
206
+ }
207
+
208
+ export const hookRequire =
209
+ (
210
+ moduleName: string,
211
+ onRequire: HookFn
212
+ ) => {
213
+
214
+ const registry =
215
+ getHookRegistry();
216
+
217
+ if (!registry.has(moduleName)) {
218
+
219
+ registry.set(
220
+ moduleName,
221
+ []
222
+ );
14
223
 
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
224
  }
22
- return exports;
23
- };
24
- };
225
+
226
+ registry
227
+ .get(moduleName)!
228
+ .push(onRequire);
229
+
230
+ patchLoaderOnce();
231
+
232
+ patchCached(
233
+ moduleName,
234
+ onRequire
235
+ );
236
+
237
+ tryRequire(
238
+ moduleName,
239
+ onRequire
240
+ );
241
+
242
+ retryPatch(
243
+ moduleName,
244
+ onRequire
245
+ );
246
+
247
+ };
@@ -0,0 +1,6 @@
1
+ import pkg from '../../package.json';
2
+
3
+ export const SDK_META = {
4
+ name: pkg.name,
5
+ version: pkg.version
6
+ };
package/tsconfig.json CHANGED
@@ -7,6 +7,7 @@
7
7
  "strict": true,
8
8
  "esModuleInterop": true,
9
9
  "skipLibCheck": true,
10
+ "resolveJsonModule": true,
10
11
  "forceConsistentCasingInFileNames": true
11
12
  },
12
13
  "include": ["src/**/*"],