@senzops/apm-node 1.1.18 → 1.2.0
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/CHANGELOG.md +4 -0
- package/README.md +386 -48
- package/dist/index.d.mts +9 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.global.js +1 -1
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/index.mjs.map +1 -1
- package/dist/register.d.mts +2 -0
- package/dist/register.d.ts +2 -0
- package/dist/register.js +2 -0
- package/dist/register.js.map +1 -0
- package/dist/register.mjs +2 -0
- package/dist/register.mjs.map +1 -0
- package/package.json +15 -4
- package/src/core/client.ts +159 -105
- package/src/core/context.ts +48 -21
- package/src/core/sanitizer.ts +203 -0
- package/src/core/transport.ts +273 -104
- package/src/core/types.ts +38 -24
- package/src/index.ts +5 -4
- package/src/instrumentation/http.ts +530 -162
- package/src/instrumentation/mongo.ts +202 -105
- package/src/instrumentation/mongoose.ts +156 -0
- package/src/instrumentation/mysql.ts +169 -0
- package/src/instrumentation/patch.ts +56 -0
- package/src/instrumentation/pg.ts +131 -41
- package/src/instrumentation/redis.ts +109 -0
- package/src/instrumentation/span.ts +73 -0
- package/src/instrumentation/undici.ts +189 -0
- package/src/register.ts +42 -0
- package/src/utils/ids.ts +7 -0
- package/src/utils/internal.ts +1 -0
- package/tsup.config.ts +21 -11
- package/wiki.md +844 -120
package/CHANGELOG.md
CHANGED
package/README.md
CHANGED
|
@@ -1,48 +1,386 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
```
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
yarn add @senzops/apm-node
|
|
20
|
-
```
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
```
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
1
|
+
# @senzops/apm-node
|
|
2
|
+
|
|
3
|
+
Official Node.js SDK for Senzor APM.
|
|
4
|
+
|
|
5
|
+
`@senzops/apm-node` captures application traces, spans, errors, logs, and task runs from Node.js API services and sends them to Senzor using the Senzor ingestion format. It is designed to be used directly instead of OpenTelemetry in Senzor-instrumented Node services.
|
|
6
|
+
|
|
7
|
+
The SDK has two supported modes:
|
|
8
|
+
|
|
9
|
+
- Production auto-instrumentation through a preload entrypoint.
|
|
10
|
+
- Explicit framework wrappers and manual APIs for environments where preload is not available.
|
|
11
|
+
|
|
12
|
+
## Installation
|
|
13
|
+
|
|
14
|
+
```sh
|
|
15
|
+
npm install @senzops/apm-node
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
```sh
|
|
19
|
+
yarn add @senzops/apm-node
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
```sh
|
|
23
|
+
pnpm add @senzops/apm-node
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Requirements
|
|
27
|
+
|
|
28
|
+
- Node.js `18.0.0` or newer.
|
|
29
|
+
- A Senzor service API key.
|
|
30
|
+
- Network access from the application runtime to the Senzor ingest endpoint.
|
|
31
|
+
|
|
32
|
+
## Recommended Production Setup
|
|
33
|
+
|
|
34
|
+
Use preload mode so Senzor can patch Node and common libraries before your application imports them.
|
|
35
|
+
|
|
36
|
+
```sh
|
|
37
|
+
SENZOR_API_KEY=sz_apm_your_key_here node -r @senzops/apm-node/register server.js
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
For ESM applications:
|
|
41
|
+
|
|
42
|
+
```sh
|
|
43
|
+
SENZOR_API_KEY=sz_apm_your_key_here node --import @senzops/apm-node/register server.mjs
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
With preload enabled, the SDK can automatically capture inbound HTTP requests for common Node frameworks because it instruments the underlying `http` and `https` server lifecycle.
|
|
47
|
+
|
|
48
|
+
## Programmatic Setup
|
|
49
|
+
|
|
50
|
+
If preload mode is not possible, initialize Senzor as early as possible in your application entrypoint.
|
|
51
|
+
|
|
52
|
+
```js
|
|
53
|
+
const Senzor = require('@senzops/apm-node').default;
|
|
54
|
+
|
|
55
|
+
Senzor.init({
|
|
56
|
+
apiKey: 'sz_apm_your_key_here',
|
|
57
|
+
endpoint: 'https://api.senzor.dev',
|
|
58
|
+
batchSize: 100,
|
|
59
|
+
flushInterval: 10000
|
|
60
|
+
});
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
For TypeScript or ESM:
|
|
64
|
+
|
|
65
|
+
```ts
|
|
66
|
+
import Senzor from '@senzops/apm-node';
|
|
67
|
+
|
|
68
|
+
Senzor.init({
|
|
69
|
+
apiKey: process.env.SENZOR_API_KEY!
|
|
70
|
+
});
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## What Gets Captured
|
|
74
|
+
|
|
75
|
+
The SDK captures these signals using the Senzor ingestion format:
|
|
76
|
+
|
|
77
|
+
- APM traces for inbound API requests.
|
|
78
|
+
- Child spans for outgoing HTTP calls, database operations, cache calls, and custom work.
|
|
79
|
+
- Errors with trace or task context.
|
|
80
|
+
- Console logs correlated with the active trace or task.
|
|
81
|
+
- Background task runs for queues and scheduled jobs.
|
|
82
|
+
|
|
83
|
+
Current native auto-instrumentation coverage:
|
|
84
|
+
|
|
85
|
+
| Area | Libraries and runtimes |
|
|
86
|
+
| --- | --- |
|
|
87
|
+
| Inbound HTTP | Node `http`, Node `https`, Express, NestJS, Fastify, Koa, H3, Nuxt/Nitro, Restify, Hapi-style services through Node server capture |
|
|
88
|
+
| Outbound HTTP | `http`, `https`, `fetch`, `undici` |
|
|
89
|
+
| Databases | `pg`, `mongodb`, `mongoose`, `mysql`, `mysql2` |
|
|
90
|
+
| Cache | `redis`, `ioredis` |
|
|
91
|
+
| Jobs | `bullmq`, `node-cron` |
|
|
92
|
+
| Logs | `console.log`, `console.info`, `console.warn`, `console.error`, `console.debug` |
|
|
93
|
+
| Errors | `uncaughtException`, `unhandledRejection`, process warnings, manual captured exceptions |
|
|
94
|
+
|
|
95
|
+
## Express Example
|
|
96
|
+
|
|
97
|
+
Preload mode is preferred:
|
|
98
|
+
|
|
99
|
+
```sh
|
|
100
|
+
SENZOR_API_KEY=sz_apm_your_key_here node -r @senzops/apm-node/register app.js
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
You can still use the Express middleware to refine route detection and capture Express error objects:
|
|
104
|
+
|
|
105
|
+
```js
|
|
106
|
+
const express = require('express');
|
|
107
|
+
const Senzor = require('@senzops/apm-node').default;
|
|
108
|
+
|
|
109
|
+
Senzor.init({
|
|
110
|
+
apiKey: process.env.SENZOR_API_KEY
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
const app = express();
|
|
114
|
+
|
|
115
|
+
app.use(Senzor.requestHandler());
|
|
116
|
+
|
|
117
|
+
app.get('/users/:id', async (req, res) => {
|
|
118
|
+
res.json({ id: req.params.id });
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
app.use(Senzor.errorHandler());
|
|
122
|
+
|
|
123
|
+
app.listen(3000);
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
## Fastify Example
|
|
127
|
+
|
|
128
|
+
```ts
|
|
129
|
+
import Fastify from 'fastify';
|
|
130
|
+
import Senzor from '@senzops/apm-node';
|
|
131
|
+
|
|
132
|
+
const fastify = Fastify();
|
|
133
|
+
|
|
134
|
+
fastify.register(Senzor.fastifyPlugin, {
|
|
135
|
+
apiKey: process.env.SENZOR_API_KEY!
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
fastify.get('/health', async () => ({ ok: true }));
|
|
139
|
+
|
|
140
|
+
await fastify.listen({ port: 3000 });
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
## Next.js Example
|
|
144
|
+
|
|
145
|
+
App Router:
|
|
146
|
+
|
|
147
|
+
```ts
|
|
148
|
+
import Senzor from '@senzops/apm-node';
|
|
149
|
+
|
|
150
|
+
Senzor.init({
|
|
151
|
+
apiKey: process.env.SENZOR_API_KEY!
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
export const GET = Senzor.wrapNextRoute(async () => {
|
|
155
|
+
return Response.json({ ok: true });
|
|
156
|
+
});
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
Pages Router:
|
|
160
|
+
|
|
161
|
+
```ts
|
|
162
|
+
import Senzor from '@senzops/apm-node';
|
|
163
|
+
|
|
164
|
+
Senzor.init({
|
|
165
|
+
apiKey: process.env.SENZOR_API_KEY!
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
export default Senzor.wrapNextPages(async function handler(req, res) {
|
|
169
|
+
res.status(200).json({ ok: true });
|
|
170
|
+
});
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
In serverless runtimes, flush before the function exits when you need deterministic delivery:
|
|
174
|
+
|
|
175
|
+
```ts
|
|
176
|
+
await Senzor.flush();
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
## Manual Spans
|
|
180
|
+
|
|
181
|
+
Use manual spans for business operations that are not covered by auto-instrumentation.
|
|
182
|
+
|
|
183
|
+
```ts
|
|
184
|
+
const span = Senzor.startSpan('calculate_invoice_total', 'function');
|
|
185
|
+
|
|
186
|
+
try {
|
|
187
|
+
const total = await calculateInvoiceTotal(invoiceId);
|
|
188
|
+
span.end({ invoiceId, total }, 200);
|
|
189
|
+
return total;
|
|
190
|
+
} catch (error) {
|
|
191
|
+
span.end({ invoiceId, error: String(error) }, 500);
|
|
192
|
+
Senzor.captureException(error, { invoiceId });
|
|
193
|
+
throw error;
|
|
194
|
+
}
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
## Background Tasks
|
|
198
|
+
|
|
199
|
+
```ts
|
|
200
|
+
const sendInvoiceEmail = Senzor.wrapTask(
|
|
201
|
+
'send_invoice_email',
|
|
202
|
+
'custom',
|
|
203
|
+
{ metadata: { owner: 'billing' } },
|
|
204
|
+
async (invoiceId: string) => {
|
|
205
|
+
await sendEmail(invoiceId);
|
|
206
|
+
}
|
|
207
|
+
);
|
|
208
|
+
|
|
209
|
+
await sendInvoiceEmail('inv_123');
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
Auto-instrumented task integrations:
|
|
213
|
+
|
|
214
|
+
- BullMQ workers.
|
|
215
|
+
- node-cron scheduled jobs.
|
|
216
|
+
|
|
217
|
+
## Configuration
|
|
218
|
+
|
|
219
|
+
| Option | Type | Default | Description |
|
|
220
|
+
| --- | --- | --- | --- |
|
|
221
|
+
| `apiKey` | `string` | Required for sending data | Senzor service API key. |
|
|
222
|
+
| `endpoint` | `string` | `https://api.senzor.dev/api/ingest/apm` | Senzor ingest endpoint or base URL. |
|
|
223
|
+
| `batchSize` | `number` | `100` | Flush when this many queued telemetry items are collected. |
|
|
224
|
+
| `flushInterval` | `number` | `10000` | Flush interval in milliseconds. |
|
|
225
|
+
| `flushTimeoutMs` | `number` | `5000` | Timeout for a single ingest request. |
|
|
226
|
+
| `maxQueueSize` | `number` | `10000` | Maximum queued items per queue before old items are dropped. |
|
|
227
|
+
| `maxSpansPerTrace` | `number` | `500` | Maximum child spans retained for a single trace or task. |
|
|
228
|
+
| `maxAttributeLength` | `number` | `2048` | Maximum string length for attributes and metadata values. |
|
|
229
|
+
| `maxAttributes` | `number` | `64` | Maximum number of attributes retained per object. |
|
|
230
|
+
| `captureHeaders` | `boolean` | `false` | Capture sanitized request headers in trace metadata. |
|
|
231
|
+
| `captureDbStatement` | `boolean` | SDK sanitizes SQL by default | Controls how much SQL statement text is retained. |
|
|
232
|
+
| `instrumentations` | `boolean \| string[]` | `true` | Disable all instrumentation with `false`, or enable only named integrations. |
|
|
233
|
+
| `autoLogs` | `boolean` | `true` | Capture console logs and correlate them with active traces or tasks. |
|
|
234
|
+
| `debug` | `boolean` | `false` | Print SDK diagnostics. |
|
|
235
|
+
|
|
236
|
+
Named instrumentation values include:
|
|
237
|
+
|
|
238
|
+
```ts
|
|
239
|
+
[
|
|
240
|
+
'http',
|
|
241
|
+
'fetch',
|
|
242
|
+
'undici',
|
|
243
|
+
'mongo',
|
|
244
|
+
'mongoose',
|
|
245
|
+
'pg',
|
|
246
|
+
'mysql',
|
|
247
|
+
'redis',
|
|
248
|
+
'bullmq',
|
|
249
|
+
'cron'
|
|
250
|
+
]
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
## Environment Variables
|
|
254
|
+
|
|
255
|
+
The preload entrypoint reads these environment variables:
|
|
256
|
+
|
|
257
|
+
| Variable | Description |
|
|
258
|
+
| --- | --- |
|
|
259
|
+
| `SENZOR_API_KEY` | Service API key. |
|
|
260
|
+
| `SENZOR_APM_API_KEY` | Alternative API key variable. |
|
|
261
|
+
| `SENZOR_SERVICE_API_KEY` | Alternative API key variable. |
|
|
262
|
+
| `SENZOR_ENDPOINT` | Ingest endpoint or base URL. |
|
|
263
|
+
| `SENZOR_APM_ENDPOINT` | Alternative endpoint variable. |
|
|
264
|
+
| `SENZOR_DEBUG` | Set to `true` or `1` to enable SDK diagnostics. |
|
|
265
|
+
| `SENZOR_AUTO_LOGS` | Set to `false` to disable console log capture. |
|
|
266
|
+
| `SENZOR_BATCH_SIZE` | Batch size. |
|
|
267
|
+
| `SENZOR_FLUSH_INTERVAL` | Flush interval in milliseconds. |
|
|
268
|
+
| `SENZOR_FLUSH_TIMEOUT_MS` | Flush timeout in milliseconds. |
|
|
269
|
+
| `SENZOR_MAX_QUEUE_SIZE` | Maximum queued telemetry items per queue. |
|
|
270
|
+
| `SENZOR_MAX_SPANS_PER_TRACE` | Maximum spans retained per trace. |
|
|
271
|
+
| `SENZOR_CAPTURE_HEADERS` | Set to `true` to capture sanitized headers. |
|
|
272
|
+
| `SENZOR_CAPTURE_DB_STATEMENT` | Set to `false` for more restrictive SQL metadata. |
|
|
273
|
+
|
|
274
|
+
## Ingestion Payload Shape
|
|
275
|
+
|
|
276
|
+
The SDK sends APM data to `/api/ingest/apm`:
|
|
277
|
+
|
|
278
|
+
```json
|
|
279
|
+
{
|
|
280
|
+
"traces": [
|
|
281
|
+
{
|
|
282
|
+
"traceId": "f3b2c2c9c70443f5a4b7f0ff6d5b9a17",
|
|
283
|
+
"method": "GET",
|
|
284
|
+
"route": "/users/:id",
|
|
285
|
+
"path": "/users/123?include=roles",
|
|
286
|
+
"status": 200,
|
|
287
|
+
"duration": 42.81,
|
|
288
|
+
"ip": "203.0.113.10",
|
|
289
|
+
"userAgent": "Mozilla/5.0",
|
|
290
|
+
"timestamp": "2026-05-16T15:30:00.000Z",
|
|
291
|
+
"spans": [
|
|
292
|
+
{
|
|
293
|
+
"spanId": "9d8a4d5f17e24d2a",
|
|
294
|
+
"parentSpanId": "91f6c551d5a2403f",
|
|
295
|
+
"name": "Postgres SELECT",
|
|
296
|
+
"type": "db",
|
|
297
|
+
"startTime": 4.22,
|
|
298
|
+
"duration": 12.45,
|
|
299
|
+
"status": 0,
|
|
300
|
+
"meta": {
|
|
301
|
+
"operation": "SELECT",
|
|
302
|
+
"db.system.name": "postgresql",
|
|
303
|
+
"db.operation.name": "SELECT"
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
]
|
|
307
|
+
}
|
|
308
|
+
],
|
|
309
|
+
"errors": [],
|
|
310
|
+
"logs": []
|
|
311
|
+
}
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
Task data is sent to `/api/ingest/task`:
|
|
315
|
+
|
|
316
|
+
```json
|
|
317
|
+
{
|
|
318
|
+
"runs": [
|
|
319
|
+
{
|
|
320
|
+
"runId": "3917bd35-b1d6-4e23-a1d2-d969e1a7d6a1",
|
|
321
|
+
"taskName": "billing:send_invoice_email",
|
|
322
|
+
"taskType": "queue",
|
|
323
|
+
"status": "success",
|
|
324
|
+
"duration": 188.3,
|
|
325
|
+
"queueDelay": 92,
|
|
326
|
+
"attempts": 1,
|
|
327
|
+
"resourceMetrics": {
|
|
328
|
+
"memoryDeltaBytes": 1048576,
|
|
329
|
+
"cpuUserUs": 12000,
|
|
330
|
+
"cpuSystemUs": 3000
|
|
331
|
+
},
|
|
332
|
+
"spans": [],
|
|
333
|
+
"timestamp": "2026-05-16T15:30:00.000Z"
|
|
334
|
+
}
|
|
335
|
+
],
|
|
336
|
+
"errors": [],
|
|
337
|
+
"logs": []
|
|
338
|
+
}
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
## Security Defaults
|
|
342
|
+
|
|
343
|
+
The SDK redacts common sensitive fields from attributes, headers, errors, and logs:
|
|
344
|
+
|
|
345
|
+
- `authorization`
|
|
346
|
+
- `cookie`
|
|
347
|
+
- `set-cookie`
|
|
348
|
+
- `password`
|
|
349
|
+
- `secret`
|
|
350
|
+
- `token`
|
|
351
|
+
- `apiKey`
|
|
352
|
+
- `x-api-key`
|
|
353
|
+
- `accessToken`
|
|
354
|
+
- `refreshToken`
|
|
355
|
+
- `clientSecret`
|
|
356
|
+
- `privateKey`
|
|
357
|
+
|
|
358
|
+
Header capture is disabled by default. SQL metadata is normalized to reduce sensitive values and high-cardinality payloads.
|
|
359
|
+
|
|
360
|
+
## Production Notes
|
|
361
|
+
|
|
362
|
+
- Use preload mode whenever possible.
|
|
363
|
+
- Initialize the SDK before importing application modules when preload mode is not available.
|
|
364
|
+
- Keep `debug` disabled in production unless actively troubleshooting.
|
|
365
|
+
- Use `Senzor.flush()` before serverless function exit.
|
|
366
|
+
- Keep route names low-cardinality, for example `/users/:id` instead of `/users/123`.
|
|
367
|
+
- Do not capture request or response bodies unless your service has a strict data policy and the ingestion backend is prepared for that data.
|
|
368
|
+
|
|
369
|
+
## Public API
|
|
370
|
+
|
|
371
|
+
```ts
|
|
372
|
+
Senzor.init(options)
|
|
373
|
+
Senzor.preload(options)
|
|
374
|
+
Senzor.flush()
|
|
375
|
+
Senzor.track(data)
|
|
376
|
+
Senzor.startSpan(name, type)
|
|
377
|
+
Senzor.captureException(error, context)
|
|
378
|
+
Senzor.wrapTask(name, type, options, fn)
|
|
379
|
+
Senzor.startTask(name, type, options, fn)
|
|
380
|
+
Senzor.requestHandler()
|
|
381
|
+
Senzor.errorHandler()
|
|
382
|
+
Senzor.wrapNextRoute(handler)
|
|
383
|
+
Senzor.wrapNextPages(handler)
|
|
384
|
+
Senzor.wrapH3(handler)
|
|
385
|
+
Senzor.fastifyPlugin
|
|
386
|
+
```
|
package/dist/index.d.mts
CHANGED
|
@@ -3,11 +3,20 @@ interface SenzorOptions {
|
|
|
3
3
|
endpoint?: string;
|
|
4
4
|
batchSize?: number;
|
|
5
5
|
flushInterval?: number;
|
|
6
|
+
flushTimeoutMs?: number;
|
|
7
|
+
maxQueueSize?: number;
|
|
8
|
+
maxSpansPerTrace?: number;
|
|
9
|
+
maxAttributeLength?: number;
|
|
10
|
+
maxAttributes?: number;
|
|
11
|
+
captureHeaders?: boolean;
|
|
12
|
+
captureDbStatement?: boolean;
|
|
13
|
+
instrumentations?: boolean | string[];
|
|
6
14
|
debug?: boolean;
|
|
7
15
|
autoLogs?: boolean;
|
|
8
16
|
}
|
|
9
17
|
|
|
10
18
|
declare const Senzor: {
|
|
19
|
+
preload: (options?: Partial<SenzorOptions>) => void;
|
|
11
20
|
init: (options: SenzorOptions) => void;
|
|
12
21
|
flush: () => Promise<void>;
|
|
13
22
|
track: (data: any) => void;
|
package/dist/index.d.ts
CHANGED
|
@@ -3,11 +3,20 @@ interface SenzorOptions {
|
|
|
3
3
|
endpoint?: string;
|
|
4
4
|
batchSize?: number;
|
|
5
5
|
flushInterval?: number;
|
|
6
|
+
flushTimeoutMs?: number;
|
|
7
|
+
maxQueueSize?: number;
|
|
8
|
+
maxSpansPerTrace?: number;
|
|
9
|
+
maxAttributeLength?: number;
|
|
10
|
+
maxAttributes?: number;
|
|
11
|
+
captureHeaders?: boolean;
|
|
12
|
+
captureDbStatement?: boolean;
|
|
13
|
+
instrumentations?: boolean | string[];
|
|
6
14
|
debug?: boolean;
|
|
7
15
|
autoLogs?: boolean;
|
|
8
16
|
}
|
|
9
17
|
|
|
10
18
|
declare const Senzor: {
|
|
19
|
+
preload: (options?: Partial<SenzorOptions>) => void;
|
|
11
20
|
init: (options: SenzorOptions) => void;
|
|
12
21
|
flush: () => Promise<void>;
|
|
13
22
|
track: (data: any) => void;
|
package/dist/index.global.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";(()=>{var ft=Object.create;var G=Object.defineProperty;var ht=Object.getOwnPropertyDescriptor;var mt=Object.getOwnPropertyNames;var yt=Object.getPrototypeOf,gt=Object.prototype.hasOwnProperty;var w=(e=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(e,{get:(t,n)=>(typeof require<"u"?require:t)[n]}):e)(function(e){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+e+'" is not supported')});var Tt=(e,t,n,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of mt(t))!gt.call(e,o)&&o!==n&&G(e,o,{get:()=>t[o],enumerable:!(r=ht(t,o))||r.enumerable});return e};var O=(e,t,n)=>(n=e!=null?ft(yt(e)):{},Tt(t||!e||!e.__esModule?G(n,"default",{value:e,enumerable:!0}):n,e));var C=class{constructor(t){this.config=t;this.traceQueue=[];this.apmErrorQueue=[];this.apmLogQueue=[];this.taskQueue=[];this.taskErrorQueue=[];this.taskLogQueue=[];this.timer=null;let n=t.endpoint||"https://api.senzor.dev";this.apmEndpoint=n.includes("/api/ingest")?n:`${n}/api/ingest/apm`,this.taskEndpoint=n.includes("/api/ingest")?n.replace("/apm","/task"):`${n}/api/ingest/task`,typeof setInterval<"u"&&(this.timer=setInterval(()=>this.flush(),t.flushInterval||1e4),this.timer&&typeof this.timer.unref=="function"&&this.timer.unref())}addTrace(t){this.traceQueue.push(t),this.checkFlush()}addTask(t){this.taskQueue.push(t),this.checkFlush()}addError(t,n="apm"){n==="task"?this.taskErrorQueue.push(t):this.apmErrorQueue.push(t),this.checkFlush()}addLog(t,n="apm"){n==="task"?this.taskLogQueue.push(t):this.apmLogQueue.push(t),this.checkFlush()}checkFlush(){let t=this.traceQueue.length+this.apmErrorQueue.length+this.apmLogQueue.length,n=this.taskQueue.length+this.taskErrorQueue.length+this.taskLogQueue.length;(t>=(this.config.batchSize||100)||n>=(this.config.batchSize||100))&&this.flush()}async flush(){let t={traces:[...this.traceQueue],errors:[...this.apmErrorQueue],logs:[...this.apmLogQueue]},n={runs:[...this.taskQueue],errors:[...this.taskErrorQueue],logs:[...this.taskLogQueue]};this.traceQueue=[],this.apmErrorQueue=[],this.apmLogQueue=[],this.taskQueue=[],this.taskErrorQueue=[],this.taskLogQueue=[];let r={"Content-Type":"application/json","x-service-api-key":this.config.apiKey};try{let o=[];(t.traces.length>0||t.errors.length>0||t.logs.length>0)&&o.push(fetch(this.apmEndpoint,{method:"POST",headers:r,body:JSON.stringify(t),keepalive:!0})),(n.runs.length>0||n.errors.length>0||n.logs.length>0)&&o.push(fetch(this.taskEndpoint,{method:"POST",headers:r,body:JSON.stringify(n),keepalive:!0})),await Promise.allSettled(o),this.config.debug&&console.log(`[Senzor] Flushed: APM(${t.traces.length} traces, ${t.logs.length} logs), Task(${n.runs.length} runs, ${n.logs.length} logs)`)}catch(o){this.config.debug&&console.error("[Senzor] Transport Flush Error:",o)}}};var _=w("async_hooks"),F=new _.AsyncLocalStorage,h={run:(e,t)=>F.run(e,t),current:()=>F.getStore(),addSpan:e=>{let t=F.getStore();t&&t.spans.push(e)}};var P=w("crypto");var R=O(w("http")),N=O(w("https")),b=w("url");var K=w("crypto");var kt=/^00-([0-9a-f]{32})-([0-9a-f]{16})-([0-9a-f]{2})$/,j=e=>{if(!e)return null;let t=Array.isArray(e)?e[0]:e;if(typeof t!="string")return null;let n=t.trim().toLowerCase().match(kt);if(!n)return null;let r=n[1],o=n[2],s=n[3];if(r==="00000000000000000000000000000000"||o==="0000000000000000")return null;let a=(parseInt(s,16)&1)===1;return{traceId:r,parentSpanId:o,sampled:a}},L=(e,t,n=!0)=>`00-${e}-${t}-${n?"01":"00"}`;var v=(e,t,n)=>{if(!e[t])return;let r=e[t];e[t]=n(r)},B=()=>(0,K.randomUUID)().replace(/-/g,"").slice(0,16),J=(e,t=!1)=>{if(!globalThis.fetch)return;let n="";try{n=new b.URL(e).hostname}catch{}let r=globalThis.fetch;globalThis.fetch=async(o,s)=>{let a="";if(typeof o=="string"?a=o:o instanceof b.URL?a=o.toString():o&&o.url&&(a=o.url),n&&a.includes(n))return r(o,s);let c=h.current();if(!c)return r(o,s);let i=(s?.method||"GET").toUpperCase(),p=performance.now()-c.startTime,d=performance.now(),u=B(),y="unknown";try{y=new b.URL(a).hostname}catch{}let m={...s};m.headers||(m.headers={});let T=(f,g)=>{m.headers instanceof Headers?m.headers.set(f,g):Array.isArray(m.headers)?m.headers.push([f,g]):m.headers[f]=g};T("traceparent",L(c.id,u)),T("x-senzor-trace-id",c.id),T("x-senzor-parent-span-id",u);try{let f=await r(o,m),g=performance.now()-d;return h.addSpan({spanId:u,name:`${i} ${y}`,type:"http",startTime:p,duration:g,status:f.status,meta:{url:a,method:i,library:"fetch"}}),f}catch(f){let g=performance.now()-d;throw h.addSpan({spanId:u,name:`${i} ${y}`,type:"http",startTime:p,duration:g,status:500,meta:{error:f.message,url:a,library:"fetch"}}),f}}},q=(e,t=!1)=>{let n="";try{n=new b.URL(e).hostname}catch{}let r=o=>function(...s){let a={},c="",i=0;if(typeof s[0]=="string"||s[0]instanceof b.URL?(c=s[0].toString(),i=1):i=0,(!s[i]||typeof s[i]!="object")&&(s[i]={}),a=s[i],!c){let S=a.protocol||(a.port===443?"https:":"http:"),k=a.hostname||a.host||"localhost",H=a.path||"/";c=`${S}//${k}${H}`}if(n&&(c.includes(n)||a.hostname&&a.hostname.includes(n)))return o.apply(this,s);let p=h.current();if(!p)return o.apply(this,s);let d=(a.method||"GET").toUpperCase(),u=performance.now()-p.startTime,y=performance.now(),m=B(),T="unknown";try{T=new b.URL(c).hostname}catch{T=a.hostname||"unknown"}a.headers||(a.headers={}),a.headers.traceparent=L(p.id,m),a.headers["x-senzor-trace-id"]=p.id,a.headers["x-senzor-parent-span-id"]=m,t&&console.log(`[Senzor] Injecting W3C traceparent headers to ${c}`);let f=o.apply(this,s),g=(S,k)=>{let H=performance.now()-y;h.addSpan({spanId:m,name:`${d} ${T}`,type:"http",startTime:u,duration:H,status:k?500:S?.statusCode||0,meta:{url:c,method:d,library:"http"}})};return f.on("response",S=>{S.once("end",()=>g(S)),S.once("close",()=>g(S)),S.once("error",k=>g(S,k))}),f.on("error",S=>g(null,S)),f};v(R.default,"request",r),v(R.default,"get",r),v(N.default,"request",r),v(N.default,"get",r)};var X=(e=!1)=>{try{let t=w("mongodb"),n=t.Collection,r=t.FindCursor||w("mongodb/lib/cursor/find_cursor").FindCursor,o=t.AggregationCursor||w("mongodb/lib/cursor/aggregation_cursor").AggregationCursor;e&&console.log("[Senzor] Instrumenting MongoDB (Collection + Cursors)...");let s=(i,p,d,u,y,m)=>{let T=performance.now()-u;h.addSpan({name:`MongoDB ${i}`,type:"db",startTime:performance.now()-y-T,duration:T,status:m?500:0,meta:{collection:d,operation:p,error:m?m.message:void 0}}),e&&console.log(`[Senzor] Captured Mongo: ${i} (${T.toFixed(2)}ms)`)};["insertOne","insertMany","updateOne","updateMany","deleteOne","deleteMany","countDocuments"].forEach(i=>{if(!n.prototype[i])return;let p=n.prototype[i];n.prototype[i]=function(...d){let u=h.current();if(!u)return p.apply(this,d);let y=performance.now(),m=u.startTime,T=this.collectionName;try{let f=p.apply(this,d);return f&&typeof f.then=="function"?f.then(g=>(s(i,i,T,y,m),g),g=>{throw s(i,i,T,y,m,g),g}):f}catch(f){throw s(i,i,T,y,m,f),f}}});let c=(i,p)=>{if(!i||!i.prototype.toArray)return;let d=i.prototype.toArray;i.prototype.toArray=function(...u){let y=h.current();if(!y)return d.apply(this,u);let m=performance.now(),T=y.startTime,f=this.namespace?.collection||"unknown",g=k=>(s(p,p,f,m,T),k),S=k=>{throw s(p,p,f,m,T,k),k};try{let k=d.apply(this,u);return k&&typeof k.then=="function"?k.then(g,S):g(k)}catch(k){S(k)}}};c(r,"find"),c(o,"aggregate")}catch(t){e&&console.warn("[Senzor] MongoDB instrumentation warning:",t.message)}};var Z=()=>{try{let e=w("pg"),t=e.Client.prototype.query;e.Client.prototype.query=function(...n){let r=h.current();if(!r)return t.apply(this,n);let o=performance.now()-r.startTime,s=performance.now(),a=typeof n[0]=="string"?n[0]:n[0].text,c=t.apply(this,n);return c&&typeof c.then=="function"?c.then(i=>{let p=performance.now()-s;return h.addSpan({name:"Postgres Query",type:"db",startTime:o,duration:p,meta:{query:a}}),i}):c}}catch{}};var A=O(w("module"));var V=Symbol.for("senzor.require.patched"),z=Symbol.for("senzor.require.hooks");function wt(){let e=A.default;return e[z]||Object.defineProperty(e,z,{value:new Map,enumerable:!1}),e[z]}function St(e,t){let n=A.default[z];if(!n)return;let r=n.get(e);if(r?.length)for(let o of r)try{o(t)}catch(s){console.error(`[Senzor] instrumentation failed for ${e}`,s)}}function Et(){let e=A.default;if(e[V])return;let t=e._load;e._load=function(r,o,s){let a=t.apply(this,arguments);return St(r,a),a},Object.defineProperty(e,V,{value:!0,enumerable:!1})}function bt(e,t){try{let n=w.resolve(e),r=w.cache?.[n];r?.exports&&t(r.exports)}catch{}}function xt(e,t){try{let n=w(e);n&&t(n)}catch{}}function It(e,t){let n=0,r=5,o=setInterval(()=>{n++;try{let s=w(e);s&&(t(s),clearInterval(o))}catch{}n>=r&&clearInterval(o)},200)}var M=(e,t)=>{let n=wt();n.has(e)||n.set(e,[]),n.get(e).push(t),Et(),bt(e,t),xt(e,t),It(e,t)};var Y=Symbol.for("senzor.bullmq.patched");function tt(e,t,n){if(!e?.Worker?.prototype)return;let r=e.Worker.prototype,o=r.processJob;typeof o!="function"||o[Y]||(r.processJob=async function(s){let a=s.timestamp?Date.now()-s.timestamp:0,c=(s.attemptsMade||0)+1,i=s.opts?.attempts??1,p=c>=i,d=s.name==="__default__"?s.queueName:`${s.queueName}:${s.name}`;return t.startTask(d,"queue",{queueDelay:a,attempts:c,isDeadLetter:!1,metadata:{jobId:s.id,queueName:s.queueName,maxAttempts:i}},async()=>{try{let u=await o.call(this,s);return t.endTask("success"),u}catch(u){try{let y=h.current();y&&y.contextType==="task"&&p&&(y.data.isDeadLetter=!0)}catch{}throw t.captureError(u,{queueName:s.queueName,jobId:s.id,isDeadLetter:p}),t.endTask("failed"),u}})},Object.defineProperty(r.processJob,Y,{value:!0}),n&&console.log("[Senzor] BullMQ instrumented"))}var et=(e,t)=>{M("bullmq",n=>{tt(n,e,t),n?.default&&tt(n.default,e,t)})};var rt=Symbol.for("senzor.cron.patched");function Ct(e){return typeof e=="object"&&e!==null?e:e?{timezone:e}:{}}function nt(e,t,n){let r=e.schedule;if(typeof r!="function"||r[rt])return;let o=r,s=function(a,c,i){if(typeof c!="function")return o.call(this,a,c,i);try{let p=Ct(i),d=p?.name??`cron: ${a}`,u=t.wrapTask(d,"cron",{expression:a,metadata:p},c);return o.call(this,a,u,i)}catch(p){return n&&console.error("[Senzor] cron wrap failed",p),o.call(this,a,c,i)}};Object.defineProperty(s,rt,{value:!0,enumerable:!1});try{e.schedule=s}catch{n&&console.warn("[Senzor] unable to patch cron schedule (readonly export)")}n&&console.log("[Senzor] node-cron instrumented")}var ot=(e,t)=>{M("node-cron",n=>{n&&(nt(n,e,t),n.default&&nt(n.default,e,t))})};var Q={name:"@senzops/apm-node",version:"1.1.18",description:"Universal APM SDK for Senzor",main:"dist/index.js",types:"dist/index.d.ts",scripts:{build:"tsup src/index.ts --format cjs,esm,iife --dts --clean --minify",prepublishOnly:"npm run build"},dependencies:{},devDependencies:{"@types/node":"^20.0.0",tsup:"^8.0.0",typescript:"^5.0.0"},engines:{node:">=18.0.0"},keywords:["apm","monitoring","senzor","node","javascript","api","observability"],author:"Senzops",license:"MIT"};var U={name:Q.name,version:Q.version};var st=()=>(0,P.randomUUID)().replace(/-/g,""),zt=e=>{let t=new Set;return JSON.stringify(e,(n,r)=>{if(typeof r=="object"&&r!==null){if(t.has(r))return"[Circular]";t.add(r)}return r})},D=class{constructor(){this.transport=null;this.options=null;this.isInstrumented=!1}init(t){if(!t.apiKey){console.warn("[Senzor] API Key missing. SDK disabled.");return}this.options=t;let n=t.endpoint||"https://api.senzor.dev/api/ingest/apm",r=t.debug||!1;if(this.transport=new C({...t,endpoint:n}),!this.isInstrumented){this.setupGlobalErrorHandlers(),this.setupLogInterception();try{q(n,r)}catch{}try{J(n,r)}catch{}try{X(r)}catch{}try{Z()}catch{}try{et(this,r)}catch{}try{ot(this,r)}catch{}this.isInstrumented=!0,r&&console.log("[Senzor] Auto-instrumentation enabled")}}setupLogInterception(){if(this.options?.autoLogs===!1)return;let t=["log","info","warn","error","debug"],n={log:console.log,info:console.info,warn:console.warn,error:console.error,debug:console.debug},r=!1;t.forEach(o=>{console[o]=(...s)=>{if(n[o].apply(console,s),!(r||!this.transport)){r=!0;try{let a="",c={};s.forEach(u=>{if(typeof u=="string")a+=(a?" ":"")+u;else if(u instanceof Error)a+=(a?" ":"")+u.message,c.errorStack=u.stack,c.errorName=u.name;else if(typeof u=="object"&&u!==null)try{let y=JSON.parse(zt(u));c={...c,...y}}catch{c.unparseableObject=!0}else a+=(a?" ":"")+String(u)}),!a&&Object.keys(c).length>0&&(a="Object Log");let i=h.current(),p=i?.contextType==="task"?"task":"apm",d={message:a||"Empty log",level:o==="log"?"info":o,attributes:c,timestamp:new Date().toISOString()};i&&(p==="task"?d.runId=i.id:d.traceId=i.id),this.transport.addLog(d,p)}catch{}finally{r=!1}}}})}setupGlobalErrorHandlers(){if(process.__senzorGlobalHandlersInstalled)return;process.__senzorGlobalHandlersInstalled=!0;let t=()=>{try{return{pid:process.pid,ppid:process.ppid,platform:process.platform,uptimeSec:Math.floor(process.uptime()),env:process.env.NODE_ENV||"unknown"}}catch{return{}}},n=()=>{try{let o=process.memoryUsage();return{rss:o.rss,heapTotal:o.heapTotal,heapUsed:o.heapUsed,external:o.external,arrayBuffers:o.arrayBuffers}}catch{return{}}},r=(o,s={})=>{try{let a;if(o instanceof Error)a=o;else if(typeof o=="string")a=new Error(o);else try{a=new Error(JSON.stringify(o))}catch{a=new Error("Non-serializable rejection reason")}let c={...s,runtime:{name:"node",version:process.version},process:t(),memory:n(),sdk:{name:U.name,version:U.version}};this.captureError(a,c)}catch(a){try{this.options?.debug&&console.error("[Senzor] Error handler failure:",a)}catch{}}};process.on("uncaughtExceptionMonitor",o=>r(o,{type:"uncaughtExceptionMonitor",severity:"fatal"})),process.on("uncaughtException",o=>r(o,{type:"uncaughtException",severity:"fatal"})),process.on("unhandledRejection",o=>r(o,{type:"unhandledRejection",severity:"error"})),process.on("warning",o=>r(o,{type:"processWarning",severity:"warning"})),process.on("multipleResolves",(o,s,a)=>r(a||new Error("Multiple promise resolves"),{type:"multipleResolves",resolveType:o,severity:"warning"})),process.on("rejectionHandled",o=>{if(this.options?.debug)try{console.warn("[Senzor] rejectionHandled event detected")}catch{}}),process.on("SIGTERM",()=>r(new Error("Process received SIGTERM"),{type:"processSignal",signal:"SIGTERM"})),process.on("SIGINT",()=>r(new Error("Process received SIGINT"),{type:"processSignal",signal:"SIGINT"}))}startTrace(t,n){if(!this.transport)return n();let r,o;if(t.headers){let c=d=>{if(t.headers[d])return t.headers[d];if(t.headers[d.toLowerCase()])return t.headers[d.toLowerCase()]},i=c("traceparent"),p=j(i);if(p)r=p.traceId,o=p.parentSpanId;else{let d=c("x-senzor-trace-id"),u=c("x-senzor-parent-span-id");r=Array.isArray(d)?d[0]:d,o=Array.isArray(u)?u[0]:u}}let a={id:r||st(),contextType:"apm",startTime:performance.now(),data:{...t,parentTraceId:r,parentSpanId:o},spans:[]};return h.run(a,n)}endTrace(t,n={}){let r=h.current();if(!r||r.contextType!=="apm"||!this.transport)return;let o=performance.now()-r.startTime,s={traceId:r.id,parentTraceId:r.data.parentTraceId,parentSpanId:r.data.parentSpanId,...r.data,...n,status:t,duration:o,spans:r.spans,timestamp:new Date().toISOString()};this.transport.addTrace(s)}startTask(t,n,r,o){if(!this.transport)return o();let s=h.current(),a=s?.contextType==="apm"?s.id:void 0,c=process.memoryUsage?process.memoryUsage().heapUsed:0,i=process.cpuUsage?process.cpuUsage():void 0,p={id:(0,P.randomUUID)(),contextType:"task",startTime:performance.now(),startMemory:c,startCpu:i,data:{taskName:t,taskType:n,triggerTraceId:a,...r},spans:[]};return h.run(p,o)}endTask(t,n={}){let r=h.current();if(!r||r.contextType!=="task"||!this.transport)return;let o;if(process.memoryUsage&&r.startMemory!==void 0&&process.cpuUsage&&r.startCpu){let a=process.memoryUsage().heapUsed,c=process.cpuUsage(r.startCpu);o={memoryDeltaBytes:a-r.startMemory,cpuUserUs:c.user,cpuSystemUs:c.system}}let s={runId:r.id,taskName:r.data.taskName,taskType:r.data.taskType,triggerTraceId:r.data.triggerTraceId,queueDelay:r.data.queueDelay,attempts:r.data.attempts,isDeadLetter:r.data.isDeadLetter,metadata:{...r.data.metadata,...n},resourceMetrics:o,status:t,duration:performance.now()-r.startTime,spans:r.spans,timestamp:new Date().toISOString()};this.transport.addTask(s)}wrapTask(t,n,r={},o){return(async(...s)=>this.startTask(t,n,r,async()=>{try{let a=await o(...s);return this.endTask("success"),a}catch(a){throw this.captureError(a,{taskName:t}),this.endTask("failed"),a}}))}captureError(t,n={}){if(!this.transport)return;let r;t instanceof Error?r=t:r=new Error(String(t));let o=h.current(),s={errorClass:r.name||"Error",message:r.message,stackTrace:r.stack,context:n,timestamp:new Date().toISOString()};o?.contextType==="task"?this.transport.addError({...s,runId:o.id},"task"):this.transport.addError({...s,traceId:o?.id},"apm")}track(t){this.transport?.addTrace({traceId:st(),...t,spans:[],timestamp:new Date().toISOString()})}startSpan(t,n="custom"){let r=h.current();if(!r)return{end:()=>{}};let o=performance.now()-r.startTime,s=performance.now(),a=(0,P.randomUUID)().replace(/-/g,"").slice(0,16);return{end:(c,i)=>{h.addSpan({spanId:a,name:t,type:n,startTime:o,duration:performance.now()-s,status:i,meta:c})}}}async flush(){this.transport&&await this.transport.flush()}},l=new D;var $=w("net"),At=e=>e.startsWith("::ffff:")?e.slice(7):e,Mt=e=>{let t=e.lastIndexOf(":");if(t===-1)return e;let n=e.slice(0,t);return(0,$.isIP)(n)===4?n:e},Pt=e=>{let t=e.match(/^\[([^\]]+)\](?::\d+)?$/);return t?t[1]:e},x=e=>{if(!e)return null;let t=e.trim();return t?(t=Pt(t),t=Mt(t),t=At(t),(0,$.isIP)(t)!==0?t:null):null},at=e=>!!(e==="127.0.0.1"||e.startsWith("10.")||e.startsWith("192.168.")||e.startsWith("169.254.")||/^172\.(1[6-9]|2\d|3[01])\./.test(e)||e==="::1"||e==="::"||e.toLowerCase().startsWith("fe80:")||e.toLowerCase().startsWith("fc")||e.toLowerCase().startsWith("fd")),Ht=e=>{let t=e.split(",");for(let n of t){let r=n.match(/for=["[]?([^\]",;>\s]+)/i);if(r){let o=x(r[1]);if(o&&!at(o))return o}}return null},Ot=e=>{let t=e.split(",").map(n=>n.trim());for(let n of t){let r=x(n);if(r&&!at(r))return r}for(let n of t){let r=x(n);if(r)return r}return null},E=e=>{let t=e.headers;{let n=x(t["cf-connecting-ip"]);if(n)return n}{let n=x(t["true-client-ip"]);if(n)return n}{let n=x(t["x-real-ip"]);if(n)return n}{let n=t.forwarded;if(n){let r=Ht(n);if(r)return r}}{let n=t["x-forwarded-for"];if(n){let r=Ot(n);if(r)return r}}{let n=e.socket?.remoteAddress,r=x(n);if(r)return r}return null};var it=()=>(e,t,n)=>{l.startTrace({method:e.method,path:e.originalUrl||e.url,ip:E(e),userAgent:e.headers["user-agent"],headers:e.headers},()=>{t.once("finish",()=>{try{let r="UNKNOWN";e.route&&e.route.path?r=(e.baseUrl||"")+e.route.path:t.statusCode===404?r="Not Found":r=e.path||"Wildcard",l.endTrace(t.statusCode,{route:r})}catch{}}),n()})},ct=()=>(e,t,n,r)=>{l.captureError(e),r(e)};var I=e=>!e||e==="/"?"/":e.replace(/[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}/g,":uuid").replace(/[0-9a-fA-F]{24}/g,":objectId").replace(/\/(\d+)(?=\/|$)/g,"/:id").split("?")[0],W=(e,t)=>e.route&&e.route.path?(e.baseUrl||"")+e.route.path:e.context&&e.context.matchedRoute?e.context.matchedRoute.path:e.routerPath?e.routerPath:I(t);var pt=e=>t=>{let n=t.node.req,r=n.originalUrl||n.url||"/";return l.startTrace({method:n.method||"GET",path:r,ip:E(n),userAgent:n.headers["user-agent"],headers:n.headers},async()=>{try{let o=await e(t),s=200;return t.node.res.statusCode&&(s=t.node.res.statusCode),o&&o.statusCode&&(s=o.statusCode),l.endTrace(s,{route:W(t,r)}),o}catch(o){l.captureError(o);let s=o.statusCode||o.status||500;throw l.endTrace(s,{route:W(t,r)}),o}})};var ut=e=>async(t,n)=>{let r=t.url?new URL(t.url):{pathname:"/"},o=t.method||"GET",s={},a,c;return typeof t.headers.get=="function"?(a=t.headers.get("user-agent"),c=t.headers.get("x-forwarded-for"),t.headers.forEach((i,p)=>{s[p]=i})):(s=t.headers,a=s["user-agent"],c=s["x-forwarded-for"]),l.startTrace({method:o,path:r.pathname,userAgent:a,ip:c||E(t),headers:s},async()=>{try{let i=await e(t,n),p=i?.status||200;return l.endTrace(p,{route:I(r.pathname)}),i}catch(i){throw l.captureError(i),l.endTrace(500,{route:I(r.pathname)}),i}})},lt=e=>async(t,n)=>{let r=t.url?t.url.split("?")[0]:"/";return l.startTrace({method:t.method||"GET",path:r,userAgent:t.headers["user-agent"],ip:E(t),headers:t.headers},async()=>{let o=()=>{l.endTrace(n.statusCode||200,{route:I(r)})};n.once("finish",o),n.once("close",o);try{return await e(t,n)}catch(s){throw l.captureError(s),s}})};var dt=(e,t,n)=>{t&&t.apiKey&&l.init(t),e.addHook("onRequest",(r,o,s)=>{l.startTrace({method:r.method,path:r.raw.url||r.url,ip:E(r),userAgent:r.headers["user-agent"],headers:r.headers},()=>s())}),e.addHook("onError",(r,o,s,a)=>{l.captureError(s),a()}),e.addHook("onResponse",(r,o,s)=>{let a=r.routeOptions?.url||r.routerPath||"UNKNOWN";l.endTrace(o.statusCode,{route:a}),s()}),n()};var Ft={init:e=>l.init(e),flush:()=>l.flush(),track:l.track.bind(l),startSpan:l.startSpan.bind(l),captureException:l.captureError.bind(l),wrapTask:l.wrapTask.bind(l),startTask:l.startTask.bind(l),requestHandler:it,errorHandler:ct,wrapNextRoute:ut,wrapNextPages:lt,wrapH3:pt,fastifyPlugin:dt},Oe=Ft;})();
|
|
1
|
+
"use strict";(()=>{var Bt=Object.create;var ct=Object.defineProperty;var Jt=Object.getOwnPropertyDescriptor;var Vt=Object.getOwnPropertyNames;var Xt=Object.getPrototypeOf,Zt=Object.prototype.hasOwnProperty;var E=(e=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(e,{get:(t,r)=>(typeof require<"u"?require:t)[r]}):e)(function(e){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+e+'" is not supported')});var Yt=(e,t,r,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of Vt(t))!Zt.call(e,o)&&o!==r&&ct(e,o,{get:()=>t[o],enumerable:!(n=Jt(t,o))||n.enumerable});return e};var K=(e,t,r)=>(r=e!=null?Bt(Xt(e)):{},Yt(t||!e||!e.__esModule?ct(r,"default",{value:e,enumerable:!0}):r,e));var A="x-senzor-sdk-internal";var _=class{constructor(t){this.config=t;this.traceQueue=[];this.apmErrorQueue=[];this.apmLogQueue=[];this.taskQueue=[];this.taskErrorQueue=[];this.taskLogQueue=[];this.timer=null;this.isFlushing=!1;this.flushAgain=!1;this.droppedItems=0;let r=t.endpoint||"https://api.senzor.dev";this.apmEndpoint=r.includes("/api/ingest")?r:`${r}/api/ingest/apm`,this.taskEndpoint=r.includes("/api/ingest")?r.replace("/apm","/task"):`${r}/api/ingest/task`,typeof setInterval<"u"&&(this.timer=setInterval(()=>{this.flush()},t.flushInterval||1e4),this.timer&&typeof this.timer.unref=="function"&&this.timer.unref()),this.installShutdownFlush()}addTrace(t){this.enqueue(this.traceQueue,t),this.checkFlush()}addTask(t){this.enqueue(this.taskQueue,t),this.checkFlush()}addError(t,r="apm"){this.enqueue(r==="task"?this.taskErrorQueue:this.apmErrorQueue,t),this.checkFlush()}addLog(t,r="apm"){this.enqueue(r==="task"?this.taskLogQueue:this.apmLogQueue,t),this.checkFlush()}enqueue(t,r){t.push(r);let n=this.config.maxQueueSize??1e4;for(;t.length>n;)t.shift(),this.droppedItems++}prependWithLimit(t,r){if(!r.length)return;t.unshift(...r);let n=this.config.maxQueueSize??1e4;for(;t.length>n;)t.pop(),this.droppedItems++}checkFlush(){let t=this.traceQueue.length+this.apmErrorQueue.length+this.apmLogQueue.length,r=this.taskQueue.length+this.taskErrorQueue.length+this.taskLogQueue.length;(t>=(this.config.batchSize||100)||r>=(this.config.batchSize||100))&&this.flush()}takeApmPayload(){let t={traces:this.traceQueue,errors:this.apmErrorQueue,logs:this.apmLogQueue};return this.traceQueue=[],this.apmErrorQueue=[],this.apmLogQueue=[],t}takeTaskPayload(){let t={runs:this.taskQueue,errors:this.taskErrorQueue,logs:this.taskLogQueue};return this.taskQueue=[],this.taskErrorQueue=[],this.taskLogQueue=[],t}restoreApmPayload(t){this.prependWithLimit(this.apmLogQueue,t.logs),this.prependWithLimit(this.apmErrorQueue,t.errors),this.prependWithLimit(this.traceQueue,t.traces)}restoreTaskPayload(t){this.prependWithLimit(this.taskLogQueue,t.logs),this.prependWithLimit(this.taskErrorQueue,t.errors),this.prependWithLimit(this.taskQueue,t.runs)}hasApmPayload(t){return t.traces.length>0||t.errors.length>0||t.logs.length>0}hasTaskPayload(t){return t.runs.length>0||t.errors.length>0||t.logs.length>0}async postJson(t,r){let n=new AbortController,o=setTimeout(()=>n.abort(),this.config.flushTimeoutMs??5e3);typeof o.unref=="function"&&o.unref();try{let s=await fetch(t,{method:"POST",headers:{"Content-Type":"application/json","x-service-api-key":this.config.apiKey,[A]:"true"},body:JSON.stringify(r),keepalive:!0,signal:n.signal});if(!s.ok)throw new Error(`Senzor ingest failed with status ${s.status}`)}finally{clearTimeout(o)}}async flush(){if(this.isFlushing){this.flushAgain=!0;return}this.isFlushing=!0;try{do{this.flushAgain=!1;let t=this.takeApmPayload(),r=this.takeTaskPayload(),n=[];if(this.hasApmPayload(t)&&n.push(this.postJson(this.apmEndpoint,t).catch(a=>{throw this.restoreApmPayload(t),a})),this.hasTaskPayload(r)&&n.push(this.postJson(this.taskEndpoint,r).catch(a=>{throw this.restoreTaskPayload(r),a})),!n.length)continue;let s=(await Promise.allSettled(n)).filter(a=>a.status==="rejected");this.config.debug&&console.log(`[Senzor] Flushed: APM(${t.traces.length} traces, ${t.logs.length} logs), Task(${r.runs.length} runs, ${r.logs.length} logs), failures=${s.length}, dropped=${this.droppedItems}`)}while(this.flushAgain)}catch(t){this.config.debug&&console.error("[Senzor] Transport Flush Error:",t)}finally{this.isFlushing=!1}}installShutdownFlush(){let t=Symbol.for("senzor.transport.shutdownFlushInstalled"),r=process;if(r[t])return;Object.defineProperty(r,t,{value:!0,enumerable:!1});let n=()=>{this.flush()};process.once("beforeExit",n)}};var pt=E("async_hooks"),H=new pt.AsyncLocalStorage,g={run:(e,t)=>H.run(e,t),withActiveSpan:(e,t)=>{let r=H.getStore();return r?H.run({...r,activeSpanId:e,data:r.data,spans:r.spans},t):t()},current:()=>H.getStore(),addSpan:e=>{let t=H.getStore();t&&g.addSpanToTrace(t,e)},addSpanToTrace:(e,t)=>{if(e.ended)return;let r=e.maxSpans??500;if(e.spans.length>=r){e.droppedSpans=(e.droppedSpans??0)+1;return}e.spans.push(t)}};var qt=E("crypto");var Y=K(E("http")),tt=K(E("https")),z=E("url");var x=e=>!e||e==="/"?"/":e.replace(/[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}/g,":uuid").replace(/[0-9a-fA-F]{24}/g,":objectId").replace(/\/(\d+)(?=\/|$)/g,"/:id").split("?")[0],$=(e,t)=>e.route&&e.route.path?(e.baseUrl||"")+e.route.path:e.context&&e.context.matchedRoute?e.context.matchedRoute.path:e.routerPath?e.routerPath:x(t);var te=64,J=2048,ee=4,re=20,ne=/(^|[-_.])(authorization|cookie|set-cookie|password|passwd|pwd|secret|token|api[-_.]?key|x-api-key|access[-_.]?token|refresh[-_.]?token|client[-_.]?secret|private[-_.]?key)([-_.]|$)/i,oe=e=>({maxAttributes:e?.maxAttributes??te,maxAttributeLength:e?.maxAttributeLength??J}),O=(e,t=J)=>e.length<=t?e:`${e.slice(0,Math.max(0,t-15))}...[truncated]`,se=e=>ne.test(e),ae=(e,t)=>{if(e==null||typeof e=="number"||typeof e=="boolean")return e;if(typeof e=="bigint")return e.toString();if(typeof e=="string")return O(e,t)},B=(e,t,r,n)=>{if(se(e))return"[REDACTED]";let o=ae(t,r.maxAttributeLength);if(o!==void 0||t===void 0)return o;if(t instanceof Error)return{name:O(t.name,r.maxAttributeLength),message:O(t.message,r.maxAttributeLength),stack:t.stack?O(t.stack,r.maxAttributeLength):void 0};if(n>=ee)return"[MaxDepth]";if(Array.isArray(t))return t.slice(0,re).map(s=>B(e,s,r,n+1));if(typeof t=="object"){let s={},a=0;for(let[p,c]of Object.entries(t)){if(a>=r.maxAttributes){s.__truncated=!0;break}s[p]=B(p,c,r,n+1),a++}return s}return O(String(t),r.maxAttributeLength)},R=(e={},t)=>{let r=oe(t),n={maxAttributes:r.maxAttributes,maxAttributeLength:r.maxAttributeLength},o={},s=0;for(let[a,p]of Object.entries(e)){if(s>=n.maxAttributes){o.__truncated=!0;break}o[a]=B(a,p,n,0),s++}return o},ut=(e,t)=>{if(!e||typeof e!="object")return{};let r={};if(typeof e.forEach=="function")e.forEach((n,o)=>{r[o.toLowerCase()]=n});else for(let[n,o]of Object.entries(e))r[n.toLowerCase()]=Array.isArray(o)?o.join(", "):o;return R(r,t)},P=(e,t)=>{if(typeof e!="string")return;let r=e.replace(/\s+/g," ").trim();if(!r)return;let n=r.replace(/'(?:''|[^'])*'/g,"?").replace(/"(?:\\"|[^"])*"/g,"?").replace(/\b\d+(\.\d+)?\b/g,"?");return O(t?.captureDbStatement===!1?n.split(" ").slice(0,6).join(" "):n,t?.maxAttributeLength??J)},q=e=>typeof e!="string"?void 0:e.trim().match(/^([a-z]+)/i)?.[1]?.toUpperCase();var V=E("net"),ie=e=>e.startsWith("::ffff:")?e.slice(7):e,ce=e=>{let t=e.lastIndexOf(":");if(t===-1)return e;let r=e.slice(0,t);return(0,V.isIP)(r)===4?r:e},pe=e=>{let t=e.match(/^\[([^\]]+)\](?::\d+)?$/);return t?t[1]:e},I=e=>{if(!e)return null;let t=e.trim();return t?(t=pe(t),t=ce(t),t=ie(t),(0,V.isIP)(t)!==0?t:null):null},dt=e=>!!(e==="127.0.0.1"||e.startsWith("10.")||e.startsWith("192.168.")||e.startsWith("169.254.")||/^172\.(1[6-9]|2\d|3[01])\./.test(e)||e==="::1"||e==="::"||e.toLowerCase().startsWith("fe80:")||e.toLowerCase().startsWith("fc")||e.toLowerCase().startsWith("fd")),ue=e=>{let t=e.split(",");for(let r of t){let n=r.match(/for=["[]?([^\]",;>\s]+)/i);if(n){let o=I(n[1]);if(o&&!dt(o))return o}}return null},de=e=>{let t=e.split(",").map(r=>r.trim());for(let r of t){let n=I(r);if(n&&!dt(n))return n}for(let r of t){let n=I(r);if(n)return n}return null},C=e=>{let t=e.headers;{let r=I(t["cf-connecting-ip"]);if(r)return r}{let r=I(t["true-client-ip"]);if(r)return r}{let r=I(t["x-real-ip"]);if(r)return r}{let r=t.forwarded;if(r){let n=ue(r);if(n)return n}}{let r=t["x-forwarded-for"];if(r){let n=de(r);if(n)return n}}{let r=e.socket?.remoteAddress,n=I(r);if(n)return n}return null};var le=/^00-([0-9a-f]{32})-([0-9a-f]{16})-([0-9a-f]{2})$/,lt=e=>{if(!e)return null;let t=Array.isArray(e)?e[0]:e;if(typeof t!="string")return null;let r=t.trim().toLowerCase().match(le);if(!r)return null;let n=r[1],o=r[2],s=r[3];if(n==="00000000000000000000000000000000"||o==="0000000000000000")return null;let a=(parseInt(s,16)&1)===1;return{traceId:n,parentSpanId:o,sampled:a}},L=(e,t,r=!0)=>`00-${e}-${t}-${r?"01":"00"}`;var ht=Symbol.for("senzor.patch.keys"),ft=Symbol.for("senzor.patch.original"),S=(e,t,r,n)=>{if(!e)return!1;let o=e[t];if(typeof o!="function")return!1;let s=o[ht];if(s?.has(r))return!1;let a=o[ft]||o,p=n(o),c=new Set(s||[]);c.add(r);try{Object.defineProperty(p,ht,{value:c,enumerable:!1}),Object.defineProperty(p,ft,{value:a,enumerable:!1})}catch{return!1}try{return e[t]=p,!0}catch{return!1}};var X=E("crypto"),Z=()=>(0,X.randomUUID)().replace(/-/g,""),F=()=>(0,X.randomUUID)().replace(/-/g,"").slice(0,16);var w=(e,t,r={},n)=>{let o=g.current();if(!o)return null;let s=F(),a=o.activeSpanId,p=performance.now()-o.startTime,c=performance.now(),i=!1;return{spanId:s,parentSpanId:a,trace:o,end:(d,u={})=>{if(i)return;i=!0;let l=R({...r,...u,parentSpanId:a},n);g.addSpanToTrace(o,{spanId:s,parentSpanId:a,name:e,type:t,startTime:p,duration:performance.now()-c,status:d,meta:l})}}},T=(e,t)=>e?g.withActiveSpan(e.spanId,t):t();var he=e=>!!e?.debug,mt=e=>typeof e=="object"&&e!==null&&!(e instanceof z.URL)&&!(e instanceof Function)&&!Array.isArray(e),fe=(e,t)=>{if(e){if(typeof Headers<"u"&&e instanceof Headers)return e.get(t);if(Array.isArray(e))return e.find(([n])=>String(n).toLowerCase()===t.toLowerCase())?.[1];if(typeof e=="object"){let r=t.toLowerCase();for(let[n,o]of Object.entries(e))if(n.toLowerCase()===r)return o}}},St=e=>String(fe(e,A)||"").toLowerCase()==="true",kt=(e,t,r)=>{if(St(r))return!0;if(!e)return!1;try{let n=new z.URL(e),o=new z.URL(t);return n.hostname===o.hostname&&n.pathname.startsWith("/api/ingest")}catch{return t?e.includes(t):!1}},et=e=>{if(!e)return{};if(typeof Headers<"u"&&e instanceof Headers){let t={};return e.forEach((r,n)=>{t[n]=r}),t}return Array.isArray(e)?e.reduce((t,[r,n])=>(t[r]=n,t),{}):typeof e=="object"?{...e}:{}},M=(e,t,r)=>{let n=Object.keys(e).find(o=>o.toLowerCase()===t.toLowerCase());e[n||t]=r},me=(e,t)=>{let r=[...e],n=0,o={},s=null;if(typeof r[0]=="string"||r[0]instanceof z.URL){try{s=new z.URL(r[0].toString())}catch{s=null}mt(r[1])?(n=1,o={...r[1],headers:et(r[1].headers)},r[1]=o):(n=1,o={headers:{}},r.splice(1,0,o))}else mt(r[0])?(n=0,o={...r[0],headers:et(r[0].headers)},r[0]=o):(n=0,o={headers:{}},r[0]=o);o.headers||(o.headers={}),r[n]=o;let a=o.protocol||s?.protocol||(o.port===443?"https:":t),p=o.hostname||o.host||s?.hostname||"localhost",c=o.path||`${s?.pathname||"/"}${s?.search||""}`,i=s?s.toString():`${a}//${p}${c}`,d=String(o.method||"GET").toUpperCase();return{args:r,options:o,url:i,method:d,hostname:String(p).replace(/:\d+$/,""),path:c}},ye=(e,t,r)=>{if(t?.statusCode===404)return"Not Found";try{return $(e,r)}catch{return x(r)}},yt=(e,t,r,n)=>{S(e,"emit",`senzor.${t}.server`,o=>function(a,...p){if(a!=="request")return o.call(this,a,...p);let c=p[0],i=p[1];if(!c||!i||g.current()?.contextType==="apm")return o.call(this,a,...p);let d=c.originalUrl||c.url||"/",u=String(d).split("?")[0]||"/",l=c.headers||{};return St(l)?o.call(this,a,...p):r.startTrace({method:c.method||"GET",path:d,route:x(u),ip:C(c),userAgent:l["user-agent"],headers:l,meta:{protocol:t,httpVersion:c.httpVersion,headers:n?.captureHeaders?ut(l,n):void 0}},()=>{let m=g.current(),y=!1,f=k=>{y||!m||(y=!0,setImmediate(()=>{m.ended||g.run(m,()=>{r.endTrace(i.statusCode||0,{route:ye(c,i,u),statusMessage:i.statusMessage,meta:{...m.data.meta,endReason:k}})})}))};i.once("finish",()=>f("finish")),i.once("close",()=>f("close")),i.once("error",k=>{r.captureError(k,{instrumentation:`${t}.server`}),f("error")});try{return o.call(this,a,...p)}catch(k){throw r.captureError(k,{instrumentation:`${t}.server`}),f("error"),k}})})},gt=(e,t,r,n)=>{let o=t==="https:"?"senzor.https":"senzor.http",s=a=>function(...c){let i=me(c,t);if(kt(i.url,r,i.options.headers))return a.apply(this,c);let d=g.current();if(!d)return a.apply(this,c);let u=w(`${i.method} ${i.hostname}`,"http",{url:i.url,method:i.method,library:t==="https:"?"https":"http","http.request.method":i.method,"url.full":i.url,"url.path":i.path,"server.address":i.hostname},n);u&&(M(i.options.headers,"traceparent",L(d.id,u.spanId)),M(i.options.headers,"x-senzor-trace-id",d.id),M(i.options.headers,"x-senzor-parent-span-id",u.spanId));let l=()=>{let m=a.apply(this,i.args);if(!u||!m||typeof m.once!="function")return m;let y=!1,f=(k,U={})=>{y||(y=!0,u.end(k,U))};return m.once("response",k=>{let U=k?.statusCode||0,at=()=>f(U,{"http.response.status_code":U});k.once("end",at),k.once("close",at),k.once("error",it=>f(500,{error:it.message,"error.type":it.name}))}),m.once("timeout",()=>f(504,{error:"Request timed out","error.type":"TimeoutError"})),m.once("error",k=>f(500,{error:k.message,"error.type":k.name})),m};return he(n)&&console.log(`[Senzor] Injecting trace headers to ${i.url}`),T(u,l)};S(e,"request",`${o}.request`,s),S(e,"get",`${o}.get`,s)},wt=(e,t)=>{globalThis.fetch&&S(globalThis,"fetch","senzor.fetch",r=>async function(o,s){let a=typeof o=="string"?o:o instanceof z.URL?o.toString():o?.url||"",p=s?.headers||o?.headers;if(kt(a,e,p))return r.call(this,o,s);let c=g.current();if(!c)return r.call(this,o,s);let i="unknown",d="/";try{let f=new z.URL(a);i=f.hostname,d=`${f.pathname}${f.search}`}catch{}let u=String(s?.method||o?.method||"GET").toUpperCase(),l=w(`${u} ${i}`,"http",{url:a,method:u,library:"fetch","http.request.method":u,"url.full":a,"url.path":d,"server.address":i},t);if(!l)return r.call(this,o,s);let m={...s||{}},y=typeof Headers<"u"?new Headers(p||void 0):et(p);return typeof Headers<"u"&&y instanceof Headers?(y.set("traceparent",L(c.id,l.spanId)),y.set("x-senzor-trace-id",c.id),y.set("x-senzor-parent-span-id",l.spanId)):(M(y,"traceparent",L(c.id,l.spanId)),M(y,"x-senzor-trace-id",c.id),M(y,"x-senzor-parent-span-id",l.spanId)),m.headers=y,T(l,async()=>{try{let f=await r.call(this,o,m);return l.end(f.status,{"http.response.status_code":f.status}),f}catch(f){throw l.end(500,{error:f?.message,"error.type":f?.name||"Error"}),f}})})},bt=(e,t,r)=>{yt(Y.default.Server?.prototype,"http",e,r),yt(tt.default.Server?.prototype,"https",e,r),gt(Y.default,"http:",t,r),gt(tt.default,"https:",t,r)};var D=K(E("module"));var Tt=Symbol.for("senzor.require.patched"),Q=Symbol.for("senzor.require.hooks");function ge(){let e=D.default;return e[Q]||Object.defineProperty(e,Q,{value:new Map,enumerable:!1}),e[Q]}function Se(e,t){let r=D.default[Q];if(!r)return;let n=r.get(e);if(n?.length)for(let o of n)try{o(t)}catch(s){console.error(`[Senzor] instrumentation failed for ${e}`,s)}}function ke(){let e=D.default;if(e[Tt])return;let t=e._load;e._load=function(n,o,s){let a=t.apply(this,arguments);return Se(n,a),a},Object.defineProperty(e,Tt,{value:!0,enumerable:!1})}function we(e,t){try{let r=E.resolve(e),n=E.cache?.[r];n?.exports&&t(n.exports)}catch{}}function be(e,t){try{let r=E(e);r&&t(r)}catch{}}function Te(e,t){let r=0,n=5,o=setInterval(()=>{r++;try{let s=E(e);s&&(t(s),clearInterval(o))}catch{}r>=n&&clearInterval(o)},200)}var b=(e,t)=>{let r=ge();r.has(e)||r.set(e,[]),r.get(e).push(t),ke(),we(e,t),be(e,t),Te(e,t)};var Ee=e=>e?.collectionName||e?.s?.namespace?.collection||e?.namespace?.collection||"unknown",Et=e=>e?.dbName||e?.s?.namespace?.db||e?.namespace?.db,Ce=e=>e?.namespace?.collection||e?.ns?.collection||e?.cursorNamespace?.collection||"unknown",xe=(e,t,r)=>{S(e,t,`senzor.mongodb.collection.${t}`,n=>function(...s){let a=Ee(this),p=w(`MongoDB ${t}`,"db",{collection:a,operation:t,"db.system.name":"mongodb","db.collection.name":a,"db.namespace":Et(this)?`${Et(this)}.${a}`:a,"db.operation.name":t,library:"mongodb"},r);return p?T(p,()=>{try{let c=n.apply(this,s);return c&&typeof c.then=="function"?c.then(i=>(p.end(0,{matchedCount:i?.matchedCount,modifiedCount:i?.modifiedCount,deletedCount:i?.deletedCount,insertedCount:i?.insertedCount}),i),i=>{throw p.end(500,{error:i?.message,"error.type":i?.name||"Error"}),i}):(p.end(0),c)}catch(c){throw p.end(500,{error:c?.message,"error.type":c?.name||"Error"}),c}}):n.apply(this,s)})},Ct=(e,t,r,n)=>{S(e,t,`senzor.mongodb.cursor.${r}.${t}`,o=>function(...a){let p=Ce(this),c=w(`MongoDB ${r}`,"db",{collection:p,operation:r,"db.system.name":"mongodb","db.collection.name":p,"db.operation.name":r,library:"mongodb"},n);return c?T(c,()=>{try{let i=o.apply(this,a);return i&&typeof i.then=="function"?i.then(d=>(c.end(0,{resultCount:Array.isArray(d)?d.length:void 0}),d),d=>{throw c.end(500,{error:d?.message,"error.type":d?.name||"Error"}),d}):(c.end(0),i)}catch(i){throw c.end(500,{error:i?.message,"error.type":i?.name||"Error"}),i}}):o.apply(this,a)})},ze=(e,t)=>{let n=(e?.Collection||e?.default?.Collection)?.prototype;["insertOne","insertMany","updateOne","updateMany","replaceOne","deleteOne","deleteMany","findOne","findOneAndUpdate","findOneAndDelete","findOneAndReplace","countDocuments","estimatedDocumentCount","distinct","bulkWrite","createIndex","dropIndex"].forEach(a=>xe(n,a,t));let o=e?.FindCursor||e?.default?.FindCursor,s=e?.AggregationCursor||e?.default?.AggregationCursor;["toArray","next","forEach"].forEach(a=>Ct(o?.prototype,a,"find",t)),["toArray","next","forEach"].forEach(a=>Ct(s?.prototype,a,"aggregate",t))},xt=e=>{b("mongodb",t=>ze(t,e))};var Ae=e=>{let t=e[0];if(typeof t=="string")return t;if(t&&typeof t.text=="string")return t.text},j=(e,t,r)=>{S(e,"query",`senzor.pg.${t}.query`,n=>function(...s){let a=Ae(s),p=q(a)||"QUERY",c=w(`Postgres ${p}`,"db",{query:P(a,r),operation:p,"db.system.name":"postgresql","db.operation.name":p,"db.query.text":P(a,r),library:"pg"},r);if(!c)return n.apply(this,s);let i=s.findIndex(d=>typeof d=="function");if(i>=0){let d=s[i];s[i]=function(l,m){return c.end(l?500:0,{error:l?.message,"error.type":l?.name,rowCount:m?.rowCount,"db.response.row_count":m?.rowCount}),d.apply(this,arguments)}}return T(c,()=>{try{let d=n.apply(this,s);return d&&typeof d.then=="function"?d.then(u=>(c.end(0,{rowCount:u?.rowCount,"db.response.row_count":u?.rowCount}),u),u=>{throw c.end(500,{error:u?.message,"error.type":u?.name||"Error"}),u}):(i<0&&d&&typeof d.once=="function"?(d.once("end",()=>c.end(0)),d.once("error",u=>c.end(500,{error:u.message,"error.type":u.name}))):i<0&&c.end(0),d)}catch(d){throw c.end(500,{error:d?.message,"error.type":d?.name||"Error"}),d}})})},Ie=(e,t)=>{e&&(j(e.Client?.prototype,"client",t),j(e.Pool?.prototype,"pool",t),e.default&&(j(e.default.Client?.prototype,"default.client",t),j(e.default.Pool?.prototype,"default.pool",t)))},zt=e=>{b("pg",t=>Ie(t,e))};var Oe=e=>e?Array.isArray(e)?e.some(([t,r])=>String(t).toLowerCase()===A&&String(r).toLowerCase()==="true"):Object.entries(e).some(([t,r])=>t.toLowerCase()===A&&String(r).toLowerCase()==="true"):!1,rt=(e,t,r)=>{if(Array.isArray(e))return e.push([t,r]),e;let n={...e||{}},o=Object.keys(n).find(s=>s.toLowerCase()===t.toLowerCase());return n[o||t]=r,n},Re=e=>{try{let t=new URL(String(e));return{url:t.toString(),hostname:t.hostname,path:`${t.pathname}${t.search}`}}catch{return{url:String(e||""),hostname:"unknown",path:"/"}}},W=(e,t,r,n)=>{S(e,t,r,o=>function(a,p,c){if(Oe(p?.headers))return o.apply(this,arguments);let i=Re(a?.origin?a.origin:a),d=String(p?.method||"GET").toUpperCase(),u=w(`${d} ${i.hostname}`,"http",{url:i.url,method:d,route:x(i.path),library:"undici","http.request.method":d,"url.full":i.url,"url.path":i.path,"server.address":i.hostname},n);if(!u)return o.apply(this,arguments);let l={...p||{}};l.headers=rt(l.headers,"traceparent",L(u.trace.id,u.spanId)),l.headers=rt(l.headers,"x-senzor-trace-id",u.trace.id),l.headers=rt(l.headers,"x-senzor-parent-span-id",u.spanId);let m=typeof c=="function"?function(f,k){return u.end(f?500:k?.statusCode||0,{error:f?.message,"error.type":f?.name,"http.response.status_code":k?.statusCode}),c.apply(this,arguments)}:c;return T(u,()=>{try{let y=o.call(this,a,l,m);return y&&typeof y.then=="function"?y.then(f=>(u.end(f?.statusCode||f?.status||0,{"http.response.status_code":f?.statusCode||f?.status}),f),f=>{throw u.end(500,{error:f?.message,"error.type":f?.name||"Error"}),f}):(typeof m!="function"&&u.end(0),y)}catch(y){throw u.end(500,{error:y?.message,"error.type":y?.name||"Error"}),y}})})},Pe=(e,t)=>{W(e,"request","senzor.undici.request",t),W(e,"stream","senzor.undici.stream",t),W(e,"pipeline","senzor.undici.pipeline",t),[e?.Client?.prototype,e?.Pool?.prototype,e?.Agent?.prototype,e?.ProxyAgent?.prototype].forEach((r,n)=>{W(r,"request",`senzor.undici.dispatcher.${n}.request`,t)})},At=e=>{b("undici",t=>Pe(t,e))};var Le=e=>typeof e=="string"?e.toUpperCase():Array.isArray(e)?String(e[0]||"COMMAND").toUpperCase():e?.name?String(e.name).toUpperCase():Array.isArray(e?.args)?String(e.args[0]||"COMMAND").toUpperCase():"COMMAND",v=(e,t,r)=>{S(e,"sendCommand",`senzor.redis.${t}.sendCommand`,n=>function(s,...a){let p=Le(s),c=w(`Redis ${p}`,"db",{command:p,operation:p,"db.system.name":"redis","db.operation.name":p,library:t},r);return c?T(c,()=>{try{let i=n.call(this,s,...a);return i&&typeof i.then=="function"?i.then(d=>(c.end(0),d),d=>{throw c.end(500,{error:d?.message,"error.type":d?.name||"Error"}),d}):(c.end(0),i)}catch(i){throw c.end(500,{error:i?.message,"error.type":i?.name||"Error"}),i}}):n.apply(this,arguments)})},Me=(e,t,r)=>(v(e,t,r),v(Object.getPrototypeOf(e),t,r),e),ve=(e,t)=>{["createClient","createCluster"].forEach(r=>{S(e,r,`senzor.redis.${r}`,n=>function(...s){let a=n.apply(this,s);return Me(a,"redis",t)})})},Ne=(e,t)=>{v(e?.prototype,"ioredis",t),v(e?.Redis?.prototype,"ioredis",t),v(e?.Cluster?.prototype,"ioredis-cluster",t),v(e?.default?.prototype,"ioredis",t)},It=e=>{b("redis",t=>ve(t,e)),b("ioredis",t=>Ne(t,e))};var He=e=>{let t=e[0];if(typeof t=="string")return t;if(t&&typeof t.sql=="string")return t.sql},N=(e,t,r,n)=>{S(e,t,`senzor.${r}.${t}`,o=>function(...a){let p=He(a),c=q(p)||t.toUpperCase(),i=w(`MySQL ${c}`,"db",{query:P(p,n),operation:c,"db.system.name":"mysql","db.operation.name":c,"db.query.text":P(p,n),library:r},n);if(!i)return o.apply(this,a);let d=a.findIndex(u=>typeof u=="function");if(d>=0){let u=a[d];a[d]=function(m,y){return i.end(m?500:0,{error:m?.message,"error.type":m?.name,rowCount:Array.isArray(y)?y.length:void 0}),u.apply(this,arguments)}}return T(i,()=>{try{let u=o.apply(this,a);return u&&typeof u.then=="function"?u.then(l=>{let m=Array.isArray(l)?l[0]:l;return i.end(0,{rowCount:Array.isArray(m)?m.length:void 0}),l},l=>{throw i.end(500,{error:l?.message,"error.type":l?.name||"Error"}),l}):(d<0&&u&&typeof u.once=="function"?(u.once("end",()=>i.end(0)),u.once("error",l=>i.end(500,{error:l.message,"error.type":l.name}))):d<0&&i.end(0),u)}catch(u){throw i.end(500,{error:u?.message,"error.type":u?.name||"Error"}),u}})})},$e=(e,t,r)=>{[e?.Connection?.prototype,e?.Pool?.prototype,e?.PoolConnection?.prototype,e?.PromiseConnection?.prototype,e?.PromisePool?.prototype,e?.default?.Connection?.prototype,e?.default?.Pool?.prototype].forEach(n=>{N(n,"query",t,r),N(n,"execute",t,r)})},Fe=(e,t,r)=>{["createConnection","createPool"].forEach(n=>{S(e,n,`senzor.${t}.${n}`,o=>function(...a){let p=o.apply(this,a);return N(p,"query",t,r),N(p,"execute",t,r),N(Object.getPrototypeOf(p),"query",t,r),N(Object.getPrototypeOf(p),"execute",t,r),p})})},Ot=(e,t,r)=>{$e(e,t,r),Fe(e,t,r)},Rt=e=>{b("mysql",t=>Ot(t,"mysql",e)),b("mysql2",t=>Ot(t,"mysql2",e))};var Lt=e=>e?.model?.modelName||e?.constructor?.modelName||e?.modelName||"unknown",Mt=e=>e?.mongooseCollection?.name||e?.collection?.name||e?.model?.collection?.name||"unknown",G=(e,t,r)=>{S(e,"exec",`senzor.mongoose.${t}.exec`,n=>function(...s){let a=String(this?.op||this?._op||t).toUpperCase(),p=Mt(this),c=w(`Mongoose ${a}`,"db",{collection:p,model:Lt(this),operation:a,"db.system.name":"mongodb","db.collection.name":p,"db.operation.name":a,library:"mongoose"},r);return c?T(c,()=>{try{let i=n.apply(this,s);return i&&typeof i.then=="function"?i.then(d=>(c.end(0,{resultCount:Array.isArray(d)?d.length:void 0}),d),d=>{throw c.end(500,{error:d?.message,"error.type":d?.name||"Error"}),d}):(c.end(0),i)}catch(i){throw c.end(500,{error:i?.message,"error.type":i?.name||"Error"}),i}}):n.apply(this,s)})},Pt=(e,t)=>{S(e,"save","senzor.mongoose.model.save",r=>function(...o){let s=Mt(this),a=w("Mongoose SAVE","db",{collection:s,model:Lt(this),operation:"SAVE","db.system.name":"mongodb","db.collection.name":s,"db.operation.name":"SAVE",library:"mongoose"},t);return a?T(a,()=>{try{let p=r.apply(this,o);return p&&typeof p.then=="function"?p.then(c=>(a.end(0),c),c=>{throw a.end(500,{error:c?.message,"error.type":c?.name||"Error"}),c}):(a.end(0),p)}catch(p){throw a.end(500,{error:p?.message,"error.type":p?.name||"Error"}),p}}):r.apply(this,o)})},Ue=(e,t)=>{G(e?.Query?.prototype,"query",t),G(e?.Aggregate?.prototype,"aggregate",t),Pt(e?.Model?.prototype,t),e?.default&&(G(e.default?.Query?.prototype,"query",t),G(e.default?.Aggregate?.prototype,"aggregate",t),Pt(e.default?.Model?.prototype,t))},vt=e=>{b("mongoose",t=>Ue(t,e))};var Nt=Symbol.for("senzor.bullmq.patched");function Ht(e,t,r){if(!e?.Worker?.prototype)return;let n=e.Worker.prototype,o=n.processJob;typeof o!="function"||o[Nt]||(n.processJob=async function(s){let a=s.timestamp?Date.now()-s.timestamp:0,p=(s.attemptsMade||0)+1,c=s.opts?.attempts??1,i=p>=c,d=s.name==="__default__"?s.queueName:`${s.queueName}:${s.name}`;return t.startTask(d,"queue",{queueDelay:a,attempts:p,isDeadLetter:!1,metadata:{jobId:s.id,queueName:s.queueName,maxAttempts:c}},async()=>{try{let u=await o.call(this,s);return t.endTask("success"),u}catch(u){try{let l=g.current();l&&l.contextType==="task"&&i&&(l.data.isDeadLetter=!0)}catch{}throw t.captureError(u,{queueName:s.queueName,jobId:s.id,isDeadLetter:i}),t.endTask("failed"),u}})},Object.defineProperty(n.processJob,Nt,{value:!0}),r&&console.log("[Senzor] BullMQ instrumented"))}var $t=(e,t)=>{b("bullmq",r=>{Ht(r,e,t),r?.default&&Ht(r.default,e,t)})};var Ft=Symbol.for("senzor.cron.patched");function _e(e){return typeof e=="object"&&e!==null?e:e?{timezone:e}:{}}function Ut(e,t,r){let n=e.schedule;if(typeof n!="function"||n[Ft])return;let o=n,s=function(a,p,c){if(typeof p!="function")return o.call(this,a,p,c);try{let i=_e(c),d=i?.name??`cron: ${a}`,u=t.wrapTask(d,"cron",{expression:a,metadata:i},p);return o.call(this,a,u,c)}catch(i){return r&&console.error("[Senzor] cron wrap failed",i),o.call(this,a,p,c)}};Object.defineProperty(s,Ft,{value:!0,enumerable:!1});try{e.schedule=s}catch{r&&console.warn("[Senzor] unable to patch cron schedule (readonly export)")}r&&console.log("[Senzor] node-cron instrumented")}var _t=(e,t)=>{b("node-cron",r=>{r&&(Ut(r,e,t),r.default&&Ut(r.default,e,t))})};var nt={name:"@senzops/apm-node",version:"1.2.0",description:"Universal APM SDK for Senzor",main:"dist/index.js",types:"dist/index.d.ts",exports:{".":{types:"./dist/index.d.ts",require:"./dist/index.js",import:"./dist/index.mjs"},"./register":{types:"./dist/register.d.ts",require:"./dist/register.js",import:"./dist/register.mjs"}},scripts:{build:"tsup",prepublishOnly:"npm run build"},devDependencies:{"@types/node":"^20.19.41",tsup:"^8.0.0",typescript:"^5.0.0"},engines:{node:">=18.0.0"},keywords:["apm","monitoring","senzor","node","javascript","api","observability"],author:"Senzops",license:"MIT"};var ot={name:nt.name,version:nt.version};var Qe=e=>{let t=new Set;return JSON.stringify(e,(r,n)=>{if(typeof n=="object"&&n!==null){if(t.has(n))return"[Circular]";t.add(n)}return n})},st=class{constructor(){this.transport=null;this.options=null;this.isInstrumented=!1}preload(t={}){let r=t.endpoint||"https://api.senzor.dev/api/ingest/apm",n=t.debug||!1;this.options={apiKey:"",...this.options,...t},this.installNativeInstrumentations(r,n)}init(t){if(!t.apiKey){console.warn("[Senzor] API Key missing. SDK disabled.");return}this.options=t;let r=t.endpoint||"https://api.senzor.dev/api/ingest/apm",n=t.debug||!1;this.transport=new _({...t,endpoint:r}),this.installNativeInstrumentations(r,n)}isInstrumentationEnabled(t){let r=this.options?.instrumentations;return r===!1?!1:Array.isArray(r)?r.includes(t):!0}installNativeInstrumentations(t,r){if(!this.isInstrumented){this.setupGlobalErrorHandlers(),this.setupLogInterception();try{this.isInstrumentationEnabled("http")&&bt(this,t,this.options||void 0)}catch{}try{this.isInstrumentationEnabled("fetch")&&wt(t,this.options||void 0)}catch{}try{this.isInstrumentationEnabled("undici")&&At(this.options||void 0)}catch{}try{this.isInstrumentationEnabled("mongo")&&xt(this.options||void 0)}catch{}try{this.isInstrumentationEnabled("mongoose")&&vt(this.options||void 0)}catch{}try{this.isInstrumentationEnabled("pg")&&zt(this.options||void 0)}catch{}try{this.isInstrumentationEnabled("mysql")&&Rt(this.options||void 0)}catch{}try{this.isInstrumentationEnabled("redis")&&It(this.options||void 0)}catch{}try{this.isInstrumentationEnabled("bullmq")&&$t(this,r)}catch{}try{this.isInstrumentationEnabled("cron")&&_t(this,r)}catch{}this.isInstrumented=!0,r&&console.log("[Senzor] Auto-instrumentation enabled")}}setupLogInterception(){if(this.options?.autoLogs===!1)return;let t=["log","info","warn","error","debug"],r={log:console.log,info:console.info,warn:console.warn,error:console.error,debug:console.debug},n=!1;t.forEach(o=>{console[o]=(...s)=>{if(r[o].apply(console,s),!(n||!this.transport)){n=!0;try{let a="",p={};s.forEach(u=>{if(typeof u=="string")a+=(a?" ":"")+u;else if(u instanceof Error)a+=(a?" ":"")+u.message,p.errorStack=u.stack,p.errorName=u.name;else if(typeof u=="object"&&u!==null)try{let l=JSON.parse(Qe(u));p={...p,...R(l,this.options||void 0)}}catch{p.unparseableObject=!0}else a+=(a?" ":"")+String(u)}),!a&&Object.keys(p).length>0&&(a="Object Log");let c=g.current(),i=c?.contextType==="task"?"task":"apm",d={message:a||"Empty log",level:o==="log"?"info":o,attributes:p,timestamp:new Date().toISOString()};c&&(i==="task"?d.runId=c.id:d.traceId=c.id),this.transport.addLog(d,i)}catch{}finally{n=!1}}}})}setupGlobalErrorHandlers(){if(process.__senzorGlobalHandlersInstalled)return;process.__senzorGlobalHandlersInstalled=!0;let t=()=>{try{return{pid:process.pid,ppid:process.ppid,platform:process.platform,uptimeSec:Math.floor(process.uptime()),env:process.env.NODE_ENV||"unknown"}}catch{return{}}},r=()=>{try{let o=process.memoryUsage();return{rss:o.rss,heapTotal:o.heapTotal,heapUsed:o.heapUsed,external:o.external,arrayBuffers:o.arrayBuffers}}catch{return{}}},n=(o,s={})=>{try{let a;if(o instanceof Error)a=o;else if(typeof o=="string")a=new Error(o);else try{a=new Error(JSON.stringify(o))}catch{a=new Error("Non-serializable rejection reason")}let p={...s,runtime:{name:"node",version:process.version},process:t(),memory:r(),sdk:{name:ot.name,version:ot.version}};this.captureError(a,p)}catch(a){try{this.options?.debug&&console.error("[Senzor] Error handler failure:",a)}catch{}}};process.on("uncaughtExceptionMonitor",o=>n(o,{type:"uncaughtExceptionMonitor",severity:"fatal"})),process.on("uncaughtException",o=>n(o,{type:"uncaughtException",severity:"fatal"})),process.on("unhandledRejection",o=>n(o,{type:"unhandledRejection",severity:"error"})),process.on("warning",o=>n(o,{type:"processWarning",severity:"warning"})),process.on("multipleResolves",(o,s,a)=>n(a||new Error("Multiple promise resolves"),{type:"multipleResolves",resolveType:o,severity:"warning"})),process.on("rejectionHandled",o=>{if(this.options?.debug)try{console.warn("[Senzor] rejectionHandled event detected")}catch{}}),process.on("SIGTERM",()=>n(new Error("Process received SIGTERM"),{type:"processSignal",signal:"SIGTERM"})),process.on("SIGINT",()=>n(new Error("Process received SIGINT"),{type:"processSignal",signal:"SIGINT"}))}startTrace(t,r){if(!this.transport)return r();let n=g.current();if(n?.contextType==="apm")return n.data={...n.data,...t},r();let o,s;if(t.headers){let i=l=>{if(t.headers[l])return t.headers[l];if(t.headers[l.toLowerCase()])return t.headers[l.toLowerCase()]},d=i("traceparent"),u=lt(d);if(u)o=u.traceId,s=u.parentSpanId;else{let l=i("x-senzor-trace-id"),m=i("x-senzor-parent-span-id");o=Array.isArray(l)?l[0]:l,s=Array.isArray(m)?m[0]:m}}let a=o||Z(),p=F(),c={id:a,contextType:"apm",startTime:performance.now(),rootSpanId:p,activeSpanId:p,data:{...t,parentTraceId:o,parentSpanId:s,rootSpanId:p},spans:[],maxSpans:this.options?.maxSpansPerTrace??500,droppedSpans:0};return g.run(c,r)}endTrace(t,r={}){let n=g.current();if(!n||n.contextType!=="apm"||!this.transport||n.ended)return;n.ended=!0;let o=performance.now()-n.startTime,s={traceId:n.id,parentTraceId:n.data.parentTraceId,parentSpanId:n.data.parentSpanId,rootSpanId:n.rootSpanId,...n.data,...r,status:t,duration:o,spans:n.spans,droppedSpans:n.droppedSpans,timestamp:new Date().toISOString()};this.transport.addTrace(s)}startTask(t,r,n,o){if(!this.transport)return o();let s=g.current(),a=s?.contextType==="apm"?s.id:void 0,p=process.memoryUsage?process.memoryUsage().heapUsed:0,c=process.cpuUsage?process.cpuUsage():void 0,i={id:(0,qt.randomUUID)(),contextType:"task",startTime:performance.now(),rootSpanId:F(),startMemory:p,startCpu:c,data:{taskName:t,taskType:r,triggerTraceId:a,...n},spans:[],maxSpans:this.options?.maxSpansPerTrace??500,droppedSpans:0};return i.activeSpanId=i.rootSpanId,g.run(i,o)}endTask(t,r={}){let n=g.current();if(!n||n.contextType!=="task"||!this.transport)return;let o;if(process.memoryUsage&&n.startMemory!==void 0&&process.cpuUsage&&n.startCpu){let a=process.memoryUsage().heapUsed,p=process.cpuUsage(n.startCpu);o={memoryDeltaBytes:a-n.startMemory,cpuUserUs:p.user,cpuSystemUs:p.system}}let s={runId:n.id,taskName:n.data.taskName,taskType:n.data.taskType,triggerTraceId:n.data.triggerTraceId,queueDelay:n.data.queueDelay,attempts:n.data.attempts,isDeadLetter:n.data.isDeadLetter,metadata:{...n.data.metadata,...r,droppedSpans:n.droppedSpans},resourceMetrics:o,status:t,duration:performance.now()-n.startTime,spans:n.spans,timestamp:new Date().toISOString()};this.transport.addTask(s)}wrapTask(t,r,n={},o){return(async(...s)=>this.startTask(t,r,n,async()=>{try{let a=await o(...s);return this.endTask("success"),a}catch(a){throw this.captureError(a,{taskName:t}),this.endTask("failed"),a}}))}captureError(t,r={}){if(!this.transport)return;let n;t instanceof Error?n=t:n=new Error(String(t));let o=g.current(),s={errorClass:n.name||"Error",message:n.message,stackTrace:n.stack,context:R(r,this.options||void 0),timestamp:new Date().toISOString()};o?.contextType==="task"?this.transport.addError({...s,runId:o.id},"task"):this.transport.addError({...s,traceId:o?.id},"apm")}track(t){this.transport?.addTrace({traceId:Z(),...t,spans:[],timestamp:new Date().toISOString()})}startSpan(t,r="custom"){let n=w(t,r,{},this.options||void 0);return n?{end:(o,s)=>n.end(s,o)}:{end:()=>{}}}async flush(){this.transport&&await this.transport.flush()}},h=new st;var Qt=()=>(e,t,r)=>{h.startTrace({method:e.method,path:e.originalUrl||e.url,ip:C(e),userAgent:e.headers["user-agent"],headers:e.headers},()=>{t.once("finish",()=>{try{let n="UNKNOWN";e.route&&e.route.path?n=(e.baseUrl||"")+e.route.path:t.statusCode===404?n="Not Found":n=e.path||"Wildcard",h.endTrace(t.statusCode,{route:n})}catch{}}),r()})},Dt=()=>(e,t,r,n)=>{h.captureError(e),n(e)};var jt=e=>t=>{let r=t.node.req,n=r.originalUrl||r.url||"/";return h.startTrace({method:r.method||"GET",path:n,ip:C(r),userAgent:r.headers["user-agent"],headers:r.headers},async()=>{try{let o=await e(t),s=200;return t.node.res.statusCode&&(s=t.node.res.statusCode),o&&o.statusCode&&(s=o.statusCode),h.endTrace(s,{route:$(t,n)}),o}catch(o){h.captureError(o);let s=o.statusCode||o.status||500;throw h.endTrace(s,{route:$(t,n)}),o}})};var Wt=e=>async(t,r)=>{let n=t.url?new URL(t.url):{pathname:"/"},o=t.method||"GET",s={},a,p;return typeof t.headers.get=="function"?(a=t.headers.get("user-agent"),p=t.headers.get("x-forwarded-for"),t.headers.forEach((c,i)=>{s[i]=c})):(s=t.headers,a=s["user-agent"],p=s["x-forwarded-for"]),h.startTrace({method:o,path:n.pathname,userAgent:a,ip:p||C(t),headers:s},async()=>{try{let c=await e(t,r),i=c?.status||200;return h.endTrace(i,{route:x(n.pathname)}),c}catch(c){throw h.captureError(c),h.endTrace(500,{route:x(n.pathname)}),c}})},Gt=e=>async(t,r)=>{let n=t.url?t.url.split("?")[0]:"/";return h.startTrace({method:t.method||"GET",path:n,userAgent:t.headers["user-agent"],ip:C(t),headers:t.headers},async()=>{let o=()=>{h.endTrace(r.statusCode||200,{route:x(n)})};r.once("finish",o),r.once("close",o);try{return await e(t,r)}catch(s){throw h.captureError(s),s}})};var Kt=(e,t,r)=>{t&&t.apiKey&&h.init(t),e.addHook("onRequest",(n,o,s)=>{h.startTrace({method:n.method,path:n.raw.url||n.url,ip:C(n),userAgent:n.headers["user-agent"],headers:n.headers},()=>s())}),e.addHook("onError",(n,o,s,a)=>{h.captureError(s),a()}),e.addHook("onResponse",(n,o,s)=>{let a=n.routeOptions?.url||n.routerPath||"UNKNOWN";h.endTrace(o.statusCode,{route:a}),s()}),r()};var De={preload:(e={})=>h.preload(e),init:e=>h.init(e),flush:()=>h.flush(),track:h.track.bind(h),startSpan:h.startSpan.bind(h),captureException:h.captureError.bind(h),wrapTask:h.wrapTask.bind(h),startTask:h.startTask.bind(h),requestHandler:Qt,errorHandler:Dt,wrapNextRoute:Wt,wrapNextPages:Gt,wrapH3:jt,fastifyPlugin:Kt},Hn=De;})();
|
|
2
2
|
//# sourceMappingURL=index.global.js.map
|