@senzops/apm-node 1.2.2 → 1.2.3

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 (53) hide show
  1. package/dist/index.global.js +1 -1
  2. package/dist/index.global.js.map +1 -1
  3. package/dist/index.js +1 -1
  4. package/dist/index.js.map +1 -1
  5. package/dist/index.mjs +1 -1
  6. package/dist/index.mjs.map +1 -1
  7. package/dist/register.js +1 -1
  8. package/dist/register.js.map +1 -1
  9. package/dist/register.mjs +1 -1
  10. package/dist/register.mjs.map +1 -1
  11. package/package.json +1 -1
  12. package/src/instrumentation/express.ts +12 -2
  13. package/.claude/worktrees/infallible-chatelet-f3fb36/.claude/settings.local.json +0 -9
  14. package/.claude/worktrees/infallible-chatelet-f3fb36/CHANGELOG.md +0 -49
  15. package/.claude/worktrees/infallible-chatelet-f3fb36/README.md +0 -398
  16. package/.claude/worktrees/infallible-chatelet-f3fb36/package-lock.json +0 -1494
  17. package/.claude/worktrees/infallible-chatelet-f3fb36/package.json +0 -42
  18. package/.claude/worktrees/infallible-chatelet-f3fb36/src/core/client.ts +0 -451
  19. package/.claude/worktrees/infallible-chatelet-f3fb36/src/core/context.ts +0 -48
  20. package/.claude/worktrees/infallible-chatelet-f3fb36/src/core/normalizer.ts +0 -44
  21. package/.claude/worktrees/infallible-chatelet-f3fb36/src/core/sanitizer.ts +0 -203
  22. package/.claude/worktrees/infallible-chatelet-f3fb36/src/core/transport.ts +0 -273
  23. package/.claude/worktrees/infallible-chatelet-f3fb36/src/core/types.ts +0 -106
  24. package/.claude/worktrees/infallible-chatelet-f3fb36/src/index.ts +0 -36
  25. package/.claude/worktrees/infallible-chatelet-f3fb36/src/instrumentation/bullmq.ts +0 -195
  26. package/.claude/worktrees/infallible-chatelet-f3fb36/src/instrumentation/cron.ts +0 -204
  27. package/.claude/worktrees/infallible-chatelet-f3fb36/src/instrumentation/express.ts +0 -338
  28. package/.claude/worktrees/infallible-chatelet-f3fb36/src/instrumentation/fastify.ts +0 -296
  29. package/.claude/worktrees/infallible-chatelet-f3fb36/src/instrumentation/framework.ts +0 -301
  30. package/.claude/worktrees/infallible-chatelet-f3fb36/src/instrumentation/hook.ts +0 -134
  31. package/.claude/worktrees/infallible-chatelet-f3fb36/src/instrumentation/http.ts +0 -530
  32. package/.claude/worktrees/infallible-chatelet-f3fb36/src/instrumentation/koa.ts +0 -173
  33. package/.claude/worktrees/infallible-chatelet-f3fb36/src/instrumentation/mongo.ts +0 -202
  34. package/.claude/worktrees/infallible-chatelet-f3fb36/src/instrumentation/mongoose.ts +0 -156
  35. package/.claude/worktrees/infallible-chatelet-f3fb36/src/instrumentation/mysql.ts +0 -169
  36. package/.claude/worktrees/infallible-chatelet-f3fb36/src/instrumentation/patch.ts +0 -56
  37. package/.claude/worktrees/infallible-chatelet-f3fb36/src/instrumentation/pg.ts +0 -131
  38. package/.claude/worktrees/infallible-chatelet-f3fb36/src/instrumentation/redis.ts +0 -109
  39. package/.claude/worktrees/infallible-chatelet-f3fb36/src/instrumentation/span.ts +0 -73
  40. package/.claude/worktrees/infallible-chatelet-f3fb36/src/instrumentation/undici.ts +0 -189
  41. package/.claude/worktrees/infallible-chatelet-f3fb36/src/middleware/express.ts +0 -48
  42. package/.claude/worktrees/infallible-chatelet-f3fb36/src/register.ts +0 -58
  43. package/.claude/worktrees/infallible-chatelet-f3fb36/src/utils/getClientIp.ts +0 -175
  44. package/.claude/worktrees/infallible-chatelet-f3fb36/src/utils/ids.ts +0 -7
  45. package/.claude/worktrees/infallible-chatelet-f3fb36/src/utils/internal.ts +0 -1
  46. package/.claude/worktrees/infallible-chatelet-f3fb36/src/utils/sdkMeta.ts +0 -6
  47. package/.claude/worktrees/infallible-chatelet-f3fb36/src/utils/traceContext.ts +0 -44
  48. package/.claude/worktrees/infallible-chatelet-f3fb36/src/wrappers/fastify.ts +0 -35
  49. package/.claude/worktrees/infallible-chatelet-f3fb36/src/wrappers/h3.ts +0 -59
  50. package/.claude/worktrees/infallible-chatelet-f3fb36/src/wrappers/next.ts +0 -131
  51. package/.claude/worktrees/infallible-chatelet-f3fb36/tsconfig.json +0 -15
  52. package/.claude/worktrees/infallible-chatelet-f3fb36/tsup.config.ts +0 -21
  53. package/.claude/worktrees/infallible-chatelet-f3fb36/wiki.md +0 -852
@@ -1,203 +0,0 @@
1
- import { SenzorOptions } from './types';
2
-
3
- const DEFAULT_MAX_ATTRIBUTES = 64;
4
- const DEFAULT_MAX_ATTRIBUTE_LENGTH = 2048;
5
- const MAX_DEPTH = 4;
6
- const MAX_ARRAY_ITEMS = 20;
7
-
8
- const SENSITIVE_KEY_PATTERN =
9
- /(^|[-_.])(authorization|cookie|set-cookie|password|passwd|pwd|secret|token|api[-_.]?key|x-api-key|access[-_.]?token|refresh[-_.]?token|client[-_.]?secret|private[-_.]?key)([-_.]|$)/i;
10
-
11
- export interface SanitizerOptions {
12
- maxAttributes?: number;
13
- maxAttributeLength?: number;
14
- }
15
-
16
- const getLimits = (options?: SanitizerOptions | SenzorOptions) => ({
17
- maxAttributes: options?.maxAttributes ?? DEFAULT_MAX_ATTRIBUTES,
18
- maxAttributeLength:
19
- options?.maxAttributeLength ?? DEFAULT_MAX_ATTRIBUTE_LENGTH
20
- });
21
-
22
- export const truncate = (
23
- value: string,
24
- maxLength = DEFAULT_MAX_ATTRIBUTE_LENGTH
25
- ): string => {
26
- if (value.length <= maxLength) return value;
27
- return `${value.slice(0, Math.max(0, maxLength - 15))}...[truncated]`;
28
- };
29
-
30
- export const isSensitiveKey = (key: string): boolean =>
31
- SENSITIVE_KEY_PATTERN.test(key);
32
-
33
- const sanitizePrimitive = (
34
- value: unknown,
35
- maxLength: number
36
- ): string | number | boolean | null | undefined => {
37
- if (value === null || value === undefined) return value;
38
-
39
- if (
40
- typeof value === 'number' ||
41
- typeof value === 'boolean'
42
- ) {
43
- return value;
44
- }
45
-
46
- if (typeof value === 'bigint') {
47
- return value.toString();
48
- }
49
-
50
- if (typeof value === 'string') {
51
- return truncate(value, maxLength);
52
- }
53
-
54
- return undefined;
55
- };
56
-
57
- const sanitizeValue = (
58
- key: string,
59
- value: unknown,
60
- options: Required<SanitizerOptions>,
61
- depth: number
62
- ): unknown => {
63
- if (isSensitiveKey(key)) return '[REDACTED]';
64
-
65
- const primitive =
66
- sanitizePrimitive(value, options.maxAttributeLength);
67
-
68
- if (primitive !== undefined || value === undefined) {
69
- return primitive;
70
- }
71
-
72
- if (value instanceof Error) {
73
- return {
74
- name: truncate(value.name, options.maxAttributeLength),
75
- message: truncate(value.message, options.maxAttributeLength),
76
- stack: value.stack
77
- ? truncate(value.stack, options.maxAttributeLength)
78
- : undefined
79
- };
80
- }
81
-
82
- if (depth >= MAX_DEPTH) {
83
- return '[MaxDepth]';
84
- }
85
-
86
- if (Array.isArray(value)) {
87
- return value
88
- .slice(0, MAX_ARRAY_ITEMS)
89
- .map((item) =>
90
- sanitizeValue(key, item, options, depth + 1)
91
- );
92
- }
93
-
94
- if (typeof value === 'object') {
95
- const output: Record<string, unknown> = {};
96
- let count = 0;
97
-
98
- for (const [childKey, childValue] of Object.entries(
99
- value as Record<string, unknown>
100
- )) {
101
- if (count >= options.maxAttributes) {
102
- output.__truncated = true;
103
- break;
104
- }
105
-
106
- output[childKey] = sanitizeValue(
107
- childKey,
108
- childValue,
109
- options,
110
- depth + 1
111
- );
112
- count++;
113
- }
114
-
115
- return output;
116
- }
117
-
118
- return truncate(String(value), options.maxAttributeLength);
119
- };
120
-
121
- export const sanitizeAttributes = (
122
- attributes: Record<string, unknown> = {},
123
- options?: SanitizerOptions | SenzorOptions
124
- ): Record<string, unknown> => {
125
- const limits = getLimits(options);
126
- const normalizedOptions: Required<SanitizerOptions> = {
127
- maxAttributes: limits.maxAttributes,
128
- maxAttributeLength: limits.maxAttributeLength
129
- };
130
-
131
- const output: Record<string, unknown> = {};
132
- let count = 0;
133
-
134
- for (const [key, value] of Object.entries(attributes)) {
135
- if (count >= normalizedOptions.maxAttributes) {
136
- output.__truncated = true;
137
- break;
138
- }
139
-
140
- output[key] = sanitizeValue(
141
- key,
142
- value,
143
- normalizedOptions,
144
- 0
145
- );
146
- count++;
147
- }
148
-
149
- return output;
150
- };
151
-
152
- export const sanitizeHeaders = (
153
- headers: unknown,
154
- options?: SanitizerOptions | SenzorOptions
155
- ): Record<string, unknown> => {
156
- if (!headers || typeof headers !== 'object') return {};
157
-
158
- const plainHeaders: Record<string, unknown> = {};
159
-
160
- if (typeof (headers as any).forEach === 'function') {
161
- (headers as any).forEach((value: unknown, key: string) => {
162
- plainHeaders[key.toLowerCase()] = value;
163
- });
164
- } else {
165
- for (const [key, value] of Object.entries(
166
- headers as Record<string, unknown>
167
- )) {
168
- plainHeaders[key.toLowerCase()] = Array.isArray(value)
169
- ? value.join(', ')
170
- : value;
171
- }
172
- }
173
-
174
- return sanitizeAttributes(plainHeaders, options);
175
- };
176
-
177
- export const normalizeSql = (
178
- sql: unknown,
179
- options?: SenzorOptions
180
- ): string | undefined => {
181
- if (typeof sql !== 'string') return undefined;
182
-
183
- const collapsed = sql.replace(/\s+/g, ' ').trim();
184
- if (!collapsed) return undefined;
185
-
186
- const withoutLiterals = collapsed
187
- .replace(/'(?:''|[^'])*'/g, '?')
188
- .replace(/"(?:\\"|[^"])*"/g, '?')
189
- .replace(/\b\d+(\.\d+)?\b/g, '?');
190
-
191
- return truncate(
192
- options?.captureDbStatement === false
193
- ? withoutLiterals.split(' ').slice(0, 6).join(' ')
194
- : withoutLiterals,
195
- options?.maxAttributeLength ?? DEFAULT_MAX_ATTRIBUTE_LENGTH
196
- );
197
- };
198
-
199
- export const getSqlOperation = (sql: unknown): string | undefined => {
200
- if (typeof sql !== 'string') return undefined;
201
- const match = sql.trim().match(/^([a-z]+)/i);
202
- return match?.[1]?.toUpperCase();
203
- };
@@ -1,273 +0,0 @@
1
- import { SENZOR_INTERNAL_HEADER } from '../utils/internal';
2
- import { SenzorOptions, Trace, TaskRun, SenzorError, SenzorLog } from './types';
3
-
4
- interface ApmPayload {
5
- traces: Trace[];
6
- errors: SenzorError[];
7
- logs: SenzorLog[];
8
- }
9
-
10
- interface TaskPayload {
11
- runs: TaskRun[];
12
- errors: SenzorError[];
13
- logs: SenzorLog[];
14
- }
15
-
16
- export class Transport {
17
- private traceQueue: Trace[] = [];
18
- private apmErrorQueue: SenzorError[] = [];
19
- private apmLogQueue: SenzorLog[] = [];
20
-
21
- private taskQueue: TaskRun[] = [];
22
- private taskErrorQueue: SenzorError[] = [];
23
- private taskLogQueue: SenzorLog[] = [];
24
-
25
- private timer: NodeJS.Timeout | null = null;
26
- private apmEndpoint: string;
27
- private taskEndpoint: string;
28
- private isFlushing = false;
29
- private flushAgain = false;
30
- private droppedItems = 0;
31
-
32
- constructor(private config: SenzorOptions) {
33
- const baseEndpoint = config.endpoint || 'https://api.senzor.dev';
34
- this.apmEndpoint = baseEndpoint.includes('/api/ingest')
35
- ? baseEndpoint
36
- : `${baseEndpoint}/api/ingest/apm`;
37
- this.taskEndpoint = baseEndpoint.includes('/api/ingest')
38
- ? baseEndpoint.replace('/apm', '/task')
39
- : `${baseEndpoint}/api/ingest/task`;
40
-
41
- if (typeof setInterval !== 'undefined') {
42
- this.timer = setInterval(
43
- () => void this.flush(),
44
- config.flushInterval || 10000
45
- );
46
- if (this.timer && typeof this.timer.unref === 'function') {
47
- this.timer.unref();
48
- }
49
- }
50
-
51
- this.installShutdownFlush();
52
- }
53
-
54
- public addTrace(trace: any) {
55
- this.enqueue(this.traceQueue, trace);
56
- this.checkFlush();
57
- }
58
-
59
- public addTask(task: TaskRun) {
60
- this.enqueue(this.taskQueue, task);
61
- this.checkFlush();
62
- }
63
-
64
- public addError(error: SenzorError, type: 'apm' | 'task' = 'apm') {
65
- this.enqueue(
66
- type === 'task' ? this.taskErrorQueue : this.apmErrorQueue,
67
- error
68
- );
69
- this.checkFlush();
70
- }
71
-
72
- public addLog(log: SenzorLog, type: 'apm' | 'task' = 'apm') {
73
- this.enqueue(
74
- type === 'task' ? this.taskLogQueue : this.apmLogQueue,
75
- log
76
- );
77
- this.checkFlush();
78
- }
79
-
80
- private enqueue<T>(queue: T[], item: T) {
81
- queue.push(item);
82
-
83
- const maxQueueSize = this.config.maxQueueSize ?? 10000;
84
- while (queue.length > maxQueueSize) {
85
- queue.shift();
86
- this.droppedItems++;
87
- }
88
- }
89
-
90
- private prependWithLimit<T>(queue: T[], items: T[]) {
91
- if (!items.length) return;
92
- queue.unshift(...items);
93
-
94
- const maxQueueSize = this.config.maxQueueSize ?? 10000;
95
- while (queue.length > maxQueueSize) {
96
- queue.pop();
97
- this.droppedItems++;
98
- }
99
- }
100
-
101
- private checkFlush() {
102
- const totalApm =
103
- this.traceQueue.length +
104
- this.apmErrorQueue.length +
105
- this.apmLogQueue.length;
106
- const totalTask =
107
- this.taskQueue.length +
108
- this.taskErrorQueue.length +
109
- this.taskLogQueue.length;
110
-
111
- if (
112
- totalApm >= (this.config.batchSize || 100) ||
113
- totalTask >= (this.config.batchSize || 100)
114
- ) {
115
- void this.flush();
116
- }
117
- }
118
-
119
- private takeApmPayload(): ApmPayload {
120
- const payload = {
121
- traces: this.traceQueue,
122
- errors: this.apmErrorQueue,
123
- logs: this.apmLogQueue
124
- };
125
-
126
- this.traceQueue = [];
127
- this.apmErrorQueue = [];
128
- this.apmLogQueue = [];
129
- return payload;
130
- }
131
-
132
- private takeTaskPayload(): TaskPayload {
133
- const payload = {
134
- runs: this.taskQueue,
135
- errors: this.taskErrorQueue,
136
- logs: this.taskLogQueue
137
- };
138
-
139
- this.taskQueue = [];
140
- this.taskErrorQueue = [];
141
- this.taskLogQueue = [];
142
- return payload;
143
- }
144
-
145
- private restoreApmPayload(payload: ApmPayload) {
146
- this.prependWithLimit(this.apmLogQueue, payload.logs);
147
- this.prependWithLimit(this.apmErrorQueue, payload.errors);
148
- this.prependWithLimit(this.traceQueue, payload.traces);
149
- }
150
-
151
- private restoreTaskPayload(payload: TaskPayload) {
152
- this.prependWithLimit(this.taskLogQueue, payload.logs);
153
- this.prependWithLimit(this.taskErrorQueue, payload.errors);
154
- this.prependWithLimit(this.taskQueue, payload.runs);
155
- }
156
-
157
- private hasApmPayload(payload: ApmPayload): boolean {
158
- return (
159
- payload.traces.length > 0 ||
160
- payload.errors.length > 0 ||
161
- payload.logs.length > 0
162
- );
163
- }
164
-
165
- private hasTaskPayload(payload: TaskPayload): boolean {
166
- return (
167
- payload.runs.length > 0 ||
168
- payload.errors.length > 0 ||
169
- payload.logs.length > 0
170
- );
171
- }
172
-
173
- private async postJson(endpoint: string, payload: unknown) {
174
- const controller = new AbortController();
175
- const timeout = setTimeout(
176
- () => controller.abort(),
177
- this.config.flushTimeoutMs ?? 5000
178
- );
179
-
180
- if (typeof timeout.unref === 'function') timeout.unref();
181
-
182
- try {
183
- const response = await fetch(endpoint, {
184
- method: 'POST',
185
- headers: {
186
- 'Content-Type': 'application/json',
187
- 'x-service-api-key': this.config.apiKey,
188
- [SENZOR_INTERNAL_HEADER]: 'true'
189
- },
190
- body: JSON.stringify(payload),
191
- keepalive: true,
192
- signal: controller.signal
193
- });
194
-
195
- if (!response.ok) {
196
- throw new Error(`Senzor ingest failed with status ${response.status}`);
197
- }
198
- } finally {
199
- clearTimeout(timeout);
200
- }
201
- }
202
-
203
- public async flush() {
204
- if (this.isFlushing) {
205
- this.flushAgain = true;
206
- return;
207
- }
208
-
209
- this.isFlushing = true;
210
-
211
- try {
212
- do {
213
- this.flushAgain = false;
214
-
215
- const apmPayload = this.takeApmPayload();
216
- const taskPayload = this.takeTaskPayload();
217
- const sends: Promise<void>[] = [];
218
-
219
- if (this.hasApmPayload(apmPayload)) {
220
- sends.push(
221
- this.postJson(this.apmEndpoint, apmPayload).catch((error) => {
222
- this.restoreApmPayload(apmPayload);
223
- throw error;
224
- })
225
- );
226
- }
227
-
228
- if (this.hasTaskPayload(taskPayload)) {
229
- sends.push(
230
- this.postJson(this.taskEndpoint, taskPayload).catch((error) => {
231
- this.restoreTaskPayload(taskPayload);
232
- throw error;
233
- })
234
- );
235
- }
236
-
237
- if (!sends.length) continue;
238
-
239
- const results = await Promise.allSettled(sends);
240
- const failures = results.filter(
241
- (result) => result.status === 'rejected'
242
- );
243
-
244
- if (this.config.debug) {
245
- console.log(
246
- `[Senzor] Flushed: APM(${apmPayload.traces.length} traces, ${apmPayload.logs.length} logs), Task(${taskPayload.runs.length} runs, ${taskPayload.logs.length} logs), failures=${failures.length}, dropped=${this.droppedItems}`
247
- );
248
- }
249
- } while (this.flushAgain);
250
- } catch (err) {
251
- if (this.config.debug) console.error('[Senzor] Transport Flush Error:', err);
252
- } finally {
253
- this.isFlushing = false;
254
- }
255
- }
256
-
257
- private installShutdownFlush() {
258
- const key = Symbol.for('senzor.transport.shutdownFlushInstalled');
259
- const proc = process as unknown as Record<symbol, boolean>;
260
- if (proc[key]) return;
261
-
262
- Object.defineProperty(proc, key, {
263
- value: true,
264
- enumerable: false
265
- });
266
-
267
- const flushSyncBestEffort = () => {
268
- void this.flush();
269
- };
270
-
271
- process.once('beforeExit', flushSyncBestEffort);
272
- }
273
- }
@@ -1,106 +0,0 @@
1
- export interface SenzorOptions {
2
- apiKey: string;
3
- endpoint?: string;
4
- batchSize?: number;
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[];
14
- frameworkSpans?: boolean;
15
- captureMiddlewareSpans?: boolean;
16
- captureRouterSpans?: boolean;
17
- captureLifecycleHookSpans?: boolean;
18
- ignoreFrameworkSpanTypes?: string[];
19
- debug?: boolean;
20
- autoLogs?: boolean;
21
- }
22
-
23
- export interface Span {
24
- spanId: string;
25
- parentSpanId?: string;
26
- name: string;
27
- type: 'db' | 'http' | 'function' | 'custom';
28
- startTime: number;
29
- duration: number;
30
- status?: number;
31
- meta?: Record<string, any>;
32
- }
33
-
34
- export interface SenzorError {
35
- errorClass: string;
36
- message: string;
37
- stackTrace?: string;
38
- traceId?: string; // Maps to APM traceId
39
- runId?: string; // Maps to Task runId
40
- context?: any;
41
- timestamp: string;
42
- }
43
-
44
- // NEW: Enterprise Log Payload
45
- export interface SenzorLog {
46
- message: string;
47
- level: 'info' | 'warn' | 'error' | 'debug' | 'fatal';
48
- attributes: Record<string, any>;
49
- traceId?: string; // Used if context is APM
50
- runId?: string; // Used if context is Task
51
- spanId?: string;
52
- timestamp: string;
53
- }
54
-
55
- export interface Trace {
56
- traceId: string;
57
- parentTraceId?: string;
58
- parentSpanId?: string;
59
- method: string;
60
- route: string;
61
- path: string;
62
- status: number;
63
- duration: number;
64
- ip?: string;
65
- userAgent?: string;
66
- timestamp: string;
67
- spans: Span[];
68
- }
69
-
70
- export interface ResourceMetrics {
71
- memoryDeltaBytes: number; // Delta of process.memoryUsage().heapUsed
72
- cpuUserUs: number; // CPU time spent in user space (microseconds)
73
- cpuSystemUs: number; // CPU time spent in OS system calls (microseconds)
74
- }
75
-
76
- export interface TaskRun {
77
- runId: string;
78
- taskName: string;
79
- taskType: 'cron' | 'queue' | 'pipeline' | 'custom';
80
- status: 'success' | 'failed';
81
- duration: number;
82
- queueDelay?: number;
83
- attempts?: number;
84
- triggerTraceId?: string;
85
- metadata?: any;
86
- resourceMetrics?: ResourceMetrics; // Hardware cost profiling
87
- isDeadLetter?: boolean; // True if the job failed its final retry
88
- spans: Span[];
89
- timestamp: string;
90
- }
91
-
92
- // Unified Context Payload for async_hooks
93
- export interface ActiveTrace {
94
- id: string; // The APM traceId OR the Task runId
95
- contextType: 'apm' | 'task';
96
- startTime: number;
97
- rootSpanId?: string;
98
- activeSpanId?: string;
99
- startMemory?: number; // Baseline heap
100
- startCpu?: NodeJS.CpuUsage; // Baseline CPU tick
101
- data: any; // Holds Partial<Trace> or Partial<TaskRun>
102
- spans: Span[];
103
- maxSpans?: number;
104
- droppedSpans?: number;
105
- ended?: boolean;
106
- }
@@ -1,36 +0,0 @@
1
- import { client } from './core/client';
2
- import { expressMiddleware, expressErrorHandler } from './middleware/express';
3
- import { wrapH3 } from './wrappers/h3';
4
- import { wrapNextRoute, wrapNextPages } from './wrappers/next';
5
- import { senzorPlugin } from './wrappers/fastify';
6
- import { SenzorOptions } from './core/types';
7
-
8
- const Senzor = {
9
- preload: (options: Partial<SenzorOptions> = {}) => client.preload(options),
10
- init: (options: SenzorOptions) => client.init(options),
11
- flush: () => client.flush(),
12
- track: client.track.bind(client),
13
- startSpan: client.startSpan.bind(client),
14
- captureException: client.captureError.bind(client),
15
-
16
- // Task Monitoring (NEW)
17
- wrapTask: client.wrapTask.bind(client),
18
- startTask: client.startTask.bind(client),
19
-
20
- // Express
21
- requestHandler: expressMiddleware,
22
- errorHandler: expressErrorHandler,
23
-
24
- // Next
25
- wrapNextRoute,
26
- wrapNextPages,
27
-
28
- // H3
29
- wrapH3,
30
-
31
- // Fastify
32
- fastifyPlugin: senzorPlugin
33
- };
34
-
35
- export default Senzor;
36
- export { Senzor };