@senzops/apm-node 1.2.2 → 1.2.4

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 (57) 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/core/client.ts +172 -167
  13. package/src/core/context.ts +2 -2
  14. package/src/core/types.ts +48 -43
  15. package/src/instrumentation/express.ts +12 -2
  16. package/src/instrumentation/http.ts +1 -1
  17. package/.claude/worktrees/infallible-chatelet-f3fb36/.claude/settings.local.json +0 -9
  18. package/.claude/worktrees/infallible-chatelet-f3fb36/CHANGELOG.md +0 -49
  19. package/.claude/worktrees/infallible-chatelet-f3fb36/README.md +0 -398
  20. package/.claude/worktrees/infallible-chatelet-f3fb36/package-lock.json +0 -1494
  21. package/.claude/worktrees/infallible-chatelet-f3fb36/package.json +0 -42
  22. package/.claude/worktrees/infallible-chatelet-f3fb36/src/core/client.ts +0 -451
  23. package/.claude/worktrees/infallible-chatelet-f3fb36/src/core/context.ts +0 -48
  24. package/.claude/worktrees/infallible-chatelet-f3fb36/src/core/normalizer.ts +0 -44
  25. package/.claude/worktrees/infallible-chatelet-f3fb36/src/core/sanitizer.ts +0 -203
  26. package/.claude/worktrees/infallible-chatelet-f3fb36/src/core/transport.ts +0 -273
  27. package/.claude/worktrees/infallible-chatelet-f3fb36/src/core/types.ts +0 -106
  28. package/.claude/worktrees/infallible-chatelet-f3fb36/src/index.ts +0 -36
  29. package/.claude/worktrees/infallible-chatelet-f3fb36/src/instrumentation/bullmq.ts +0 -195
  30. package/.claude/worktrees/infallible-chatelet-f3fb36/src/instrumentation/cron.ts +0 -204
  31. package/.claude/worktrees/infallible-chatelet-f3fb36/src/instrumentation/express.ts +0 -338
  32. package/.claude/worktrees/infallible-chatelet-f3fb36/src/instrumentation/fastify.ts +0 -296
  33. package/.claude/worktrees/infallible-chatelet-f3fb36/src/instrumentation/framework.ts +0 -301
  34. package/.claude/worktrees/infallible-chatelet-f3fb36/src/instrumentation/hook.ts +0 -134
  35. package/.claude/worktrees/infallible-chatelet-f3fb36/src/instrumentation/http.ts +0 -530
  36. package/.claude/worktrees/infallible-chatelet-f3fb36/src/instrumentation/koa.ts +0 -173
  37. package/.claude/worktrees/infallible-chatelet-f3fb36/src/instrumentation/mongo.ts +0 -202
  38. package/.claude/worktrees/infallible-chatelet-f3fb36/src/instrumentation/mongoose.ts +0 -156
  39. package/.claude/worktrees/infallible-chatelet-f3fb36/src/instrumentation/mysql.ts +0 -169
  40. package/.claude/worktrees/infallible-chatelet-f3fb36/src/instrumentation/patch.ts +0 -56
  41. package/.claude/worktrees/infallible-chatelet-f3fb36/src/instrumentation/pg.ts +0 -131
  42. package/.claude/worktrees/infallible-chatelet-f3fb36/src/instrumentation/redis.ts +0 -109
  43. package/.claude/worktrees/infallible-chatelet-f3fb36/src/instrumentation/span.ts +0 -73
  44. package/.claude/worktrees/infallible-chatelet-f3fb36/src/instrumentation/undici.ts +0 -189
  45. package/.claude/worktrees/infallible-chatelet-f3fb36/src/middleware/express.ts +0 -48
  46. package/.claude/worktrees/infallible-chatelet-f3fb36/src/register.ts +0 -58
  47. package/.claude/worktrees/infallible-chatelet-f3fb36/src/utils/getClientIp.ts +0 -175
  48. package/.claude/worktrees/infallible-chatelet-f3fb36/src/utils/ids.ts +0 -7
  49. package/.claude/worktrees/infallible-chatelet-f3fb36/src/utils/internal.ts +0 -1
  50. package/.claude/worktrees/infallible-chatelet-f3fb36/src/utils/sdkMeta.ts +0 -6
  51. package/.claude/worktrees/infallible-chatelet-f3fb36/src/utils/traceContext.ts +0 -44
  52. package/.claude/worktrees/infallible-chatelet-f3fb36/src/wrappers/fastify.ts +0 -35
  53. package/.claude/worktrees/infallible-chatelet-f3fb36/src/wrappers/h3.ts +0 -59
  54. package/.claude/worktrees/infallible-chatelet-f3fb36/src/wrappers/next.ts +0 -131
  55. package/.claude/worktrees/infallible-chatelet-f3fb36/tsconfig.json +0 -15
  56. package/.claude/worktrees/infallible-chatelet-f3fb36/tsup.config.ts +0 -21
  57. package/.claude/worktrees/infallible-chatelet-f3fb36/wiki.md +0 -852
@@ -1,56 +0,0 @@
1
- const PATCHES = Symbol.for('senzor.patch.keys');
2
- const ORIGINAL = Symbol.for('senzor.patch.original');
3
-
4
- type WrappedFunction = Function & {
5
- [PATCHES]?: Set<string>;
6
- [ORIGINAL]?: Function;
7
- };
8
-
9
- export const patchMethod = (
10
- target: any,
11
- methodName: string,
12
- patchKey: string,
13
- wrapper: (original: Function) => Function
14
- ): boolean => {
15
- if (!target) return false;
16
-
17
- const current = target[methodName] as WrappedFunction | undefined;
18
- if (typeof current !== 'function') return false;
19
-
20
- const existingPatches = current[PATCHES];
21
- if (existingPatches?.has(patchKey)) return false;
22
-
23
- const original = current[ORIGINAL] || current;
24
- const wrapped = wrapper(current) as WrappedFunction;
25
- const patches = new Set(existingPatches || []);
26
- patches.add(patchKey);
27
-
28
- try {
29
- Object.defineProperty(wrapped, PATCHES, {
30
- value: patches,
31
- enumerable: false
32
- });
33
- Object.defineProperty(wrapped, ORIGINAL, {
34
- value: original,
35
- enumerable: false
36
- });
37
- } catch {
38
- return false;
39
- }
40
-
41
- try {
42
- target[methodName] = wrapped;
43
- return true;
44
- } catch {
45
- return false;
46
- }
47
- };
48
-
49
- export const isPatched = (
50
- target: any,
51
- methodName: string,
52
- patchKey: string
53
- ): boolean => {
54
- const current = target?.[methodName] as WrappedFunction | undefined;
55
- return Boolean(current?.[PATCHES]?.has(patchKey));
56
- };
@@ -1,131 +0,0 @@
1
- import { getSqlOperation, normalizeSql } from '../core/sanitizer';
2
- import { SenzorOptions } from '../core/types';
3
- import { hookRequire } from './hook';
4
- import { patchMethod } from './patch';
5
- import { runWithCapturedSpan, startCapturedSpan } from './span';
6
-
7
- const extractSql = (args: any[]): string | undefined => {
8
- const first = args[0];
9
- if (typeof first === 'string') return first;
10
- if (first && typeof first.text === 'string') return first.text;
11
- return undefined;
12
- };
13
-
14
- const wrapQueryMethod = (
15
- proto: any,
16
- label: string,
17
- options?: SenzorOptions
18
- ) => {
19
- patchMethod(
20
- proto,
21
- 'query',
22
- `senzor.pg.${label}.query`,
23
- (original) =>
24
- function patchedPgQuery(this: any, ...args: any[]) {
25
- const sql = extractSql(args);
26
- const operation = getSqlOperation(sql) || 'QUERY';
27
- const span = startCapturedSpan(
28
- `Postgres ${operation}`,
29
- 'db',
30
- {
31
- query: normalizeSql(sql, options),
32
- operation,
33
- 'db.system.name': 'postgresql',
34
- 'db.operation.name': operation,
35
- 'db.query.text': normalizeSql(sql, options),
36
- library: 'pg'
37
- },
38
- options
39
- );
40
-
41
- if (!span) return original.apply(this, args);
42
-
43
- const callbackIndex = args.findIndex(
44
- (arg) => typeof arg === 'function'
45
- );
46
-
47
- if (callbackIndex >= 0) {
48
- const originalCallback = args[callbackIndex];
49
- args[callbackIndex] = function wrappedPgCallback(
50
- this: unknown,
51
- err: Error | null,
52
- result: any
53
- ) {
54
- span.end(err ? 500 : 0, {
55
- error: err?.message,
56
- 'error.type': err?.name,
57
- rowCount: result?.rowCount,
58
- 'db.response.row_count': result?.rowCount
59
- });
60
-
61
- return originalCallback.apply(this, arguments as any);
62
- };
63
- }
64
-
65
- return runWithCapturedSpan(span, () => {
66
- try {
67
- const result = original.apply(this, args);
68
-
69
- if (result && typeof result.then === 'function') {
70
- return result.then(
71
- (value: any) => {
72
- span.end(0, {
73
- rowCount: value?.rowCount,
74
- 'db.response.row_count': value?.rowCount
75
- });
76
- return value;
77
- },
78
- (error: any) => {
79
- span.end(500, {
80
- error: error?.message,
81
- 'error.type': error?.name || 'Error'
82
- });
83
- throw error;
84
- }
85
- );
86
- }
87
-
88
- if (
89
- callbackIndex < 0 &&
90
- result &&
91
- typeof result.once === 'function'
92
- ) {
93
- result.once('end', () => span.end(0));
94
- result.once('error', (error: Error) =>
95
- span.end(500, {
96
- error: error.message,
97
- 'error.type': error.name
98
- })
99
- );
100
- } else if (callbackIndex < 0) {
101
- span.end(0);
102
- }
103
-
104
- return result;
105
- } catch (error: any) {
106
- span.end(500, {
107
- error: error?.message,
108
- 'error.type': error?.name || 'Error'
109
- });
110
- throw error;
111
- }
112
- });
113
- }
114
- );
115
- };
116
-
117
- const patchPg = (pg: any, options?: SenzorOptions) => {
118
- if (!pg) return;
119
-
120
- wrapQueryMethod(pg.Client?.prototype, 'client', options);
121
- wrapQueryMethod(pg.Pool?.prototype, 'pool', options);
122
-
123
- if (pg.default) {
124
- wrapQueryMethod(pg.default.Client?.prototype, 'default.client', options);
125
- wrapQueryMethod(pg.default.Pool?.prototype, 'default.pool', options);
126
- }
127
- };
128
-
129
- export const instrumentPg = (options?: SenzorOptions) => {
130
- hookRequire('pg', (exports: any) => patchPg(exports, options));
131
- };
@@ -1,109 +0,0 @@
1
- import { SenzorOptions } from '../core/types';
2
- import { hookRequire } from './hook';
3
- import { patchMethod } from './patch';
4
- import { runWithCapturedSpan, startCapturedSpan } from './span';
5
-
6
- const getCommandName = (command: any): string => {
7
- if (typeof command === 'string') return command.toUpperCase();
8
- if (Array.isArray(command)) return String(command[0] || 'COMMAND').toUpperCase();
9
- if (command?.name) return String(command.name).toUpperCase();
10
- if (Array.isArray(command?.args)) return String(command.args[0] || 'COMMAND').toUpperCase();
11
- return 'COMMAND';
12
- };
13
-
14
- const patchSendCommand = (
15
- target: any,
16
- label: string,
17
- options?: SenzorOptions
18
- ) => {
19
- patchMethod(
20
- target,
21
- 'sendCommand',
22
- `senzor.redis.${label}.sendCommand`,
23
- (original) =>
24
- function patchedRedisSendCommand(this: any, command: any, ...args: any[]) {
25
- const commandName = getCommandName(command);
26
- const span = startCapturedSpan(
27
- `Redis ${commandName}`,
28
- 'db',
29
- {
30
- command: commandName,
31
- operation: commandName,
32
- 'db.system.name': label === 'ioredis' ? 'redis' : 'redis',
33
- 'db.operation.name': commandName,
34
- library: label
35
- },
36
- options
37
- );
38
-
39
- if (!span) return original.apply(this, arguments as any);
40
-
41
- return runWithCapturedSpan(span, () => {
42
- try {
43
- const result = original.call(this, command, ...args);
44
- if (result && typeof result.then === 'function') {
45
- return result.then(
46
- (value: any) => {
47
- span.end(0);
48
- return value;
49
- },
50
- (error: any) => {
51
- span.end(500, {
52
- error: error?.message,
53
- 'error.type': error?.name || 'Error'
54
- });
55
- throw error;
56
- }
57
- );
58
- }
59
-
60
- span.end(0);
61
- return result;
62
- } catch (error: any) {
63
- span.end(500, {
64
- error: error?.message,
65
- 'error.type': error?.name || 'Error'
66
- });
67
- throw error;
68
- }
69
- });
70
- }
71
- );
72
- };
73
-
74
- const patchCreatedClient = (
75
- client: any,
76
- label: string,
77
- options?: SenzorOptions
78
- ) => {
79
- patchSendCommand(client, label, options);
80
- patchSendCommand(Object.getPrototypeOf(client), label, options);
81
- return client;
82
- };
83
-
84
- const patchRedisPackage = (redis: any, options?: SenzorOptions) => {
85
- ['createClient', 'createCluster'].forEach((factory) => {
86
- patchMethod(
87
- redis,
88
- factory,
89
- `senzor.redis.${factory}`,
90
- (original) =>
91
- function patchedRedisFactory(this: any, ...args: any[]) {
92
- const client = original.apply(this, args);
93
- return patchCreatedClient(client, 'redis', options);
94
- }
95
- );
96
- });
97
- };
98
-
99
- const patchIORedisPackage = (ioredis: any, options?: SenzorOptions) => {
100
- patchSendCommand(ioredis?.prototype, 'ioredis', options);
101
- patchSendCommand(ioredis?.Redis?.prototype, 'ioredis', options);
102
- patchSendCommand(ioredis?.Cluster?.prototype, 'ioredis-cluster', options);
103
- patchSendCommand(ioredis?.default?.prototype, 'ioredis', options);
104
- };
105
-
106
- export const instrumentRedis = (options?: SenzorOptions) => {
107
- hookRequire('redis', (exports: any) => patchRedisPackage(exports, options));
108
- hookRequire('ioredis', (exports: any) => patchIORedisPackage(exports, options));
109
- };
@@ -1,73 +0,0 @@
1
- import { Context } from '../core/context';
2
- import { sanitizeAttributes } from '../core/sanitizer';
3
- import { ActiveTrace, SenzorOptions, Span } from '../core/types';
4
- import { generateSpanId } from '../utils/ids';
5
-
6
- type SpanType = Span['type'];
7
-
8
- export interface CapturedSpan {
9
- spanId: string;
10
- parentSpanId?: string;
11
- trace?: ActiveTrace;
12
- end: (
13
- status?: number,
14
- meta?: Record<string, unknown>
15
- ) => void;
16
- }
17
-
18
- export const startCapturedSpan = (
19
- name: string,
20
- type: SpanType,
21
- meta: Record<string, unknown> = {},
22
- options?: SenzorOptions
23
- ): CapturedSpan | null => {
24
- const trace = Context.current();
25
- if (!trace) return null;
26
-
27
- const spanId = generateSpanId();
28
- const parentSpanId = trace.activeSpanId;
29
- const startTime = performance.now() - trace.startTime;
30
- const startedAt = performance.now();
31
- let ended = false;
32
-
33
- return {
34
- spanId,
35
- parentSpanId,
36
- trace,
37
- end: (
38
- status?: number,
39
- extraMeta: Record<string, unknown> = {}
40
- ) => {
41
- if (ended) return;
42
- ended = true;
43
-
44
- const mergedMeta = sanitizeAttributes(
45
- {
46
- ...meta,
47
- ...extraMeta,
48
- parentSpanId
49
- },
50
- options
51
- );
52
-
53
- Context.addSpanToTrace(trace, {
54
- spanId,
55
- parentSpanId,
56
- name,
57
- type,
58
- startTime,
59
- duration: performance.now() - startedAt,
60
- status,
61
- meta: mergedMeta
62
- });
63
- }
64
- };
65
- };
66
-
67
- export const runWithCapturedSpan = <T>(
68
- span: CapturedSpan | null,
69
- fn: () => T
70
- ): T => {
71
- if (!span) return fn();
72
- return Context.withActiveSpan(span.spanId, fn);
73
- };
@@ -1,189 +0,0 @@
1
- import { normalizePath } from '../core/normalizer';
2
- import { SenzorOptions } from '../core/types';
3
- import { SENZOR_INTERNAL_HEADER } from '../utils/internal';
4
- import { generateTraceparent } from '../utils/traceContext';
5
- import { hookRequire } from './hook';
6
- import { patchMethod } from './patch';
7
- import { runWithCapturedSpan, startCapturedSpan } from './span';
8
-
9
- const hasInternalHeader = (headers: any): boolean => {
10
- if (!headers) return false;
11
- if (Array.isArray(headers)) {
12
- return headers.some(
13
- ([key, value]) =>
14
- String(key).toLowerCase() === SENZOR_INTERNAL_HEADER &&
15
- String(value).toLowerCase() === 'true'
16
- );
17
- }
18
-
19
- return Object.entries(headers).some(
20
- ([key, value]) =>
21
- key.toLowerCase() === SENZOR_INTERNAL_HEADER &&
22
- String(value).toLowerCase() === 'true'
23
- );
24
- };
25
-
26
- const setHeader = (headers: any, key: string, value: string) => {
27
- if (Array.isArray(headers)) {
28
- headers.push([key, value]);
29
- return headers;
30
- }
31
-
32
- const nextHeaders = { ...(headers || {}) };
33
- const existingKey = Object.keys(nextHeaders).find(
34
- (header) => header.toLowerCase() === key.toLowerCase()
35
- );
36
- nextHeaders[existingKey || key] = value;
37
- return nextHeaders;
38
- };
39
-
40
- const getUrlDetails = (input: any) => {
41
- try {
42
- const url = new URL(String(input));
43
- return {
44
- url: url.toString(),
45
- hostname: url.hostname,
46
- path: `${url.pathname}${url.search}`
47
- };
48
- } catch {
49
- return {
50
- url: String(input || ''),
51
- hostname: 'unknown',
52
- path: '/'
53
- };
54
- }
55
- };
56
-
57
- const patchRequestLike = (
58
- target: any,
59
- methodName: string,
60
- patchKey: string,
61
- options?: SenzorOptions
62
- ) => {
63
- patchMethod(
64
- target,
65
- methodName,
66
- patchKey,
67
- (original) =>
68
- function patchedUndiciRequest(this: any, input: any, opts?: any, cb?: any) {
69
- if (hasInternalHeader(opts?.headers)) {
70
- return original.apply(this, arguments as any);
71
- }
72
-
73
- const details = getUrlDetails(input?.origin ? input.origin : input);
74
- const method = String(opts?.method || 'GET').toUpperCase();
75
- const span = startCapturedSpan(
76
- `${method} ${details.hostname}`,
77
- 'http',
78
- {
79
- url: details.url,
80
- method,
81
- route: normalizePath(details.path),
82
- library: 'undici',
83
- 'http.request.method': method,
84
- 'url.full': details.url,
85
- 'url.path': details.path,
86
- 'server.address': details.hostname
87
- },
88
- options
89
- );
90
-
91
- if (!span) return original.apply(this, arguments as any);
92
-
93
- const nextOptions = { ...(opts || {}) };
94
- nextOptions.headers = setHeader(
95
- nextOptions.headers,
96
- 'traceparent',
97
- generateTraceparent(span.trace!.id, span.spanId)
98
- );
99
- nextOptions.headers = setHeader(
100
- nextOptions.headers,
101
- 'x-senzor-trace-id',
102
- span.trace!.id
103
- );
104
- nextOptions.headers = setHeader(
105
- nextOptions.headers,
106
- 'x-senzor-parent-span-id',
107
- span.spanId
108
- );
109
-
110
- const wrappedCallback =
111
- typeof cb === 'function'
112
- ? function wrappedUndiciCallback(this: unknown, err: any, data: any) {
113
- span.end(err ? 500 : data?.statusCode || 0, {
114
- error: err?.message,
115
- 'error.type': err?.name,
116
- 'http.response.status_code': data?.statusCode
117
- });
118
- return cb.apply(this, arguments as any);
119
- }
120
- : cb;
121
-
122
- return runWithCapturedSpan(span, () => {
123
- try {
124
- const result = original.call(
125
- this,
126
- input,
127
- nextOptions,
128
- wrappedCallback
129
- );
130
-
131
- if (result && typeof result.then === 'function') {
132
- return result.then(
133
- (value: any) => {
134
- span.end(value?.statusCode || value?.status || 0, {
135
- 'http.response.status_code':
136
- value?.statusCode || value?.status
137
- });
138
- return value;
139
- },
140
- (error: any) => {
141
- span.end(500, {
142
- error: error?.message,
143
- 'error.type': error?.name || 'Error'
144
- });
145
- throw error;
146
- }
147
- );
148
- }
149
-
150
- if (typeof wrappedCallback !== 'function') {
151
- span.end(0);
152
- }
153
-
154
- return result;
155
- } catch (error: any) {
156
- span.end(500, {
157
- error: error?.message,
158
- 'error.type': error?.name || 'Error'
159
- });
160
- throw error;
161
- }
162
- });
163
- }
164
- );
165
- };
166
-
167
- const patchUndici = (undici: any, options?: SenzorOptions) => {
168
- patchRequestLike(undici, 'request', 'senzor.undici.request', options);
169
- patchRequestLike(undici, 'stream', 'senzor.undici.stream', options);
170
- patchRequestLike(undici, 'pipeline', 'senzor.undici.pipeline', options);
171
-
172
- [
173
- undici?.Client?.prototype,
174
- undici?.Pool?.prototype,
175
- undici?.Agent?.prototype,
176
- undici?.ProxyAgent?.prototype
177
- ].forEach((proto, index) => {
178
- patchRequestLike(
179
- proto,
180
- 'request',
181
- `senzor.undici.dispatcher.${index}.request`,
182
- options
183
- );
184
- });
185
- };
186
-
187
- export const instrumentUndici = (options?: SenzorOptions) => {
188
- hookRequire('undici', (exports: any) => patchUndici(exports, options));
189
- };
@@ -1,48 +0,0 @@
1
- import { client } from '../core/client';
2
- import { getClientIp } from '../utils/getClientIp';
3
-
4
- // 1. Request Handler (Place before routes)
5
- export const expressMiddleware = () => {
6
- return (req: any, res: any, next: () => void) => {
7
- client.startTrace({
8
- method: req.method,
9
- path: req.originalUrl || req.url,
10
- ip: getClientIp(req),
11
- userAgent: req.headers['user-agent'],
12
- headers: req.headers
13
- }, () => {
14
-
15
- // Auto-detect status code on finish
16
- res.once('finish', () => {
17
- try {
18
- let route = 'UNKNOWN';
19
- // Express populates req.route only if a route matched
20
- if (req.route && req.route.path) {
21
- route = (req.baseUrl || '') + req.route.path;
22
- } else if (res.statusCode === 404) {
23
- route = 'Not Found';
24
- } else {
25
- route = req.path || 'Wildcard';
26
- }
27
-
28
- client.endTrace(res.statusCode, { route });
29
- } catch (e) { /* Fail open */ }
30
- });
31
-
32
- next();
33
- });
34
- };
35
- };
36
-
37
- // 2. Error Handler (Place after routes)
38
- // This is required in Express to capture the actual Error Object (Stack Trace)
39
- export const expressErrorHandler = () => {
40
- return (err: any, req: any, res: any, next: (err?: any) => void) => {
41
-
42
- // 1. Capture the exception context
43
- client.captureError(err);
44
-
45
- // 2. Pass it to the next error handler (don't swallow it)
46
- next(err);
47
- };
48
- };
@@ -1,58 +0,0 @@
1
- import { client } from './core/client';
2
-
3
- const truthy = (value: string | undefined): boolean =>
4
- value === '1' || value === 'true' || value === 'yes';
5
-
6
- const numberFromEnv = (value: string | undefined): number | undefined => {
7
- if (!value) return undefined;
8
- const parsed = Number(value);
9
- return Number.isFinite(parsed) && parsed > 0 ? parsed : undefined;
10
- };
11
-
12
- const apiKey =
13
- process.env.SENZOR_API_KEY ||
14
- process.env.SENZOR_APM_API_KEY ||
15
- process.env.SENZOR_SERVICE_API_KEY;
16
-
17
- const endpoint =
18
- process.env.SENZOR_ENDPOINT ||
19
- process.env.SENZOR_APM_ENDPOINT;
20
-
21
- const options = {
22
- apiKey: apiKey || '',
23
- endpoint,
24
- debug: truthy(process.env.SENZOR_DEBUG),
25
- autoLogs: process.env.SENZOR_AUTO_LOGS === 'false' ? false : undefined,
26
- batchSize: numberFromEnv(process.env.SENZOR_BATCH_SIZE),
27
- flushInterval: numberFromEnv(process.env.SENZOR_FLUSH_INTERVAL),
28
- flushTimeoutMs: numberFromEnv(process.env.SENZOR_FLUSH_TIMEOUT_MS),
29
- maxQueueSize: numberFromEnv(process.env.SENZOR_MAX_QUEUE_SIZE),
30
- maxSpansPerTrace: numberFromEnv(process.env.SENZOR_MAX_SPANS_PER_TRACE),
31
- captureHeaders: truthy(process.env.SENZOR_CAPTURE_HEADERS),
32
- captureDbStatement:
33
- process.env.SENZOR_CAPTURE_DB_STATEMENT === 'false'
34
- ? false
35
- : undefined,
36
- frameworkSpans:
37
- process.env.SENZOR_FRAMEWORK_SPANS === 'false'
38
- ? false
39
- : undefined,
40
- captureMiddlewareSpans:
41
- process.env.SENZOR_CAPTURE_MIDDLEWARE_SPANS === 'false'
42
- ? false
43
- : undefined,
44
- captureRouterSpans:
45
- process.env.SENZOR_CAPTURE_ROUTER_SPANS === 'false'
46
- ? false
47
- : undefined,
48
- captureLifecycleHookSpans:
49
- process.env.SENZOR_CAPTURE_LIFECYCLE_HOOK_SPANS === 'false'
50
- ? false
51
- : undefined
52
- };
53
-
54
- if (apiKey) {
55
- client.init(options);
56
- } else {
57
- client.preload(options);
58
- }