@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.
Files changed (261) hide show
  1. package/dist/config/index.d.ts +0 -1
  2. package/dist/config/index.js +0 -1
  3. package/dist/config/index.js.map +1 -1
  4. package/dist/config/metadata/decorators/declare-property.decorator.d.ts +2 -1
  5. package/dist/config/metadata/decorators/declare-property.decorator.js.map +1 -1
  6. package/dist/config/metadata/decorators/property.decorator.d.ts +2 -1
  7. package/dist/config/metadata/decorators/property.decorator.js.map +1 -1
  8. package/dist/config/sources/implementations/json-file.source.js +1 -2
  9. package/dist/config/sources/implementations/json-file.source.js.map +1 -1
  10. package/dist/config/sources/implementations/relodable-json-file.source.js +1 -2
  11. package/dist/config/sources/implementations/relodable-json-file.source.js.map +1 -1
  12. package/dist/config/types.d.ts +1 -20
  13. package/dist/config/types.js.map +1 -1
  14. package/dist/exceptions.handling/default.formatter.d.ts +6 -0
  15. package/dist/exceptions.handling/default.formatter.js +12 -0
  16. package/dist/exceptions.handling/default.formatter.js.map +1 -0
  17. package/dist/exceptions.handling/default.sender.d.ts +8 -0
  18. package/dist/exceptions.handling/default.sender.js +13 -0
  19. package/dist/exceptions.handling/default.sender.js.map +1 -0
  20. package/dist/exceptions.handling/global-exceptions.config.js +1 -1
  21. package/dist/exceptions.handling/global-exceptions.config.js.map +1 -1
  22. package/dist/exceptions.handling/global-exceptions.filter.d.ts +8 -11
  23. package/dist/exceptions.handling/global-exceptions.filter.js +38 -56
  24. package/dist/exceptions.handling/global-exceptions.filter.js.map +1 -1
  25. package/dist/exceptions.handling/global-exceptions.interceptor.d.ts +18 -0
  26. package/dist/exceptions.handling/global-exceptions.interceptor.js +57 -0
  27. package/dist/exceptions.handling/global-exceptions.interceptor.js.map +1 -0
  28. package/dist/exceptions.handling/global-exceptions.module.d.ts +2 -23
  29. package/dist/exceptions.handling/global-exceptions.module.js +38 -3
  30. package/dist/exceptions.handling/global-exceptions.module.js.map +1 -1
  31. package/dist/exceptions.handling/types.d.ts +2 -2
  32. package/dist/index.d.ts +31 -2
  33. package/dist/index.js +34 -1
  34. package/dist/index.js.map +1 -1
  35. package/dist/logging/constants.d.ts +1 -0
  36. package/dist/logging/constants.js +5 -0
  37. package/dist/logging/constants.js.map +1 -0
  38. package/dist/logging/decorators/inject-logger.decorator.js +2 -2
  39. package/dist/logging/decorators/inject-logger.decorator.js.map +1 -1
  40. package/dist/logging/formatters/default.formatter.d.ts +7 -0
  41. package/dist/logging/formatters/default.formatter.js +17 -0
  42. package/dist/logging/formatters/default.formatter.js.map +1 -0
  43. package/dist/logging/formatters/index.d.ts +2 -0
  44. package/dist/{config/parsers/array → logging/formatters}/index.js +2 -1
  45. package/dist/logging/formatters/index.js.map +1 -0
  46. package/dist/logging/formatters/interfaces.d.ts +23 -0
  47. package/dist/logging/formatters/interfaces.js +3 -0
  48. package/dist/logging/formatters/interfaces.js.map +1 -0
  49. package/dist/logging/index.d.ts +3 -2
  50. package/dist/logging/index.js +6 -4
  51. package/dist/logging/index.js.map +1 -1
  52. package/dist/logging/logging-core.module.d.ts +10 -0
  53. package/dist/logging/{logger-initializing.module.js → logging-core.module.js} +46 -10
  54. package/dist/logging/logging-core.module.js.map +1 -0
  55. package/dist/logging/{logging.module.d.ts → logging-instances.module.d.ts} +1 -1
  56. package/dist/logging/{logging.module.js → logging-instances.module.js} +8 -9
  57. package/dist/logging/logging-instances.module.js.map +1 -0
  58. package/dist/logging/logging.config.d.ts +3 -0
  59. package/dist/logging/logging.config.js +29 -4
  60. package/dist/logging/logging.config.js.map +1 -1
  61. package/dist/logging/logging.interceptor.d.ts +37 -0
  62. package/dist/logging/logging.interceptor.js +124 -0
  63. package/dist/logging/logging.interceptor.js.map +1 -0
  64. package/dist/metrics/metrics.config.js +3 -2
  65. package/dist/metrics/metrics.config.js.map +1 -1
  66. package/dist/platform.context.d.ts +1 -1
  67. package/dist/platform.context.js +3 -2
  68. package/dist/platform.context.js.map +1 -1
  69. package/dist/platform.module.js +19 -6
  70. package/dist/platform.module.js.map +1 -1
  71. package/dist/tracing/constants.d.ts +4 -5
  72. package/dist/tracing/constants.js +9 -7
  73. package/dist/tracing/constants.js.map +1 -1
  74. package/dist/tracing/index.d.ts +1 -0
  75. package/dist/tracing/index.js +1 -0
  76. package/dist/tracing/index.js.map +1 -1
  77. package/dist/tracing/request-id/index.d.ts +4 -0
  78. package/dist/{config/parsers/enum → tracing/request-id}/index.js +4 -1
  79. package/dist/tracing/request-id/index.js.map +1 -0
  80. package/dist/tracing/request-id/metadata.helpers.d.ts +13 -0
  81. package/dist/tracing/request-id/metadata.helpers.js +23 -0
  82. package/dist/tracing/request-id/metadata.helpers.js.map +1 -0
  83. package/dist/tracing/request-id/request-id-gen.decorator.d.ts +8 -0
  84. package/dist/tracing/request-id/request-id-gen.decorator.js +17 -0
  85. package/dist/tracing/request-id/request-id-gen.decorator.js.map +1 -0
  86. package/dist/tracing/request-id/types.d.ts +2 -0
  87. package/dist/tracing/request-id/types.js +3 -0
  88. package/dist/tracing/request-id/types.js.map +1 -0
  89. package/dist/tracing/request-id/with-prefix.fn.d.ts +30 -0
  90. package/dist/tracing/request-id/with-prefix.fn.js +36 -0
  91. package/dist/tracing/request-id/with-prefix.fn.js.map +1 -0
  92. package/dist/tracing/tracing.config.d.ts +5 -0
  93. package/dist/tracing/tracing.config.js +42 -0
  94. package/dist/tracing/tracing.config.js.map +1 -0
  95. package/dist/tracing/tracing.interceptor.d.ts +7 -9
  96. package/dist/tracing/tracing.interceptor.js +30 -28
  97. package/dist/tracing/tracing.interceptor.js.map +1 -1
  98. package/dist/tracing/tracing.module.d.ts +13 -2
  99. package/dist/tracing/tracing.module.js +60 -17
  100. package/dist/tracing/tracing.module.js.map +1 -1
  101. package/dist/transport/protocol.detector.d.ts +1 -1
  102. package/dist/transport/protocol.detector.js +17 -2
  103. package/dist/transport/protocol.detector.js.map +1 -1
  104. package/dist/transport/transport.module.d.ts +0 -1
  105. package/dist/transport/transport.module.js +0 -20
  106. package/dist/transport/transport.module.js.map +1 -1
  107. package/dist/types/plugins.d.ts +2 -15
  108. package/dist/types/plugins.js.map +1 -1
  109. package/dist/types/transports.d.ts +23 -13
  110. package/dist/types/transports.js.map +1 -1
  111. package/dist/unhandled-rejection.handler.js +8 -13
  112. package/dist/unhandled-rejection.handler.js.map +1 -1
  113. package/package.json +3 -2
  114. package/src/config/index.ts +0 -1
  115. package/src/config/metadata/decorators/declare-property.decorator.ts +3 -1
  116. package/src/config/metadata/decorators/property.decorator.ts +3 -5
  117. package/src/config/sources/implementations/json-file.source.ts +1 -2
  118. package/src/config/sources/implementations/relodable-json-file.source.ts +1 -2
  119. package/src/config/types.ts +2 -23
  120. package/src/exceptions.handling/default.formatter.ts +11 -0
  121. package/src/exceptions.handling/default.sender.ts +15 -0
  122. package/src/exceptions.handling/global-exceptions.config.ts +2 -2
  123. package/src/exceptions.handling/global-exceptions.filter.ts +45 -77
  124. package/src/exceptions.handling/global-exceptions.interceptor.ts +57 -0
  125. package/src/exceptions.handling/global-exceptions.module.ts +46 -33
  126. package/src/exceptions.handling/types.ts +2 -2
  127. package/src/index.ts +53 -2
  128. package/src/logging/constants.ts +1 -0
  129. package/src/logging/decorators/inject-logger.decorator.ts +2 -2
  130. package/src/logging/formatters/default.formatter.ts +17 -0
  131. package/src/logging/formatters/index.ts +2 -0
  132. package/src/logging/formatters/interfaces.ts +34 -0
  133. package/src/logging/index.ts +3 -2
  134. package/src/logging/logging-core.module.ts +102 -0
  135. package/src/logging/{logging.module.ts → logging-instances.module.ts} +2 -4
  136. package/src/logging/logging.config.ts +22 -6
  137. package/src/logging/logging.interceptor.ts +138 -0
  138. package/src/metrics/metrics.config.ts +3 -1
  139. package/src/platform.context.ts +5 -2
  140. package/src/platform.module.ts +28 -7
  141. package/src/tracing/constants.ts +8 -7
  142. package/src/tracing/index.ts +1 -0
  143. package/src/tracing/request-id/index.ts +4 -0
  144. package/src/tracing/request-id/metadata.helpers.ts +24 -0
  145. package/src/tracing/request-id/request-id-gen.decorator.ts +16 -0
  146. package/src/tracing/request-id/types.ts +6 -0
  147. package/src/tracing/request-id/with-prefix.fn.ts +44 -0
  148. package/src/tracing/tracing.config.ts +23 -0
  149. package/src/tracing/tracing.interceptor.ts +36 -31
  150. package/src/tracing/tracing.module.ts +68 -19
  151. package/src/transport/protocol.detector.ts +24 -4
  152. package/src/transport/transport.module.ts +0 -25
  153. package/src/types/plugins.ts +11 -22
  154. package/src/types/transports.ts +32 -16
  155. package/src/unhandled-rejection.handler.ts +10 -18
  156. package/test/logging.interceptor.spec.ts +292 -0
  157. package/dist/config/parsers/array/array.parser.d.ts +0 -11
  158. package/dist/config/parsers/array/array.parser.js +0 -33
  159. package/dist/config/parsers/array/array.parser.js.map +0 -1
  160. package/dist/config/parsers/array/index.d.ts +0 -1
  161. package/dist/config/parsers/array/index.js.map +0 -1
  162. package/dist/config/parsers/boolean/bool.parser.d.ts +0 -6
  163. package/dist/config/parsers/boolean/bool.parser.js +0 -20
  164. package/dist/config/parsers/boolean/bool.parser.js.map +0 -1
  165. package/dist/config/parsers/boolean/index.d.ts +0 -1
  166. package/dist/config/parsers/boolean/index.js +0 -18
  167. package/dist/config/parsers/boolean/index.js.map +0 -1
  168. package/dist/config/parsers/enum/enum.parser.d.ts +0 -9
  169. package/dist/config/parsers/enum/enum.parser.js +0 -24
  170. package/dist/config/parsers/enum/enum.parser.js.map +0 -1
  171. package/dist/config/parsers/enum/index.d.ts +0 -1
  172. package/dist/config/parsers/enum/index.js.map +0 -1
  173. package/dist/config/parsers/index.d.ts +0 -11
  174. package/dist/config/parsers/index.js +0 -28
  175. package/dist/config/parsers/index.js.map +0 -1
  176. package/dist/config/parsers/int/index.d.ts +0 -1
  177. package/dist/config/parsers/int/index.js +0 -18
  178. package/dist/config/parsers/int/index.js.map +0 -1
  179. package/dist/config/parsers/int/int.parser.d.ts +0 -6
  180. package/dist/config/parsers/int/int.parser.js +0 -20
  181. package/dist/config/parsers/int/int.parser.js.map +0 -1
  182. package/dist/config/parsers/json/index.d.ts +0 -1
  183. package/dist/config/parsers/json/index.js +0 -18
  184. package/dist/config/parsers/json/index.js.map +0 -1
  185. package/dist/config/parsers/json/json.parser.d.ts +0 -6
  186. package/dist/config/parsers/json/json.parser.js +0 -16
  187. package/dist/config/parsers/json/json.parser.js.map +0 -1
  188. package/dist/config/parsers/number/index.d.ts +0 -1
  189. package/dist/config/parsers/number/index.js +0 -18
  190. package/dist/config/parsers/number/index.js.map +0 -1
  191. package/dist/config/parsers/number/number.parser.d.ts +0 -6
  192. package/dist/config/parsers/number/number.parser.js +0 -23
  193. package/dist/config/parsers/number/number.parser.js.map +0 -1
  194. package/dist/config/parsers/path/fspath.parser.d.ts +0 -8
  195. package/dist/config/parsers/path/fspath.parser.js +0 -59
  196. package/dist/config/parsers/path/fspath.parser.js.map +0 -1
  197. package/dist/config/parsers/path/index.d.ts +0 -1
  198. package/dist/config/parsers/path/index.js +0 -18
  199. package/dist/config/parsers/path/index.js.map +0 -1
  200. package/dist/config/parsers/size/index.d.ts +0 -1
  201. package/dist/config/parsers/size/index.js +0 -18
  202. package/dist/config/parsers/size/index.js.map +0 -1
  203. package/dist/config/parsers/size/size.parser.d.ts +0 -7
  204. package/dist/config/parsers/size/size.parser.js +0 -21
  205. package/dist/config/parsers/size/size.parser.js.map +0 -1
  206. package/dist/config/parsers/string/index.d.ts +0 -1
  207. package/dist/config/parsers/string/index.js +0 -18
  208. package/dist/config/parsers/string/index.js.map +0 -1
  209. package/dist/config/parsers/string/string.parser.d.ts +0 -8
  210. package/dist/config/parsers/string/string.parser.js +0 -29
  211. package/dist/config/parsers/string/string.parser.js.map +0 -1
  212. package/dist/config/parsers/timespan/index.d.ts +0 -1
  213. package/dist/config/parsers/timespan/index.js +0 -18
  214. package/dist/config/parsers/timespan/index.js.map +0 -1
  215. package/dist/config/parsers/timespan/timespan.parser.d.ts +0 -7
  216. package/dist/config/parsers/timespan/timespan.parser.js +0 -21
  217. package/dist/config/parsers/timespan/timespan.parser.js.map +0 -1
  218. package/dist/config/parsers/url/exception.d.ts +0 -7
  219. package/dist/config/parsers/url/exception.js +0 -25
  220. package/dist/config/parsers/url/exception.js.map +0 -1
  221. package/dist/config/parsers/url/index.d.ts +0 -2
  222. package/dist/config/parsers/url/index.js +0 -21
  223. package/dist/config/parsers/url/index.js.map +0 -1
  224. package/dist/config/parsers/url/url.parser.d.ts +0 -9
  225. package/dist/config/parsers/url/url.parser.js +0 -38
  226. package/dist/config/parsers/url/url.parser.js.map +0 -1
  227. package/dist/logging/logger-initializing.module.d.ts +0 -6
  228. package/dist/logging/logger-initializing.module.js.map +0 -1
  229. package/dist/logging/logging.module.js.map +0 -1
  230. package/src/config/parsers/array/array.parser.ts +0 -34
  231. package/src/config/parsers/array/index.ts +0 -1
  232. package/src/config/parsers/boolean/bool.parser.ts +0 -20
  233. package/src/config/parsers/boolean/bool.spec.ts +0 -4
  234. package/src/config/parsers/boolean/index.ts +0 -1
  235. package/src/config/parsers/enum/enum.parser.ts +0 -23
  236. package/src/config/parsers/enum/enum.spec.ts +0 -5
  237. package/src/config/parsers/enum/index.ts +0 -1
  238. package/src/config/parsers/index.ts +0 -11
  239. package/src/config/parsers/int/index.ts +0 -1
  240. package/src/config/parsers/int/int.parser.ts +0 -20
  241. package/src/config/parsers/int/int.spec.ts +0 -5
  242. package/src/config/parsers/json/index.ts +0 -1
  243. package/src/config/parsers/json/json.parser.ts +0 -15
  244. package/src/config/parsers/number/index.ts +0 -1
  245. package/src/config/parsers/number/number.parser.ts +0 -23
  246. package/src/config/parsers/number/number.spec.ts +0 -5
  247. package/src/config/parsers/path/fspath.parser.ts +0 -64
  248. package/src/config/parsers/path/index.ts +0 -1
  249. package/src/config/parsers/size/index.ts +0 -1
  250. package/src/config/parsers/size/size.parser.ts +0 -22
  251. package/src/config/parsers/size/size.spec.ts +0 -4
  252. package/src/config/parsers/string/index.ts +0 -1
  253. package/src/config/parsers/string/string.parser.ts +0 -26
  254. package/src/config/parsers/string/string.spec.ts +0 -10
  255. package/src/config/parsers/timespan/index.ts +0 -1
  256. package/src/config/parsers/timespan/timespan.parser.ts +0 -22
  257. package/src/config/parsers/timespan/timespan.spec.ts +0 -5
  258. package/src/config/parsers/url/exception.ts +0 -21
  259. package/src/config/parsers/url/index.ts +0 -2
  260. package/src/config/parsers/url/url.parser.ts +0 -44
  261. package/src/logging/logger-initializing.module.ts +0 -55
@@ -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 { BoolParser, Config, ConfigSection, Property } from '../config';
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 { InternalException, PipelineException } from '../exceptions';
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, TRANSFORMERS } from './constants';
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
- @Inject(FORMATTERS) private readonly formatters: IErrorsFormatter[],
24
- @Inject(TRANSFORMERS) private readonly transformers: IErrorsTransformer[],
25
- @Inject(SENDERS) private readonly senders: IErrorsSender[],
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: any, host: ArgumentsHost): Observable<any> {
33
- const transformed =
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 err = new InternalException(ex.message ?? 'UNKNOWN ERROR', ex);
31
+ const sender = this.getSender(host, protocol);
32
+ const formatter = this.getFormatter(host, protocol);
51
33
 
52
- err.stack = ex.stack;
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 err;
40
+ return sender.send(host, normalized);
55
41
  }
56
42
 
57
- private format(host: ArgumentsHost, ex: unknown): unknown {
58
- const protocol = this.detector.getProtocol(host);
59
- const formatter = this.getFormatter(host, protocol);
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 (formatter) {
62
- this.logger.trace(`Found formatter: ${formatter.constructor.name}`);
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.trace('No formatter for error!');
68
-
69
- if (this.config.verbose) {
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 { message: 'NO FORMATTER' };
56
+ return DEFAULT_SENDER;
78
57
  }
79
58
 
80
59
  private getFormatter(
81
60
  host: ArgumentsHost,
82
- protocol: string | undefined,
83
- ): IErrorsFormatter | undefined {
84
- return (
85
- this.formatters.find((x) => x.protocol === protocol) ??
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
- private send(host: ArgumentsHost, ex: any): Observable<unknown> {
91
- const protocol = this.detector.getProtocol(host);
92
- const sender = this.getSender(host, protocol);
66
+ if (formatter) {
67
+ this.logger.trace(`Found formatter: ${formatter.constructor.name}`);
68
+ return formatter;
69
+ }
93
70
 
94
- return sender?.send(host, ex) ?? throwError(() => ex);
95
- }
71
+ this.logger.warn(text`
72
+ No formatter for protocol = ${protocol}
73
+ (hostType = ${host.getType()})`);
96
74
 
97
- private getSender(
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 type {
8
- IErrorsFormatter,
9
- IErrorsSender,
10
- IErrorsTransformer,
11
- } from './types';
9
+ import { GlobalExceptionsInterceptor } from './global-exceptions.interceptor';
10
+ import { IErrorsFormatter, IErrorsSender } from './types';
12
11
 
13
- export interface GlobalExceptionModuleOptions {
14
- /**
15
- * Formatters are used to transform exceptions to transport specific
16
- * final implementations. Usually formatter expects transport agnostic
17
- * subclasses of BaseException.
18
- */
19
- formatters: IErrorsFormatter[];
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
- * Senders are used to actually respond to client (algorithm
23
- * is transport specific)
24
- */
25
- senders: IErrorsSender[];
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
- * Sometimes application throws a lot of unconventional
29
- * (not inheriting BaseExceptions). Usually they are throw by
30
- * libraries: typeorm, axios, etc. Transformers are used to
31
- * catch them and convert to any subtype of BaseException which
32
- * will be processed further by transport specific formatters.
33
- */
34
- transformers?: IErrorsTransformer[];
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: options.formatters,
62
+ useValue: formatters,
50
63
  },
51
64
  {
52
65
  provide: SENDERS,
53
- useValue: options.senders,
66
+ useValue: senders,
54
67
  },
55
68
  {
56
69
  provide: TRANSFORMERS,
57
- useValue: options.transformers || [],
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
- * buisiness exception to transport-specific on (with appropriate
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
- * Transformating algorithm
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 { TracingHeaders } from './tracing';
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 { LoggingModule } from '../logging.module';
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
- LoggingModule.register(target, context, token);
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,2 @@
1
+ export * from './default.formatter';
2
+ export * from './interfaces';
@@ -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
+ }
@@ -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 { LoggerInitializingModule } from './logger-initializing.module';
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
+ }