@loggerjs/node 0.5.0 → 0.5.2

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 (102) hide show
  1. package/README.md +5 -1
  2. package/dist/bullmq-integration.cjs +169 -0
  3. package/dist/bullmq-integration.cjs.map +1 -0
  4. package/dist/bullmq-integration.js +168 -0
  5. package/dist/bullmq-integration.js.map +1 -0
  6. package/dist/cli-integration.cjs +116 -0
  7. package/dist/cli-integration.cjs.map +1 -0
  8. package/dist/cli-integration.js +115 -0
  9. package/dist/cli-integration.js.map +1 -0
  10. package/dist/context.cjs +37 -0
  11. package/dist/context.cjs.map +1 -0
  12. package/dist/context.js +35 -0
  13. package/dist/context.js.map +1 -0
  14. package/dist/database-integration.cjs +128 -0
  15. package/dist/database-integration.cjs.map +1 -0
  16. package/dist/database-integration.js +127 -0
  17. package/dist/database-integration.js.map +1 -0
  18. package/dist/diagnostics-channel-integration.cjs +66 -0
  19. package/dist/diagnostics-channel-integration.cjs.map +1 -0
  20. package/dist/diagnostics-channel-integration.js +65 -0
  21. package/dist/diagnostics-channel-integration.js.map +1 -0
  22. package/dist/express-integration.cjs +130 -0
  23. package/dist/express-integration.cjs.map +1 -0
  24. package/dist/express-integration.js +129 -0
  25. package/dist/express-integration.js.map +1 -0
  26. package/dist/fastify-integration.cjs +120 -0
  27. package/dist/fastify-integration.cjs.map +1 -0
  28. package/dist/fastify-integration.js +119 -0
  29. package/dist/fastify-integration.js.map +1 -0
  30. package/dist/file-transport.cjs +260 -0
  31. package/dist/file-transport.cjs.map +1 -0
  32. package/dist/file-transport.js +259 -0
  33. package/dist/file-transport.js.map +1 -0
  34. package/dist/hapi-integration.cjs +61 -0
  35. package/dist/hapi-integration.cjs.map +1 -0
  36. package/dist/hapi-integration.js +60 -0
  37. package/dist/hapi-integration.js.map +1 -0
  38. package/dist/http-transport.cjs +55 -0
  39. package/dist/http-transport.cjs.map +1 -0
  40. package/dist/http-transport.js +54 -0
  41. package/dist/http-transport.js.map +1 -0
  42. package/dist/koa-integration.cjs +57 -0
  43. package/dist/koa-integration.cjs.map +1 -0
  44. package/dist/koa-integration.js +56 -0
  45. package/dist/koa-integration.js.map +1 -0
  46. package/dist/logger-diagnostics.cjs +46 -0
  47. package/dist/logger-diagnostics.cjs.map +1 -0
  48. package/dist/logger-diagnostics.js +45 -0
  49. package/dist/logger-diagnostics.js.map +1 -0
  50. package/dist/nest-integration.cjs +138 -0
  51. package/dist/nest-integration.cjs.map +1 -0
  52. package/dist/nest-integration.js +137 -0
  53. package/dist/nest-integration.js.map +1 -0
  54. package/dist/node-fetch-integration.cjs +113 -0
  55. package/dist/node-fetch-integration.cjs.map +1 -0
  56. package/dist/node-fetch-integration.js +112 -0
  57. package/dist/node-fetch-integration.js.map +1 -0
  58. package/dist/node-http-client-integration.cjs +192 -0
  59. package/dist/node-http-client-integration.cjs.map +1 -0
  60. package/dist/node-http-client-integration.js +192 -0
  61. package/dist/node-http-client-integration.js.map +1 -0
  62. package/dist/payload-transforms.cjs +29 -0
  63. package/dist/payload-transforms.cjs.map +1 -0
  64. package/dist/payload-transforms.js +28 -0
  65. package/dist/payload-transforms.js.map +1 -0
  66. package/dist/prisma-integration.cjs +150 -0
  67. package/dist/prisma-integration.cjs.map +1 -0
  68. package/dist/prisma-integration.js +149 -0
  69. package/dist/prisma-integration.js.map +1 -0
  70. package/dist/process-integration.cjs +134 -0
  71. package/dist/process-integration.cjs.map +1 -0
  72. package/dist/process-integration.js +133 -0
  73. package/dist/process-integration.js.map +1 -0
  74. package/dist/queue-integration.cjs +148 -0
  75. package/dist/queue-integration.cjs.map +1 -0
  76. package/dist/queue-integration.js +147 -0
  77. package/dist/queue-integration.js.map +1 -0
  78. package/dist/redis-integration.cjs +154 -0
  79. package/dist/redis-integration.cjs.map +1 -0
  80. package/dist/redis-integration.js +153 -0
  81. package/dist/redis-integration.js.map +1 -0
  82. package/dist/rotating-file-transport.cjs +318 -0
  83. package/dist/rotating-file-transport.cjs.map +1 -0
  84. package/dist/rotating-file-transport.js +317 -0
  85. package/dist/rotating-file-transport.js.map +1 -0
  86. package/dist/serverless-integration.cjs +104 -0
  87. package/dist/serverless-integration.cjs.map +1 -0
  88. package/dist/serverless-integration.js +103 -0
  89. package/dist/serverless-integration.js.map +1 -0
  90. package/dist/stdout-transport.cjs +197 -0
  91. package/dist/stdout-transport.cjs.map +1 -0
  92. package/dist/stdout-transport.js +195 -0
  93. package/dist/stdout-transport.js.map +1 -0
  94. package/dist/syslog-transport.cjs +135 -0
  95. package/dist/syslog-transport.cjs.map +1 -0
  96. package/dist/syslog-transport.js +133 -0
  97. package/dist/syslog-transport.js.map +1 -0
  98. package/dist/worker-transport.cjs +285 -0
  99. package/dist/worker-transport.cjs.map +1 -0
  100. package/dist/worker-transport.js +284 -0
  101. package/dist/worker-transport.js.map +1 -0
  102. package/package.json +104 -77
@@ -0,0 +1,134 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ let _loggerjs_core = require("@loggerjs/core");
3
+ //#region src/process-integration.ts
4
+ const signalExitCodes = {
5
+ SIGINT: 130,
6
+ SIGTERM: 143
7
+ };
8
+ function captureProcessIntegration(options = {}) {
9
+ const uncaughtException = options.uncaughtException ?? true;
10
+ const unhandledRejection = options.unhandledRejection ?? true;
11
+ const warning = options.warning ?? true;
12
+ const beforeExitFlush = options.beforeExitFlush ?? true;
13
+ const exitFlush = options.exitFlush ?? true;
14
+ const signalFlush = options.signalFlush ?? true;
15
+ const signals = options.signals ?? ["SIGTERM"];
16
+ const exitOnSignal = options.exitOnSignal ?? true;
17
+ const exitOnUncaught = options.exitOnUncaught ?? true;
18
+ const flushTimeoutMs = options.flushTimeoutMs ?? 250;
19
+ const exitFn = options.exitFn ?? ((code) => process.exit(code));
20
+ return {
21
+ name: "capture-process",
22
+ setup(api) {
23
+ const disposers = [];
24
+ let disposed = false;
25
+ const capture = api.guard((input) => api.capture(input));
26
+ const flushSync = () => {
27
+ try {
28
+ api.flushSync?.();
29
+ } catch {}
30
+ };
31
+ const flushBounded = async () => {
32
+ let timer;
33
+ try {
34
+ await Promise.race([api.flush(), new Promise((resolve) => {
35
+ timer = setTimeout(resolve, flushTimeoutMs);
36
+ })]);
37
+ } catch {} finally {
38
+ if (timer) clearTimeout(timer);
39
+ }
40
+ };
41
+ const flushBestEffort = () => {
42
+ flushSync();
43
+ flushBounded();
44
+ };
45
+ if (uncaughtException) {
46
+ const onUncaughtException = (error) => {
47
+ capture({
48
+ level: "fatal",
49
+ message: error.message,
50
+ error,
51
+ props: { process: { kind: "uncaughtException" } }
52
+ });
53
+ flushSync();
54
+ const flushed = flushBounded();
55
+ if (exitOnUncaught) flushed.finally(() => exitFn(1));
56
+ };
57
+ process.on("uncaughtException", onUncaughtException);
58
+ disposers.push(() => process.off("uncaughtException", onUncaughtException));
59
+ }
60
+ if (unhandledRejection) {
61
+ const onUnhandledRejection = (reason) => {
62
+ capture({
63
+ level: "error",
64
+ message: reason instanceof Error ? reason.message : "Unhandled promise rejection",
65
+ error: reason,
66
+ props: {
67
+ process: { kind: "unhandledRejection" },
68
+ reason: (0, _loggerjs_core.normalizeValue)(reason, { maxDepth: 5 })
69
+ }
70
+ });
71
+ flushBestEffort();
72
+ };
73
+ process.on("unhandledRejection", onUnhandledRejection);
74
+ disposers.push(() => process.off("unhandledRejection", onUnhandledRejection));
75
+ }
76
+ if (warning) {
77
+ const onWarning = (warn) => {
78
+ capture({
79
+ level: "warn",
80
+ message: warn.message,
81
+ error: warn,
82
+ props: { process: {
83
+ kind: "warning",
84
+ name: warn.name,
85
+ code: warn.code
86
+ } }
87
+ });
88
+ };
89
+ process.on("warning", onWarning);
90
+ disposers.push(() => process.off("warning", onWarning));
91
+ }
92
+ if (beforeExitFlush) {
93
+ const onBeforeExit = () => {
94
+ flushBounded();
95
+ };
96
+ process.on("beforeExit", onBeforeExit);
97
+ disposers.push(() => process.off("beforeExit", onBeforeExit));
98
+ }
99
+ if (exitFlush) {
100
+ const onExit = () => {
101
+ flushSync();
102
+ };
103
+ process.on("exit", onExit);
104
+ disposers.push(() => process.off("exit", onExit));
105
+ }
106
+ if (signalFlush) for (const signal of signals) {
107
+ const onSignal = () => {
108
+ capture({
109
+ level: "fatal",
110
+ message: `Process signal ${signal}`,
111
+ props: { process: {
112
+ kind: "signal",
113
+ signal
114
+ } }
115
+ });
116
+ flushSync();
117
+ const flushed = flushBounded();
118
+ if (exitOnSignal) flushed.finally(() => exitFn(signalExitCodes[signal] ?? 1));
119
+ };
120
+ process.on(signal, onSignal);
121
+ disposers.push(() => process.off(signal, onSignal));
122
+ }
123
+ return () => {
124
+ if (disposed) return;
125
+ disposed = true;
126
+ for (const dispose of disposers) dispose();
127
+ };
128
+ }
129
+ };
130
+ }
131
+ //#endregion
132
+ exports.captureProcessIntegration = captureProcessIntegration;
133
+
134
+ //# sourceMappingURL=process-integration.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"process-integration.cjs","names":[],"sources":["../src/process-integration.ts"],"sourcesContent":["import {\n normalizeValue,\n type CaptureInput,\n type Integration,\n type IntegrationSetupContext,\n} from \"@loggerjs/core\";\n\nexport type ProcessSignal = \"SIGHUP\" | \"SIGINT\" | \"SIGQUIT\" | \"SIGTERM\";\n\nexport interface CaptureProcessOptions {\n uncaughtException?: boolean;\n unhandledRejection?: boolean;\n warning?: boolean;\n beforeExitFlush?: boolean;\n exitFlush?: boolean;\n signalFlush?: boolean;\n signals?: ProcessSignal[];\n exitOnSignal?: boolean;\n exitOnUncaught?: boolean;\n flushTimeoutMs?: number;\n exitFn?: (code: number) => void;\n}\n\nconst signalExitCodes: Partial<Record<ProcessSignal, number>> = {\n SIGINT: 130,\n SIGTERM: 143,\n};\n\nexport function captureProcessIntegration(options: CaptureProcessOptions = {}): Integration {\n const uncaughtException = options.uncaughtException ?? true;\n const unhandledRejection = options.unhandledRejection ?? true;\n const warning = options.warning ?? true;\n const beforeExitFlush = options.beforeExitFlush ?? true;\n const exitFlush = options.exitFlush ?? true;\n const signalFlush = options.signalFlush ?? true;\n const signals = options.signals ?? ([\"SIGTERM\"] satisfies ProcessSignal[]);\n const exitOnSignal = options.exitOnSignal ?? true;\n const exitOnUncaught = options.exitOnUncaught ?? true;\n const flushTimeoutMs = options.flushTimeoutMs ?? 250;\n const exitFn = options.exitFn ?? ((code: number) => process.exit(code));\n\n return {\n name: \"capture-process\",\n setup(api: IntegrationSetupContext) {\n const disposers: Array<() => void> = [];\n let disposed = false;\n\n const capture = api.guard((input: CaptureInput) => api.capture(input));\n const flushSync = () => {\n try {\n api.flushSync?.();\n } catch {\n // Logger.flushSync reports transport errors; this protects custom IntegrationAPI contexts.\n }\n };\n const flushBounded = async () => {\n let timer: ReturnType<typeof setTimeout> | undefined;\n try {\n await Promise.race([\n api.flush(),\n new Promise<void>((resolve) => {\n timer = setTimeout(resolve, flushTimeoutMs);\n }),\n ]);\n } catch {\n // Process handlers must not throw back into fatal runtime paths.\n } finally {\n if (timer) clearTimeout(timer);\n }\n };\n const flushBestEffort = () => {\n flushSync();\n void flushBounded();\n };\n\n if (uncaughtException) {\n const onUncaughtException = (error: Error) => {\n capture({\n level: \"fatal\",\n message: error.message,\n error,\n props: { process: { kind: \"uncaughtException\" } },\n });\n flushSync();\n const flushed = flushBounded();\n if (exitOnUncaught) void flushed.finally(() => exitFn(1));\n };\n process.on(\"uncaughtException\", onUncaughtException);\n disposers.push(() => process.off(\"uncaughtException\", onUncaughtException));\n }\n\n if (unhandledRejection) {\n const onUnhandledRejection = (reason: unknown) => {\n capture({\n level: \"error\",\n message: reason instanceof Error ? reason.message : \"Unhandled promise rejection\",\n error: reason,\n props: {\n process: { kind: \"unhandledRejection\" },\n reason: normalizeValue(reason, { maxDepth: 5 }),\n },\n });\n flushBestEffort();\n };\n process.on(\"unhandledRejection\", onUnhandledRejection);\n disposers.push(() => process.off(\"unhandledRejection\", onUnhandledRejection));\n }\n\n if (warning) {\n const onWarning = (warn: Error) => {\n capture({\n level: \"warn\",\n message: warn.message,\n error: warn,\n props: {\n process: {\n kind: \"warning\",\n name: warn.name,\n code: (warn as Error & { code?: string }).code,\n },\n },\n });\n };\n process.on(\"warning\", onWarning);\n disposers.push(() => process.off(\"warning\", onWarning));\n }\n\n if (beforeExitFlush) {\n const onBeforeExit = () => {\n void flushBounded();\n };\n process.on(\"beforeExit\", onBeforeExit);\n disposers.push(() => process.off(\"beforeExit\", onBeforeExit));\n }\n\n if (exitFlush) {\n const onExit = () => {\n flushSync();\n };\n process.on(\"exit\", onExit);\n disposers.push(() => process.off(\"exit\", onExit));\n }\n\n if (signalFlush) {\n for (const signal of signals) {\n const onSignal = () => {\n capture({\n level: \"fatal\",\n message: `Process signal ${signal}`,\n props: { process: { kind: \"signal\", signal } },\n });\n flushSync();\n const flushed = flushBounded();\n if (exitOnSignal) {\n void flushed.finally(() => exitFn(signalExitCodes[signal] ?? 1));\n }\n };\n process.on(signal, onSignal);\n disposers.push(() => process.off(signal, onSignal));\n }\n }\n\n return () => {\n if (disposed) return;\n disposed = true;\n for (const dispose of disposers) dispose();\n };\n },\n };\n}\n"],"mappings":"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"}
@@ -0,0 +1,133 @@
1
+ import { normalizeValue } from "@loggerjs/core";
2
+ //#region src/process-integration.ts
3
+ const signalExitCodes = {
4
+ SIGINT: 130,
5
+ SIGTERM: 143
6
+ };
7
+ function captureProcessIntegration(options = {}) {
8
+ const uncaughtException = options.uncaughtException ?? true;
9
+ const unhandledRejection = options.unhandledRejection ?? true;
10
+ const warning = options.warning ?? true;
11
+ const beforeExitFlush = options.beforeExitFlush ?? true;
12
+ const exitFlush = options.exitFlush ?? true;
13
+ const signalFlush = options.signalFlush ?? true;
14
+ const signals = options.signals ?? ["SIGTERM"];
15
+ const exitOnSignal = options.exitOnSignal ?? true;
16
+ const exitOnUncaught = options.exitOnUncaught ?? true;
17
+ const flushTimeoutMs = options.flushTimeoutMs ?? 250;
18
+ const exitFn = options.exitFn ?? ((code) => process.exit(code));
19
+ return {
20
+ name: "capture-process",
21
+ setup(api) {
22
+ const disposers = [];
23
+ let disposed = false;
24
+ const capture = api.guard((input) => api.capture(input));
25
+ const flushSync = () => {
26
+ try {
27
+ api.flushSync?.();
28
+ } catch {}
29
+ };
30
+ const flushBounded = async () => {
31
+ let timer;
32
+ try {
33
+ await Promise.race([api.flush(), new Promise((resolve) => {
34
+ timer = setTimeout(resolve, flushTimeoutMs);
35
+ })]);
36
+ } catch {} finally {
37
+ if (timer) clearTimeout(timer);
38
+ }
39
+ };
40
+ const flushBestEffort = () => {
41
+ flushSync();
42
+ flushBounded();
43
+ };
44
+ if (uncaughtException) {
45
+ const onUncaughtException = (error) => {
46
+ capture({
47
+ level: "fatal",
48
+ message: error.message,
49
+ error,
50
+ props: { process: { kind: "uncaughtException" } }
51
+ });
52
+ flushSync();
53
+ const flushed = flushBounded();
54
+ if (exitOnUncaught) flushed.finally(() => exitFn(1));
55
+ };
56
+ process.on("uncaughtException", onUncaughtException);
57
+ disposers.push(() => process.off("uncaughtException", onUncaughtException));
58
+ }
59
+ if (unhandledRejection) {
60
+ const onUnhandledRejection = (reason) => {
61
+ capture({
62
+ level: "error",
63
+ message: reason instanceof Error ? reason.message : "Unhandled promise rejection",
64
+ error: reason,
65
+ props: {
66
+ process: { kind: "unhandledRejection" },
67
+ reason: normalizeValue(reason, { maxDepth: 5 })
68
+ }
69
+ });
70
+ flushBestEffort();
71
+ };
72
+ process.on("unhandledRejection", onUnhandledRejection);
73
+ disposers.push(() => process.off("unhandledRejection", onUnhandledRejection));
74
+ }
75
+ if (warning) {
76
+ const onWarning = (warn) => {
77
+ capture({
78
+ level: "warn",
79
+ message: warn.message,
80
+ error: warn,
81
+ props: { process: {
82
+ kind: "warning",
83
+ name: warn.name,
84
+ code: warn.code
85
+ } }
86
+ });
87
+ };
88
+ process.on("warning", onWarning);
89
+ disposers.push(() => process.off("warning", onWarning));
90
+ }
91
+ if (beforeExitFlush) {
92
+ const onBeforeExit = () => {
93
+ flushBounded();
94
+ };
95
+ process.on("beforeExit", onBeforeExit);
96
+ disposers.push(() => process.off("beforeExit", onBeforeExit));
97
+ }
98
+ if (exitFlush) {
99
+ const onExit = () => {
100
+ flushSync();
101
+ };
102
+ process.on("exit", onExit);
103
+ disposers.push(() => process.off("exit", onExit));
104
+ }
105
+ if (signalFlush) for (const signal of signals) {
106
+ const onSignal = () => {
107
+ capture({
108
+ level: "fatal",
109
+ message: `Process signal ${signal}`,
110
+ props: { process: {
111
+ kind: "signal",
112
+ signal
113
+ } }
114
+ });
115
+ flushSync();
116
+ const flushed = flushBounded();
117
+ if (exitOnSignal) flushed.finally(() => exitFn(signalExitCodes[signal] ?? 1));
118
+ };
119
+ process.on(signal, onSignal);
120
+ disposers.push(() => process.off(signal, onSignal));
121
+ }
122
+ return () => {
123
+ if (disposed) return;
124
+ disposed = true;
125
+ for (const dispose of disposers) dispose();
126
+ };
127
+ }
128
+ };
129
+ }
130
+ //#endregion
131
+ export { captureProcessIntegration };
132
+
133
+ //# sourceMappingURL=process-integration.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"process-integration.js","names":[],"sources":["../src/process-integration.ts"],"sourcesContent":["import {\n normalizeValue,\n type CaptureInput,\n type Integration,\n type IntegrationSetupContext,\n} from \"@loggerjs/core\";\n\nexport type ProcessSignal = \"SIGHUP\" | \"SIGINT\" | \"SIGQUIT\" | \"SIGTERM\";\n\nexport interface CaptureProcessOptions {\n uncaughtException?: boolean;\n unhandledRejection?: boolean;\n warning?: boolean;\n beforeExitFlush?: boolean;\n exitFlush?: boolean;\n signalFlush?: boolean;\n signals?: ProcessSignal[];\n exitOnSignal?: boolean;\n exitOnUncaught?: boolean;\n flushTimeoutMs?: number;\n exitFn?: (code: number) => void;\n}\n\nconst signalExitCodes: Partial<Record<ProcessSignal, number>> = {\n SIGINT: 130,\n SIGTERM: 143,\n};\n\nexport function captureProcessIntegration(options: CaptureProcessOptions = {}): Integration {\n const uncaughtException = options.uncaughtException ?? true;\n const unhandledRejection = options.unhandledRejection ?? true;\n const warning = options.warning ?? true;\n const beforeExitFlush = options.beforeExitFlush ?? true;\n const exitFlush = options.exitFlush ?? true;\n const signalFlush = options.signalFlush ?? true;\n const signals = options.signals ?? ([\"SIGTERM\"] satisfies ProcessSignal[]);\n const exitOnSignal = options.exitOnSignal ?? true;\n const exitOnUncaught = options.exitOnUncaught ?? true;\n const flushTimeoutMs = options.flushTimeoutMs ?? 250;\n const exitFn = options.exitFn ?? ((code: number) => process.exit(code));\n\n return {\n name: \"capture-process\",\n setup(api: IntegrationSetupContext) {\n const disposers: Array<() => void> = [];\n let disposed = false;\n\n const capture = api.guard((input: CaptureInput) => api.capture(input));\n const flushSync = () => {\n try {\n api.flushSync?.();\n } catch {\n // Logger.flushSync reports transport errors; this protects custom IntegrationAPI contexts.\n }\n };\n const flushBounded = async () => {\n let timer: ReturnType<typeof setTimeout> | undefined;\n try {\n await Promise.race([\n api.flush(),\n new Promise<void>((resolve) => {\n timer = setTimeout(resolve, flushTimeoutMs);\n }),\n ]);\n } catch {\n // Process handlers must not throw back into fatal runtime paths.\n } finally {\n if (timer) clearTimeout(timer);\n }\n };\n const flushBestEffort = () => {\n flushSync();\n void flushBounded();\n };\n\n if (uncaughtException) {\n const onUncaughtException = (error: Error) => {\n capture({\n level: \"fatal\",\n message: error.message,\n error,\n props: { process: { kind: \"uncaughtException\" } },\n });\n flushSync();\n const flushed = flushBounded();\n if (exitOnUncaught) void flushed.finally(() => exitFn(1));\n };\n process.on(\"uncaughtException\", onUncaughtException);\n disposers.push(() => process.off(\"uncaughtException\", onUncaughtException));\n }\n\n if (unhandledRejection) {\n const onUnhandledRejection = (reason: unknown) => {\n capture({\n level: \"error\",\n message: reason instanceof Error ? reason.message : \"Unhandled promise rejection\",\n error: reason,\n props: {\n process: { kind: \"unhandledRejection\" },\n reason: normalizeValue(reason, { maxDepth: 5 }),\n },\n });\n flushBestEffort();\n };\n process.on(\"unhandledRejection\", onUnhandledRejection);\n disposers.push(() => process.off(\"unhandledRejection\", onUnhandledRejection));\n }\n\n if (warning) {\n const onWarning = (warn: Error) => {\n capture({\n level: \"warn\",\n message: warn.message,\n error: warn,\n props: {\n process: {\n kind: \"warning\",\n name: warn.name,\n code: (warn as Error & { code?: string }).code,\n },\n },\n });\n };\n process.on(\"warning\", onWarning);\n disposers.push(() => process.off(\"warning\", onWarning));\n }\n\n if (beforeExitFlush) {\n const onBeforeExit = () => {\n void flushBounded();\n };\n process.on(\"beforeExit\", onBeforeExit);\n disposers.push(() => process.off(\"beforeExit\", onBeforeExit));\n }\n\n if (exitFlush) {\n const onExit = () => {\n flushSync();\n };\n process.on(\"exit\", onExit);\n disposers.push(() => process.off(\"exit\", onExit));\n }\n\n if (signalFlush) {\n for (const signal of signals) {\n const onSignal = () => {\n capture({\n level: \"fatal\",\n message: `Process signal ${signal}`,\n props: { process: { kind: \"signal\", signal } },\n });\n flushSync();\n const flushed = flushBounded();\n if (exitOnSignal) {\n void flushed.finally(() => exitFn(signalExitCodes[signal] ?? 1));\n }\n };\n process.on(signal, onSignal);\n disposers.push(() => process.off(signal, onSignal));\n }\n }\n\n return () => {\n if (disposed) return;\n disposed = true;\n for (const dispose of disposers) dispose();\n };\n },\n };\n}\n"],"mappings":"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"}
@@ -0,0 +1,148 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ let _loggerjs_core = require("@loggerjs/core");
3
+ //#region src/queue-integration.ts
4
+ const defaultMethods = [
5
+ "add",
6
+ "ack",
7
+ "consume",
8
+ "dequeue",
9
+ "nack",
10
+ "process",
11
+ "publish",
12
+ "receive",
13
+ "send",
14
+ "sendToQueue"
15
+ ];
16
+ const defaultRandom = () => Math.random();
17
+ function defaultLevel(_durationMs, error) {
18
+ return error ? "error" : "debug";
19
+ }
20
+ function isPromiseLike(value) {
21
+ return typeof value === "object" && value !== null && typeof value.then === "function";
22
+ }
23
+ function defaultOperation(method) {
24
+ switch (method) {
25
+ case "add":
26
+ case "publish":
27
+ case "send":
28
+ case "sendToQueue": return "publish";
29
+ case "consume":
30
+ case "dequeue":
31
+ case "process":
32
+ case "receive": return "consume";
33
+ case "ack": return "ack";
34
+ case "nack": return "nack";
35
+ default: return "other";
36
+ }
37
+ }
38
+ function defaultPayload(args) {
39
+ return typeof args[0] === "string" && args.length > 1 ? args[1] : args[0];
40
+ }
41
+ function defaultMessageId(args) {
42
+ const payload = defaultPayload(args);
43
+ if (typeof payload !== "object" || payload === null) return void 0;
44
+ const value = payload.messageId ?? payload.id;
45
+ return value === void 0 ? void 0 : String(value);
46
+ }
47
+ function payloadFor(args, method, options) {
48
+ if (!options.capturePayload) return void 0;
49
+ const payload = options.getPayload?.(args, method) ?? defaultPayload(args);
50
+ return payload === void 0 ? void 0 : (0, _loggerjs_core.normalizeValue)(payload, {
51
+ maxDepth: 4,
52
+ maxObjectKeys: 80
53
+ });
54
+ }
55
+ function queueIntegration(options = {}) {
56
+ const targets = options.targets ?? (options.client ? [{
57
+ client: options.client,
58
+ name: options.name,
59
+ system: options.system,
60
+ queueName: options.queueName,
61
+ methods: options.methods
62
+ }] : []);
63
+ const captureAll = options.captureAll ?? options.captureSuccessful ?? false;
64
+ const sampleRate = options.sampleRate ?? 1;
65
+ const random = options.random ?? defaultRandom;
66
+ const levelFor = options.level ?? defaultLevel;
67
+ const shouldCapture = (durationMs, error) => {
68
+ if (error) return true;
69
+ if (options.minDurationMs !== void 0 && durationMs >= options.minDurationMs) return true;
70
+ if (!captureAll) return false;
71
+ return sampleRate >= 1 || random() < sampleRate;
72
+ };
73
+ return {
74
+ name: "queue",
75
+ setup(api) {
76
+ const capture = api.guard((input) => api.capture(input));
77
+ const disposers = [];
78
+ let disposed = false;
79
+ const captureResult = (info, started, args, error) => {
80
+ const durationMs = Date.now() - started;
81
+ if (disposed || !shouldCapture(durationMs, error)) return;
82
+ capture({
83
+ level: levelFor(durationMs, error, info),
84
+ message: error ? `Queue error ${info.operation} ${info.queueName ?? info.method}` : `Queue ${info.operation} ${info.queueName ?? info.method}`,
85
+ error,
86
+ props: { queue: {
87
+ kind: info.target,
88
+ system: info.system,
89
+ queueName: info.queueName,
90
+ method: info.method,
91
+ operation: info.operation,
92
+ durationMs,
93
+ messageId: options.getMessageId?.(args, info.method) ?? defaultMessageId(args),
94
+ payload: payloadFor(args, info.method, options)
95
+ } }
96
+ });
97
+ };
98
+ for (const target of targets) {
99
+ const methods = target.methods ?? options.methods ?? defaultMethods;
100
+ for (const method of methods) {
101
+ const original = target.client[method];
102
+ if (typeof original !== "function") continue;
103
+ const originalMethod = original;
104
+ const targetName = target.name ?? options.name ?? "queue";
105
+ const system = target.system ?? options.system;
106
+ target.client[method] = function wrappedQueueMethod(...args) {
107
+ const started = Date.now();
108
+ const operation = options.getOperation?.(method, args) ?? defaultOperation(method);
109
+ const info = {
110
+ target: targetName,
111
+ system,
112
+ queueName: options.getQueueName?.(args, method) ?? target.queueName ?? options.queueName ?? (typeof args[0] === "string" ? args[0] : void 0),
113
+ method,
114
+ operation
115
+ };
116
+ try {
117
+ const result = originalMethod.apply(this, args);
118
+ if (isPromiseLike(result)) return result.then((value) => {
119
+ captureResult(info, started, args, void 0);
120
+ return value;
121
+ }, (error) => {
122
+ captureResult(info, started, args, error);
123
+ throw error;
124
+ });
125
+ captureResult(info, started, args, void 0);
126
+ return result;
127
+ } catch (error) {
128
+ captureResult(info, started, args, error);
129
+ throw error;
130
+ }
131
+ };
132
+ disposers.push(() => {
133
+ target.client[method] = originalMethod;
134
+ });
135
+ }
136
+ }
137
+ return () => {
138
+ if (disposed) return;
139
+ disposed = true;
140
+ for (const dispose of disposers) dispose();
141
+ };
142
+ }
143
+ };
144
+ }
145
+ //#endregion
146
+ exports.queueIntegration = queueIntegration;
147
+
148
+ //# sourceMappingURL=queue-integration.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queue-integration.cjs","names":[],"sources":["../src/queue-integration.ts"],"sourcesContent":["import {\n normalizeValue,\n type CaptureInput,\n type Integration,\n type IntegrationSetupContext,\n type LoggerLevel,\n} from \"@loggerjs/core\";\n\nexport type QueueOperation = \"publish\" | \"consume\" | \"ack\" | \"nack\" | \"other\";\n\nexport interface QueueClientLike {\n [method: string]: unknown;\n}\n\nexport interface QueueIntegrationTarget {\n client: QueueClientLike;\n name?: string;\n system?: string;\n queueName?: string;\n methods?: readonly string[];\n}\n\nexport interface QueueOperationInfo {\n target: string;\n system?: string;\n queueName?: string;\n method: string;\n operation: QueueOperation;\n}\n\nexport interface QueueIntegrationOptions {\n client?: QueueClientLike;\n targets?: readonly QueueIntegrationTarget[];\n name?: string;\n system?: string;\n queueName?: string;\n methods?: readonly string[];\n captureAll?: boolean;\n captureSuccessful?: boolean;\n minDurationMs?: number;\n sampleRate?: number;\n random?: () => number;\n capturePayload?: boolean;\n getOperation?: (method: string, args: readonly unknown[]) => QueueOperation;\n getQueueName?: (args: readonly unknown[], method: string) => string | undefined;\n getMessageId?: (args: readonly unknown[], method: string) => string | undefined;\n getPayload?: (args: readonly unknown[], method: string) => unknown;\n level?: (durationMs: number, error: unknown, info: QueueOperationInfo) => LoggerLevel;\n}\n\ntype QueueMethod = (this: unknown, ...args: unknown[]) => unknown;\n\nconst defaultMethods = [\n \"add\",\n \"ack\",\n \"consume\",\n \"dequeue\",\n \"nack\",\n \"process\",\n \"publish\",\n \"receive\",\n \"send\",\n \"sendToQueue\",\n] as const;\nconst defaultRandom = () => Math.random();\n\nfunction defaultLevel(_durationMs: number, error: unknown): LoggerLevel {\n return error ? \"error\" : \"debug\";\n}\n\nfunction isPromiseLike(value: unknown): value is PromiseLike<unknown> {\n return (\n typeof value === \"object\" &&\n value !== null &&\n typeof (value as { then?: unknown }).then === \"function\"\n );\n}\n\nfunction defaultOperation(method: string): QueueOperation {\n switch (method) {\n case \"add\":\n case \"publish\":\n case \"send\":\n case \"sendToQueue\":\n return \"publish\";\n case \"consume\":\n case \"dequeue\":\n case \"process\":\n case \"receive\":\n return \"consume\";\n case \"ack\":\n return \"ack\";\n case \"nack\":\n return \"nack\";\n default:\n return \"other\";\n }\n}\n\nfunction defaultPayload(args: readonly unknown[]) {\n return typeof args[0] === \"string\" && args.length > 1 ? args[1] : args[0];\n}\n\nfunction defaultMessageId(args: readonly unknown[]) {\n const payload = defaultPayload(args);\n if (typeof payload !== \"object\" || payload === null) return undefined;\n const value =\n (payload as { id?: unknown; messageId?: unknown }).messageId ??\n (payload as { id?: unknown }).id;\n return value === undefined ? undefined : String(value);\n}\n\nfunction payloadFor(args: readonly unknown[], method: string, options: QueueIntegrationOptions) {\n if (!options.capturePayload) return undefined;\n const payload = options.getPayload?.(args, method) ?? defaultPayload(args);\n return payload === undefined\n ? undefined\n : normalizeValue(payload, { maxDepth: 4, maxObjectKeys: 80 });\n}\n\nexport function queueIntegration(options: QueueIntegrationOptions = {}): Integration {\n const targets =\n options.targets ??\n (options.client\n ? [\n {\n client: options.client,\n name: options.name,\n system: options.system,\n queueName: options.queueName,\n methods: options.methods,\n },\n ]\n : []);\n const captureAll = options.captureAll ?? options.captureSuccessful ?? false;\n const sampleRate = options.sampleRate ?? 1;\n const random = options.random ?? defaultRandom;\n const levelFor = options.level ?? defaultLevel;\n\n const shouldCapture = (durationMs: number, error: unknown) => {\n if (error) return true;\n if (options.minDurationMs !== undefined && durationMs >= options.minDurationMs) return true;\n if (!captureAll) return false;\n return sampleRate >= 1 || random() < sampleRate;\n };\n\n return {\n name: \"queue\",\n setup(api: IntegrationSetupContext) {\n const capture = api.guard((input: CaptureInput) => api.capture(input));\n const disposers: Array<() => void> = [];\n let disposed = false;\n\n const captureResult = (\n info: QueueOperationInfo,\n started: number,\n args: readonly unknown[],\n error: unknown,\n ) => {\n const durationMs = Date.now() - started;\n if (disposed || !shouldCapture(durationMs, error)) return;\n capture({\n level: levelFor(durationMs, error, info),\n message: error\n ? `Queue error ${info.operation} ${info.queueName ?? info.method}`\n : `Queue ${info.operation} ${info.queueName ?? info.method}`,\n error,\n props: {\n queue: {\n kind: info.target,\n system: info.system,\n queueName: info.queueName,\n method: info.method,\n operation: info.operation,\n durationMs,\n messageId: options.getMessageId?.(args, info.method) ?? defaultMessageId(args),\n payload: payloadFor(args, info.method, options),\n },\n },\n });\n };\n\n for (const target of targets) {\n const methods = target.methods ?? options.methods ?? defaultMethods;\n for (const method of methods) {\n const original = target.client[method];\n if (typeof original !== \"function\") continue;\n const originalMethod = original as QueueMethod;\n const targetName = target.name ?? options.name ?? \"queue\";\n const system = target.system ?? options.system;\n\n target.client[method] = function wrappedQueueMethod(this: unknown, ...args: unknown[]) {\n const started = Date.now();\n const operation = options.getOperation?.(method, args) ?? defaultOperation(method);\n const info: QueueOperationInfo = {\n target: targetName,\n system,\n queueName:\n options.getQueueName?.(args, method) ??\n target.queueName ??\n options.queueName ??\n (typeof args[0] === \"string\" ? args[0] : undefined),\n method,\n operation,\n };\n try {\n const result = originalMethod.apply(this, args);\n if (isPromiseLike(result)) {\n return result.then(\n (value) => {\n captureResult(info, started, args, undefined);\n return value;\n },\n (error) => {\n captureResult(info, started, args, error);\n throw error;\n },\n );\n }\n captureResult(info, started, args, undefined);\n return result;\n } catch (error) {\n captureResult(info, started, args, error);\n throw error;\n }\n };\n\n disposers.push(() => {\n target.client[method] = originalMethod;\n });\n }\n }\n\n return () => {\n if (disposed) return;\n disposed = true;\n for (const dispose of disposers) dispose();\n };\n },\n };\n}\n"],"mappings":"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"}
@@ -0,0 +1,147 @@
1
+ import { normalizeValue } from "@loggerjs/core";
2
+ //#region src/queue-integration.ts
3
+ const defaultMethods = [
4
+ "add",
5
+ "ack",
6
+ "consume",
7
+ "dequeue",
8
+ "nack",
9
+ "process",
10
+ "publish",
11
+ "receive",
12
+ "send",
13
+ "sendToQueue"
14
+ ];
15
+ const defaultRandom = () => Math.random();
16
+ function defaultLevel(_durationMs, error) {
17
+ return error ? "error" : "debug";
18
+ }
19
+ function isPromiseLike(value) {
20
+ return typeof value === "object" && value !== null && typeof value.then === "function";
21
+ }
22
+ function defaultOperation(method) {
23
+ switch (method) {
24
+ case "add":
25
+ case "publish":
26
+ case "send":
27
+ case "sendToQueue": return "publish";
28
+ case "consume":
29
+ case "dequeue":
30
+ case "process":
31
+ case "receive": return "consume";
32
+ case "ack": return "ack";
33
+ case "nack": return "nack";
34
+ default: return "other";
35
+ }
36
+ }
37
+ function defaultPayload(args) {
38
+ return typeof args[0] === "string" && args.length > 1 ? args[1] : args[0];
39
+ }
40
+ function defaultMessageId(args) {
41
+ const payload = defaultPayload(args);
42
+ if (typeof payload !== "object" || payload === null) return void 0;
43
+ const value = payload.messageId ?? payload.id;
44
+ return value === void 0 ? void 0 : String(value);
45
+ }
46
+ function payloadFor(args, method, options) {
47
+ if (!options.capturePayload) return void 0;
48
+ const payload = options.getPayload?.(args, method) ?? defaultPayload(args);
49
+ return payload === void 0 ? void 0 : normalizeValue(payload, {
50
+ maxDepth: 4,
51
+ maxObjectKeys: 80
52
+ });
53
+ }
54
+ function queueIntegration(options = {}) {
55
+ const targets = options.targets ?? (options.client ? [{
56
+ client: options.client,
57
+ name: options.name,
58
+ system: options.system,
59
+ queueName: options.queueName,
60
+ methods: options.methods
61
+ }] : []);
62
+ const captureAll = options.captureAll ?? options.captureSuccessful ?? false;
63
+ const sampleRate = options.sampleRate ?? 1;
64
+ const random = options.random ?? defaultRandom;
65
+ const levelFor = options.level ?? defaultLevel;
66
+ const shouldCapture = (durationMs, error) => {
67
+ if (error) return true;
68
+ if (options.minDurationMs !== void 0 && durationMs >= options.minDurationMs) return true;
69
+ if (!captureAll) return false;
70
+ return sampleRate >= 1 || random() < sampleRate;
71
+ };
72
+ return {
73
+ name: "queue",
74
+ setup(api) {
75
+ const capture = api.guard((input) => api.capture(input));
76
+ const disposers = [];
77
+ let disposed = false;
78
+ const captureResult = (info, started, args, error) => {
79
+ const durationMs = Date.now() - started;
80
+ if (disposed || !shouldCapture(durationMs, error)) return;
81
+ capture({
82
+ level: levelFor(durationMs, error, info),
83
+ message: error ? `Queue error ${info.operation} ${info.queueName ?? info.method}` : `Queue ${info.operation} ${info.queueName ?? info.method}`,
84
+ error,
85
+ props: { queue: {
86
+ kind: info.target,
87
+ system: info.system,
88
+ queueName: info.queueName,
89
+ method: info.method,
90
+ operation: info.operation,
91
+ durationMs,
92
+ messageId: options.getMessageId?.(args, info.method) ?? defaultMessageId(args),
93
+ payload: payloadFor(args, info.method, options)
94
+ } }
95
+ });
96
+ };
97
+ for (const target of targets) {
98
+ const methods = target.methods ?? options.methods ?? defaultMethods;
99
+ for (const method of methods) {
100
+ const original = target.client[method];
101
+ if (typeof original !== "function") continue;
102
+ const originalMethod = original;
103
+ const targetName = target.name ?? options.name ?? "queue";
104
+ const system = target.system ?? options.system;
105
+ target.client[method] = function wrappedQueueMethod(...args) {
106
+ const started = Date.now();
107
+ const operation = options.getOperation?.(method, args) ?? defaultOperation(method);
108
+ const info = {
109
+ target: targetName,
110
+ system,
111
+ queueName: options.getQueueName?.(args, method) ?? target.queueName ?? options.queueName ?? (typeof args[0] === "string" ? args[0] : void 0),
112
+ method,
113
+ operation
114
+ };
115
+ try {
116
+ const result = originalMethod.apply(this, args);
117
+ if (isPromiseLike(result)) return result.then((value) => {
118
+ captureResult(info, started, args, void 0);
119
+ return value;
120
+ }, (error) => {
121
+ captureResult(info, started, args, error);
122
+ throw error;
123
+ });
124
+ captureResult(info, started, args, void 0);
125
+ return result;
126
+ } catch (error) {
127
+ captureResult(info, started, args, error);
128
+ throw error;
129
+ }
130
+ };
131
+ disposers.push(() => {
132
+ target.client[method] = originalMethod;
133
+ });
134
+ }
135
+ }
136
+ return () => {
137
+ if (disposed) return;
138
+ disposed = true;
139
+ for (const dispose of disposers) dispose();
140
+ };
141
+ }
142
+ };
143
+ }
144
+ //#endregion
145
+ export { queueIntegration };
146
+
147
+ //# sourceMappingURL=queue-integration.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queue-integration.js","names":[],"sources":["../src/queue-integration.ts"],"sourcesContent":["import {\n normalizeValue,\n type CaptureInput,\n type Integration,\n type IntegrationSetupContext,\n type LoggerLevel,\n} from \"@loggerjs/core\";\n\nexport type QueueOperation = \"publish\" | \"consume\" | \"ack\" | \"nack\" | \"other\";\n\nexport interface QueueClientLike {\n [method: string]: unknown;\n}\n\nexport interface QueueIntegrationTarget {\n client: QueueClientLike;\n name?: string;\n system?: string;\n queueName?: string;\n methods?: readonly string[];\n}\n\nexport interface QueueOperationInfo {\n target: string;\n system?: string;\n queueName?: string;\n method: string;\n operation: QueueOperation;\n}\n\nexport interface QueueIntegrationOptions {\n client?: QueueClientLike;\n targets?: readonly QueueIntegrationTarget[];\n name?: string;\n system?: string;\n queueName?: string;\n methods?: readonly string[];\n captureAll?: boolean;\n captureSuccessful?: boolean;\n minDurationMs?: number;\n sampleRate?: number;\n random?: () => number;\n capturePayload?: boolean;\n getOperation?: (method: string, args: readonly unknown[]) => QueueOperation;\n getQueueName?: (args: readonly unknown[], method: string) => string | undefined;\n getMessageId?: (args: readonly unknown[], method: string) => string | undefined;\n getPayload?: (args: readonly unknown[], method: string) => unknown;\n level?: (durationMs: number, error: unknown, info: QueueOperationInfo) => LoggerLevel;\n}\n\ntype QueueMethod = (this: unknown, ...args: unknown[]) => unknown;\n\nconst defaultMethods = [\n \"add\",\n \"ack\",\n \"consume\",\n \"dequeue\",\n \"nack\",\n \"process\",\n \"publish\",\n \"receive\",\n \"send\",\n \"sendToQueue\",\n] as const;\nconst defaultRandom = () => Math.random();\n\nfunction defaultLevel(_durationMs: number, error: unknown): LoggerLevel {\n return error ? \"error\" : \"debug\";\n}\n\nfunction isPromiseLike(value: unknown): value is PromiseLike<unknown> {\n return (\n typeof value === \"object\" &&\n value !== null &&\n typeof (value as { then?: unknown }).then === \"function\"\n );\n}\n\nfunction defaultOperation(method: string): QueueOperation {\n switch (method) {\n case \"add\":\n case \"publish\":\n case \"send\":\n case \"sendToQueue\":\n return \"publish\";\n case \"consume\":\n case \"dequeue\":\n case \"process\":\n case \"receive\":\n return \"consume\";\n case \"ack\":\n return \"ack\";\n case \"nack\":\n return \"nack\";\n default:\n return \"other\";\n }\n}\n\nfunction defaultPayload(args: readonly unknown[]) {\n return typeof args[0] === \"string\" && args.length > 1 ? args[1] : args[0];\n}\n\nfunction defaultMessageId(args: readonly unknown[]) {\n const payload = defaultPayload(args);\n if (typeof payload !== \"object\" || payload === null) return undefined;\n const value =\n (payload as { id?: unknown; messageId?: unknown }).messageId ??\n (payload as { id?: unknown }).id;\n return value === undefined ? undefined : String(value);\n}\n\nfunction payloadFor(args: readonly unknown[], method: string, options: QueueIntegrationOptions) {\n if (!options.capturePayload) return undefined;\n const payload = options.getPayload?.(args, method) ?? defaultPayload(args);\n return payload === undefined\n ? undefined\n : normalizeValue(payload, { maxDepth: 4, maxObjectKeys: 80 });\n}\n\nexport function queueIntegration(options: QueueIntegrationOptions = {}): Integration {\n const targets =\n options.targets ??\n (options.client\n ? [\n {\n client: options.client,\n name: options.name,\n system: options.system,\n queueName: options.queueName,\n methods: options.methods,\n },\n ]\n : []);\n const captureAll = options.captureAll ?? options.captureSuccessful ?? false;\n const sampleRate = options.sampleRate ?? 1;\n const random = options.random ?? defaultRandom;\n const levelFor = options.level ?? defaultLevel;\n\n const shouldCapture = (durationMs: number, error: unknown) => {\n if (error) return true;\n if (options.minDurationMs !== undefined && durationMs >= options.minDurationMs) return true;\n if (!captureAll) return false;\n return sampleRate >= 1 || random() < sampleRate;\n };\n\n return {\n name: \"queue\",\n setup(api: IntegrationSetupContext) {\n const capture = api.guard((input: CaptureInput) => api.capture(input));\n const disposers: Array<() => void> = [];\n let disposed = false;\n\n const captureResult = (\n info: QueueOperationInfo,\n started: number,\n args: readonly unknown[],\n error: unknown,\n ) => {\n const durationMs = Date.now() - started;\n if (disposed || !shouldCapture(durationMs, error)) return;\n capture({\n level: levelFor(durationMs, error, info),\n message: error\n ? `Queue error ${info.operation} ${info.queueName ?? info.method}`\n : `Queue ${info.operation} ${info.queueName ?? info.method}`,\n error,\n props: {\n queue: {\n kind: info.target,\n system: info.system,\n queueName: info.queueName,\n method: info.method,\n operation: info.operation,\n durationMs,\n messageId: options.getMessageId?.(args, info.method) ?? defaultMessageId(args),\n payload: payloadFor(args, info.method, options),\n },\n },\n });\n };\n\n for (const target of targets) {\n const methods = target.methods ?? options.methods ?? defaultMethods;\n for (const method of methods) {\n const original = target.client[method];\n if (typeof original !== \"function\") continue;\n const originalMethod = original as QueueMethod;\n const targetName = target.name ?? options.name ?? \"queue\";\n const system = target.system ?? options.system;\n\n target.client[method] = function wrappedQueueMethod(this: unknown, ...args: unknown[]) {\n const started = Date.now();\n const operation = options.getOperation?.(method, args) ?? defaultOperation(method);\n const info: QueueOperationInfo = {\n target: targetName,\n system,\n queueName:\n options.getQueueName?.(args, method) ??\n target.queueName ??\n options.queueName ??\n (typeof args[0] === \"string\" ? args[0] : undefined),\n method,\n operation,\n };\n try {\n const result = originalMethod.apply(this, args);\n if (isPromiseLike(result)) {\n return result.then(\n (value) => {\n captureResult(info, started, args, undefined);\n return value;\n },\n (error) => {\n captureResult(info, started, args, error);\n throw error;\n },\n );\n }\n captureResult(info, started, args, undefined);\n return result;\n } catch (error) {\n captureResult(info, started, args, error);\n throw error;\n }\n };\n\n disposers.push(() => {\n target.client[method] = originalMethod;\n });\n }\n }\n\n return () => {\n if (disposed) return;\n disposed = true;\n for (const dispose of disposers) dispose();\n };\n },\n };\n}\n"],"mappings":"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"}