@rsdk/core 4.2.0-next.0 → 4.2.0-next.1
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/CHANGELOG.md +6 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.js +3 -2
- package/dist/index.js.map +1 -1
- package/dist/platform.module.js +6 -1
- package/dist/platform.module.js.map +1 -1
- package/dist/tracing/auto-instrumentations.config.js +2 -3
- package/dist/tracing/auto-instrumentations.config.js.map +1 -1
- package/dist/tracing/grpc.headers.d.ts +11 -0
- package/dist/tracing/grpc.headers.js +24 -0
- package/dist/tracing/grpc.headers.js.map +1 -0
- package/dist/tracing/http.headers.d.ts +11 -0
- package/dist/tracing/http.headers.js +22 -0
- package/dist/tracing/http.headers.js.map +1 -0
- package/dist/tracing/index.d.ts +0 -1
- package/dist/tracing/index.js +0 -1
- package/dist/tracing/index.js.map +1 -1
- package/dist/tracing/open-telemetry.interceptor.d.ts +5 -0
- package/dist/tracing/open-telemetry.interceptor.js +83 -0
- package/dist/tracing/open-telemetry.interceptor.js.map +1 -0
- package/dist/tracing/request-metadata.module.js +1 -5
- package/dist/tracing/request-metadata.module.js.map +1 -1
- package/dist/tracing/services/instrumentation.service.d.ts +0 -1
- package/dist/tracing/services/instrumentation.service.js +0 -7
- package/dist/tracing/services/instrumentation.service.js.map +1 -1
- package/dist/tracing/services/request-id.provider.d.ts +11 -0
- package/dist/tracing/services/request-id.provider.js +13 -0
- package/dist/tracing/services/request-id.provider.js.map +1 -0
- package/dist/tracing/services/trace.injector.d.ts +4 -4
- package/dist/tracing/services/trace.injector.js +1 -132
- package/dist/tracing/services/trace.injector.js.map +1 -1
- package/dist/tracing/tracing.interceptor.d.ts +6 -5
- package/dist/tracing/tracing.interceptor.js +92 -7
- package/dist/tracing/tracing.interceptor.js.map +1 -1
- package/dist/tracing/tracing.module.d.ts +2 -2
- package/dist/tracing/tracing.module.js +8 -9
- package/dist/tracing/tracing.module.js.map +1 -1
- package/package.json +11 -10
- package/src/index.ts +1 -3
- package/src/platform.module.ts +7 -1
- package/src/tracing/auto-instrumentations.config.ts +2 -3
- package/src/tracing/grpc.headers.ts +29 -0
- package/src/tracing/http.headers.ts +32 -0
- package/src/tracing/index.ts +0 -1
- package/src/tracing/open-telemetry.interceptor.ts +114 -0
- package/src/tracing/request-metadata.module.ts +1 -6
- package/src/tracing/services/instrumentation.service.ts +0 -11
- package/src/tracing/services/request-id.provider.ts +21 -0
- package/src/tracing/services/trace.injector.ts +4 -170
- package/src/tracing/tracing.interceptor.ts +131 -5
- package/src/tracing/tracing.module.ts +10 -12
- package/dist/tracing/services/request-metadata.injector.d.ts +0 -6
- package/dist/tracing/services/request-metadata.injector.js +0 -123
- package/dist/tracing/services/request-metadata.injector.js.map +0 -1
- package/dist/tracing/services/request-metadata.storage.d.ts +0 -32
- package/dist/tracing/services/request-metadata.storage.js +0 -64
- package/dist/tracing/services/request-metadata.storage.js.map +0 -1
- package/src/tracing/services/request-metadata.injector.ts +0 -157
- package/src/tracing/services/request-metadata.storage.ts +0 -69
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"trace.injector.js","sourceRoot":"","sources":["../../../src/tracing/services/trace.injector.ts"],"names":[],"mappings":";;;;;;
|
|
1
|
+
{"version":3,"file":"trace.injector.js","sourceRoot":"","sources":["../../../src/tracing/services/trace.injector.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import type { CallHandler, ExecutionContext, NestInterceptor } from '@nestjs/common';
|
|
2
2
|
import type { Observable } from 'rxjs';
|
|
3
|
-
/**
|
|
4
|
-
* Интернал глобальный интерцептор для работы опентелеметрии
|
|
5
|
-
* его поведение будет модифицировано в зависимости от включенного или выключенного состояния глобального трэйсинга
|
|
6
|
-
*/
|
|
7
3
|
export declare class TracingInterceptor implements NestInterceptor {
|
|
8
|
-
intercept(
|
|
4
|
+
intercept(context: ExecutionContext, next: CallHandler): Observable<any>;
|
|
5
|
+
private static extractTracingHeaders;
|
|
6
|
+
private static extractFromGraphql;
|
|
7
|
+
private static extractFromHttp;
|
|
8
|
+
private static extractFromRpc;
|
|
9
|
+
private static createRequestId;
|
|
9
10
|
}
|
|
@@ -5,20 +5,105 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
5
5
|
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
6
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
7
|
};
|
|
8
|
+
var TracingInterceptor_1;
|
|
8
9
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
10
|
exports.TracingInterceptor = void 0;
|
|
10
11
|
const common_1 = require("@nestjs/common");
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
12
|
+
const propagator_b3_1 = require("@opentelemetry/propagator-b3");
|
|
13
|
+
const common_node_1 = require("@rsdk/common.node");
|
|
14
|
+
const node_crypto_1 = require("node:crypto");
|
|
15
|
+
const request_id_provider_1 = require("./services/request-id.provider");
|
|
16
|
+
const constants_1 = require("./constants");
|
|
17
|
+
const grpc_headers_1 = require("./grpc.headers");
|
|
18
|
+
const http_headers_1 = require("./http.headers");
|
|
19
|
+
const tracingHeaders = [
|
|
20
|
+
constants_1.X_REQUEST_ID,
|
|
21
|
+
propagator_b3_1.X_B3_TRACE_ID,
|
|
22
|
+
propagator_b3_1.X_B3_SPAN_ID,
|
|
23
|
+
propagator_b3_1.X_B3_PARENT_SPAN_ID,
|
|
24
|
+
];
|
|
25
|
+
let TracingInterceptor = TracingInterceptor_1 = class TracingInterceptor {
|
|
26
|
+
intercept(context, next) {
|
|
27
|
+
const requestId = TracingInterceptor_1.extractTracingHeaders(context);
|
|
28
|
+
request_id_provider_1.RequestIdProvider.set(requestId[constants_1.X_REQUEST_ID]);
|
|
29
|
+
request_id_provider_1.OpenTelemetryProvider.set((0, common_node_1.omitUndefined)(requestId));
|
|
17
30
|
return next.handle();
|
|
18
31
|
}
|
|
32
|
+
static extractTracingHeaders(executionContext) {
|
|
33
|
+
/**
|
|
34
|
+
* В зависимости от типа контекста запускаем парсинг переданной Metadata
|
|
35
|
+
*/
|
|
36
|
+
switch (executionContext.getType()) {
|
|
37
|
+
case 'rpc':
|
|
38
|
+
return this.extractFromRpc(executionContext);
|
|
39
|
+
case 'http':
|
|
40
|
+
return this.extractFromHttp(executionContext);
|
|
41
|
+
case 'graphql':
|
|
42
|
+
return this.extractFromGraphql(executionContext);
|
|
43
|
+
}
|
|
44
|
+
return {
|
|
45
|
+
[constants_1.X_REQUEST_ID]: this.createRequestId(),
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
static extractFromGraphql(executionContext) {
|
|
49
|
+
const req = executionContext.getArgs()[2]?.req; // аналог GqlExecutionContext.create(executionContext).getContext().req
|
|
50
|
+
/**
|
|
51
|
+
* При работе с сабскрипшен через веб сокет, заголовки передаются в опции подключения к сабскрипшен в переменную connectionParams
|
|
52
|
+
* и мы перегоняем эти данные в request заголовки
|
|
53
|
+
*/
|
|
54
|
+
const headers = {
|
|
55
|
+
...req?.headers,
|
|
56
|
+
...req?.connectionParams?.headers,
|
|
57
|
+
};
|
|
58
|
+
const extractedHeaders = new http_headers_1.HttpHeaders(headers).get([
|
|
59
|
+
constants_1.X_REQUEST_ID,
|
|
60
|
+
propagator_b3_1.X_B3_TRACE_ID,
|
|
61
|
+
propagator_b3_1.X_B3_SPAN_ID,
|
|
62
|
+
]);
|
|
63
|
+
const h = extractedHeaders;
|
|
64
|
+
h.http = {
|
|
65
|
+
httpMethod: req.method,
|
|
66
|
+
httpRoute: req.route?.path || req.routeOptions?.url || req.routerPath,
|
|
67
|
+
httpUrl: req.originalUrl || req.url,
|
|
68
|
+
};
|
|
69
|
+
h[constants_1.X_REQUEST_ID] ??= (0, node_crypto_1.randomUUID)();
|
|
70
|
+
return h;
|
|
71
|
+
}
|
|
72
|
+
static extractFromHttp(executionContext) {
|
|
73
|
+
// TODO:
|
|
74
|
+
const req = executionContext.switchToHttp().getRequest();
|
|
75
|
+
const headers = new http_headers_1.HttpHeaders(req.headers).get(tracingHeaders);
|
|
76
|
+
const h = headers;
|
|
77
|
+
h[constants_1.X_REQUEST_ID] ??= (0, node_crypto_1.randomUUID)();
|
|
78
|
+
h.http = {
|
|
79
|
+
httpMethod: req.method,
|
|
80
|
+
httpRoute: req.route?.path || req.routeOptions?.url || req.routerPath,
|
|
81
|
+
httpUrl: req.originalUrl || req.url,
|
|
82
|
+
};
|
|
83
|
+
return headers;
|
|
84
|
+
}
|
|
85
|
+
static extractFromRpc(executionContext) {
|
|
86
|
+
const metadata = executionContext.switchToRpc().getContext();
|
|
87
|
+
/**
|
|
88
|
+
* Если мы пришли в GRPC и у нас есть методы для работы с Metadata
|
|
89
|
+
* то мы конвертируем Metadata в некий виртуальный request с заголовками (заголовки выбраны как общий стандарт проброса мета информации)
|
|
90
|
+
*/
|
|
91
|
+
if (metadata?.get) {
|
|
92
|
+
const grpcHeaders = new grpc_headers_1.GrpcHeaders(metadata);
|
|
93
|
+
const h = grpcHeaders.get(tracingHeaders);
|
|
94
|
+
h[constants_1.X_REQUEST_ID] ??= this.createRequestId();
|
|
95
|
+
return h;
|
|
96
|
+
}
|
|
97
|
+
return {
|
|
98
|
+
[constants_1.X_REQUEST_ID]: (0, node_crypto_1.randomUUID)(),
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
static createRequestId() {
|
|
102
|
+
return (0, node_crypto_1.randomUUID)();
|
|
103
|
+
}
|
|
19
104
|
};
|
|
20
105
|
exports.TracingInterceptor = TracingInterceptor;
|
|
21
|
-
exports.TracingInterceptor = TracingInterceptor = __decorate([
|
|
106
|
+
exports.TracingInterceptor = TracingInterceptor = TracingInterceptor_1 = __decorate([
|
|
22
107
|
(0, common_1.Injectable)()
|
|
23
108
|
], TracingInterceptor);
|
|
24
109
|
//# sourceMappingURL=tracing.interceptor.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tracing.interceptor.js","sourceRoot":"","sources":["../../src/tracing/tracing.interceptor.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"tracing.interceptor.js","sourceRoot":"","sources":["../../src/tracing/tracing.interceptor.ts"],"names":[],"mappings":";;;;;;;;;;AAKA,2CAA4C;AAC5C,gEAIsC;AACtC,mDAAkD;AAClD,6CAAyC;AAGzC,wEAGwC;AACxC,2CAA2C;AAC3C,iDAA6C;AAC7C,iDAA6C;AAS7C,MAAM,cAAc,GAAG;IACrB,wBAAY;IACZ,6BAAa;IACb,4BAAY;IACZ,mCAAmB;CACX,CAAC;AAGJ,IAAM,kBAAkB,0BAAxB,MAAM,kBAAkB;IAC7B,SAAS,CAAC,OAAyB,EAAE,IAAiB;QACpD,MAAM,SAAS,GAAG,oBAAkB,CAAC,qBAAqB,CAAC,OAAO,CAAC,CAAC;QAEpE,uCAAiB,CAAC,GAAG,CAAC,SAAS,CAAC,wBAAY,CAAC,CAAC,CAAC;QAC/C,2CAAqB,CAAC,GAAG,CAAC,IAAA,2BAAa,EAAC,SAAS,CAAC,CAAC,CAAC;QACpD,OAAO,IAAI,CAAC,MAAM,EAAE,CAAC;IACvB,CAAC;IAEO,MAAM,CAAC,qBAAqB,CAClC,gBAAkC;QAElC;;WAEG;QACH,QAAQ,gBAAgB,CAAC,OAAO,EAAU,EAAE,CAAC;YAC3C,KAAK,KAAK;gBACR,OAAO,IAAI,CAAC,cAAc,CAAC,gBAAgB,CAAC,CAAC;YAC/C,KAAK,MAAM;gBACT,OAAO,IAAI,CAAC,eAAe,CAAC,gBAAgB,CAAC,CAAC;YAChD,KAAK,SAAS;gBACZ,OAAO,IAAI,CAAC,kBAAkB,CAAC,gBAAgB,CAAC,CAAC;QACrD,CAAC;QACD,OAAO;YACL,CAAC,wBAAY,CAAC,EAAE,IAAI,CAAC,eAAe,EAAE;SACvC,CAAC;IACJ,CAAC;IAEO,MAAM,CAAC,kBAAkB,CAC/B,gBAAkC;QAElC,MAAM,GAAG,GAAG,gBAAgB,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,uEAAuE;QAEvH;;;WAGG;QACH,MAAM,OAAO,GAAG;YACd,GAAG,GAAG,EAAE,OAAO;YACf,GAAG,GAAG,EAAE,gBAAgB,EAAE,OAAO;SAClC,CAAC;QAEF,MAAM,gBAAgB,GAAG,IAAI,0BAAW,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC;YACpD,wBAAY;YACZ,6BAAa;YACb,4BAAY;SACb,CAAC,CAAC;QAEH,MAAM,CAAC,GAAG,gBAAkC,CAAC;QAE7C,CAAC,CAAC,IAAI,GAAG;YACP,UAAU,EAAE,GAAG,CAAC,MAAO;YACvB,SAAS,EAAE,GAAG,CAAC,KAAK,EAAE,IAAI,IAAI,GAAG,CAAC,YAAY,EAAE,GAAG,IAAI,GAAG,CAAC,UAAU;YACrE,OAAO,EAAE,GAAG,CAAC,WAAW,IAAI,GAAG,CAAC,GAAG;SACpC,CAAC;QAEF,CAAC,CAAC,wBAAY,CAAC,KAAK,IAAA,wBAAU,GAAE,CAAC;QACjC,OAAO,CAAmB,CAAC;IAC7B,CAAC;IAEO,MAAM,CAAC,eAAe,CAC5B,gBAAkC;QAElC,QAAQ;QACR,MAAM,GAAG,GAAG,gBAAgB,CAAC,YAAY,EAAE,CAAC,UAAU,EAAO,CAAC;QAE9D,MAAM,OAAO,GAAG,IAAI,0BAAW,CAAC,GAAG,CAAC,OAAiC,CAAC,CAAC,GAAG,CACxE,cAAc,CACf,CAAC;QAEF,MAAM,CAAC,GAAmB,OAAyB,CAAC;QAEpD,CAAC,CAAC,wBAAY,CAAC,KAAK,IAAA,wBAAU,GAAE,CAAC;QACjC,CAAC,CAAC,IAAI,GAAG;YACP,UAAU,EAAE,GAAG,CAAC,MAAO;YACvB,SAAS,EAAE,GAAG,CAAC,KAAK,EAAE,IAAI,IAAI,GAAG,CAAC,YAAY,EAAE,GAAG,IAAI,GAAG,CAAC,UAAU;YACrE,OAAO,EAAE,GAAG,CAAC,WAAW,IAAI,GAAG,CAAC,GAAG;SACpC,CAAC;QACF,OAAO,OAAyB,CAAC;IACnC,CAAC;IAEO,MAAM,CAAC,cAAc,CAC3B,gBAAkC;QAElC,MAAM,QAAQ,GAAG,gBAAgB,CAAC,WAAW,EAAE,CAAC,UAAU,EAAE,CAAC;QAC7D;;;WAGG;QACH,IAAI,QAAQ,EAAE,GAAG,EAAE,CAAC;YAClB,MAAM,WAAW,GAAG,IAAI,0BAAW,CAAC,QAAQ,CAAC,CAAC;YAE9C,MAAM,CAAC,GAAG,WAAW,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;YAE1C,CAAC,CAAC,wBAAY,CAAC,KAAK,IAAI,CAAC,eAAe,EAAE,CAAC;YAC3C,OAAO,CAAmB,CAAC;QAC7B,CAAC;QACD,OAAO;YACL,CAAC,wBAAY,CAAC,EAAE,IAAA,wBAAU,GAAE;SAC7B,CAAC;IACJ,CAAC;IAEO,MAAM,CAAC,eAAe;QAC5B,OAAO,IAAA,wBAAU,GAAE,CAAC;IACtB,CAAC;CACF,CAAA;AAzGY,gDAAkB;6BAAlB,kBAAkB;IAD9B,IAAA,mBAAU,GAAE;GACA,kBAAkB,CAyG9B"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { DynamicModule } from '@nestjs/common';
|
|
1
|
+
import type { DynamicModule, OnModuleInit } from '@nestjs/common';
|
|
2
2
|
import { NodeSDK } from '@opentelemetry/sdk-node';
|
|
3
3
|
import type { SpanExporter } from '@opentelemetry/sdk-trace-base';
|
|
4
4
|
import { ILogger } from '@rsdk/logging';
|
|
@@ -9,7 +9,7 @@ export interface TracingModuleOptions {
|
|
|
9
9
|
processing: 'simple' | 'batch';
|
|
10
10
|
exporter?: SpanExporter;
|
|
11
11
|
}
|
|
12
|
-
export declare class TracingModule {
|
|
12
|
+
export declare class TracingModule implements OnModuleInit {
|
|
13
13
|
private readonly logger;
|
|
14
14
|
private readonly instrumentations;
|
|
15
15
|
private readonly sdk;
|
|
@@ -27,9 +27,10 @@ const sdk_trace_base_1 = require("@opentelemetry/sdk-trace-base");
|
|
|
27
27
|
const semantic_conventions_1 = require("@opentelemetry/semantic-conventions");
|
|
28
28
|
const logging_1 = require("@rsdk/logging");
|
|
29
29
|
const logging_2 = require("../logging");
|
|
30
|
-
const
|
|
30
|
+
const request_id_provider_1 = require("./services/request-id.provider");
|
|
31
31
|
const active_span_module_1 = require("./active-span.module");
|
|
32
32
|
const auto_instrumentations_config_1 = require("./auto-instrumentations.config");
|
|
33
|
+
const open_telemetry_interceptor_1 = require("./open-telemetry.interceptor");
|
|
33
34
|
const request_metadata_module_1 = require("./request-metadata.module");
|
|
34
35
|
const services_1 = require("./services");
|
|
35
36
|
const tracing_config_1 = require("./tracing.config");
|
|
@@ -50,24 +51,22 @@ let TracingModule = TracingModule_1 = class TracingModule {
|
|
|
50
51
|
module: TracingModule_1,
|
|
51
52
|
imports: [request_metadata_module_1.RequestMetadataModule, active_span_module_1.ActiveSpanModule],
|
|
52
53
|
providers: [
|
|
54
|
+
{ provide: core_1.APP_INTERCEPTOR, useValue: new tracing_interceptor_1.TracingInterceptor() },
|
|
55
|
+
{
|
|
56
|
+
provide: core_1.APP_INTERCEPTOR,
|
|
57
|
+
useValue: new open_telemetry_interceptor_1.OpenTelemetryInterceptor(),
|
|
58
|
+
},
|
|
53
59
|
services_1.InstrumentationService,
|
|
54
60
|
this.createSDKProvider(options),
|
|
55
|
-
/**
|
|
56
|
-
* Глобальный интерцептор для проброса входящих traceId, spanId и requestId из заголовков и метадаты в активный AsyncLocalStorage запроса
|
|
57
|
-
*/
|
|
58
|
-
{ provide: core_1.APP_INTERCEPTOR, useClass: tracing_interceptor_1.TracingInterceptor },
|
|
59
61
|
],
|
|
60
62
|
};
|
|
61
63
|
}
|
|
62
64
|
// Можно добавить включение и выключение при изменении конфига.
|
|
63
65
|
async onModuleInit() {
|
|
64
|
-
this.logger.debug('Injecting request-metadata storage...');
|
|
65
|
-
this.instrumentations.injectWrapRequestMetadataInjector();
|
|
66
66
|
if (!this.config.enabled) {
|
|
67
67
|
this.logger.info('Tracing is disabled');
|
|
68
68
|
logging_1.LoggerFactory.applyInstrumentations((record) => {
|
|
69
|
-
record['request_id'] =
|
|
70
|
-
request_metadata_storage_1.RequestMetadataStorage.getInstance()?.getRequestMetadata().requestId;
|
|
69
|
+
record['request_id'] = request_id_provider_1.RequestIdProvider.get();
|
|
71
70
|
});
|
|
72
71
|
return;
|
|
73
72
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tracing.module.js","sourceRoot":"","sources":["../../src/tracing/tracing.module.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AACA,2CAAwC;AACxC,uCAA+C;AAC/C,4CAAoD;AACpD,4EAAqF;AACrF,8CAA0D;AAC1D,sFAA4E;AAC5E,gEAA8E;AAC9E,wDAAoD;AACpD,sDAAkD;AAElD,kEAGuC;AACvC,8EAAiF;AACjF,2CAAuD;AAEvD,wCAA0C;AAE1C,
|
|
1
|
+
{"version":3,"file":"tracing.module.js","sourceRoot":"","sources":["../../src/tracing/tracing.module.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rsdk/core",
|
|
3
|
-
"version": "4.2.0-next.
|
|
3
|
+
"version": "4.2.0-next.1",
|
|
4
4
|
"description": "Nestjs based microservice chassis",
|
|
5
5
|
"license": "Apache License 2.0",
|
|
6
6
|
"publishConfig": {
|
|
@@ -32,18 +32,19 @@
|
|
|
32
32
|
"@nestjs/common": "^10.0.0",
|
|
33
33
|
"@nestjs/core": "^10.0.0",
|
|
34
34
|
"@nestjs/microservices": "^10.0.0",
|
|
35
|
-
"@rsdk/
|
|
36
|
-
"@rsdk/
|
|
37
|
-
"@rsdk/common
|
|
38
|
-
"@rsdk/common.
|
|
39
|
-
"@rsdk/
|
|
40
|
-
"@rsdk/
|
|
41
|
-
"@rsdk/
|
|
42
|
-
"@rsdk/
|
|
35
|
+
"@rsdk/actx": "^4.2.0-next.1",
|
|
36
|
+
"@rsdk/autodoc.protocol": "^4.2.0-next.1",
|
|
37
|
+
"@rsdk/common": "^4.2.0-next.1",
|
|
38
|
+
"@rsdk/common.nestjs": "^4.2.0-next.1",
|
|
39
|
+
"@rsdk/common.node": "^4.2.0-next.1",
|
|
40
|
+
"@rsdk/decorators": "^4.2.0-next.1",
|
|
41
|
+
"@rsdk/logging": "^4.2.0-next.1",
|
|
42
|
+
"@rsdk/metadata": "^4.2.0-next.1",
|
|
43
|
+
"@rsdk/nest-tools": "^4.2.0-next.1",
|
|
43
44
|
"axios": "^1.1.3",
|
|
44
45
|
"pino": "^8.16.1",
|
|
45
46
|
"reflect-metadata": "^0.1.13",
|
|
46
47
|
"rxjs": "^7.0.0"
|
|
47
48
|
},
|
|
48
|
-
"gitHead": "
|
|
49
|
+
"gitHead": "e42244b7badde74fec2badc60a85d53878fe75ae"
|
|
49
50
|
}
|
package/src/index.ts
CHANGED
|
@@ -7,10 +7,7 @@ export { Manifest } from './manifest/manifest';
|
|
|
7
7
|
export { ProtocolDetector } from './transport/protocol.detector';
|
|
8
8
|
|
|
9
9
|
export { X_REQUEST_ID } from './tracing/constants';
|
|
10
|
-
|
|
11
10
|
export {
|
|
12
|
-
RequestMetadata,
|
|
13
|
-
RequestMetadataStorage,
|
|
14
11
|
TracingModule,
|
|
15
12
|
saveAsyncHooksContext,
|
|
16
13
|
createSpan,
|
|
@@ -75,3 +72,4 @@ export {
|
|
|
75
72
|
X_B3_SPAN_ID,
|
|
76
73
|
X_B3_TRACE_ID,
|
|
77
74
|
} from '@opentelemetry/propagator-b3';
|
|
75
|
+
export { RequestIdProvider } from './tracing/services/request-id.provider';
|
package/src/platform.module.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { DynamicModule, NestModule } from '@nestjs/common';
|
|
2
2
|
import { Inject } from '@nestjs/common';
|
|
3
3
|
import type { MiddlewareConsumer } from '@nestjs/common/interfaces';
|
|
4
|
+
import { AsyncContextModule } from '@rsdk/actx';
|
|
4
5
|
import type { Constructor } from '@rsdk/common';
|
|
5
6
|
|
|
6
7
|
import { PlatformPluginModule } from './plugin/plugin.module';
|
|
@@ -19,13 +20,18 @@ export class PlatformModule implements NestModule {
|
|
|
19
20
|
|
|
20
21
|
static forRoot(options: PlatformExtendedOptions): DynamicModule {
|
|
21
22
|
const imports: (DynamicModule | Constructor)[] = [
|
|
23
|
+
/**
|
|
24
|
+
* Последовательность принципиально важна так как в этом модуле происходит инициализация глобального асинхронного контекста (AsyncLocalStorage)
|
|
25
|
+
*/
|
|
26
|
+
AsyncContextModule,
|
|
27
|
+
TracingModule.forRoot({ appName: options.name, processing: 'simple' }),
|
|
28
|
+
|
|
22
29
|
// Plugins
|
|
23
30
|
PlatformPluginModule.forOptions(options),
|
|
24
31
|
|
|
25
32
|
// Infrastructure
|
|
26
33
|
AppMetadataModule.forRoot(options),
|
|
27
34
|
PlatformConfigModule.forRoot(options),
|
|
28
|
-
TracingModule.forRoot({ appName: options.name, processing: 'simple' }),
|
|
29
35
|
LoggerInitializingModule,
|
|
30
36
|
...(options.modules ?? []),
|
|
31
37
|
];
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { getNodeAutoInstrumentations } from '@opentelemetry/auto-instrumentations-node';
|
|
2
2
|
import { ClientRequest, IncomingMessage } from 'node:http';
|
|
3
3
|
|
|
4
|
-
import {
|
|
4
|
+
import { RequestIdProvider } from './services/request-id.provider';
|
|
5
5
|
|
|
6
6
|
export const autoInstumentationOptions: any[] = getNodeAutoInstrumentations({
|
|
7
7
|
'@opentelemetry/instrumentation-aws-sdk': {
|
|
@@ -38,8 +38,7 @@ export const autoInstumentationOptions: any[] = getNodeAutoInstrumentations({
|
|
|
38
38
|
'@opentelemetry/instrumentation-pino': {
|
|
39
39
|
enabled: true,
|
|
40
40
|
logHook: (_span, record) => {
|
|
41
|
-
record['request_id'] =
|
|
42
|
-
RequestMetadataStorage.getInstance()?.getRequestMetadata().requestId;
|
|
41
|
+
record['request_id'] = RequestIdProvider.get();
|
|
43
42
|
},
|
|
44
43
|
},
|
|
45
44
|
});
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { Metadata } from '@grpc/grpc-js';
|
|
2
|
+
import type { MaybeReadonlyArray } from '@rsdk/common.node';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @description хелпер для нормализованного извлечения заголовков из grpc запроса
|
|
6
|
+
*/
|
|
7
|
+
export class GrpcHeaders {
|
|
8
|
+
constructor(private metadata: Metadata) {}
|
|
9
|
+
|
|
10
|
+
get<K extends string>(
|
|
11
|
+
key: MaybeReadonlyArray<K>,
|
|
12
|
+
): Record<K, string | undefined>;
|
|
13
|
+
get(key: string): string | undefined;
|
|
14
|
+
get(
|
|
15
|
+
key: string | MaybeReadonlyArray<string>,
|
|
16
|
+
): Record<string, string | undefined> | string | undefined {
|
|
17
|
+
if (Array.isArray(key)) {
|
|
18
|
+
return Object.fromEntries(key.map((k) => [k, this.get(k)])) as Record<
|
|
19
|
+
string,
|
|
20
|
+
any
|
|
21
|
+
>;
|
|
22
|
+
}
|
|
23
|
+
const requestIdMetadata = this.metadata.get(key as string);
|
|
24
|
+
if (requestIdMetadata.length > 0) {
|
|
25
|
+
return requestIdMetadata[0].toString();
|
|
26
|
+
}
|
|
27
|
+
return undefined;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { MaybeReadonlyArray } from '@rsdk/common.node';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @description хелпер для нормализованного извлечения заголовков из http запроса
|
|
5
|
+
*/
|
|
6
|
+
export class HttpHeaders {
|
|
7
|
+
constructor(private headers: Record<string, string>) {
|
|
8
|
+
this.normalizedHeaders = Object.fromEntries(
|
|
9
|
+
Object.entries(headers).map(([k, v]) => [k.toLowerCase(), v]),
|
|
10
|
+
);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
get<K extends string>(
|
|
14
|
+
key: MaybeReadonlyArray<K>,
|
|
15
|
+
): Record<K, string | undefined>;
|
|
16
|
+
|
|
17
|
+
get(key: string): string | undefined;
|
|
18
|
+
|
|
19
|
+
get(
|
|
20
|
+
key: string | MaybeReadonlyArray<string>,
|
|
21
|
+
): Record<string, string | undefined> | string | undefined {
|
|
22
|
+
if (Array.isArray(key)) {
|
|
23
|
+
return Object.fromEntries(key.map((k) => [k, this.get(k)])) as Record<
|
|
24
|
+
string,
|
|
25
|
+
any
|
|
26
|
+
>;
|
|
27
|
+
}
|
|
28
|
+
return this.normalizedHeaders[(key as string).toLowerCase()];
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
private normalizedHeaders: Record<string, string>;
|
|
32
|
+
}
|
package/src/tracing/index.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
export * from './active-span.module';
|
|
2
2
|
export * from './request-metadata.module';
|
|
3
3
|
export * from './services/active-span.storage';
|
|
4
|
-
export * from './services/request-metadata.storage';
|
|
5
4
|
export * from './tracing.module';
|
|
6
5
|
export * from './utils/create-span';
|
|
7
6
|
export * from './utils/save-async-hooks-context';
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
CallHandler,
|
|
3
|
+
ExecutionContext,
|
|
4
|
+
NestInterceptor,
|
|
5
|
+
} from '@nestjs/common';
|
|
6
|
+
import { trace } from '@opentelemetry/api';
|
|
7
|
+
import {
|
|
8
|
+
X_B3_PARENT_SPAN_ID,
|
|
9
|
+
X_B3_SPAN_ID,
|
|
10
|
+
X_B3_TRACE_ID,
|
|
11
|
+
} from '@opentelemetry/propagator-b3';
|
|
12
|
+
import { api } from '@opentelemetry/sdk-node';
|
|
13
|
+
import { SemanticAttributes } from '@opentelemetry/semantic-conventions';
|
|
14
|
+
import { catchError, mergeMap, Observable, of, throwError } from 'rxjs';
|
|
15
|
+
|
|
16
|
+
import { OpenTelemetryProvider } from './services/request-id.provider';
|
|
17
|
+
import { TraceInjector } from './services';
|
|
18
|
+
|
|
19
|
+
export class OpenTelemetryInterceptor implements NestInterceptor {
|
|
20
|
+
intercept(
|
|
21
|
+
_context: ExecutionContext,
|
|
22
|
+
next: CallHandler<any>,
|
|
23
|
+
): Observable<any> | Promise<Observable<any>> {
|
|
24
|
+
const tracer = trace.getTracer('@rsdk/open-telemetry', '1.0.0');
|
|
25
|
+
|
|
26
|
+
const spanName = TraceInjector.createSpanName(
|
|
27
|
+
OpenTelemetryInterceptor.name,
|
|
28
|
+
'intercept',
|
|
29
|
+
);
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Создаем новый спан
|
|
33
|
+
*/
|
|
34
|
+
const span = tracer.startSpan(spanName, {});
|
|
35
|
+
|
|
36
|
+
const openTelemetryValues = OpenTelemetryProvider.getOrThrow();
|
|
37
|
+
|
|
38
|
+
const parentSpanId = openTelemetryValues[X_B3_PARENT_SPAN_ID];
|
|
39
|
+
if (parentSpanId) {
|
|
40
|
+
(span as any).parentSpanId = parentSpanId;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const spanId = openTelemetryValues[X_B3_SPAN_ID];
|
|
44
|
+
/**
|
|
45
|
+
* После создания контекста ранее при входе в приложение, у нас новый спан ид
|
|
46
|
+
* мы перетираем значением которе получили через заголовок
|
|
47
|
+
* в рамках приложения он корректный, но при переходе из одного приложения в другой - слетает
|
|
48
|
+
* и чтобы 100% все было норм, мы всегда патчим его
|
|
49
|
+
*/
|
|
50
|
+
if (spanId) {
|
|
51
|
+
span.spanContext().spanId = spanId;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const traceId = openTelemetryValues[X_B3_TRACE_ID];
|
|
55
|
+
/**
|
|
56
|
+
* Патчим трайс ид, причина выше
|
|
57
|
+
*/
|
|
58
|
+
if (traceId) {
|
|
59
|
+
span.spanContext().traceId = traceId;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Обычно самая первая точка входа это фронтовый запрос, который содержит некие заголовки хттп
|
|
63
|
+
* мы их кладем в рутовый спан
|
|
64
|
+
*/
|
|
65
|
+
if (openTelemetryValues.http) {
|
|
66
|
+
span.setAttribute(
|
|
67
|
+
SemanticAttributes.HTTP_METHOD,
|
|
68
|
+
openTelemetryValues.http.httpMethod,
|
|
69
|
+
);
|
|
70
|
+
span.setAttribute(
|
|
71
|
+
SemanticAttributes.HTTP_URL,
|
|
72
|
+
openTelemetryValues.http.httpUrl,
|
|
73
|
+
);
|
|
74
|
+
span.setAttribute(
|
|
75
|
+
SemanticAttributes.HTTP_ROUTE,
|
|
76
|
+
openTelemetryValues.http.httpRoute,
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Чтобы пробросить пропатченный спан нужно запустить две строчки ниже:
|
|
81
|
+
* 1) создаем контекст в котором активный спан перебиваем новым
|
|
82
|
+
* 2) созданный контекст ставим основным и в нем запускаем под процесс
|
|
83
|
+
*/
|
|
84
|
+
const spanContext = api.trace.setSpan(api.context.active(), span);
|
|
85
|
+
|
|
86
|
+
return new Observable((observer) => {
|
|
87
|
+
api.context.with(spanContext, () => {
|
|
88
|
+
next
|
|
89
|
+
.handle()
|
|
90
|
+
.pipe(
|
|
91
|
+
mergeMap((result) => {
|
|
92
|
+
TraceInjector.enrich(span, result);
|
|
93
|
+
span.end();
|
|
94
|
+
return of(result);
|
|
95
|
+
}),
|
|
96
|
+
catchError((error) => {
|
|
97
|
+
TraceInjector.recordAndRethrow(error, span);
|
|
98
|
+
span.end();
|
|
99
|
+
return throwError(() => error);
|
|
100
|
+
}),
|
|
101
|
+
)
|
|
102
|
+
.subscribe({
|
|
103
|
+
complete: () => {
|
|
104
|
+
observer.complete();
|
|
105
|
+
},
|
|
106
|
+
error: (error) => {
|
|
107
|
+
observer.error(error);
|
|
108
|
+
},
|
|
109
|
+
next: (res) => observer.next(res),
|
|
110
|
+
});
|
|
111
|
+
});
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
}
|
|
@@ -1,13 +1,8 @@
|
|
|
1
1
|
import { Global, Module } from '@nestjs/common';
|
|
2
2
|
|
|
3
|
-
import { RequestMetadataStorage } from './services/request-metadata.storage';
|
|
4
|
-
|
|
5
3
|
/**
|
|
6
4
|
* Модуль для хранения и получения данных из аскин локал стораджа
|
|
7
5
|
*/
|
|
8
6
|
@Global()
|
|
9
|
-
@Module({
|
|
10
|
-
providers: [RequestMetadataStorage],
|
|
11
|
-
exports: [RequestMetadataStorage],
|
|
12
|
-
})
|
|
7
|
+
@Module({})
|
|
13
8
|
export class RequestMetadataModule {}
|
|
@@ -2,21 +2,10 @@ import { Injectable } from '@nestjs/common';
|
|
|
2
2
|
|
|
3
3
|
import { TracingInterceptor } from '../tracing.interceptor';
|
|
4
4
|
|
|
5
|
-
import { RequestMetadataInjector } from './request-metadata.injector';
|
|
6
5
|
import { TraceInjector } from './trace.injector';
|
|
7
6
|
|
|
8
7
|
@Injectable()
|
|
9
8
|
export class InstrumentationService {
|
|
10
|
-
public injectWrapRequestMetadataInjector(): void {
|
|
11
|
-
/**
|
|
12
|
-
* Оборачиваем интерцептор в логику которая несет с собою асинк локал сторадж с requestId
|
|
13
|
-
*/
|
|
14
|
-
RequestMetadataInjector.wrap(
|
|
15
|
-
TracingInterceptor.prototype,
|
|
16
|
-
TracingInterceptor.prototype['intercept'],
|
|
17
|
-
);
|
|
18
|
-
}
|
|
19
|
-
|
|
20
9
|
public injectWrapTraceInjector(): void {
|
|
21
10
|
/**
|
|
22
11
|
* Оборачиваем интерцептор в логику которая несет с собою асинк локал сторадж с traceId, spanId
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
X_B3_PARENT_SPAN_ID,
|
|
3
|
+
X_B3_SPAN_ID,
|
|
4
|
+
X_B3_TRACE_ID,
|
|
5
|
+
} from '@opentelemetry/propagator-b3';
|
|
6
|
+
import { createAsyncContextProvider } from '@rsdk/actx';
|
|
7
|
+
|
|
8
|
+
export const RequestIdProvider = createAsyncContextProvider<string>({
|
|
9
|
+
name: 'RequestId',
|
|
10
|
+
rewritable: false,
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
export const OpenTelemetryProvider = createAsyncContextProvider<{
|
|
14
|
+
[X_B3_SPAN_ID]?: string;
|
|
15
|
+
[X_B3_TRACE_ID]?: string;
|
|
16
|
+
[X_B3_PARENT_SPAN_ID]?: string;
|
|
17
|
+
http?: { httpMethod: string; httpUrl: string; httpRoute: string };
|
|
18
|
+
}>({
|
|
19
|
+
name: 'OpenTelemetryPropagation',
|
|
20
|
+
rewritable: false,
|
|
21
|
+
});
|