@rsdk/core 5.7.0-next.3 → 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
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
/* eslint-disable sort-keys */
|
|
2
|
-
|
|
3
1
|
import type { DynamicModule } from '@nestjs/common';
|
|
4
2
|
import { Module } from '@nestjs/common';
|
|
5
3
|
import type { Constructor } from '@rsdk/common';
|
|
@@ -15,7 +13,7 @@ import { getLoggerToken } from './helpers';
|
|
|
15
13
|
import type { LoggingRsdkMetadata } from './types';
|
|
16
14
|
|
|
17
15
|
@Module({})
|
|
18
|
-
export class
|
|
16
|
+
export class LoggerInstancesModule {
|
|
19
17
|
static register(
|
|
20
18
|
target: object,
|
|
21
19
|
context: string | Constructor,
|
|
@@ -73,7 +71,7 @@ export class LoggingModule {
|
|
|
73
71
|
): DynamicModule {
|
|
74
72
|
return {
|
|
75
73
|
global: true,
|
|
76
|
-
module:
|
|
74
|
+
module: LoggerInstancesModule,
|
|
77
75
|
providers: [
|
|
78
76
|
{
|
|
79
77
|
provide: token,
|
|
@@ -1,14 +1,12 @@
|
|
|
1
|
-
import { DEFAULT_LEVEL, LogLevel } from '@rsdk/logging';
|
|
2
|
-
|
|
3
1
|
import {
|
|
4
2
|
ArrayParser,
|
|
5
3
|
BoolParser,
|
|
6
|
-
Config,
|
|
7
|
-
ConfigSection,
|
|
8
4
|
EnumParser,
|
|
9
|
-
Property,
|
|
10
5
|
StringParser,
|
|
11
|
-
} from '
|
|
6
|
+
} from '@rsdk/common';
|
|
7
|
+
import { DEFAULT_LEVEL, LogLevel } from '@rsdk/logging';
|
|
8
|
+
|
|
9
|
+
import { Config, ConfigSection, Property } from '../config';
|
|
12
10
|
import { ConfigTag } from '../config/config.const';
|
|
13
11
|
|
|
14
12
|
@ConfigSection({
|
|
@@ -41,4 +39,22 @@ export class LoggingConfig extends Config {
|
|
|
41
39
|
description: 'Enable OpenTelemetry exporter',
|
|
42
40
|
})
|
|
43
41
|
readonly otelEnabled!: boolean;
|
|
42
|
+
|
|
43
|
+
@Property('LOG_EXCLUDE_ZONES', new ArrayParser(new StringParser()), {
|
|
44
|
+
defaultValue: [],
|
|
45
|
+
description: 'Disable request/response logging for zones',
|
|
46
|
+
})
|
|
47
|
+
readonly excludeZones!: string[];
|
|
48
|
+
|
|
49
|
+
@Property('LOG_REQUEST_BODY', new BoolParser(), {
|
|
50
|
+
description: 'Enable request body (content) logging',
|
|
51
|
+
defaultValue: false,
|
|
52
|
+
})
|
|
53
|
+
readonly logRequestBody!: boolean;
|
|
54
|
+
|
|
55
|
+
@Property('LOG_RESPONSE_BODY', new BoolParser(), {
|
|
56
|
+
description: 'Enable response body (content) logging',
|
|
57
|
+
defaultValue: false,
|
|
58
|
+
})
|
|
59
|
+
readonly logResponseBody!: boolean;
|
|
44
60
|
}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
CallHandler,
|
|
3
|
+
ExecutionContext,
|
|
4
|
+
NestInterceptor,
|
|
5
|
+
} from '@nestjs/common';
|
|
6
|
+
import { Inject, Injectable } from '@nestjs/common';
|
|
7
|
+
import { ILogger } from '@rsdk/logging';
|
|
8
|
+
import { Zone } from '@rsdk/zones';
|
|
9
|
+
import type { Observable } from 'rxjs';
|
|
10
|
+
import { catchError, tap, throwError } from 'rxjs';
|
|
11
|
+
|
|
12
|
+
import { PipelineException } from '../exceptions';
|
|
13
|
+
import { ProtocolDetector } from '../transport/protocol.detector';
|
|
14
|
+
|
|
15
|
+
import { InjectLogger } from './decorators/inject-logger.decorator';
|
|
16
|
+
import { LOG_FORMATTERS } from './constants';
|
|
17
|
+
import { DefaultLogFormatter, LogFormatter } from './formatters';
|
|
18
|
+
import { LoggingConfig } from './logging.config';
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* LOG_LEVEL=
|
|
22
|
+
* LOG_REDACT=
|
|
23
|
+
* LOG_SYNC=
|
|
24
|
+
* LOG_OTEL_ENABLED=
|
|
25
|
+
*
|
|
26
|
+
* 1. Я хочу, чтобы сообщения в логе писались можно было писать
|
|
27
|
+
* с большим или меньшим количество подробностей. В зависимости
|
|
28
|
+
* от уровня логирования.
|
|
29
|
+
*
|
|
30
|
+
* 2. Я хочу, чтобы логирование успешных ответов и логирование ошибок
|
|
31
|
+
* было в принципе унифицировано. Сейчас этим занимаются разные интерцепторы.
|
|
32
|
+
* а мог бы один, отвечающий за логирование.
|
|
33
|
+
*
|
|
34
|
+
* 3. Логирование бинарных данных должны быть исключено.
|
|
35
|
+
* Возможность исключать логи запросов по ApiZone... кроме ошибок.
|
|
36
|
+
*
|
|
37
|
+
* 4. В логе ошибок писать больше о контексте запроса.
|
|
38
|
+
*
|
|
39
|
+
* РАЗОБРАТЬСЯ, ПОЧЕМУ kicker мы не можем сделать контроллером?
|
|
40
|
+
*/
|
|
41
|
+
|
|
42
|
+
@Injectable()
|
|
43
|
+
export class LoggingInterceptor implements NestInterceptor {
|
|
44
|
+
private readonly defaultFormatter = new DefaultLogFormatter();
|
|
45
|
+
|
|
46
|
+
constructor(
|
|
47
|
+
@InjectLogger(LoggingInterceptor)
|
|
48
|
+
private readonly logger: ILogger,
|
|
49
|
+
@Inject(LOG_FORMATTERS)
|
|
50
|
+
private readonly formatters: Map<string, LogFormatter>,
|
|
51
|
+
private detector: ProtocolDetector,
|
|
52
|
+
private config: LoggingConfig,
|
|
53
|
+
) {}
|
|
54
|
+
|
|
55
|
+
intercept(
|
|
56
|
+
context: ExecutionContext,
|
|
57
|
+
next: CallHandler<any>,
|
|
58
|
+
): Observable<any> {
|
|
59
|
+
const receivedAt = Date.now();
|
|
60
|
+
|
|
61
|
+
const protocol = this.detector.getProtocol(context);
|
|
62
|
+
|
|
63
|
+
const formatter: LogFormatter = protocol
|
|
64
|
+
? this.getFormatter(protocol)
|
|
65
|
+
: this.defaultFormatter;
|
|
66
|
+
|
|
67
|
+
const shouldLog = formatter.shouldLog?.(context) ?? true;
|
|
68
|
+
if (!shouldLog) {
|
|
69
|
+
return next.handle();
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const { logRequestBody, logResponseBody, excludeZones, level } =
|
|
73
|
+
this.config;
|
|
74
|
+
|
|
75
|
+
const path = formatter.getPath(context);
|
|
76
|
+
const requestDetails = formatter.formatRequest(context, logRequestBody);
|
|
77
|
+
|
|
78
|
+
const zone = Zone.getForContext(context);
|
|
79
|
+
const isExcluded = !!zone && excludeZones.includes(zone);
|
|
80
|
+
|
|
81
|
+
if (!isExcluded) {
|
|
82
|
+
this.logger.debug(`>>> Received [${protocol.toUpperCase()}] ${path}`, {
|
|
83
|
+
details: requestDetails,
|
|
84
|
+
path,
|
|
85
|
+
zone,
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return next.handle().pipe(
|
|
90
|
+
catchError((ex: PipelineException) => {
|
|
91
|
+
/**
|
|
92
|
+
* Добавляем параметры запроса, если они не были залогированы ранее.
|
|
93
|
+
*/
|
|
94
|
+
const request =
|
|
95
|
+
isExcluded || !['trace', 'debug'].includes(level)
|
|
96
|
+
? requestDetails
|
|
97
|
+
: '[ALREADY LOGGED]';
|
|
98
|
+
|
|
99
|
+
this.logger.error(`Failed [${protocol.toUpperCase()}] ${path}`, {
|
|
100
|
+
request,
|
|
101
|
+
cause: ex,
|
|
102
|
+
path,
|
|
103
|
+
zone,
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
return throwError(() => ex);
|
|
107
|
+
}),
|
|
108
|
+
tap((body) => {
|
|
109
|
+
if (isExcluded) {
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
const responseDetails = formatter.formatResponse(
|
|
114
|
+
context,
|
|
115
|
+
logResponseBody ? body : undefined,
|
|
116
|
+
);
|
|
117
|
+
|
|
118
|
+
this.logger.debug(`<<< Handled [${protocol.toUpperCase()}] ${path}`, {
|
|
119
|
+
details: responseDetails,
|
|
120
|
+
executionTime: Date.now() - receivedAt,
|
|
121
|
+
path,
|
|
122
|
+
zone,
|
|
123
|
+
});
|
|
124
|
+
}),
|
|
125
|
+
);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
private getFormatter(protocol: string): LogFormatter {
|
|
129
|
+
const formatter = this.formatters.get(protocol);
|
|
130
|
+
|
|
131
|
+
if (!formatter) {
|
|
132
|
+
this.logger.warn(`no formatter for protocol <${protocol}>...`);
|
|
133
|
+
return this.defaultFormatter;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
return formatter;
|
|
137
|
+
}
|
|
138
|
+
}
|
package/src/platform.context.ts
CHANGED
|
@@ -3,7 +3,8 @@ import type { INestApplication } from '@nestjs/common/interfaces';
|
|
|
3
3
|
import type { NestApplicationOptions } from '@nestjs/common/interfaces/nest-application-options.interface';
|
|
4
4
|
import type { AbstractHttpAdapter } from '@nestjs/core';
|
|
5
5
|
import type { Constructor } from '@rsdk/common';
|
|
6
|
-
import {
|
|
6
|
+
import type { ILogger } from '@rsdk/logging';
|
|
7
|
+
import { LoggerFactory, NoopLogger } from '@rsdk/logging';
|
|
7
8
|
import type { RsdkMetadataProvider } from '@rsdk/metadata';
|
|
8
9
|
import { groupBy, intersection } from 'lodash';
|
|
9
10
|
|
|
@@ -39,7 +40,7 @@ import {
|
|
|
39
40
|
* Агрегат для хранения опций приложения, а также методы для конфигурации и запуска приложения
|
|
40
41
|
*/
|
|
41
42
|
export class PlatformContext {
|
|
42
|
-
private readonly logger
|
|
43
|
+
private readonly logger: ILogger;
|
|
43
44
|
private readonly microservices = new Map<
|
|
44
45
|
INestMicroservice,
|
|
45
46
|
IMicroserviceTransport
|
|
@@ -68,12 +69,14 @@ export class PlatformContext {
|
|
|
68
69
|
// force set appName
|
|
69
70
|
forceAppName?: string;
|
|
70
71
|
},
|
|
72
|
+
silent?: boolean,
|
|
71
73
|
) {
|
|
72
74
|
this.assertTransportCompatibility(options);
|
|
73
75
|
this.assertPluginCompatibility(options);
|
|
74
76
|
|
|
75
77
|
this.httpTransport = options.transports?.find?.(isHttpTransport);
|
|
76
78
|
this.aggregator = new ContextAggregator(this);
|
|
79
|
+
this.logger = silent ? new NoopLogger() : LoggerFactory.create('App');
|
|
77
80
|
}
|
|
78
81
|
|
|
79
82
|
get extendedOptions(): PlatformExtendedOptions {
|
package/src/platform.module.ts
CHANGED
|
@@ -8,7 +8,8 @@ import { PlatformPluginModule } from './plugin/plugin.module';
|
|
|
8
8
|
import { PlatformTransportModule } from './transport/transport.module';
|
|
9
9
|
import { AppMetadataModule } from './app-metadata';
|
|
10
10
|
import { PlatformConfigModule } from './config';
|
|
11
|
-
import {
|
|
11
|
+
import { GlobalExceptionsModule } from './exceptions.handling';
|
|
12
|
+
import { LoggingCoreModule } from './logging';
|
|
12
13
|
import { TracingModule } from './tracing';
|
|
13
14
|
import type { PlatformAppPlugin, PlatformExtendedOptions } from './types';
|
|
14
15
|
import { APP_PLUGINS, APP_TRANSPORTS } from './types';
|
|
@@ -19,21 +20,41 @@ export class PlatformModule implements NestModule {
|
|
|
19
20
|
static forRoot(options: PlatformExtendedOptions): DynamicModule {
|
|
20
21
|
const imports: (DynamicModule | Constructor)[] = [
|
|
21
22
|
/**
|
|
22
|
-
* Последовательность принципиально важна так как
|
|
23
|
-
*
|
|
23
|
+
* Последовательность принципиально важна так как от порядка подключения будет зависеть
|
|
24
|
+
* порядок отработки глобальных интерцепторов
|
|
24
25
|
*/
|
|
26
|
+
|
|
27
|
+
// Interceptor: инициализация асинхронного контекста
|
|
25
28
|
AsyncContextModule,
|
|
29
|
+
|
|
30
|
+
// Interceptor: Извлечение трассируемых заголовков из запроса
|
|
26
31
|
TracingModule.forRoot(options),
|
|
27
32
|
|
|
28
|
-
//
|
|
33
|
+
// Interceptor: LoggingInterceptor
|
|
34
|
+
LoggingCoreModule.forRoot(options),
|
|
35
|
+
|
|
36
|
+
// Interceptor: Форматирование ошибок
|
|
37
|
+
GlobalExceptionsModule.forRoot(options),
|
|
38
|
+
|
|
39
|
+
// Interceptor: из конкретных реализаций транспортов (если есть)
|
|
40
|
+
PlatformTransportModule.forOptions(options),
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Далее порядок не важен, т. к. интерцепторов нет. Последовательность
|
|
44
|
+
* инициализации провайдеров Nest.js разрулит самостоятельно.
|
|
45
|
+
*/
|
|
46
|
+
|
|
47
|
+
// Инициализация плагинов
|
|
29
48
|
PlatformPluginModule.forOptions(options),
|
|
30
49
|
|
|
31
|
-
//
|
|
50
|
+
// Метаданные сервиса
|
|
32
51
|
AppMetadataModule.forRoot(options),
|
|
52
|
+
|
|
53
|
+
// Чтение и валидация конфигурации приложения
|
|
33
54
|
PlatformConfigModule.forRoot(options),
|
|
34
|
-
|
|
55
|
+
|
|
56
|
+
// Прикладные модули
|
|
35
57
|
...(options.modules ?? []),
|
|
36
|
-
PlatformTransportModule.forOptions(options),
|
|
37
58
|
];
|
|
38
59
|
|
|
39
60
|
const providers = [
|
package/src/tracing/constants.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import type { TracingOptions } from './tracing.module';
|
|
2
1
|
import type { TracingHeaderMappings } from './types';
|
|
3
2
|
|
|
4
3
|
/**
|
|
@@ -7,13 +6,15 @@ import type { TracingHeaderMappings } from './types';
|
|
|
7
6
|
export const HEADER_MAPPINGS = Symbol('HEADER_MAPPINGS');
|
|
8
7
|
|
|
9
8
|
/**
|
|
10
|
-
*
|
|
9
|
+
* Header extractors injection token
|
|
11
10
|
*/
|
|
12
|
-
export const
|
|
13
|
-
['requestId', 'X-Request-Id', 'X-Requestid'],
|
|
14
|
-
];
|
|
11
|
+
export const HEADER_EXTRACTORS = Symbol('HEADER_EXTRACTORS');
|
|
15
12
|
|
|
16
13
|
/**
|
|
17
|
-
* Default tracing
|
|
14
|
+
* Default mappings for tracing headers
|
|
18
15
|
*/
|
|
19
|
-
export const
|
|
16
|
+
export const REQUEST_ID_HEADERS: TracingHeaderMappings = [
|
|
17
|
+
'requestId',
|
|
18
|
+
'X-Request-Id',
|
|
19
|
+
'X-Requestid',
|
|
20
|
+
];
|
package/src/tracing/index.ts
CHANGED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { GenerateRequestId } from './types';
|
|
2
|
+
|
|
3
|
+
const REQUEST_ID_GEN_STRATEGY_KEY = Symbol('REQUEST_ID_GEN_STRATEGY');
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Sets the requestId generation strategy for a class
|
|
7
|
+
* @param {object} target - The target object to set the strategy on
|
|
8
|
+
* @param {GenerateRequestId} strategy - The strategy to use for generating requestIds
|
|
9
|
+
*/
|
|
10
|
+
export const setStrategy = (
|
|
11
|
+
target: object,
|
|
12
|
+
strategy: GenerateRequestId,
|
|
13
|
+
): void => {
|
|
14
|
+
Reflect.defineMetadata(REQUEST_ID_GEN_STRATEGY_KEY, strategy, target);
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Gets the requestId generation strategy for a class
|
|
19
|
+
* @param {object} target - The target object to get the strategy from
|
|
20
|
+
* @returns {GenerateRequestId | undefined} The requestId generation strategy for the class
|
|
21
|
+
*/
|
|
22
|
+
export const getStrategy = (target: object): GenerateRequestId | undefined => {
|
|
23
|
+
return Reflect.getMetadata(REQUEST_ID_GEN_STRATEGY_KEY, target);
|
|
24
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { setStrategy } from './metadata.helpers';
|
|
2
|
+
import type { GenerateRequestId } from './types';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Decorator that sets the requestId generation strategy for
|
|
6
|
+
* all controller methods
|
|
7
|
+
* @param {GenerateRequestId} strategy - The strategy to use for generating requestIds
|
|
8
|
+
* @returns {ClassDecorator} A decorator that sets the requestId generation strategy for a class
|
|
9
|
+
*/
|
|
10
|
+
export const RequestIdGenStrategy = (
|
|
11
|
+
strategy: GenerateRequestId,
|
|
12
|
+
): ClassDecorator => {
|
|
13
|
+
return (target: object) => {
|
|
14
|
+
setStrategy(target, strategy);
|
|
15
|
+
};
|
|
16
|
+
};
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { randomBytes } from 'node:crypto';
|
|
2
|
+
|
|
3
|
+
import type { GenerateRequestId } from './types';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Generates a random hex string of the given length
|
|
7
|
+
* @param {number} length - The length of the random hex string to generate
|
|
8
|
+
* @returns {string} A random hex string of the given length
|
|
9
|
+
*/
|
|
10
|
+
export const randomHex = (length: number): string =>
|
|
11
|
+
randomBytes(length).toString('hex');
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Default length of the generated requestId
|
|
15
|
+
* random bytes part
|
|
16
|
+
*/
|
|
17
|
+
export const DEFAULT_LENGTH = 8;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Default prefix of the generated requestId
|
|
21
|
+
*/
|
|
22
|
+
export const DEFAULT_PREFIX = 'gen';
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Creates a function that generates a requestId with
|
|
26
|
+
* a static prefix and a random bytes part.
|
|
27
|
+
* Ex: {prefix}:{randomHex(length)}
|
|
28
|
+
*
|
|
29
|
+
* @param {string} [prefix=DEFAULT_PREFIX] - The prefix to use for the generated requestId.
|
|
30
|
+
* @param {number} [length=DEFAULT_LENGTH] - The length of the random bytes part of the requestId.
|
|
31
|
+
* @returns {GenerateRequestId} A function that generates a requestId in the format {prefix}:{randomHex(length)}.
|
|
32
|
+
*/
|
|
33
|
+
export const withPrefix =
|
|
34
|
+
(
|
|
35
|
+
prefix: string = DEFAULT_PREFIX,
|
|
36
|
+
length: number = DEFAULT_LENGTH,
|
|
37
|
+
): GenerateRequestId =>
|
|
38
|
+
() =>
|
|
39
|
+
`${prefix}:${randomHex(length)}`;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Default requestId generator function
|
|
43
|
+
*/
|
|
44
|
+
export const generateDefault = withPrefix();
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { BoolParser, text } from '@rsdk/common';
|
|
2
|
+
|
|
3
|
+
import { Config, ConfigSection, Property } from '../config';
|
|
4
|
+
import { ConfigTag } from '../config/config.const';
|
|
5
|
+
|
|
6
|
+
@ConfigSection({ tags: [ConfigTag.tracing] })
|
|
7
|
+
export class TracingConfig extends Config {
|
|
8
|
+
@Property('TRACING_REQUEST_ID', new BoolParser(), {
|
|
9
|
+
description: 'Add requestId (X-Request-ID) tracing',
|
|
10
|
+
defaultValue: true,
|
|
11
|
+
})
|
|
12
|
+
traceRequestId!: boolean;
|
|
13
|
+
|
|
14
|
+
@Property('TRACING_REQUEST_ID_AUTOGENERATE', new BoolParser(), {
|
|
15
|
+
description: text`
|
|
16
|
+
Automatically generate requestId (correlationId) if it
|
|
17
|
+
is not set in the headers. It will be created as
|
|
18
|
+
some random bytes (hex) string with "gen:" prefix.
|
|
19
|
+
`,
|
|
20
|
+
defaultValue: false,
|
|
21
|
+
})
|
|
22
|
+
autogenerate!: boolean;
|
|
23
|
+
}
|
|
@@ -9,15 +9,12 @@ import type { Observable } from 'rxjs';
|
|
|
9
9
|
import { InternalException } from '../exceptions';
|
|
10
10
|
import { ILogger, InjectLogger } from '../logging';
|
|
11
11
|
import { ProtocolDetector } from '../transport/protocol.detector';
|
|
12
|
-
import type {
|
|
13
|
-
ITransport,
|
|
14
|
-
PlatformAppPlugin,
|
|
15
|
-
WithGenericHeaders,
|
|
16
|
-
} from '../types';
|
|
17
|
-
import { APP_PLUGINS, APP_TRANSPORTS } from '../types';
|
|
12
|
+
import type { WithGenericHeaders } from '../types';
|
|
18
13
|
|
|
19
|
-
import { HEADER_MAPPINGS } from './constants';
|
|
14
|
+
import { HEADER_EXTRACTORS, HEADER_MAPPINGS } from './constants';
|
|
15
|
+
import { generateDefault, getStrategy } from './request-id';
|
|
20
16
|
import { TracingHeaders } from './tracing.actx';
|
|
17
|
+
import { TracingConfig } from './tracing.config';
|
|
21
18
|
import type { TracingHeaderMappings } from './types';
|
|
22
19
|
|
|
23
20
|
/**
|
|
@@ -26,29 +23,15 @@ import type { TracingHeaderMappings } from './types';
|
|
|
26
23
|
*/
|
|
27
24
|
@Injectable()
|
|
28
25
|
export class TracingInterceptor implements NestInterceptor {
|
|
29
|
-
/**
|
|
30
|
-
* Extractors can be either transports or additional strategies
|
|
31
|
-
* supplied by plugins
|
|
32
|
-
*/
|
|
33
|
-
private readonly extractors = new Map<string, WithGenericHeaders>();
|
|
34
|
-
|
|
35
26
|
constructor(
|
|
27
|
+
/* eslint-disable prettier/prettier */
|
|
36
28
|
@InjectLogger(TracingInterceptor) private logger: ILogger,
|
|
37
|
-
@Inject(APP_TRANSPORTS) private transports: Set<ITransport>,
|
|
38
|
-
@Inject(APP_PLUGINS) private plugins: Set<PlatformAppPlugin>,
|
|
39
29
|
@Inject(HEADER_MAPPINGS) private mappings: TracingHeaderMappings[],
|
|
40
|
-
private
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
for (const plugin of this.plugins) {
|
|
47
|
-
for (const x of plugin.tracingHeadersExtractors?.() ?? []) {
|
|
48
|
-
this.extractors.set(x.protocol, x.extractor);
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
}
|
|
30
|
+
@Inject(HEADER_EXTRACTORS) private readonly extractors: Map<string, WithGenericHeaders>,
|
|
31
|
+
private readonly detector: ProtocolDetector,
|
|
32
|
+
private readonly config: TracingConfig,
|
|
33
|
+
/* eslint-enable prettier/prettier */
|
|
34
|
+
) {}
|
|
52
35
|
|
|
53
36
|
intercept(ctx: ExecutionContext, next: CallHandler): Observable<any> {
|
|
54
37
|
const protocol = this.detector.getProtocol(ctx) ?? ctx.getType();
|
|
@@ -60,6 +43,24 @@ export class TracingInterceptor implements NestInterceptor {
|
|
|
60
43
|
);
|
|
61
44
|
}
|
|
62
45
|
|
|
46
|
+
const headers = this.extractHeaders(ctx, extractor);
|
|
47
|
+
|
|
48
|
+
const { traceRequestId, autogenerate } = this.config;
|
|
49
|
+
if (!headers.requestId && traceRequestId && autogenerate) {
|
|
50
|
+
headers.requestId = this.generateRequestId(ctx, protocol);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
this.logger.trace('Extracted traceable headers', { headers });
|
|
54
|
+
|
|
55
|
+
TracingHeaders.set(headers);
|
|
56
|
+
|
|
57
|
+
return next.handle();
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
private extractHeaders(
|
|
61
|
+
ctx: ExecutionContext,
|
|
62
|
+
extractor: WithGenericHeaders,
|
|
63
|
+
): Record<string, string> {
|
|
63
64
|
const headers: Record<string, string> = {};
|
|
64
65
|
|
|
65
66
|
for (const aliases of this.mappings) {
|
|
@@ -68,13 +69,17 @@ export class TracingInterceptor implements NestInterceptor {
|
|
|
68
69
|
.map((x) => extractor.extractHeaders(ctx).get(x))
|
|
69
70
|
.find((x) => x);
|
|
70
71
|
|
|
71
|
-
|
|
72
|
+
if (value) {
|
|
73
|
+
headers[key] = value;
|
|
74
|
+
}
|
|
72
75
|
}
|
|
73
76
|
|
|
74
|
-
|
|
77
|
+
return headers;
|
|
78
|
+
}
|
|
75
79
|
|
|
76
|
-
|
|
80
|
+
private generateRequestId(ctx: ExecutionContext, protocol: string): string {
|
|
81
|
+
const generate = getStrategy(ctx.getClass()) ?? generateDefault;
|
|
77
82
|
|
|
78
|
-
return
|
|
83
|
+
return generate(ctx, protocol);
|
|
79
84
|
}
|
|
80
85
|
}
|