Skip to content

Commit 5c03584

Browse files
le0mfquffio
authored andcommitted
fix: trace decorator's types
1 parent 087c50c commit 5c03584

File tree

4 files changed

+49
-28
lines changed

4 files changed

+49
-28
lines changed

packages/utils/src/lib/server/cache/base.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import type { JitterFn, JitterMode } from '../../utils/misc.js';
22
import type { StorageReadWriter } from '../storage.js';
3-
import { trace, ATTR_PEER_SERVICE } from '../telemetry.js';
3+
import { ATTR_PEER_SERVICE, trace } from '../telemetry.js';
44
import { SpanKind } from '@opentelemetry/api';
55

66
/**

packages/utils/src/lib/server/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ export * from './cache/index.js';
22
export * from './hooks/index.js';
33
export * from './session.js';
44
export * from './sitemap.js';
5+
export { traceDecoratorFactory, ATTR_PEER_SERVICE } from './telemetry.js';
56
export * from './utils.js';
67

78
import type { Session } from './session.js';

packages/utils/src/lib/server/telemetry.ts

Lines changed: 45 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -6,36 +6,56 @@ import api, { type Span, type SpanOptions, SpanStatusCode } from '@opentelemetry
66
*/
77
export const ATTR_PEER_SERVICE = 'peer.service' as const;
88

9-
export const tracer = api.trace.getTracer('@chialab/sveltekit-utils');
9+
export const traceDecoratorFactory = (name: string, version?: string) => {
10+
const tracer = api.trace.getTracer(name, version);
1011

11-
/**
12-
* Decorator to trace a method or function by wrapping it in a new active span.
13-
*
14-
* @param options Span options
15-
*/
16-
export const trace =
17-
(options: SpanOptions = {}) =>
18-
(_: any, method: PropertyKey, descriptor: PropertyDescriptor) => ({
19-
...descriptor,
20-
value(...args: any[]) {
21-
return tracer.startActiveSpan(
22-
[this?.constructor?.name, method].filter(Boolean).join('.'),
23-
options,
24-
async (span: Span) => {
12+
return <This, Value extends (this: This, ...args: any) => unknown>(options: SpanOptions = {}) =>
13+
(target: Value, ctx: ClassMethodDecoratorContext<This, Value>): Value => {
14+
type R = ReturnType<Value>;
15+
16+
return function (this: This, ...args: Parameters<Value>): R {
17+
// @ts-expect-error Typing this properly would be cumbersome.
18+
const className = ctx.static ? this.name : this.constructor.name;
19+
20+
return tracer.startActiveSpan([className, ctx.name].filter(Boolean).join('.'), options, (span: Span): R => {
2521
try {
26-
// Wait for the wrapped function to end before closing the span and returning
27-
return await descriptor.value.call(this, ...args);
28-
} catch (e) {
22+
const result = target.call(this, ...args) as R;
23+
if (result && typeof result === 'object' && 'then' in result && typeof result.then === 'function') {
24+
return result.then(
25+
(result: R) => {
26+
span.end();
27+
28+
return result;
29+
},
30+
(err: unknown) => {
31+
span.setStatus({ code: SpanStatusCode.ERROR });
32+
if (err instanceof Error) {
33+
span.recordException(err);
34+
}
35+
span.end();
36+
37+
throw err;
38+
},
39+
);
40+
}
41+
42+
return result;
43+
} catch (err: unknown) {
2944
span.setStatus({ code: SpanStatusCode.ERROR });
30-
if (e instanceof Error) {
31-
span.recordException(e);
45+
if (err instanceof Error) {
46+
span.recordException(err);
3247
}
3348

34-
throw e;
49+
throw err;
3550
} finally {
3651
span.end();
3752
}
38-
},
39-
);
40-
},
41-
});
53+
});
54+
} as Value;
55+
};
56+
};
57+
58+
/**
59+
* Decorator to trace a method or function by wrapping it in a new active span.
60+
*/
61+
export const trace = traceDecoratorFactory('@chialab/sveltekit-utils');

packages/utils/tsconfig.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,13 @@
44
"allowJs": true,
55
"checkJs": true,
66
"esModuleInterop": true,
7-
"experimentalDecorators": true,
87
"forceConsistentCasingInFileNames": true,
98
"moduleResolution": "Bundler",
109
"resolveJsonModule": true,
1110
"skipLibCheck": true,
1211
"sourceMap": true,
13-
"strict": true
12+
"strict": true,
13+
"target": "es2022"
1414
},
1515
"exclude": ["./tests/coverage/**"]
1616
// Path aliases are handled by https://kit.svelte.dev/docs/configuration#alias

0 commit comments

Comments
 (0)