-
-
Notifications
You must be signed in to change notification settings - Fork 436
/
Copy pathdecorators.ts
64 lines (59 loc) · 1.87 KB
/
decorators.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
import type { CancellationToken } from '@theia/core/lib/common/cancellation';
import { default as stringifySafe } from 'fast-safe-stringify';
export interface DurationOptions {
/**
* If not specified, falls back to the `String()` value of the `PropertyKey`.
*/
name?: string;
/**
* If the duration exceeds this timeout (in millis), then the duration will be logged as an error.
*/
timeout?: number;
}
export function duration(options?: DurationOptions) {
return (
_target: unknown,
key: PropertyKey,
descriptor: PropertyDescriptor
): PropertyDescriptor => {
const original = descriptor.value;
descriptor.value = async function (...args: unknown[]) {
const input = args
.filter((arg) => !Boolean(isCancellationToken(arg)))
.map(stringify)
.join(',');
const start = performance.now();
const result = await original.apply(this, args);
const end = performance.now();
const duration = end - start;
const slow = duration > (options?.timeout ?? 100);
const message = `---- ${slow ? '!!!SLOW!!! ' : ''}DURATION: ${
options?.name ?? String(key)
} took ${duration.toFixed(3)} ms. Args: [${input}] ----`;
if (slow) {
console.error(message);
} else {
console.info(message);
}
return result;
};
return descriptor;
};
}
function stringify(arg: unknown): string {
try {
return JSON.stringify(arg);
} catch {
return stringifySafe(arg);
}
}
// The cancellation token is implicitly the last arg of the JSON-RPC invocation. We want to filter it out from the logs.
// See: https://github.com/eclipse-theia/theia/issues/10129
function isCancellationToken(arg: unknown): arg is CancellationToken {
return (
typeof arg === 'object' &&
arg !== null &&
'onCancellationRequested' in arg &&
'isCancellationRequested' in arg
);
}