@rsdk/core 5.7.0-next.2 → 6.0.0-next.0
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/config/index.d.ts +0 -1
- package/dist/config/index.js +0 -1
- package/dist/config/index.js.map +1 -1
- package/dist/config/metadata/decorators/declare-property.decorator.d.ts +2 -1
- package/dist/config/metadata/decorators/declare-property.decorator.js.map +1 -1
- package/dist/config/metadata/decorators/property.decorator.d.ts +2 -1
- package/dist/config/metadata/decorators/property.decorator.js.map +1 -1
- package/dist/config/sources/implementations/json-file.source.js +1 -2
- package/dist/config/sources/implementations/json-file.source.js.map +1 -1
- package/dist/config/sources/implementations/relodable-json-file.source.js +1 -2
- package/dist/config/sources/implementations/relodable-json-file.source.js.map +1 -1
- package/dist/config/types.d.ts +1 -20
- package/dist/config/types.js.map +1 -1
- package/dist/exceptions.handling/default.formatter.d.ts +6 -0
- package/dist/exceptions.handling/default.formatter.js +12 -0
- package/dist/exceptions.handling/default.formatter.js.map +1 -0
- package/dist/exceptions.handling/default.sender.d.ts +8 -0
- package/dist/exceptions.handling/default.sender.js +13 -0
- package/dist/exceptions.handling/default.sender.js.map +1 -0
- package/dist/exceptions.handling/global-exceptions.config.js +1 -1
- package/dist/exceptions.handling/global-exceptions.config.js.map +1 -1
- package/dist/exceptions.handling/global-exceptions.filter.d.ts +8 -11
- package/dist/exceptions.handling/global-exceptions.filter.js +38 -56
- package/dist/exceptions.handling/global-exceptions.filter.js.map +1 -1
- package/dist/exceptions.handling/global-exceptions.interceptor.d.ts +18 -0
- package/dist/exceptions.handling/global-exceptions.interceptor.js +57 -0
- package/dist/exceptions.handling/global-exceptions.interceptor.js.map +1 -0
- package/dist/exceptions.handling/global-exceptions.module.d.ts +2 -23
- package/dist/exceptions.handling/global-exceptions.module.js +38 -3
- package/dist/exceptions.handling/global-exceptions.module.js.map +1 -1
- package/dist/exceptions.handling/types.d.ts +2 -2
- package/dist/index.d.ts +31 -2
- package/dist/index.js +34 -1
- package/dist/index.js.map +1 -1
- package/dist/logging/constants.d.ts +1 -0
- package/dist/logging/constants.js +5 -0
- package/dist/logging/constants.js.map +1 -0
- package/dist/logging/decorators/inject-logger.decorator.js +2 -2
- package/dist/logging/decorators/inject-logger.decorator.js.map +1 -1
- package/dist/logging/formatters/default.formatter.d.ts +7 -0
- package/dist/logging/formatters/default.formatter.js +17 -0
- package/dist/logging/formatters/default.formatter.js.map +1 -0
- package/dist/logging/formatters/index.d.ts +2 -0
- package/dist/{config/parsers/array → logging/formatters}/index.js +2 -1
- package/dist/logging/formatters/index.js.map +1 -0
- package/dist/logging/formatters/interfaces.d.ts +23 -0
- package/dist/logging/formatters/interfaces.js +3 -0
- package/dist/logging/formatters/interfaces.js.map +1 -0
- package/dist/logging/index.d.ts +3 -2
- package/dist/logging/index.js +6 -4
- package/dist/logging/index.js.map +1 -1
- package/dist/logging/logging-core.module.d.ts +10 -0
- package/dist/logging/{logger-initializing.module.js → logging-core.module.js} +46 -10
- package/dist/logging/logging-core.module.js.map +1 -0
- package/dist/logging/{logging.module.d.ts → logging-instances.module.d.ts} +1 -1
- package/dist/logging/{logging.module.js → logging-instances.module.js} +8 -9
- package/dist/logging/logging-instances.module.js.map +1 -0
- package/dist/logging/logging.config.d.ts +3 -0
- package/dist/logging/logging.config.js +29 -4
- package/dist/logging/logging.config.js.map +1 -1
- package/dist/logging/logging.interceptor.d.ts +37 -0
- package/dist/logging/logging.interceptor.js +124 -0
- package/dist/logging/logging.interceptor.js.map +1 -0
- package/dist/metrics/metrics.config.js +3 -2
- package/dist/metrics/metrics.config.js.map +1 -1
- package/dist/platform.context.d.ts +1 -1
- package/dist/platform.context.js +3 -2
- package/dist/platform.context.js.map +1 -1
- package/dist/platform.module.js +19 -6
- package/dist/platform.module.js.map +1 -1
- package/dist/tracing/constants.d.ts +4 -5
- package/dist/tracing/constants.js +9 -7
- package/dist/tracing/constants.js.map +1 -1
- package/dist/tracing/index.d.ts +1 -0
- package/dist/tracing/index.js +1 -0
- package/dist/tracing/index.js.map +1 -1
- package/dist/tracing/request-id/index.d.ts +4 -0
- package/dist/{config/parsers/enum → tracing/request-id}/index.js +4 -1
- package/dist/tracing/request-id/index.js.map +1 -0
- package/dist/tracing/request-id/metadata.helpers.d.ts +13 -0
- package/dist/tracing/request-id/metadata.helpers.js +23 -0
- package/dist/tracing/request-id/metadata.helpers.js.map +1 -0
- package/dist/tracing/request-id/request-id-gen.decorator.d.ts +8 -0
- package/dist/tracing/request-id/request-id-gen.decorator.js +17 -0
- package/dist/tracing/request-id/request-id-gen.decorator.js.map +1 -0
- package/dist/tracing/request-id/types.d.ts +2 -0
- package/dist/tracing/request-id/types.js +3 -0
- package/dist/tracing/request-id/types.js.map +1 -0
- package/dist/tracing/request-id/with-prefix.fn.d.ts +30 -0
- package/dist/tracing/request-id/with-prefix.fn.js +36 -0
- package/dist/tracing/request-id/with-prefix.fn.js.map +1 -0
- package/dist/tracing/tracing.config.d.ts +5 -0
- package/dist/tracing/tracing.config.js +42 -0
- package/dist/tracing/tracing.config.js.map +1 -0
- package/dist/tracing/tracing.interceptor.d.ts +7 -9
- package/dist/tracing/tracing.interceptor.js +30 -28
- package/dist/tracing/tracing.interceptor.js.map +1 -1
- package/dist/tracing/tracing.module.d.ts +13 -2
- package/dist/tracing/tracing.module.js +60 -17
- package/dist/tracing/tracing.module.js.map +1 -1
- package/dist/transport/protocol.detector.d.ts +1 -1
- package/dist/transport/protocol.detector.js +17 -2
- package/dist/transport/protocol.detector.js.map +1 -1
- package/dist/transport/transport.module.d.ts +0 -1
- package/dist/transport/transport.module.js +0 -20
- package/dist/transport/transport.module.js.map +1 -1
- package/dist/types/plugins.d.ts +2 -15
- package/dist/types/plugins.js.map +1 -1
- package/dist/types/transports.d.ts +23 -13
- package/dist/types/transports.js.map +1 -1
- package/dist/unhandled-rejection.handler.js +8 -13
- package/dist/unhandled-rejection.handler.js.map +1 -1
- package/package.json +3 -2
- package/src/config/index.ts +0 -1
- package/src/config/metadata/decorators/declare-property.decorator.ts +3 -1
- package/src/config/metadata/decorators/property.decorator.ts +3 -5
- package/src/config/sources/implementations/json-file.source.ts +1 -2
- package/src/config/sources/implementations/relodable-json-file.source.ts +1 -2
- package/src/config/types.ts +2 -23
- package/src/exceptions.handling/default.formatter.ts +11 -0
- package/src/exceptions.handling/default.sender.ts +15 -0
- package/src/exceptions.handling/global-exceptions.config.ts +2 -2
- package/src/exceptions.handling/global-exceptions.filter.ts +45 -77
- package/src/exceptions.handling/global-exceptions.interceptor.ts +57 -0
- package/src/exceptions.handling/global-exceptions.module.ts +46 -33
- package/src/exceptions.handling/types.ts +2 -2
- package/src/index.ts +53 -2
- package/src/logging/constants.ts +1 -0
- package/src/logging/decorators/inject-logger.decorator.ts +2 -2
- package/src/logging/formatters/default.formatter.ts +17 -0
- package/src/logging/formatters/index.ts +2 -0
- package/src/logging/formatters/interfaces.ts +34 -0
- package/src/logging/index.ts +3 -2
- package/src/logging/logging-core.module.ts +102 -0
- package/src/logging/{logging.module.ts → logging-instances.module.ts} +2 -4
- package/src/logging/logging.config.ts +22 -6
- package/src/logging/logging.interceptor.ts +138 -0
- package/src/metrics/metrics.config.ts +3 -1
- package/src/platform.context.ts +5 -2
- package/src/platform.module.ts +28 -7
- package/src/tracing/constants.ts +8 -7
- package/src/tracing/index.ts +1 -0
- package/src/tracing/request-id/index.ts +4 -0
- package/src/tracing/request-id/metadata.helpers.ts +24 -0
- package/src/tracing/request-id/request-id-gen.decorator.ts +16 -0
- package/src/tracing/request-id/types.ts +6 -0
- package/src/tracing/request-id/with-prefix.fn.ts +44 -0
- package/src/tracing/tracing.config.ts +23 -0
- package/src/tracing/tracing.interceptor.ts +36 -31
- package/src/tracing/tracing.module.ts +68 -19
- package/src/transport/protocol.detector.ts +24 -4
- package/src/transport/transport.module.ts +0 -25
- package/src/types/plugins.ts +11 -22
- package/src/types/transports.ts +32 -16
- package/src/unhandled-rejection.handler.ts +10 -18
- package/test/logging.interceptor.spec.ts +292 -0
- package/dist/config/parsers/array/array.parser.d.ts +0 -11
- package/dist/config/parsers/array/array.parser.js +0 -33
- package/dist/config/parsers/array/array.parser.js.map +0 -1
- package/dist/config/parsers/array/index.d.ts +0 -1
- package/dist/config/parsers/array/index.js.map +0 -1
- package/dist/config/parsers/boolean/bool.parser.d.ts +0 -6
- package/dist/config/parsers/boolean/bool.parser.js +0 -20
- package/dist/config/parsers/boolean/bool.parser.js.map +0 -1
- package/dist/config/parsers/boolean/index.d.ts +0 -1
- package/dist/config/parsers/boolean/index.js +0 -18
- package/dist/config/parsers/boolean/index.js.map +0 -1
- package/dist/config/parsers/enum/enum.parser.d.ts +0 -9
- package/dist/config/parsers/enum/enum.parser.js +0 -24
- package/dist/config/parsers/enum/enum.parser.js.map +0 -1
- package/dist/config/parsers/enum/index.d.ts +0 -1
- package/dist/config/parsers/enum/index.js.map +0 -1
- package/dist/config/parsers/index.d.ts +0 -11
- package/dist/config/parsers/index.js +0 -28
- package/dist/config/parsers/index.js.map +0 -1
- package/dist/config/parsers/int/index.d.ts +0 -1
- package/dist/config/parsers/int/index.js +0 -18
- package/dist/config/parsers/int/index.js.map +0 -1
- package/dist/config/parsers/int/int.parser.d.ts +0 -6
- package/dist/config/parsers/int/int.parser.js +0 -20
- package/dist/config/parsers/int/int.parser.js.map +0 -1
- package/dist/config/parsers/json/index.d.ts +0 -1
- package/dist/config/parsers/json/index.js +0 -18
- package/dist/config/parsers/json/index.js.map +0 -1
- package/dist/config/parsers/json/json.parser.d.ts +0 -6
- package/dist/config/parsers/json/json.parser.js +0 -16
- package/dist/config/parsers/json/json.parser.js.map +0 -1
- package/dist/config/parsers/number/index.d.ts +0 -1
- package/dist/config/parsers/number/index.js +0 -18
- package/dist/config/parsers/number/index.js.map +0 -1
- package/dist/config/parsers/number/number.parser.d.ts +0 -6
- package/dist/config/parsers/number/number.parser.js +0 -23
- package/dist/config/parsers/number/number.parser.js.map +0 -1
- package/dist/config/parsers/path/fspath.parser.d.ts +0 -8
- package/dist/config/parsers/path/fspath.parser.js +0 -59
- package/dist/config/parsers/path/fspath.parser.js.map +0 -1
- package/dist/config/parsers/path/index.d.ts +0 -1
- package/dist/config/parsers/path/index.js +0 -18
- package/dist/config/parsers/path/index.js.map +0 -1
- package/dist/config/parsers/size/index.d.ts +0 -1
- package/dist/config/parsers/size/index.js +0 -18
- package/dist/config/parsers/size/index.js.map +0 -1
- package/dist/config/parsers/size/size.parser.d.ts +0 -7
- package/dist/config/parsers/size/size.parser.js +0 -21
- package/dist/config/parsers/size/size.parser.js.map +0 -1
- package/dist/config/parsers/string/index.d.ts +0 -1
- package/dist/config/parsers/string/index.js +0 -18
- package/dist/config/parsers/string/index.js.map +0 -1
- package/dist/config/parsers/string/string.parser.d.ts +0 -8
- package/dist/config/parsers/string/string.parser.js +0 -29
- package/dist/config/parsers/string/string.parser.js.map +0 -1
- package/dist/config/parsers/timespan/index.d.ts +0 -1
- package/dist/config/parsers/timespan/index.js +0 -18
- package/dist/config/parsers/timespan/index.js.map +0 -1
- package/dist/config/parsers/timespan/timespan.parser.d.ts +0 -7
- package/dist/config/parsers/timespan/timespan.parser.js +0 -21
- package/dist/config/parsers/timespan/timespan.parser.js.map +0 -1
- package/dist/config/parsers/url/exception.d.ts +0 -7
- package/dist/config/parsers/url/exception.js +0 -25
- package/dist/config/parsers/url/exception.js.map +0 -1
- package/dist/config/parsers/url/index.d.ts +0 -2
- package/dist/config/parsers/url/index.js +0 -21
- package/dist/config/parsers/url/index.js.map +0 -1
- package/dist/config/parsers/url/url.parser.d.ts +0 -9
- package/dist/config/parsers/url/url.parser.js +0 -38
- package/dist/config/parsers/url/url.parser.js.map +0 -1
- package/dist/logging/logger-initializing.module.d.ts +0 -6
- package/dist/logging/logger-initializing.module.js.map +0 -1
- package/dist/logging/logging.module.js.map +0 -1
- package/src/config/parsers/array/array.parser.ts +0 -34
- package/src/config/parsers/array/index.ts +0 -1
- package/src/config/parsers/boolean/bool.parser.ts +0 -20
- package/src/config/parsers/boolean/bool.spec.ts +0 -4
- package/src/config/parsers/boolean/index.ts +0 -1
- package/src/config/parsers/enum/enum.parser.ts +0 -23
- package/src/config/parsers/enum/enum.spec.ts +0 -5
- package/src/config/parsers/enum/index.ts +0 -1
- package/src/config/parsers/index.ts +0 -11
- package/src/config/parsers/int/index.ts +0 -1
- package/src/config/parsers/int/int.parser.ts +0 -20
- package/src/config/parsers/int/int.spec.ts +0 -5
- package/src/config/parsers/json/index.ts +0 -1
- package/src/config/parsers/json/json.parser.ts +0 -15
- package/src/config/parsers/number/index.ts +0 -1
- package/src/config/parsers/number/number.parser.ts +0 -23
- package/src/config/parsers/number/number.spec.ts +0 -5
- package/src/config/parsers/path/fspath.parser.ts +0 -64
- package/src/config/parsers/path/index.ts +0 -1
- package/src/config/parsers/size/index.ts +0 -1
- package/src/config/parsers/size/size.parser.ts +0 -22
- package/src/config/parsers/size/size.spec.ts +0 -4
- package/src/config/parsers/string/index.ts +0 -1
- package/src/config/parsers/string/string.parser.ts +0 -26
- package/src/config/parsers/string/string.spec.ts +0 -10
- package/src/config/parsers/timespan/index.ts +0 -1
- package/src/config/parsers/timespan/timespan.parser.ts +0 -22
- package/src/config/parsers/timespan/timespan.spec.ts +0 -5
- package/src/config/parsers/url/exception.ts +0 -21
- package/src/config/parsers/url/index.ts +0 -2
- package/src/config/parsers/url/url.parser.ts +0 -44
- package/src/logging/logger-initializing.module.ts +0 -55
package/src/config/types.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import type { PropertyParser } from '@rsdk/common';
|
|
2
|
+
|
|
1
3
|
export type SourceType = 'static' | 'reloadable';
|
|
2
4
|
|
|
3
5
|
export interface Changes {
|
|
@@ -54,29 +56,6 @@ export interface ParserMetadata {
|
|
|
54
56
|
description: string;
|
|
55
57
|
}
|
|
56
58
|
|
|
57
|
-
/**
|
|
58
|
-
* Implement this interface to create more parsers.
|
|
59
|
-
* For example: email, BigInt, guid etc.
|
|
60
|
-
*
|
|
61
|
-
* NOTE: In other modules it is more common to define metadata
|
|
62
|
-
* via decorators. But this case is a bit different.
|
|
63
|
-
*
|
|
64
|
-
* 1. Parser implementations can have constructors with parameters
|
|
65
|
-
* which will affect it's behaviour. It's will be nice to have it
|
|
66
|
-
* in metadata, and decorators won't provide this.
|
|
67
|
-
*
|
|
68
|
-
* 2. Metadata will be extracted via type() and description() methods
|
|
69
|
-
* mostly during decorator factories (such as @Property()) code is
|
|
70
|
-
* executed. Thus output **can** be used in autodoc
|
|
71
|
-
*/
|
|
72
|
-
export interface PropertyParser<T = any> {
|
|
73
|
-
type(): string;
|
|
74
|
-
|
|
75
|
-
description(): string;
|
|
76
|
-
|
|
77
|
-
parse(value: unknown): T;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
59
|
export type RawValues = Map<string, unknown>;
|
|
81
60
|
|
|
82
61
|
export enum AppNameStrategyType {
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { IErrorsFormatter } from './types';
|
|
2
|
+
|
|
3
|
+
export class DefaultFormatter implements IErrorsFormatter {
|
|
4
|
+
readonly protocol = 'default';
|
|
5
|
+
|
|
6
|
+
format(ex: unknown, verbose: boolean): unknown {
|
|
7
|
+
return verbose ? ex : { message: 'NO FORMATTER' };
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export const DEFAULT_FORMATTER = new DefaultFormatter();
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { ArgumentsHost } from '@nestjs/common';
|
|
2
|
+
import type { Observable } from 'rxjs';
|
|
3
|
+
import { throwError } from 'rxjs';
|
|
4
|
+
|
|
5
|
+
import type { IErrorsSender } from './types';
|
|
6
|
+
|
|
7
|
+
export class DefaultSender implements IErrorsSender {
|
|
8
|
+
readonly protocol = 'default';
|
|
9
|
+
|
|
10
|
+
send(_: ArgumentsHost, ex: unknown): Observable<any> {
|
|
11
|
+
return throwError(() => ex);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export const DEFAULT_SENDER = new DefaultSender();
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { text } from '@rsdk/common';
|
|
1
|
+
import { BoolParser, text } from '@rsdk/common';
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { Config, ConfigSection, Property } from '../config';
|
|
4
4
|
import { ConfigTag } from '../config/config.const';
|
|
5
5
|
|
|
6
6
|
@ConfigSection({
|
|
@@ -1,109 +1,77 @@
|
|
|
1
1
|
import type { ArgumentsHost, ExceptionFilter } from '@nestjs/common';
|
|
2
2
|
import { Catch, Inject } from '@nestjs/common';
|
|
3
|
-
import { normalizer, sortErrorKeys } from '@rsdk/common';
|
|
4
|
-
import { ILogger } from '@rsdk/logging';
|
|
3
|
+
import { normalizer, sortErrorKeys, text } from '@rsdk/common';
|
|
5
4
|
import type { Observable } from 'rxjs';
|
|
6
|
-
import { throwError } from 'rxjs';
|
|
7
5
|
|
|
8
|
-
import {
|
|
9
|
-
import { InjectLogger } from '../logging';
|
|
6
|
+
import { PipelineException } from '../exceptions';
|
|
7
|
+
import { ILogger, InjectLogger } from '../logging';
|
|
10
8
|
import { ProtocolDetector } from '../transport/protocol.detector';
|
|
11
9
|
|
|
12
|
-
import { FORMATTERS, SENDERS
|
|
10
|
+
import { FORMATTERS, SENDERS } from './constants';
|
|
11
|
+
import { DEFAULT_FORMATTER } from './default.formatter';
|
|
12
|
+
import { DEFAULT_SENDER } from './default.sender';
|
|
13
13
|
import { GlobalExceptionsConfig } from './global-exceptions.config';
|
|
14
|
-
import type {
|
|
15
|
-
IErrorsFormatter,
|
|
16
|
-
IErrorsSender,
|
|
17
|
-
IErrorsTransformer,
|
|
18
|
-
} from './types';
|
|
14
|
+
import type { IErrorsFormatter, IErrorsSender } from './types';
|
|
19
15
|
|
|
20
16
|
@Catch()
|
|
21
17
|
export class GlobalExceptionsFilter implements ExceptionFilter {
|
|
22
18
|
constructor(
|
|
23
|
-
|
|
24
|
-
@Inject(
|
|
25
|
-
@Inject(
|
|
26
|
-
@InjectLogger(GlobalExceptionsFilter)
|
|
27
|
-
private readonly logger: ILogger,
|
|
28
|
-
private readonly config: GlobalExceptionsConfig,
|
|
19
|
+
/* eslint-disable prettier/prettier */
|
|
20
|
+
@Inject(SENDERS) private readonly senders: Map<string, IErrorsSender>,
|
|
21
|
+
@Inject(FORMATTERS) private readonly formatters: Map<string, IErrorsFormatter>,
|
|
22
|
+
@InjectLogger(GlobalExceptionsFilter) private readonly logger: ILogger,
|
|
29
23
|
private readonly detector: ProtocolDetector,
|
|
24
|
+
private readonly config: GlobalExceptionsConfig,
|
|
25
|
+
/* eslint-enable prettier/prettier */
|
|
30
26
|
) {}
|
|
31
27
|
|
|
32
|
-
catch(ex:
|
|
33
|
-
const
|
|
34
|
-
ex instanceof PipelineException ? ex : this.transform(ex);
|
|
35
|
-
|
|
36
|
-
// Error is transformed to standard PipelineException
|
|
37
|
-
this.logger.error(transformed);
|
|
38
|
-
|
|
39
|
-
const formatted = this.format(host, transformed);
|
|
40
|
-
|
|
41
|
-
return this.send(host, formatted);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
private transform(ex: any): PipelineException {
|
|
45
|
-
const transformer = this.transformers.find((x) => x.match(ex));
|
|
46
|
-
if (transformer) {
|
|
47
|
-
return transformer.transform(ex);
|
|
48
|
-
}
|
|
28
|
+
catch(ex: PipelineException, host: ArgumentsHost): Observable<any> {
|
|
29
|
+
const protocol = this.detector.getProtocol(host);
|
|
49
30
|
|
|
50
|
-
const
|
|
31
|
+
const sender = this.getSender(host, protocol);
|
|
32
|
+
const formatter = this.getFormatter(host, protocol);
|
|
51
33
|
|
|
52
|
-
|
|
34
|
+
const formatted = formatter.format(ex, this.config.verbose);
|
|
35
|
+
const normalized = normalizer()(formatted, {
|
|
36
|
+
filterKeys: ['stack'],
|
|
37
|
+
sortKeys: sortErrorKeys,
|
|
38
|
+
});
|
|
53
39
|
|
|
54
|
-
return
|
|
40
|
+
return sender.send(host, normalized);
|
|
55
41
|
}
|
|
56
42
|
|
|
57
|
-
private
|
|
58
|
-
const
|
|
59
|
-
|
|
43
|
+
private getSender(host: ArgumentsHost, protocol: string): IErrorsSender {
|
|
44
|
+
const sender =
|
|
45
|
+
this.senders.get(protocol) ?? this.senders.get(host.getType());
|
|
60
46
|
|
|
61
|
-
if (
|
|
62
|
-
this.logger.trace(`Found
|
|
63
|
-
|
|
64
|
-
return formatter.format(ex, this.config.verbose);
|
|
47
|
+
if (sender) {
|
|
48
|
+
this.logger.trace(`Found sender: ${sender.constructor.name}`);
|
|
49
|
+
return sender;
|
|
65
50
|
}
|
|
66
51
|
|
|
67
|
-
this.logger.
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
return normalizer()(ex, {
|
|
71
|
-
// This means stacktrace will never be sent to user
|
|
72
|
-
filterKeys: ['stack'],
|
|
73
|
-
sortKeys: sortErrorKeys,
|
|
74
|
-
}) as object;
|
|
75
|
-
}
|
|
52
|
+
this.logger.warn(text`
|
|
53
|
+
No sender for protocol = ${protocol}
|
|
54
|
+
(hostType = ${host.getType()})`);
|
|
76
55
|
|
|
77
|
-
return
|
|
56
|
+
return DEFAULT_SENDER;
|
|
78
57
|
}
|
|
79
58
|
|
|
80
59
|
private getFormatter(
|
|
81
60
|
host: ArgumentsHost,
|
|
82
|
-
protocol: string
|
|
83
|
-
): IErrorsFormatter
|
|
84
|
-
|
|
85
|
-
this.formatters.
|
|
86
|
-
this.formatters.find((x) => x.protocol === host.getType())
|
|
87
|
-
);
|
|
88
|
-
}
|
|
61
|
+
protocol: string,
|
|
62
|
+
): IErrorsFormatter {
|
|
63
|
+
const formatter =
|
|
64
|
+
this.formatters.get(protocol) ?? this.formatters.get(host.getType());
|
|
89
65
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
66
|
+
if (formatter) {
|
|
67
|
+
this.logger.trace(`Found formatter: ${formatter.constructor.name}`);
|
|
68
|
+
return formatter;
|
|
69
|
+
}
|
|
93
70
|
|
|
94
|
-
|
|
95
|
-
|
|
71
|
+
this.logger.warn(text`
|
|
72
|
+
No formatter for protocol = ${protocol}
|
|
73
|
+
(hostType = ${host.getType()})`);
|
|
96
74
|
|
|
97
|
-
|
|
98
|
-
host: ArgumentsHost,
|
|
99
|
-
protocol: string | undefined,
|
|
100
|
-
): IErrorsSender | undefined {
|
|
101
|
-
const s: IErrorsSender | undefined = this.senders.find(
|
|
102
|
-
(x) => x.protocol === protocol,
|
|
103
|
-
);
|
|
104
|
-
if (!s) {
|
|
105
|
-
return this.senders.find((x) => x.protocol === host.getType());
|
|
106
|
-
}
|
|
107
|
-
return s;
|
|
75
|
+
return DEFAULT_FORMATTER;
|
|
108
76
|
}
|
|
109
77
|
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
CallHandler,
|
|
3
|
+
ExecutionContext,
|
|
4
|
+
NestInterceptor,
|
|
5
|
+
} from '@nestjs/common';
|
|
6
|
+
import { Inject, Injectable } from '@nestjs/common';
|
|
7
|
+
import type { Observable } from 'rxjs';
|
|
8
|
+
import { catchError, throwError } from 'rxjs';
|
|
9
|
+
|
|
10
|
+
import { InternalException, PipelineException } from '../exceptions';
|
|
11
|
+
|
|
12
|
+
import { TRANSFORMERS } from './constants';
|
|
13
|
+
import type { IErrorsTransformer } from './types';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Обработка ошибки состоит из трёх этапов:
|
|
17
|
+
* 1. Трансформация ошибки в PipelineException
|
|
18
|
+
* 2. Логирование ошибки
|
|
19
|
+
* 3. Отправка ошибки клиенту, в зависимости от транспорта.
|
|
20
|
+
*
|
|
21
|
+
* Этот интерцептор отвечает за 1-й этап. Важно, что в пайплайне обработки
|
|
22
|
+
* он должен стоять перед LoggingInterceptor, который обеспечивает логирование
|
|
23
|
+
*/
|
|
24
|
+
@Injectable()
|
|
25
|
+
export class GlobalExceptionsInterceptor implements NestInterceptor {
|
|
26
|
+
constructor(
|
|
27
|
+
@Inject(TRANSFORMERS) private readonly transformers: IErrorsTransformer[],
|
|
28
|
+
) {}
|
|
29
|
+
|
|
30
|
+
intercept(
|
|
31
|
+
_: ExecutionContext,
|
|
32
|
+
next: CallHandler<any>,
|
|
33
|
+
): Observable<any> | Promise<Observable<any>> {
|
|
34
|
+
return next.handle().pipe(
|
|
35
|
+
catchError((error) => {
|
|
36
|
+
// Error is transformed to standard PipelineException
|
|
37
|
+
const transformed =
|
|
38
|
+
error instanceof PipelineException ? error : this.transform(error);
|
|
39
|
+
|
|
40
|
+
return throwError(() => transformed);
|
|
41
|
+
}),
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
private transform(ex: any): PipelineException {
|
|
46
|
+
const transformer = this.transformers.find((x) => x.match(ex));
|
|
47
|
+
if (transformer) {
|
|
48
|
+
return transformer.transform(ex);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const err = new InternalException(ex.message ?? 'UNKNOWN ERROR', ex);
|
|
52
|
+
|
|
53
|
+
err.stack = ex.stack;
|
|
54
|
+
|
|
55
|
+
return err;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
@@ -1,60 +1,73 @@
|
|
|
1
1
|
import type { DynamicModule } from '@nestjs/common';
|
|
2
2
|
import { Module } from '@nestjs/common';
|
|
3
|
-
import { APP_FILTER } from '@nestjs/core';
|
|
3
|
+
import { APP_FILTER, APP_INTERCEPTOR } from '@nestjs/core';
|
|
4
|
+
|
|
5
|
+
import { PlatformExtendedOptions } from '../types';
|
|
4
6
|
|
|
5
7
|
import { FORMATTERS, SENDERS, TRANSFORMERS } from './constants';
|
|
6
8
|
import { GlobalExceptionsFilter } from './global-exceptions.filter';
|
|
7
|
-
import
|
|
8
|
-
|
|
9
|
-
IErrorsSender,
|
|
10
|
-
IErrorsTransformer,
|
|
11
|
-
} from './types';
|
|
9
|
+
import { GlobalExceptionsInterceptor } from './global-exceptions.interceptor';
|
|
10
|
+
import { IErrorsFormatter, IErrorsSender } from './types';
|
|
12
11
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
12
|
+
@Module({})
|
|
13
|
+
export class GlobalExceptionsModule {
|
|
14
|
+
static forRoot(options: PlatformExtendedOptions): DynamicModule {
|
|
15
|
+
const entities = [
|
|
16
|
+
...(options.transports || []),
|
|
17
|
+
...(options.plugins || []),
|
|
18
|
+
];
|
|
20
19
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
20
|
+
/**
|
|
21
|
+
* Formatters are used to transform exceptions to transport specific
|
|
22
|
+
* final implementations. Usually formatter expects transport agnostic
|
|
23
|
+
* subclasses of BaseException.
|
|
24
|
+
*/
|
|
25
|
+
const formatters: Map<string, IErrorsFormatter> = entities
|
|
26
|
+
.flatMap((x) => x.errorFormatter?.() || [])
|
|
27
|
+
.reduce((acc, x) => acc.set(x.protocol, x), new Map());
|
|
26
28
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
29
|
+
/**
|
|
30
|
+
* Senders are used to actually respond to client (algorithm
|
|
31
|
+
* is transport specific)
|
|
32
|
+
*/
|
|
33
|
+
const senders: Map<string, IErrorsSender> = entities
|
|
34
|
+
.flatMap((x) => x.errorSender?.() || [])
|
|
35
|
+
.reduce((acc, x) => acc.set(x.protocol, x), new Map());
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Sometimes application throws a lot of unconventional
|
|
39
|
+
* (not inheriting BaseExceptions). Usually they are throw by
|
|
40
|
+
* libraries: typeorm, axios, etc. Transformers are used to
|
|
41
|
+
* catch them and convert to any subtype of BaseException which
|
|
42
|
+
* will be processed further by transport specific formatters.
|
|
43
|
+
*
|
|
44
|
+
* NOTE: Unlike formatters and senders, transformers can't be grouped
|
|
45
|
+
* by protocol, because their matchers are a bit more complex.
|
|
46
|
+
*/
|
|
47
|
+
const transformers = entities.flatMap((x) => x.errorTransformers?.() || []);
|
|
36
48
|
|
|
37
|
-
@Module({})
|
|
38
|
-
export class GlobalExceptionsModule {
|
|
39
|
-
static forRoot(options: GlobalExceptionModuleOptions): DynamicModule {
|
|
40
49
|
return {
|
|
41
50
|
module: GlobalExceptionsModule,
|
|
42
51
|
providers: [
|
|
52
|
+
{
|
|
53
|
+
provide: APP_INTERCEPTOR,
|
|
54
|
+
useClass: GlobalExceptionsInterceptor,
|
|
55
|
+
},
|
|
43
56
|
{
|
|
44
57
|
provide: APP_FILTER,
|
|
45
58
|
useClass: GlobalExceptionsFilter,
|
|
46
59
|
},
|
|
47
60
|
{
|
|
48
61
|
provide: FORMATTERS,
|
|
49
|
-
useValue:
|
|
62
|
+
useValue: formatters,
|
|
50
63
|
},
|
|
51
64
|
{
|
|
52
65
|
provide: SENDERS,
|
|
53
|
-
useValue:
|
|
66
|
+
useValue: senders,
|
|
54
67
|
},
|
|
55
68
|
{
|
|
56
69
|
provide: TRANSFORMERS,
|
|
57
|
-
useValue:
|
|
70
|
+
useValue: transformers,
|
|
58
71
|
},
|
|
59
72
|
],
|
|
60
73
|
};
|
|
@@ -5,7 +5,7 @@ import type { PipelineException } from '../exceptions/base';
|
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Errors formatter is used to map transport-agnostic
|
|
8
|
-
*
|
|
8
|
+
* business exception to transport-specific on (with appropriate
|
|
9
9
|
* status code and other attributes)
|
|
10
10
|
*
|
|
11
11
|
* @implementme Implement this interface if you need to create a
|
|
@@ -73,7 +73,7 @@ export interface IErrorsTransformer {
|
|
|
73
73
|
match(ex: any): boolean;
|
|
74
74
|
|
|
75
75
|
/**
|
|
76
|
-
*
|
|
76
|
+
* Transformation algorithm
|
|
77
77
|
*
|
|
78
78
|
* @param ex Exception itself
|
|
79
79
|
*/
|
package/src/index.ts
CHANGED
|
@@ -37,7 +37,7 @@ export * from './exceptions';
|
|
|
37
37
|
|
|
38
38
|
export * from './exceptions.handling';
|
|
39
39
|
|
|
40
|
-
export { InjectLogger } from './logging';
|
|
40
|
+
export { InjectLogger, LogFormatter, LogLevel } from './logging';
|
|
41
41
|
|
|
42
42
|
export {
|
|
43
43
|
AnyMetric,
|
|
@@ -58,4 +58,55 @@ export * from './app-metadata/decorators';
|
|
|
58
58
|
|
|
59
59
|
export * from './app-metadata/app-metadata.const';
|
|
60
60
|
|
|
61
|
-
export {
|
|
61
|
+
export {
|
|
62
|
+
withPrefix,
|
|
63
|
+
generateDefault,
|
|
64
|
+
RequestIdGenStrategy,
|
|
65
|
+
TracingHeaders,
|
|
66
|
+
} from './tracing';
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* FIXME: Remove this after migration to @rsdk/common
|
|
70
|
+
*/
|
|
71
|
+
|
|
72
|
+
export {
|
|
73
|
+
// eslint-disable-next-line prettier/prettier
|
|
74
|
+
/** @deprecated Import from @rsdk/common instead */
|
|
75
|
+
ArrayParser,
|
|
76
|
+
|
|
77
|
+
/** @deprecated Import from @rsdk/common instead */
|
|
78
|
+
BoolParser,
|
|
79
|
+
|
|
80
|
+
/** @deprecated Import from @rsdk/common instead */
|
|
81
|
+
EnumParser,
|
|
82
|
+
|
|
83
|
+
/** @deprecated Import from @rsdk/common instead */
|
|
84
|
+
IntParser,
|
|
85
|
+
|
|
86
|
+
/** @deprecated Import from @rsdk/common instead */
|
|
87
|
+
JsonParser,
|
|
88
|
+
|
|
89
|
+
/** @deprecated Import from @rsdk/common instead */
|
|
90
|
+
NumberParser,
|
|
91
|
+
|
|
92
|
+
/** @deprecated Import from @rsdk/common instead */
|
|
93
|
+
PropertyParser,
|
|
94
|
+
|
|
95
|
+
/** @deprecated Import from @rsdk/common instead */
|
|
96
|
+
SizeParser,
|
|
97
|
+
|
|
98
|
+
/** @deprecated Import from @rsdk/common instead */
|
|
99
|
+
StringParser,
|
|
100
|
+
|
|
101
|
+
/** @deprecated Import from @rsdk/common instead */
|
|
102
|
+
UrlParser,
|
|
103
|
+
|
|
104
|
+
/** @deprecated Import from @rsdk/common instead */
|
|
105
|
+
TimespanParser,
|
|
106
|
+
} from '@rsdk/common';
|
|
107
|
+
|
|
108
|
+
export {
|
|
109
|
+
// eslint-disable-next-line @stylistic/lines-around-comment
|
|
110
|
+
/** @deprecated Import from @rsdk/common.node instead */
|
|
111
|
+
FsPathParser,
|
|
112
|
+
} from '@rsdk/common.node';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const LOG_FORMATTERS = Symbol('LOG_FORMATTERS');
|
|
@@ -2,7 +2,7 @@ import { Inject } from '@nestjs/common';
|
|
|
2
2
|
import type { Constructor } from '@rsdk/common';
|
|
3
3
|
|
|
4
4
|
import { getLoggerToken } from '../helpers';
|
|
5
|
-
import {
|
|
5
|
+
import { LoggerInstancesModule } from '../logging-instances.module';
|
|
6
6
|
|
|
7
7
|
export const InjectLogger = (
|
|
8
8
|
context: string | Constructor,
|
|
@@ -11,6 +11,6 @@ export const InjectLogger = (
|
|
|
11
11
|
const token = getLoggerToken(context);
|
|
12
12
|
|
|
13
13
|
Inject(token)(target, propertyKey, parameterIndex);
|
|
14
|
-
|
|
14
|
+
LoggerInstancesModule.register(target, context, token);
|
|
15
15
|
};
|
|
16
16
|
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { LogFormatter } from './interfaces';
|
|
2
|
+
|
|
3
|
+
export class DefaultLogFormatter implements LogFormatter {
|
|
4
|
+
readonly protocol = '__default';
|
|
5
|
+
|
|
6
|
+
getPath(): string {
|
|
7
|
+
return 'unknown';
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
formatRequest(): Record<string, unknown> {
|
|
11
|
+
return {};
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
formatResponse(): Record<string, unknown> {
|
|
15
|
+
return {};
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { ExecutionContext } from '@nestjs/common';
|
|
2
|
+
|
|
3
|
+
export interface LogFormatter {
|
|
4
|
+
readonly protocol: string;
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Получает путь запроса - строку, по которой будет проще всего идентифицировать запрос
|
|
8
|
+
* Например для GRPC это будет путь запроса, для HTTP это будет url, для Kafka - топик
|
|
9
|
+
*/
|
|
10
|
+
getPath(context: ExecutionContext): string;
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Форматирует запрос
|
|
14
|
+
*/
|
|
15
|
+
formatRequest(
|
|
16
|
+
context: ExecutionContext,
|
|
17
|
+
includeBody: boolean,
|
|
18
|
+
): Record<string, unknown>;
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Форматирует ответ
|
|
22
|
+
*/
|
|
23
|
+
formatResponse(
|
|
24
|
+
context: ExecutionContext,
|
|
25
|
+
body: unknown | undefined,
|
|
26
|
+
): Record<string, unknown>;
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Определяет, нужно ли логировать запрос. Строго говоря,
|
|
30
|
+
* это костыль исключительно под graphql, чтобы не логировать
|
|
31
|
+
* отдельно вызов каждого резолвера.
|
|
32
|
+
*/
|
|
33
|
+
shouldLog?(context: ExecutionContext): boolean;
|
|
34
|
+
}
|
package/src/logging/index.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
export * from '@rsdk/logging';
|
|
2
|
-
export * from './logging.module';
|
|
3
2
|
export * from './adapters';
|
|
4
3
|
export * from './decorators';
|
|
4
|
+
export * from './formatters';
|
|
5
5
|
export { LOGGING_RSDK_METADATA_SCOPE } from './metadata/constants';
|
|
6
6
|
export { LoggingRsdkMetadata } from './types';
|
|
7
|
-
export {
|
|
7
|
+
export { LoggerInstancesModule } from './logging-instances.module';
|
|
8
|
+
export { LoggingCoreModule } from './logging-core.module';
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { DynamicModule, Module } from '@nestjs/common';
|
|
2
|
+
import { APP_INTERCEPTOR } from '@nestjs/core';
|
|
3
|
+
import { LoggerFactory } from '@rsdk/logging';
|
|
4
|
+
import type { TransportMultiOptions, TransportTargetOptions } from 'pino';
|
|
5
|
+
import pino from 'pino';
|
|
6
|
+
|
|
7
|
+
import { SequenceException } from '../exceptions';
|
|
8
|
+
import type { PlatformExtendedOptions } from '../types';
|
|
9
|
+
|
|
10
|
+
import { LOG_FORMATTERS } from './constants';
|
|
11
|
+
import { LogFormatter } from './formatters';
|
|
12
|
+
import { LoggingConfig } from './logging.config';
|
|
13
|
+
import { LoggingInterceptor } from './logging.interceptor';
|
|
14
|
+
|
|
15
|
+
@Module({})
|
|
16
|
+
export class LoggingCoreModule {
|
|
17
|
+
private static logger = LoggerFactory.create(LoggingCoreModule);
|
|
18
|
+
|
|
19
|
+
constructor(config: LoggingConfig) {
|
|
20
|
+
const cfg = (): void => {
|
|
21
|
+
LoggingCoreModule.logger.info(`Setting log level: <${config.level}>`, {
|
|
22
|
+
logLevel: config.level,
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
LoggerFactory.reconfigure({
|
|
26
|
+
...config,
|
|
27
|
+
stream: pino.transport(this.buildTransportOptions(config)),
|
|
28
|
+
});
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
config.onUpdate(cfg);
|
|
32
|
+
cfg();
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
static forRoot(options: PlatformExtendedOptions): DynamicModule {
|
|
36
|
+
return {
|
|
37
|
+
module: LoggingCoreModule,
|
|
38
|
+
providers: [
|
|
39
|
+
{
|
|
40
|
+
provide: APP_INTERCEPTOR,
|
|
41
|
+
useClass: LoggingInterceptor,
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
provide: LOG_FORMATTERS,
|
|
45
|
+
useValue: this.buildFormattersMap(options),
|
|
46
|
+
},
|
|
47
|
+
],
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
private static buildFormattersMap(
|
|
52
|
+
options: PlatformExtendedOptions,
|
|
53
|
+
): Map<string, LogFormatter> {
|
|
54
|
+
const transports = options.transports || [];
|
|
55
|
+
const plugins = options.plugins || [];
|
|
56
|
+
|
|
57
|
+
const array: LogFormatter[] = [
|
|
58
|
+
...transports.map((x) => x.logFormatter()),
|
|
59
|
+
...plugins.flatMap((x) => x.logFormatter?.() || []),
|
|
60
|
+
];
|
|
61
|
+
|
|
62
|
+
const formatters = new Map<string, LogFormatter>();
|
|
63
|
+
|
|
64
|
+
for (const formatter of array) {
|
|
65
|
+
if (formatters.has(formatter.protocol)) {
|
|
66
|
+
throw new SequenceException(
|
|
67
|
+
`log formatter for ${formatter.protocol} already registered`,
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
formatters.set(formatter.protocol, formatter);
|
|
72
|
+
this.logger.debug(`registered log formatter for ${formatter.protocol}`);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return formatters;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
private buildTransportOptions(config: LoggingConfig): TransportMultiOptions {
|
|
79
|
+
const targets: TransportTargetOptions[] = [
|
|
80
|
+
{
|
|
81
|
+
target: 'pino/file',
|
|
82
|
+
options: { destination: process.stdout.fd },
|
|
83
|
+
level: config.level,
|
|
84
|
+
},
|
|
85
|
+
];
|
|
86
|
+
|
|
87
|
+
if (config.otelEnabled) {
|
|
88
|
+
targets.push({
|
|
89
|
+
target: 'pino-opentelemetry-transport',
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* NOTE: {} required to avoid runtime error "Cannot read property 'xxx' of undefined"
|
|
93
|
+
* (unsafe destructuring in pino-opentelemetry-transport)
|
|
94
|
+
*/
|
|
95
|
+
options: {},
|
|
96
|
+
level: config.level,
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return { targets };
|
|
101
|
+
}
|
|
102
|
+
}
|