@tramvai/module-opentelemetry 5.21.0 → 5.24.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/lib/instrumentation/router.d.ts +12 -0
- package/lib/instrumentation/router.es.js +115 -0
- package/lib/instrumentation/router.js +119 -0
- package/lib/instrumentation/server.d.ts +4 -2
- package/lib/instrumentation/server.es.js +7 -3
- package/lib/instrumentation/server.js +6 -1
- package/lib/server.es.js +8 -4
- package/lib/server.js +6 -2
- package/lib/tokens.d.ts +7 -4
- package/lib/tracer/tracer.d.ts +8 -6
- package/lib/tracer/tracer.es.js +15 -9
- package/lib/tracer/tracer.js +15 -9
- package/package.json +8 -7
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
export declare const providers: import("@tramvai/core").Provider<{
|
|
3
|
+
tracer: import("../tokens").TramvaiTracer & {
|
|
4
|
+
__type?: "base token" | undefined;
|
|
5
|
+
};
|
|
6
|
+
request: import("fastify").FastifyRequest<import("fastify").RouteGenericInterface, import("fastify").RawServerDefault, import("http").IncomingMessage, import("fastify").FastifySchema, import("fastify").FastifyTypeProviderDefault, unknown, import("fastify").FastifyBaseLogger, import("fastify/types/type-provider").ResolveFastifyRequestType<import("fastify").FastifyTypeProviderDefault, import("fastify").FastifySchema, import("fastify").RouteGenericInterface>> & {
|
|
7
|
+
__type?: "base token" | undefined;
|
|
8
|
+
};
|
|
9
|
+
}, import("@tinkoff/router").RouterPlugin & {
|
|
10
|
+
__type?: "multi token" | undefined;
|
|
11
|
+
}>[];
|
|
12
|
+
//# sourceMappingURL=router.d.ts.map
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { isRedirectFoundError, isNotFoundError } from '@tinkoff/errors';
|
|
2
|
+
import { provide } from '@tramvai/core';
|
|
3
|
+
import { ROUTER_PLUGIN } from '@tramvai/tokens-router';
|
|
4
|
+
import { SpanKind } from '@opentelemetry/api';
|
|
5
|
+
import { ATTR_URL_PATH, ATTR_HTTP_ROUTE, ATTR_URL_QUERY, ATTR_URL_FULL } from '@opentelemetry/semantic-conventions';
|
|
6
|
+
import { FASTIFY_REQUEST } from '@tramvai/tokens-server-private';
|
|
7
|
+
import { OPENTELEMETRY_TRACER_TOKEN } from '../tokens.es.js';
|
|
8
|
+
import { REQUEST_SPAN } from './server.es.js';
|
|
9
|
+
|
|
10
|
+
function skipError(error) {
|
|
11
|
+
return isRedirectFoundError(error) || isNotFoundError(error);
|
|
12
|
+
}
|
|
13
|
+
class OpentelemetryRouterPlugin {
|
|
14
|
+
constructor({ tracer, request }) {
|
|
15
|
+
this.tracer = tracer;
|
|
16
|
+
this.request = request;
|
|
17
|
+
}
|
|
18
|
+
apply(router) {
|
|
19
|
+
router.navigateHook.wrap(async (_, payload, next) => {
|
|
20
|
+
return this.tracer.trace(`navigate`, { kind: SpanKind.SERVER }, async (span) => {
|
|
21
|
+
const url = typeof payload.navigateOptions === 'string'
|
|
22
|
+
? payload.navigateOptions
|
|
23
|
+
: payload.navigateOptions.url;
|
|
24
|
+
span.setAttribute('tramvai.scope', 'router');
|
|
25
|
+
if (url) {
|
|
26
|
+
span.setAttribute(ATTR_URL_PATH, url);
|
|
27
|
+
}
|
|
28
|
+
await next(payload);
|
|
29
|
+
}, { skipError });
|
|
30
|
+
});
|
|
31
|
+
// TODO: is updateCurrentRoute tracing necessary at server-side?
|
|
32
|
+
// router.updateHook.wrap(async (_, payload, next) => {
|
|
33
|
+
// return this.tracer.trace(`update`, { kind: SpanKind.SERVER }, async (span) => {
|
|
34
|
+
// span.setAttribute('tramvai.scope', 'router');
|
|
35
|
+
// await next(payload);
|
|
36
|
+
// });
|
|
37
|
+
// });
|
|
38
|
+
router.runNavigateHook.wrap(async (_, payload, next) => {
|
|
39
|
+
return this.tracer.trace(`run navigate`, { kind: SpanKind.SERVER }, async (span) => {
|
|
40
|
+
span.setAttribute('tramvai.scope', 'router');
|
|
41
|
+
if (payload.navigation.to && payload.navigation.url) {
|
|
42
|
+
const { path } = payload.navigation.to;
|
|
43
|
+
const { pathname, search, href } = payload.navigation.url;
|
|
44
|
+
span.setAttribute(ATTR_HTTP_ROUTE, path);
|
|
45
|
+
span.setAttribute(ATTR_URL_PATH, pathname);
|
|
46
|
+
span.setAttribute(ATTR_URL_QUERY, search.replace('?', ''));
|
|
47
|
+
span.setAttribute(ATTR_URL_FULL, href);
|
|
48
|
+
// bubble current page route to root server request span
|
|
49
|
+
if (this.request[REQUEST_SPAN]) {
|
|
50
|
+
this.request[REQUEST_SPAN].setAttribute(ATTR_HTTP_ROUTE, path);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
await next(payload);
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
router.redirectHook.wrap(async (_, payload, next) => {
|
|
57
|
+
return this.tracer.trace(`redirect`, { kind: SpanKind.SERVER }, async (span) => {
|
|
58
|
+
span.setAttribute('tramvai.scope', 'router');
|
|
59
|
+
if (payload.navigation.url) {
|
|
60
|
+
// TODO не корректный урл, как будто уже после модификации
|
|
61
|
+
span.setAttribute('tramvai.router.redirect.from', payload.navigation.fromUrl.href);
|
|
62
|
+
span.setAttribute('tramvai.router.redirect.to', payload.navigation.url.href);
|
|
63
|
+
if (payload.navigation.code) {
|
|
64
|
+
span.setAttribute('tramvai.router.redirect.code', payload.navigation.code);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
await next(payload);
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
router.notfoundHook.wrap(async (_, payload, next) => {
|
|
71
|
+
return this.tracer.trace(`notfound`, { kind: SpanKind.SERVER }, async (span) => {
|
|
72
|
+
span.setAttribute('tramvai.scope', 'router');
|
|
73
|
+
if (payload.navigation.url) {
|
|
74
|
+
span.setAttribute('tramvai.router.notfound.url', payload.navigation.url.href);
|
|
75
|
+
}
|
|
76
|
+
await next(payload);
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
router.blockHook.wrap(async (_, payload, next) => {
|
|
80
|
+
return this.tracer.trace(`block`, { kind: SpanKind.SERVER }, async (span) => {
|
|
81
|
+
span.setAttribute('tramvai.scope', 'router');
|
|
82
|
+
if (payload.navigation.url) {
|
|
83
|
+
span.setAttribute('tramvai.router.block.url', payload.navigation.url.href);
|
|
84
|
+
}
|
|
85
|
+
await next(payload);
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
for (const [hookName, hook] of router.hooks.entries()) {
|
|
89
|
+
hook.wrap(async (_, payload, next) => {
|
|
90
|
+
return this.tracer.trace(`${hookName} hooks`, { kind: SpanKind.SERVER }, async (span) => {
|
|
91
|
+
span.setAttribute('tramvai.scope', 'router');
|
|
92
|
+
await next(payload);
|
|
93
|
+
});
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
router.guards.wrap(async (_, payload, next) => {
|
|
97
|
+
return this.tracer.trace(`guards`, { kind: SpanKind.SERVER }, async (span) => {
|
|
98
|
+
span.setAttribute('tramvai.scope', 'router');
|
|
99
|
+
await next(payload);
|
|
100
|
+
});
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
const providers = [
|
|
105
|
+
provide({
|
|
106
|
+
provide: ROUTER_PLUGIN,
|
|
107
|
+
useClass: OpentelemetryRouterPlugin,
|
|
108
|
+
deps: {
|
|
109
|
+
tracer: OPENTELEMETRY_TRACER_TOKEN,
|
|
110
|
+
request: FASTIFY_REQUEST,
|
|
111
|
+
},
|
|
112
|
+
}),
|
|
113
|
+
];
|
|
114
|
+
|
|
115
|
+
export { providers };
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var errors = require('@tinkoff/errors');
|
|
6
|
+
var core = require('@tramvai/core');
|
|
7
|
+
var tokensRouter = require('@tramvai/tokens-router');
|
|
8
|
+
var api = require('@opentelemetry/api');
|
|
9
|
+
var semanticConventions = require('@opentelemetry/semantic-conventions');
|
|
10
|
+
var tokensServerPrivate = require('@tramvai/tokens-server-private');
|
|
11
|
+
var tokens = require('../tokens.js');
|
|
12
|
+
var server = require('./server.js');
|
|
13
|
+
|
|
14
|
+
function skipError(error) {
|
|
15
|
+
return errors.isRedirectFoundError(error) || errors.isNotFoundError(error);
|
|
16
|
+
}
|
|
17
|
+
class OpentelemetryRouterPlugin {
|
|
18
|
+
constructor({ tracer, request }) {
|
|
19
|
+
this.tracer = tracer;
|
|
20
|
+
this.request = request;
|
|
21
|
+
}
|
|
22
|
+
apply(router) {
|
|
23
|
+
router.navigateHook.wrap(async (_, payload, next) => {
|
|
24
|
+
return this.tracer.trace(`navigate`, { kind: api.SpanKind.SERVER }, async (span) => {
|
|
25
|
+
const url = typeof payload.navigateOptions === 'string'
|
|
26
|
+
? payload.navigateOptions
|
|
27
|
+
: payload.navigateOptions.url;
|
|
28
|
+
span.setAttribute('tramvai.scope', 'router');
|
|
29
|
+
if (url) {
|
|
30
|
+
span.setAttribute(semanticConventions.ATTR_URL_PATH, url);
|
|
31
|
+
}
|
|
32
|
+
await next(payload);
|
|
33
|
+
}, { skipError });
|
|
34
|
+
});
|
|
35
|
+
// TODO: is updateCurrentRoute tracing necessary at server-side?
|
|
36
|
+
// router.updateHook.wrap(async (_, payload, next) => {
|
|
37
|
+
// return this.tracer.trace(`update`, { kind: SpanKind.SERVER }, async (span) => {
|
|
38
|
+
// span.setAttribute('tramvai.scope', 'router');
|
|
39
|
+
// await next(payload);
|
|
40
|
+
// });
|
|
41
|
+
// });
|
|
42
|
+
router.runNavigateHook.wrap(async (_, payload, next) => {
|
|
43
|
+
return this.tracer.trace(`run navigate`, { kind: api.SpanKind.SERVER }, async (span) => {
|
|
44
|
+
span.setAttribute('tramvai.scope', 'router');
|
|
45
|
+
if (payload.navigation.to && payload.navigation.url) {
|
|
46
|
+
const { path } = payload.navigation.to;
|
|
47
|
+
const { pathname, search, href } = payload.navigation.url;
|
|
48
|
+
span.setAttribute(semanticConventions.ATTR_HTTP_ROUTE, path);
|
|
49
|
+
span.setAttribute(semanticConventions.ATTR_URL_PATH, pathname);
|
|
50
|
+
span.setAttribute(semanticConventions.ATTR_URL_QUERY, search.replace('?', ''));
|
|
51
|
+
span.setAttribute(semanticConventions.ATTR_URL_FULL, href);
|
|
52
|
+
// bubble current page route to root server request span
|
|
53
|
+
if (this.request[server.REQUEST_SPAN]) {
|
|
54
|
+
this.request[server.REQUEST_SPAN].setAttribute(semanticConventions.ATTR_HTTP_ROUTE, path);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
await next(payload);
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
router.redirectHook.wrap(async (_, payload, next) => {
|
|
61
|
+
return this.tracer.trace(`redirect`, { kind: api.SpanKind.SERVER }, async (span) => {
|
|
62
|
+
span.setAttribute('tramvai.scope', 'router');
|
|
63
|
+
if (payload.navigation.url) {
|
|
64
|
+
// TODO не корректный урл, как будто уже после модификации
|
|
65
|
+
span.setAttribute('tramvai.router.redirect.from', payload.navigation.fromUrl.href);
|
|
66
|
+
span.setAttribute('tramvai.router.redirect.to', payload.navigation.url.href);
|
|
67
|
+
if (payload.navigation.code) {
|
|
68
|
+
span.setAttribute('tramvai.router.redirect.code', payload.navigation.code);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
await next(payload);
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
router.notfoundHook.wrap(async (_, payload, next) => {
|
|
75
|
+
return this.tracer.trace(`notfound`, { kind: api.SpanKind.SERVER }, async (span) => {
|
|
76
|
+
span.setAttribute('tramvai.scope', 'router');
|
|
77
|
+
if (payload.navigation.url) {
|
|
78
|
+
span.setAttribute('tramvai.router.notfound.url', payload.navigation.url.href);
|
|
79
|
+
}
|
|
80
|
+
await next(payload);
|
|
81
|
+
});
|
|
82
|
+
});
|
|
83
|
+
router.blockHook.wrap(async (_, payload, next) => {
|
|
84
|
+
return this.tracer.trace(`block`, { kind: api.SpanKind.SERVER }, async (span) => {
|
|
85
|
+
span.setAttribute('tramvai.scope', 'router');
|
|
86
|
+
if (payload.navigation.url) {
|
|
87
|
+
span.setAttribute('tramvai.router.block.url', payload.navigation.url.href);
|
|
88
|
+
}
|
|
89
|
+
await next(payload);
|
|
90
|
+
});
|
|
91
|
+
});
|
|
92
|
+
for (const [hookName, hook] of router.hooks.entries()) {
|
|
93
|
+
hook.wrap(async (_, payload, next) => {
|
|
94
|
+
return this.tracer.trace(`${hookName} hooks`, { kind: api.SpanKind.SERVER }, async (span) => {
|
|
95
|
+
span.setAttribute('tramvai.scope', 'router');
|
|
96
|
+
await next(payload);
|
|
97
|
+
});
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
router.guards.wrap(async (_, payload, next) => {
|
|
101
|
+
return this.tracer.trace(`guards`, { kind: api.SpanKind.SERVER }, async (span) => {
|
|
102
|
+
span.setAttribute('tramvai.scope', 'router');
|
|
103
|
+
await next(payload);
|
|
104
|
+
});
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
const providers = [
|
|
109
|
+
core.provide({
|
|
110
|
+
provide: tokensRouter.ROUTER_PLUGIN,
|
|
111
|
+
useClass: OpentelemetryRouterPlugin,
|
|
112
|
+
deps: {
|
|
113
|
+
tracer: tokens.OPENTELEMETRY_TRACER_TOKEN,
|
|
114
|
+
request: tokensServerPrivate.FASTIFY_REQUEST,
|
|
115
|
+
},
|
|
116
|
+
}),
|
|
117
|
+
];
|
|
118
|
+
|
|
119
|
+
exports.providers = providers;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
2
|
import { type Span } from '@opentelemetry/api';
|
|
3
|
-
declare const REQUEST_SPAN: unique symbol;
|
|
3
|
+
export declare const REQUEST_SPAN: unique symbol;
|
|
4
4
|
declare module 'fastify' {
|
|
5
5
|
interface FastifyRequest {
|
|
6
6
|
[REQUEST_SPAN]?: Span;
|
|
@@ -16,10 +16,12 @@ export declare const providers: (import("@tramvai/core").Provider<{
|
|
|
16
16
|
tracesExcludePaths: string & {
|
|
17
17
|
__type?: "multi token" | undefined;
|
|
18
18
|
};
|
|
19
|
+
envManager: import("@tramvai/tokens-common").EnvironmentManager & {
|
|
20
|
+
__type?: "base token" | undefined;
|
|
21
|
+
};
|
|
19
22
|
}, import("@tramvai/tokens-server-private").FASTIFY_APP_INIT_HANDLER & {
|
|
20
23
|
__type?: "multi token" | undefined;
|
|
21
24
|
}> | import("@tramvai/core").Provider<{}, import("@tramvai/tokens-server-private").FASTIFY_APP_ERROR_HANDLER & {
|
|
22
25
|
__type?: "multi token" | undefined;
|
|
23
26
|
}>)[];
|
|
24
|
-
export {};
|
|
25
27
|
//# sourceMappingURL=server.d.ts.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ATTR_HTTP_REQUEST_METHOD, ATTR_HTTP_ROUTE, ATTR_URL_PATH, ATTR_URL_QUERY, ATTR_URL_SCHEME, ATTR_URL_FULL, ATTR_HTTP_RESPONSE_STATUS_CODE } from '@opentelemetry/semantic-conventions';
|
|
1
|
+
import { ATTR_HTTP_REQUEST_METHOD, ATTR_SERVER_ADDRESS, ATTR_SERVER_PORT, ATTR_HTTP_ROUTE, ATTR_URL_PATH, ATTR_URL_QUERY, ATTR_URL_SCHEME, ATTR_URL_FULL, ATTR_HTTP_RESPONSE_STATUS_CODE } from '@opentelemetry/semantic-conventions';
|
|
2
2
|
import { propagation, ROOT_CONTEXT, SpanKind, SpanStatusCode } from '@opentelemetry/api';
|
|
3
3
|
import pathToRegexp from 'path-to-regexp';
|
|
4
4
|
import flatten from '@tinkoff/utils/array/flatten';
|
|
@@ -6,13 +6,14 @@ import { isNotFoundError, isHttpError } from '@tinkoff/errors';
|
|
|
6
6
|
import { provide } from '@tramvai/core';
|
|
7
7
|
import { UTILITY_SERVER_PATHS } from '@tramvai/tokens-server';
|
|
8
8
|
import { WEB_FASTIFY_APP_INIT_TOKEN, WEB_FASTIFY_APP_TOKEN, WEB_FASTIFY_APP_AFTER_ERROR_TOKEN } from '@tramvai/tokens-server-private';
|
|
9
|
+
import { ENV_MANAGER_TOKEN } from '@tramvai/tokens-common';
|
|
9
10
|
import { OPENTELEMETRY_TRACER_TOKEN } from '../tokens.es.js';
|
|
10
11
|
|
|
11
12
|
const REQUEST_SPAN = Symbol('opentelemetry.tramvai.server.request.span');
|
|
12
13
|
const providers = [
|
|
13
14
|
provide({
|
|
14
15
|
provide: WEB_FASTIFY_APP_INIT_TOKEN,
|
|
15
|
-
useFactory: ({ app, tracer, tracesExcludePaths }) => {
|
|
16
|
+
useFactory: ({ app, tracer, tracesExcludePaths, envManager }) => {
|
|
16
17
|
return () => {
|
|
17
18
|
// todo copypaste from @tinkoff/measure-fastify-requests
|
|
18
19
|
const excludePatterns = flatten(tracesExcludePaths).map((p) => pathToRegexp(p));
|
|
@@ -50,6 +51,8 @@ const providers = [
|
|
|
50
51
|
span.setAttribute('tramvai.server.framework', 'fastify');
|
|
51
52
|
// https://github.com/open-telemetry/semantic-conventions/blob/main/docs/attributes-registry/http.md
|
|
52
53
|
span.setAttribute(ATTR_HTTP_REQUEST_METHOD, httpMethod);
|
|
54
|
+
span.setAttribute(ATTR_SERVER_ADDRESS, req.headers['x-original-host'] || req.headers.host || envManager.get('PORT'));
|
|
55
|
+
span.setAttribute(ATTR_SERVER_PORT, envManager.get('PORT'));
|
|
53
56
|
// route should have low-cardinality - https://github.com/open-telemetry/semantic-conventions/blob/main/docs/attributes-registry/http.md
|
|
54
57
|
span.setAttribute(ATTR_HTTP_ROUTE, httpRoute);
|
|
55
58
|
span.setAttribute(ATTR_URL_PATH, parsedUrl.pathname);
|
|
@@ -76,6 +79,7 @@ const providers = [
|
|
|
76
79
|
app: WEB_FASTIFY_APP_TOKEN,
|
|
77
80
|
tracer: OPENTELEMETRY_TRACER_TOKEN,
|
|
78
81
|
tracesExcludePaths: UTILITY_SERVER_PATHS,
|
|
82
|
+
envManager: ENV_MANAGER_TOKEN,
|
|
79
83
|
},
|
|
80
84
|
}),
|
|
81
85
|
provide({
|
|
@@ -116,4 +120,4 @@ const providers = [
|
|
|
116
120
|
}),
|
|
117
121
|
];
|
|
118
122
|
|
|
119
|
-
export { providers };
|
|
123
|
+
export { REQUEST_SPAN, providers };
|
|
@@ -10,6 +10,7 @@ var errors = require('@tinkoff/errors');
|
|
|
10
10
|
var core = require('@tramvai/core');
|
|
11
11
|
var tokensServer = require('@tramvai/tokens-server');
|
|
12
12
|
var tokensServerPrivate = require('@tramvai/tokens-server-private');
|
|
13
|
+
var tokensCommon = require('@tramvai/tokens-common');
|
|
13
14
|
var tokens = require('../tokens.js');
|
|
14
15
|
|
|
15
16
|
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
@@ -21,7 +22,7 @@ const REQUEST_SPAN = Symbol('opentelemetry.tramvai.server.request.span');
|
|
|
21
22
|
const providers = [
|
|
22
23
|
core.provide({
|
|
23
24
|
provide: tokensServerPrivate.WEB_FASTIFY_APP_INIT_TOKEN,
|
|
24
|
-
useFactory: ({ app, tracer, tracesExcludePaths }) => {
|
|
25
|
+
useFactory: ({ app, tracer, tracesExcludePaths, envManager }) => {
|
|
25
26
|
return () => {
|
|
26
27
|
// todo copypaste from @tinkoff/measure-fastify-requests
|
|
27
28
|
const excludePatterns = flatten__default["default"](tracesExcludePaths).map((p) => pathToRegexp__default["default"](p));
|
|
@@ -59,6 +60,8 @@ const providers = [
|
|
|
59
60
|
span.setAttribute('tramvai.server.framework', 'fastify');
|
|
60
61
|
// https://github.com/open-telemetry/semantic-conventions/blob/main/docs/attributes-registry/http.md
|
|
61
62
|
span.setAttribute(semanticConventions.ATTR_HTTP_REQUEST_METHOD, httpMethod);
|
|
63
|
+
span.setAttribute(semanticConventions.ATTR_SERVER_ADDRESS, req.headers['x-original-host'] || req.headers.host || envManager.get('PORT'));
|
|
64
|
+
span.setAttribute(semanticConventions.ATTR_SERVER_PORT, envManager.get('PORT'));
|
|
62
65
|
// route should have low-cardinality - https://github.com/open-telemetry/semantic-conventions/blob/main/docs/attributes-registry/http.md
|
|
63
66
|
span.setAttribute(semanticConventions.ATTR_HTTP_ROUTE, httpRoute);
|
|
64
67
|
span.setAttribute(semanticConventions.ATTR_URL_PATH, parsedUrl.pathname);
|
|
@@ -85,6 +88,7 @@ const providers = [
|
|
|
85
88
|
app: tokensServerPrivate.WEB_FASTIFY_APP_TOKEN,
|
|
86
89
|
tracer: tokens.OPENTELEMETRY_TRACER_TOKEN,
|
|
87
90
|
tracesExcludePaths: tokensServer.UTILITY_SERVER_PATHS,
|
|
91
|
+
envManager: tokensCommon.ENV_MANAGER_TOKEN,
|
|
88
92
|
},
|
|
89
93
|
}),
|
|
90
94
|
core.provide({
|
|
@@ -125,4 +129,5 @@ const providers = [
|
|
|
125
129
|
}),
|
|
126
130
|
];
|
|
127
131
|
|
|
132
|
+
exports.REQUEST_SPAN = REQUEST_SPAN;
|
|
128
133
|
exports.providers = providers;
|
package/lib/server.es.js
CHANGED
|
@@ -2,8 +2,8 @@ import { __decorate } from 'tslib';
|
|
|
2
2
|
import { Module, provide, commandLineListTokens, optional, APP_INFO_TOKEN } from '@tramvai/core';
|
|
3
3
|
import { NodeTracerProvider, SimpleSpanProcessor, ConsoleSpanExporter } from '@opentelemetry/sdk-trace-node';
|
|
4
4
|
import { Resource } from '@opentelemetry/resources';
|
|
5
|
-
import { ATTR_SERVICE_NAME } from '@opentelemetry/semantic-conventions';
|
|
6
|
-
import { LOGGER_TOKEN } from '@tramvai/tokens-common';
|
|
5
|
+
import { ATTR_SERVICE_NAME, ATTR_SERVICE_VERSION } from '@opentelemetry/semantic-conventions';
|
|
6
|
+
import { LOGGER_TOKEN, ENV_MANAGER_TOKEN } from '@tramvai/tokens-common';
|
|
7
7
|
import { OPENTELEMETRY_PROVIDER_TOKEN, OPENTELEMETRY_PROVIDER_CONFIG_TOKEN, OPENTELEMETRY_PROVIDER_RESOURCE_TOKEN, OPENTELEMETRY_PROVIDER_SPAN_PROCESSOR_TOKEN, OPENTELEMETRY_PROVIDER_RESOURCE_ATTRIBUTES_TOKEN, OPENTELEMETRY_TRACER_TOKEN } from './tokens.es.js';
|
|
8
8
|
export { OPENTELEMETRY_PROVIDER_CONFIG_TOKEN, OPENTELEMETRY_PROVIDER_RESOURCE_ATTRIBUTES_TOKEN, OPENTELEMETRY_PROVIDER_RESOURCE_TOKEN, OPENTELEMETRY_PROVIDER_SPAN_PROCESSOR_TOKEN, OPENTELEMETRY_PROVIDER_TOKEN, OPENTELEMETRY_TRACER_TOKEN } from './tokens.es.js';
|
|
9
9
|
import { TramvaiTracerImpl } from './tracer/tracer.es.js';
|
|
@@ -11,6 +11,7 @@ import { providers } from './instrumentation/server.es.js';
|
|
|
11
11
|
import { providers as providers$1 } from './instrumentation/httpClient.es.js';
|
|
12
12
|
import { providers as providers$2 } from './instrumentation/logs.es.js';
|
|
13
13
|
import { providers as providers$3 } from './instrumentation/commandLineRunner.es.js';
|
|
14
|
+
import { providers as providers$4 } from './instrumentation/router.es.js';
|
|
14
15
|
|
|
15
16
|
let OpenTelemetryModule = class OpenTelemetryModule {
|
|
16
17
|
};
|
|
@@ -22,6 +23,7 @@ OpenTelemetryModule = __decorate([
|
|
|
22
23
|
...providers$1,
|
|
23
24
|
...providers$2,
|
|
24
25
|
...providers$3,
|
|
26
|
+
...providers$4,
|
|
25
27
|
provide({
|
|
26
28
|
provide: commandLineListTokens.init,
|
|
27
29
|
useFactory: ({ provider }) => {
|
|
@@ -89,20 +91,22 @@ OpenTelemetryModule = __decorate([
|
|
|
89
91
|
}),
|
|
90
92
|
provide({
|
|
91
93
|
provide: OPENTELEMETRY_PROVIDER_RESOURCE_ATTRIBUTES_TOKEN,
|
|
92
|
-
useFactory: ({ appInfo }) => {
|
|
94
|
+
useFactory: ({ appInfo, envManager }) => {
|
|
93
95
|
return {
|
|
94
96
|
[ATTR_SERVICE_NAME]: appInfo.appName,
|
|
97
|
+
[ATTR_SERVICE_VERSION]: envManager.get('APP_VERSION'),
|
|
95
98
|
};
|
|
96
99
|
},
|
|
97
100
|
deps: {
|
|
98
101
|
appInfo: APP_INFO_TOKEN,
|
|
102
|
+
envManager: ENV_MANAGER_TOKEN,
|
|
99
103
|
},
|
|
100
104
|
}),
|
|
101
105
|
provide({
|
|
102
106
|
provide: OPENTELEMETRY_TRACER_TOKEN,
|
|
103
107
|
useFactory: ({ provider }) => {
|
|
104
108
|
const tracer = provider.getTracer('tramvai', '1.0.0');
|
|
105
|
-
return new TramvaiTracerImpl(tracer);
|
|
109
|
+
return new TramvaiTracerImpl({ tracer });
|
|
106
110
|
},
|
|
107
111
|
deps: {
|
|
108
112
|
provider: OPENTELEMETRY_PROVIDER_TOKEN,
|
package/lib/server.js
CHANGED
|
@@ -14,6 +14,7 @@ var server = require('./instrumentation/server.js');
|
|
|
14
14
|
var httpClient = require('./instrumentation/httpClient.js');
|
|
15
15
|
var logs = require('./instrumentation/logs.js');
|
|
16
16
|
var commandLineRunner = require('./instrumentation/commandLineRunner.js');
|
|
17
|
+
var router = require('./instrumentation/router.js');
|
|
17
18
|
|
|
18
19
|
exports.OpenTelemetryModule = class OpenTelemetryModule {
|
|
19
20
|
};
|
|
@@ -25,6 +26,7 @@ exports.OpenTelemetryModule = tslib.__decorate([
|
|
|
25
26
|
...httpClient.providers,
|
|
26
27
|
...logs.providers,
|
|
27
28
|
...commandLineRunner.providers,
|
|
29
|
+
...router.providers,
|
|
28
30
|
core.provide({
|
|
29
31
|
provide: core.commandLineListTokens.init,
|
|
30
32
|
useFactory: ({ provider }) => {
|
|
@@ -92,20 +94,22 @@ exports.OpenTelemetryModule = tslib.__decorate([
|
|
|
92
94
|
}),
|
|
93
95
|
core.provide({
|
|
94
96
|
provide: tokens.OPENTELEMETRY_PROVIDER_RESOURCE_ATTRIBUTES_TOKEN,
|
|
95
|
-
useFactory: ({ appInfo }) => {
|
|
97
|
+
useFactory: ({ appInfo, envManager }) => {
|
|
96
98
|
return {
|
|
97
99
|
[semanticConventions.ATTR_SERVICE_NAME]: appInfo.appName,
|
|
100
|
+
[semanticConventions.ATTR_SERVICE_VERSION]: envManager.get('APP_VERSION'),
|
|
98
101
|
};
|
|
99
102
|
},
|
|
100
103
|
deps: {
|
|
101
104
|
appInfo: core.APP_INFO_TOKEN,
|
|
105
|
+
envManager: tokensCommon.ENV_MANAGER_TOKEN,
|
|
102
106
|
},
|
|
103
107
|
}),
|
|
104
108
|
core.provide({
|
|
105
109
|
provide: tokens.OPENTELEMETRY_TRACER_TOKEN,
|
|
106
110
|
useFactory: ({ provider }) => {
|
|
107
111
|
const tracer$1 = provider.getTracer('tramvai', '1.0.0');
|
|
108
|
-
return new tracer.TramvaiTracerImpl(tracer$1);
|
|
112
|
+
return new tracer.TramvaiTracerImpl({ tracer: tracer$1 });
|
|
109
113
|
},
|
|
110
114
|
deps: {
|
|
111
115
|
provider: tokens.OPENTELEMETRY_PROVIDER_TOKEN,
|
package/lib/tokens.d.ts
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import type { Context, Span, SpanOptions } from '@opentelemetry/api';
|
|
2
2
|
import type { SpanProcessor, TracerConfig, BasicTracerProvider } from '@opentelemetry/sdk-trace-node';
|
|
3
3
|
import type { Resource } from '@opentelemetry/resources';
|
|
4
|
+
export type TraceParams = {
|
|
5
|
+
skipError?: (error: Error) => boolean;
|
|
6
|
+
};
|
|
4
7
|
/**
|
|
5
8
|
* API inspired by:
|
|
6
9
|
* - https://github.com/DataDog/dd-trace-js/blob/59e9a2a75f4256755b4e6c9951a0bdf8d39b4015/index.d.ts#L9
|
|
@@ -12,10 +15,10 @@ export interface TramvaiTracer {
|
|
|
12
15
|
startActiveSpan<F extends (span: Span) => unknown>(name: string, options: SpanOptions, fn: F): ReturnType<F>;
|
|
13
16
|
startActiveSpan<F extends (span: Span) => unknown>(name: string, options: SpanOptions, context: Context, fn: F): ReturnType<F>;
|
|
14
17
|
getActiveSpan(): Span | undefined;
|
|
15
|
-
trace<T>(name: string, fn: (span: Span) => Promise<T
|
|
16
|
-
trace<T>(name: string, fn: (span: Span) => T): T;
|
|
17
|
-
trace<T>(name: string, options: SpanOptions, fn: (span: Span) => Promise<T
|
|
18
|
-
trace<T>(name: string, options: SpanOptions, fn: (span: Span) => T): T;
|
|
18
|
+
trace<T>(name: string, fn: (span: Span) => Promise<T>, params?: TraceParams): Promise<T>;
|
|
19
|
+
trace<T>(name: string, fn: (span: Span) => T, params?: TraceParams): T;
|
|
20
|
+
trace<T>(name: string, options: SpanOptions, fn: (span: Span) => Promise<T>, params?: TraceParams): Promise<T>;
|
|
21
|
+
trace<T>(name: string, options: SpanOptions, fn: (span: Span) => T, params?: TraceParams): T;
|
|
19
22
|
}
|
|
20
23
|
export declare const OPENTELEMETRY_PROVIDER_TOKEN: BasicTracerProvider & {
|
|
21
24
|
__type?: "base token" | undefined;
|
package/lib/tracer/tracer.d.ts
CHANGED
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
import type { Context, Span, SpanOptions, Tracer } from '@opentelemetry/api';
|
|
2
|
-
import type { TramvaiTracer } from '../tokens';
|
|
2
|
+
import type { TraceParams, TramvaiTracer } from '../tokens';
|
|
3
3
|
export declare class TramvaiTracerImpl implements TramvaiTracer {
|
|
4
4
|
private tracer;
|
|
5
|
-
constructor(tracer:
|
|
5
|
+
constructor({ tracer }: {
|
|
6
|
+
tracer: Tracer;
|
|
7
|
+
});
|
|
6
8
|
startSpan(...args: any[]): Span;
|
|
7
9
|
startActiveSpan<F extends (span: Span) => unknown>(name: string, fn: F): ReturnType<F>;
|
|
8
10
|
startActiveSpan<F extends (span: Span) => unknown>(name: string, options: SpanOptions, fn: F): ReturnType<F>;
|
|
9
11
|
startActiveSpan<F extends (span: Span) => unknown>(name: string, options: SpanOptions, ctx: Context, fn: F): ReturnType<F>;
|
|
10
12
|
getActiveSpan(): Span | undefined;
|
|
11
|
-
trace<T>(name: string, fn: (span: Span) => Promise<T
|
|
12
|
-
trace<T>(name: string, fn: (span: Span) => T): T;
|
|
13
|
-
trace<T>(name: string, options: SpanOptions, fn: (span: Span) => Promise<T
|
|
14
|
-
trace<T>(name: string, options: SpanOptions, fn: (span: Span) => T): T;
|
|
13
|
+
trace<T>(name: string, fn: (span: Span) => Promise<T>, params?: TraceParams): Promise<T>;
|
|
14
|
+
trace<T>(name: string, fn: (span: Span) => T, params?: TraceParams): T;
|
|
15
|
+
trace<T>(name: string, options: SpanOptions, fn: (span: Span) => Promise<T>, params?: TraceParams): Promise<T>;
|
|
16
|
+
trace<T>(name: string, options: SpanOptions, fn: (span: Span, params?: TraceParams) => T): T;
|
|
15
17
|
}
|
|
16
18
|
//# sourceMappingURL=tracer.d.ts.map
|
package/lib/tracer/tracer.es.js
CHANGED
|
@@ -1,18 +1,21 @@
|
|
|
1
1
|
import isPromise from '@tinkoff/utils/is/promise';
|
|
2
2
|
import { trace, context, ROOT_CONTEXT, SpanStatusCode } from '@opentelemetry/api';
|
|
3
|
+
import { isSilentError } from '@tinkoff/errors';
|
|
3
4
|
|
|
4
5
|
/* eslint-disable prefer-destructuring */
|
|
5
|
-
function recordAndThrowError(span, error) {
|
|
6
|
+
function recordAndThrowError(span, error, { skipError = () => false }) {
|
|
6
7
|
span.recordException(error);
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
if (!(skipError(error) || isSilentError(error))) {
|
|
9
|
+
span.setStatus({
|
|
10
|
+
code: SpanStatusCode.ERROR,
|
|
11
|
+
message: error?.message ?? 'Unknown error',
|
|
12
|
+
});
|
|
13
|
+
}
|
|
11
14
|
span.end();
|
|
12
15
|
throw error;
|
|
13
16
|
}
|
|
14
17
|
class TramvaiTracerImpl {
|
|
15
|
-
constructor(tracer) {
|
|
18
|
+
constructor({ tracer }) {
|
|
16
19
|
this.tracer = tracer;
|
|
17
20
|
}
|
|
18
21
|
startSpan(...args) {
|
|
@@ -30,13 +33,16 @@ class TramvaiTracerImpl {
|
|
|
30
33
|
const name = args[0];
|
|
31
34
|
let fn;
|
|
32
35
|
let options;
|
|
33
|
-
|
|
36
|
+
let params;
|
|
37
|
+
if (args.length === 2 || (args.length === 3 && typeof args[2] === 'object')) {
|
|
34
38
|
fn = args[1];
|
|
35
39
|
options = {};
|
|
40
|
+
params = args[2] || {};
|
|
36
41
|
}
|
|
37
42
|
else {
|
|
38
43
|
fn = args[2];
|
|
39
44
|
options = args[1];
|
|
45
|
+
params = args[3] || {};
|
|
40
46
|
}
|
|
41
47
|
const activeSpan = trace.getSpan(context.active());
|
|
42
48
|
const spanContext = activeSpan ? trace.setSpan(context.active(), activeSpan) : undefined;
|
|
@@ -52,7 +58,7 @@ class TramvaiTracerImpl {
|
|
|
52
58
|
return res;
|
|
53
59
|
})
|
|
54
60
|
.catch((error) => {
|
|
55
|
-
recordAndThrowError(span, error);
|
|
61
|
+
recordAndThrowError(span, error, params);
|
|
56
62
|
});
|
|
57
63
|
}
|
|
58
64
|
// otherwise, end span immediately
|
|
@@ -60,7 +66,7 @@ class TramvaiTracerImpl {
|
|
|
60
66
|
return result;
|
|
61
67
|
}
|
|
62
68
|
catch (error) {
|
|
63
|
-
recordAndThrowError(span, error);
|
|
69
|
+
recordAndThrowError(span, error, params);
|
|
64
70
|
}
|
|
65
71
|
});
|
|
66
72
|
}
|
package/lib/tracer/tracer.js
CHANGED
|
@@ -4,23 +4,26 @@ Object.defineProperty(exports, '__esModule', { value: true });
|
|
|
4
4
|
|
|
5
5
|
var isPromise = require('@tinkoff/utils/is/promise');
|
|
6
6
|
var api = require('@opentelemetry/api');
|
|
7
|
+
var errors = require('@tinkoff/errors');
|
|
7
8
|
|
|
8
9
|
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
9
10
|
|
|
10
11
|
var isPromise__default = /*#__PURE__*/_interopDefaultLegacy(isPromise);
|
|
11
12
|
|
|
12
13
|
/* eslint-disable prefer-destructuring */
|
|
13
|
-
function recordAndThrowError(span, error) {
|
|
14
|
+
function recordAndThrowError(span, error, { skipError = () => false }) {
|
|
14
15
|
span.recordException(error);
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
if (!(skipError(error) || errors.isSilentError(error))) {
|
|
17
|
+
span.setStatus({
|
|
18
|
+
code: api.SpanStatusCode.ERROR,
|
|
19
|
+
message: error?.message ?? 'Unknown error',
|
|
20
|
+
});
|
|
21
|
+
}
|
|
19
22
|
span.end();
|
|
20
23
|
throw error;
|
|
21
24
|
}
|
|
22
25
|
class TramvaiTracerImpl {
|
|
23
|
-
constructor(tracer) {
|
|
26
|
+
constructor({ tracer }) {
|
|
24
27
|
this.tracer = tracer;
|
|
25
28
|
}
|
|
26
29
|
startSpan(...args) {
|
|
@@ -38,13 +41,16 @@ class TramvaiTracerImpl {
|
|
|
38
41
|
const name = args[0];
|
|
39
42
|
let fn;
|
|
40
43
|
let options;
|
|
41
|
-
|
|
44
|
+
let params;
|
|
45
|
+
if (args.length === 2 || (args.length === 3 && typeof args[2] === 'object')) {
|
|
42
46
|
fn = args[1];
|
|
43
47
|
options = {};
|
|
48
|
+
params = args[2] || {};
|
|
44
49
|
}
|
|
45
50
|
else {
|
|
46
51
|
fn = args[2];
|
|
47
52
|
options = args[1];
|
|
53
|
+
params = args[3] || {};
|
|
48
54
|
}
|
|
49
55
|
const activeSpan = api.trace.getSpan(api.context.active());
|
|
50
56
|
const spanContext = activeSpan ? api.trace.setSpan(api.context.active(), activeSpan) : undefined;
|
|
@@ -60,7 +66,7 @@ class TramvaiTracerImpl {
|
|
|
60
66
|
return res;
|
|
61
67
|
})
|
|
62
68
|
.catch((error) => {
|
|
63
|
-
recordAndThrowError(span, error);
|
|
69
|
+
recordAndThrowError(span, error, params);
|
|
64
70
|
});
|
|
65
71
|
}
|
|
66
72
|
// otherwise, end span immediately
|
|
@@ -68,7 +74,7 @@ class TramvaiTracerImpl {
|
|
|
68
74
|
return result;
|
|
69
75
|
}
|
|
70
76
|
catch (error) {
|
|
71
|
-
recordAndThrowError(span, error);
|
|
77
|
+
recordAndThrowError(span, error, params);
|
|
72
78
|
}
|
|
73
79
|
});
|
|
74
80
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tramvai/module-opentelemetry",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.24.0",
|
|
4
4
|
"description": "Интеграция OpenTelemetry",
|
|
5
5
|
"browser": "lib/browser.js",
|
|
6
6
|
"main": "lib/server.js",
|
|
@@ -28,18 +28,19 @@
|
|
|
28
28
|
"@opentelemetry/sdk-trace-node": "^1.28.0",
|
|
29
29
|
"@opentelemetry/semantic-conventions": "^1.28.0",
|
|
30
30
|
"path-to-regexp": "0.1.7",
|
|
31
|
-
"@tramvai/tokens-common": "5.
|
|
32
|
-
"@tramvai/tokens-metrics": "5.
|
|
33
|
-
"@tramvai/tokens-http-client": "5.
|
|
34
|
-
"@tramvai/tokens-server": "5.
|
|
35
|
-
"@tramvai/tokens-
|
|
31
|
+
"@tramvai/tokens-common": "5.24.0",
|
|
32
|
+
"@tramvai/tokens-metrics": "5.24.0",
|
|
33
|
+
"@tramvai/tokens-http-client": "5.24.0",
|
|
34
|
+
"@tramvai/tokens-server": "5.24.0",
|
|
35
|
+
"@tramvai/tokens-router": "5.24.0",
|
|
36
|
+
"@tramvai/tokens-server-private": "5.24.0",
|
|
36
37
|
"@tinkoff/utils": "^2.1.2",
|
|
37
38
|
"@tinkoff/errors": "0.6.2"
|
|
38
39
|
},
|
|
39
40
|
"devDependencies": {},
|
|
40
41
|
"peerDependencies": {
|
|
41
42
|
"@tinkoff/dippy": "0.11.3",
|
|
42
|
-
"@tramvai/core": "5.
|
|
43
|
+
"@tramvai/core": "5.24.0",
|
|
43
44
|
"tslib": "^2.4.0"
|
|
44
45
|
}
|
|
45
46
|
}
|