-
Notifications
You must be signed in to change notification settings - Fork 233
/
Copy pathdebug-log.decorator.ts
83 lines (70 loc) · 2.82 KB
/
debug-log.decorator.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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
import { Logger } from '@nestjs/common';
import { performance } from 'perf_hooks';
// import { isAsyncFunction } from 'util/types'; // >= v15.3.0
import { types } from 'util';
import type { Func } from './debug.interface';
const MethodLog =
(context?: string): MethodDecorator =>
(target: object, propertyKey: string | symbol, descriptor: PropertyDescriptor): void => {
const originalMethod: unknown = descriptor.value;
if (typeof originalMethod !== 'function') {
return;
}
const log = function (time: number, args: unknown[]): void {
const ownKey = typeof target === 'function' ? target.name : '';
const name = context ? `${ownKey}.${String(propertyKey)}` : String(propertyKey);
const params = args.length > 0 ? `(${args.toString()})` : '';
Logger.debug(`${name}${params} +${time.toFixed(2)}ms`, context ?? ownKey);
};
if (types.isAsyncFunction(originalMethod)) {
descriptor.value = async function (...args: unknown[]): Promise<unknown> {
const start = performance.now();
const result: unknown = await originalMethod.apply(this, args);
const end = performance.now();
log(end - start, args);
// or Use result to add response log
return result;
};
} else {
descriptor.value = function (...args: unknown[]): unknown {
const start = performance.now();
const result: unknown = originalMethod.apply(this, args);
const end = performance.now();
log(end - start, args);
return result;
};
}
};
/**
* https://stackoverflow.com/questions/47621364
* https://github.com/Papooch/decorate-all
*/
const ClassLog =
(context?: string): ClassDecorator =>
(target: Func): void => {
const descriptors = Object.getOwnPropertyDescriptors(target.prototype);
for (const [propertyKey, descriptor] of Object.entries(descriptors)) {
const originalMethod: unknown = descriptor.value;
if (!(originalMethod instanceof Function) || propertyKey === 'constructor') {
continue;
}
MethodLog(context)(target, propertyKey, descriptor);
if (originalMethod !== descriptor.value) {
const metadataKeys = Reflect.getMetadataKeys(originalMethod);
for (const key of metadataKeys) {
const value: unknown = Reflect.getMetadata(key, originalMethod);
Reflect.defineMetadata(key, value, <object>descriptor.value);
}
}
Object.defineProperty(target.prototype, propertyKey, descriptor);
}
};
export const DebugLog =
(context?: string): ClassDecorator & MethodDecorator =>
(target: object, propertyKey?: string | symbol, descriptor?: PropertyDescriptor): void => {
if (!descriptor) {
ClassLog(context)(<Func>target);
} else if (propertyKey) {
MethodLog(context)(target, propertyKey, descriptor);
}
};