@monocle.sh/adonisjs-agent 1.0.0-beta.13 → 1.0.0-beta.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/helpers.d.mts
CHANGED
|
@@ -9,7 +9,6 @@ import { extractTraceContext, getCurrentSpan, injectTraceContext, otelLoggingPre
|
|
|
9
9
|
* to extract source context lines from the stack trace.
|
|
10
10
|
*/
|
|
11
11
|
declare function handleError(span: Span, error: Error): Promise<never>;
|
|
12
|
-
type RecordCallback<T> = (span: Span) => T | Promise<T>;
|
|
13
12
|
/**
|
|
14
13
|
* Record a code section as a span in your traces.
|
|
15
14
|
*
|
|
@@ -17,8 +16,9 @@ type RecordCallback<T> = (span: Span) => T | Promise<T>;
|
|
|
17
16
|
* to capture exceptions with source context lines (pre/post context around
|
|
18
17
|
* the error location).
|
|
19
18
|
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
19
|
+
* Preserves sync/async semantics: if the callback is synchronous, the return
|
|
20
|
+
* type is `T`. If the callback returns a Promise-like value, the return type
|
|
21
|
+
* is async-compatible.
|
|
22
22
|
*
|
|
23
23
|
* Automatically handles:
|
|
24
24
|
* - Creating and closing the span
|
|
@@ -29,10 +29,10 @@ type RecordCallback<T> = (span: Span) => T | Promise<T>;
|
|
|
29
29
|
* ```ts
|
|
30
30
|
* import { record } from '@monocle.sh/adonisjs-agent'
|
|
31
31
|
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
* })
|
|
32
|
+
* // Sync callback returns T directly
|
|
33
|
+
* const value = record('compute.hash', () => computeHash(data))
|
|
35
34
|
*
|
|
35
|
+
* // Async callback returns Promise<T>
|
|
36
36
|
* const user = await record('user.fetch', async () => {
|
|
37
37
|
* return await userService.findById(id)
|
|
38
38
|
* })
|
|
@@ -44,6 +44,6 @@ type RecordCallback<T> = (span: Span) => T | Promise<T>;
|
|
|
44
44
|
* })
|
|
45
45
|
* ```
|
|
46
46
|
*/
|
|
47
|
-
declare function record<T>(name: string, callback:
|
|
47
|
+
declare function record<T>(name: string, callback: (span: Span) => T): T;
|
|
48
48
|
//#endregion
|
|
49
49
|
export { extractTraceContext, getCurrentSpan, handleError, injectTraceContext, otelLoggingPreset, record, recordEvent, setAttributes };
|
package/dist/helpers.mjs
CHANGED
|
@@ -1,8 +1,31 @@
|
|
|
1
1
|
import { ExceptionReporter } from "./src/exception_reporter.mjs";
|
|
2
|
-
import {
|
|
2
|
+
import { trace } from "@opentelemetry/api";
|
|
3
3
|
import { extractTraceContext, getCurrentSpan, injectTraceContext, otelLoggingPreset, recordEvent, setAttributes } from "@adonisjs/otel/helpers";
|
|
4
4
|
|
|
5
5
|
//#region src/helpers.ts
|
|
6
|
+
function isPromiseLike(value) {
|
|
7
|
+
if (!value) return false;
|
|
8
|
+
if (typeof value !== "object" && typeof value !== "function") return false;
|
|
9
|
+
return typeof value.then === "function";
|
|
10
|
+
}
|
|
11
|
+
async function reportErrorAndEndSpan(span, error, endTime) {
|
|
12
|
+
const reporter = new ExceptionReporter();
|
|
13
|
+
try {
|
|
14
|
+
await reporter.report({
|
|
15
|
+
span,
|
|
16
|
+
error,
|
|
17
|
+
shouldReport: true
|
|
18
|
+
});
|
|
19
|
+
} catch {
|
|
20
|
+
reporter.reportSync({
|
|
21
|
+
span,
|
|
22
|
+
error,
|
|
23
|
+
shouldReport: true
|
|
24
|
+
});
|
|
25
|
+
} finally {
|
|
26
|
+
span.end(endTime);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
6
29
|
/**
|
|
7
30
|
* Handle an error by reporting it with context frames extraction.
|
|
8
31
|
*
|
|
@@ -10,16 +33,7 @@ import { extractTraceContext, getCurrentSpan, injectTraceContext, otelLoggingPre
|
|
|
10
33
|
* to extract source context lines from the stack trace.
|
|
11
34
|
*/
|
|
12
35
|
async function handleError(span, error) {
|
|
13
|
-
await new
|
|
14
|
-
span,
|
|
15
|
-
error,
|
|
16
|
-
shouldReport: true
|
|
17
|
-
});
|
|
18
|
-
span.setStatus({
|
|
19
|
-
code: SpanStatusCode.ERROR,
|
|
20
|
-
message: error?.message
|
|
21
|
-
});
|
|
22
|
-
span.end();
|
|
36
|
+
await reportErrorAndEndSpan(span, error, /* @__PURE__ */ new Date());
|
|
23
37
|
throw error;
|
|
24
38
|
}
|
|
25
39
|
/**
|
|
@@ -29,8 +43,9 @@ async function handleError(span, error) {
|
|
|
29
43
|
* to capture exceptions with source context lines (pre/post context around
|
|
30
44
|
* the error location).
|
|
31
45
|
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
46
|
+
* Preserves sync/async semantics: if the callback is synchronous, the return
|
|
47
|
+
* type is `T`. If the callback returns a Promise-like value, the return type
|
|
48
|
+
* is async-compatible.
|
|
34
49
|
*
|
|
35
50
|
* Automatically handles:
|
|
36
51
|
* - Creating and closing the span
|
|
@@ -41,10 +56,10 @@ async function handleError(span, error) {
|
|
|
41
56
|
* ```ts
|
|
42
57
|
* import { record } from '@monocle.sh/adonisjs-agent'
|
|
43
58
|
*
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
* })
|
|
59
|
+
* // Sync callback returns T directly
|
|
60
|
+
* const value = record('compute.hash', () => computeHash(data))
|
|
47
61
|
*
|
|
62
|
+
* // Async callback returns Promise<T>
|
|
48
63
|
* const user = await record('user.fetch', async () => {
|
|
49
64
|
* return await userService.findById(id)
|
|
50
65
|
* })
|
|
@@ -56,14 +71,19 @@ async function handleError(span, error) {
|
|
|
56
71
|
* })
|
|
57
72
|
* ```
|
|
58
73
|
*/
|
|
59
|
-
|
|
60
|
-
return trace.getTracer("@monocle.sh/agent").startActiveSpan(name,
|
|
74
|
+
function record(name, callback) {
|
|
75
|
+
return trace.getTracer("@monocle.sh/agent").startActiveSpan(name, (span) => {
|
|
61
76
|
try {
|
|
62
|
-
const result =
|
|
77
|
+
const result = callback(span);
|
|
78
|
+
if (isPromiseLike(result)) return Promise.resolve(result).then((value) => {
|
|
79
|
+
span.end();
|
|
80
|
+
return value;
|
|
81
|
+
}).catch((error) => handleError(span, error));
|
|
63
82
|
span.end();
|
|
64
83
|
return result;
|
|
65
84
|
} catch (error) {
|
|
66
|
-
|
|
85
|
+
reportErrorAndEndSpan(span, error, /* @__PURE__ */ new Date());
|
|
86
|
+
throw error;
|
|
67
87
|
}
|
|
68
88
|
});
|
|
69
89
|
}
|
|
@@ -33,6 +33,23 @@ var ExceptionReporter = class {
|
|
|
33
33
|
const attributes = this.#buildAttributes(error, causeChain);
|
|
34
34
|
span.addEvent("exception", attributes);
|
|
35
35
|
}
|
|
36
|
+
/**
|
|
37
|
+
* Synchronous version of report. Uses buildCauseChain (no file I/O)
|
|
38
|
+
* so source context frames won't be available, but the full stack trace,
|
|
39
|
+
* cause chain, error status, and exception event are still recorded.
|
|
40
|
+
*/
|
|
41
|
+
reportSync(options) {
|
|
42
|
+
const { span, shouldReport } = options;
|
|
43
|
+
const error = toHttpError(options.error);
|
|
44
|
+
span.setStatus({
|
|
45
|
+
code: SpanStatusCode.ERROR,
|
|
46
|
+
message: error.message
|
|
47
|
+
});
|
|
48
|
+
span.setAttribute("monocle.exception.should_report", shouldReport);
|
|
49
|
+
const causeChain = buildCauseChain(error);
|
|
50
|
+
const attributes = this.#buildAttributes(error, causeChain);
|
|
51
|
+
span.addEvent("exception", attributes);
|
|
52
|
+
}
|
|
36
53
|
#buildAttributes(error, causeChain) {
|
|
37
54
|
const hasCauses = causeChain.length > 1;
|
|
38
55
|
const attributes = {
|
|
@@ -39,6 +39,15 @@ async function instrumentCache(config, appRoot) {
|
|
|
39
39
|
suppressInternalOperations: true
|
|
40
40
|
});
|
|
41
41
|
instrumentation.enable();
|
|
42
|
+
/**
|
|
43
|
+
* Eagerly import bentocache to trigger the ESM hook.
|
|
44
|
+
* If the hook didn't patch BentoCache (e.g. race condition),
|
|
45
|
+
* fall back to manual registration.
|
|
46
|
+
*/
|
|
47
|
+
try {
|
|
48
|
+
const bentocache = await import("bentocache");
|
|
49
|
+
if (bentocache.BentoCache.name !== "BentoCachePatched") instrumentation.manuallyRegister(bentocache);
|
|
50
|
+
} catch {}
|
|
42
51
|
return instrumentation;
|
|
43
52
|
}
|
|
44
53
|
|