@tramvai/module-opentelemetry 5.14.9
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/README.md +3 -0
- package/lib/browser.d.ts +4 -0
- package/lib/browser.js +15 -0
- package/lib/instrumentation/httpClient.d.ts +11 -0
- package/lib/instrumentation/httpClient.es.js +95 -0
- package/lib/instrumentation/httpClient.js +99 -0
- package/lib/instrumentation/logs.d.ts +4 -0
- package/lib/instrumentation/logs.es.js +26 -0
- package/lib/instrumentation/logs.js +30 -0
- package/lib/instrumentation/server.d.ts +25 -0
- package/lib/instrumentation/server.es.js +119 -0
- package/lib/instrumentation/server.js +128 -0
- package/lib/server.d.ts +4 -0
- package/lib/server.es.js +125 -0
- package/lib/server.js +133 -0
- package/lib/tokens.browser.js +10 -0
- package/lib/tokens.d.ts +38 -0
- package/lib/tokens.es.js +10 -0
- package/lib/tokens.js +19 -0
- package/lib/tracer/tracer.d.ts +16 -0
- package/lib/tracer/tracer.es.js +70 -0
- package/lib/tracer/tracer.js +78 -0
- package/package.json +45 -0
package/README.md
ADDED
package/lib/browser.d.ts
ADDED
package/lib/browser.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { __decorate } from 'tslib';
|
|
2
|
+
import { Module } from '@tramvai/core';
|
|
3
|
+
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.browser.js';
|
|
4
|
+
|
|
5
|
+
let OpenTelemetryModule = class OpenTelemetryModule {
|
|
6
|
+
};
|
|
7
|
+
OpenTelemetryModule = __decorate([
|
|
8
|
+
Module({
|
|
9
|
+
imports: [],
|
|
10
|
+
providers: [],
|
|
11
|
+
})
|
|
12
|
+
], OpenTelemetryModule);
|
|
13
|
+
// todo declareModule!
|
|
14
|
+
|
|
15
|
+
export { OpenTelemetryModule };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export declare const providers: import("@tramvai/core").Provider<{
|
|
2
|
+
tracer: import("../tokens").TramvaiTracer & {
|
|
3
|
+
__type?: "base token" | undefined;
|
|
4
|
+
};
|
|
5
|
+
metricsServicesRegistry: import("@tramvai/tokens-metrics").MetricsServicesRegistryInterface & {
|
|
6
|
+
__type?: "base token" | undefined;
|
|
7
|
+
};
|
|
8
|
+
}, import("@tramvai/http-client").HttpClientInterceptor & {
|
|
9
|
+
__type?: "multi token" | undefined;
|
|
10
|
+
}>[];
|
|
11
|
+
//# sourceMappingURL=httpClient.d.ts.map
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { provide } from '@tramvai/core';
|
|
2
|
+
import { DEFAULT_HTTP_CLIENT_INTERCEPTORS } from '@tramvai/tokens-http-client';
|
|
3
|
+
import { METRICS_SERVICES_REGISTRY_TOKEN } from '@tramvai/tokens-metrics';
|
|
4
|
+
import { propagation, context, SpanKind } from '@opentelemetry/api';
|
|
5
|
+
import { ATTR_HTTP_REQUEST_METHOD, ATTR_SERVER_ADDRESS, ATTR_URL_PATH, ATTR_URL_QUERY, ATTR_URL_SCHEME, ATTR_URL_FULL, ATTR_HTTP_RESPONSE_STATUS_CODE } from '@opentelemetry/semantic-conventions';
|
|
6
|
+
import { OPENTELEMETRY_TRACER_TOKEN } from '../tokens.es.js';
|
|
7
|
+
|
|
8
|
+
const providers = [
|
|
9
|
+
provide({
|
|
10
|
+
provide: DEFAULT_HTTP_CLIENT_INTERCEPTORS,
|
|
11
|
+
useFactory: ({ tracer, metricsServicesRegistry }) => {
|
|
12
|
+
return (request, next) => {
|
|
13
|
+
const url = request.url ??
|
|
14
|
+
// todo add leading slash before path if needed
|
|
15
|
+
(request.baseUrl ? `${request.baseUrl}${request.path}` : request.path ?? '');
|
|
16
|
+
const parsedUrl = new URL(request.query ? `${url}?${new URLSearchParams(request.query).toString()}` : url);
|
|
17
|
+
const serviceName = metricsServicesRegistry.getServiceName(url, request) ?? 'unknown';
|
|
18
|
+
const method = request.method ?? 'GET';
|
|
19
|
+
// propagate context from outgoing request
|
|
20
|
+
// https://opentelemetry.io/docs/languages/js/propagation/#manual-context-propagation
|
|
21
|
+
const output = {};
|
|
22
|
+
propagation.inject(context.active(), output);
|
|
23
|
+
if (output.traceparent) {
|
|
24
|
+
if (!request.headers) {
|
|
25
|
+
request.headers = {};
|
|
26
|
+
}
|
|
27
|
+
request.headers.traceparent = output.traceparent;
|
|
28
|
+
}
|
|
29
|
+
if (output.tracestate) {
|
|
30
|
+
if (!request.headers) {
|
|
31
|
+
request.headers = {};
|
|
32
|
+
}
|
|
33
|
+
request.headers.tracestate = output.tracestate;
|
|
34
|
+
}
|
|
35
|
+
// https://github.com/open-telemetry/semantic-conventions/blob/main/docs/http/http-spans.md#http-client
|
|
36
|
+
return tracer.trace(`${method} ${serviceName}`, { kind: SpanKind.CLIENT }, (span) => {
|
|
37
|
+
// todo: move custom tramvai attrs to constants
|
|
38
|
+
/**
|
|
39
|
+
* - `tramvai.http-client.transport` - internal HTTP client, `node-fetch` at server-side (possible `undici` in future), `fetch` at client-side
|
|
40
|
+
*/
|
|
41
|
+
span.setAttribute('tramvai.scope', 'http-client');
|
|
42
|
+
span.setAttribute('tramvai.http-client.transport', 'node-fetch');
|
|
43
|
+
span.setAttribute(ATTR_HTTP_REQUEST_METHOD, method);
|
|
44
|
+
span.setAttribute(ATTR_SERVER_ADDRESS, parsedUrl.hostname);
|
|
45
|
+
span.setAttribute(ATTR_URL_PATH, parsedUrl.pathname);
|
|
46
|
+
span.setAttribute(ATTR_URL_QUERY, parsedUrl.search.replace('?', ''));
|
|
47
|
+
span.setAttribute(ATTR_URL_SCHEME, parsedUrl.protocol.replace(':', ''));
|
|
48
|
+
span.setAttribute(ATTR_URL_FULL, parsedUrl.href);
|
|
49
|
+
// todo req/res headers?
|
|
50
|
+
// todo http.request.resend_count?
|
|
51
|
+
return next(request)
|
|
52
|
+
.then((response) => {
|
|
53
|
+
span.setAttribute(ATTR_HTTP_RESPONSE_STATUS_CODE, response.status);
|
|
54
|
+
const meta = response.__meta;
|
|
55
|
+
if (meta) {
|
|
56
|
+
writeMetaAttributes(span, meta);
|
|
57
|
+
}
|
|
58
|
+
return response;
|
|
59
|
+
})
|
|
60
|
+
.catch((error) => {
|
|
61
|
+
span.setAttribute(ATTR_HTTP_RESPONSE_STATUS_CODE, error?.status ?? 500);
|
|
62
|
+
const meta = error.__meta;
|
|
63
|
+
if (meta) {
|
|
64
|
+
writeMetaAttributes(span, meta);
|
|
65
|
+
}
|
|
66
|
+
throw error;
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
};
|
|
70
|
+
},
|
|
71
|
+
deps: {
|
|
72
|
+
tracer: OPENTELEMETRY_TRACER_TOKEN,
|
|
73
|
+
metricsServicesRegistry: METRICS_SERVICES_REGISTRY_TOKEN,
|
|
74
|
+
},
|
|
75
|
+
}),
|
|
76
|
+
];
|
|
77
|
+
function writeMetaAttributes(span, meta) {
|
|
78
|
+
const { cache, CIRCUIT_BREAKER } = meta;
|
|
79
|
+
if (cache) {
|
|
80
|
+
span.setAttribute('tramvai.http-client.cache.forced', cache.forced);
|
|
81
|
+
span.setAttribute('tramvai.http-client.cache.enabled', cache.enabled);
|
|
82
|
+
span.setAttribute('tramvai.http-client.cache.enabled', cache.enabled);
|
|
83
|
+
span.setAttribute('tramvai.http-client.cache.memory.enabled', cache.memoryEnabled);
|
|
84
|
+
span.setAttribute('tramvai.http-client.cache.memory.force', cache.memoryForce);
|
|
85
|
+
span.setAttribute('tramvai.http-client.cache.memory.cache', cache.memoryCache);
|
|
86
|
+
span.setAttribute('tramvai.http-client.cache.memory.cache.outdated', cache.memoryCacheOutdated);
|
|
87
|
+
span.setAttribute('tramvai.http-client.cache.deduplicate.enabled', cache.deduplicateEnabled);
|
|
88
|
+
span.setAttribute('tramvai.http-client.cache.deduplicate.force', cache.deduplicateForce);
|
|
89
|
+
}
|
|
90
|
+
if (CIRCUIT_BREAKER) {
|
|
91
|
+
span.setAttribute('tramvai.http-client.circuit-breaker.open', CIRCUIT_BREAKER?.open);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export { providers };
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var core = require('@tramvai/core');
|
|
6
|
+
var tokensHttpClient = require('@tramvai/tokens-http-client');
|
|
7
|
+
var tokensMetrics = require('@tramvai/tokens-metrics');
|
|
8
|
+
var api = require('@opentelemetry/api');
|
|
9
|
+
var semanticConventions = require('@opentelemetry/semantic-conventions');
|
|
10
|
+
var tokens = require('../tokens.js');
|
|
11
|
+
|
|
12
|
+
const providers = [
|
|
13
|
+
core.provide({
|
|
14
|
+
provide: tokensHttpClient.DEFAULT_HTTP_CLIENT_INTERCEPTORS,
|
|
15
|
+
useFactory: ({ tracer, metricsServicesRegistry }) => {
|
|
16
|
+
return (request, next) => {
|
|
17
|
+
const url = request.url ??
|
|
18
|
+
// todo add leading slash before path if needed
|
|
19
|
+
(request.baseUrl ? `${request.baseUrl}${request.path}` : request.path ?? '');
|
|
20
|
+
const parsedUrl = new URL(request.query ? `${url}?${new URLSearchParams(request.query).toString()}` : url);
|
|
21
|
+
const serviceName = metricsServicesRegistry.getServiceName(url, request) ?? 'unknown';
|
|
22
|
+
const method = request.method ?? 'GET';
|
|
23
|
+
// propagate context from outgoing request
|
|
24
|
+
// https://opentelemetry.io/docs/languages/js/propagation/#manual-context-propagation
|
|
25
|
+
const output = {};
|
|
26
|
+
api.propagation.inject(api.context.active(), output);
|
|
27
|
+
if (output.traceparent) {
|
|
28
|
+
if (!request.headers) {
|
|
29
|
+
request.headers = {};
|
|
30
|
+
}
|
|
31
|
+
request.headers.traceparent = output.traceparent;
|
|
32
|
+
}
|
|
33
|
+
if (output.tracestate) {
|
|
34
|
+
if (!request.headers) {
|
|
35
|
+
request.headers = {};
|
|
36
|
+
}
|
|
37
|
+
request.headers.tracestate = output.tracestate;
|
|
38
|
+
}
|
|
39
|
+
// https://github.com/open-telemetry/semantic-conventions/blob/main/docs/http/http-spans.md#http-client
|
|
40
|
+
return tracer.trace(`${method} ${serviceName}`, { kind: api.SpanKind.CLIENT }, (span) => {
|
|
41
|
+
// todo: move custom tramvai attrs to constants
|
|
42
|
+
/**
|
|
43
|
+
* - `tramvai.http-client.transport` - internal HTTP client, `node-fetch` at server-side (possible `undici` in future), `fetch` at client-side
|
|
44
|
+
*/
|
|
45
|
+
span.setAttribute('tramvai.scope', 'http-client');
|
|
46
|
+
span.setAttribute('tramvai.http-client.transport', 'node-fetch');
|
|
47
|
+
span.setAttribute(semanticConventions.ATTR_HTTP_REQUEST_METHOD, method);
|
|
48
|
+
span.setAttribute(semanticConventions.ATTR_SERVER_ADDRESS, parsedUrl.hostname);
|
|
49
|
+
span.setAttribute(semanticConventions.ATTR_URL_PATH, parsedUrl.pathname);
|
|
50
|
+
span.setAttribute(semanticConventions.ATTR_URL_QUERY, parsedUrl.search.replace('?', ''));
|
|
51
|
+
span.setAttribute(semanticConventions.ATTR_URL_SCHEME, parsedUrl.protocol.replace(':', ''));
|
|
52
|
+
span.setAttribute(semanticConventions.ATTR_URL_FULL, parsedUrl.href);
|
|
53
|
+
// todo req/res headers?
|
|
54
|
+
// todo http.request.resend_count?
|
|
55
|
+
return next(request)
|
|
56
|
+
.then((response) => {
|
|
57
|
+
span.setAttribute(semanticConventions.ATTR_HTTP_RESPONSE_STATUS_CODE, response.status);
|
|
58
|
+
const meta = response.__meta;
|
|
59
|
+
if (meta) {
|
|
60
|
+
writeMetaAttributes(span, meta);
|
|
61
|
+
}
|
|
62
|
+
return response;
|
|
63
|
+
})
|
|
64
|
+
.catch((error) => {
|
|
65
|
+
span.setAttribute(semanticConventions.ATTR_HTTP_RESPONSE_STATUS_CODE, error?.status ?? 500);
|
|
66
|
+
const meta = error.__meta;
|
|
67
|
+
if (meta) {
|
|
68
|
+
writeMetaAttributes(span, meta);
|
|
69
|
+
}
|
|
70
|
+
throw error;
|
|
71
|
+
});
|
|
72
|
+
});
|
|
73
|
+
};
|
|
74
|
+
},
|
|
75
|
+
deps: {
|
|
76
|
+
tracer: tokens.OPENTELEMETRY_TRACER_TOKEN,
|
|
77
|
+
metricsServicesRegistry: tokensMetrics.METRICS_SERVICES_REGISTRY_TOKEN,
|
|
78
|
+
},
|
|
79
|
+
}),
|
|
80
|
+
];
|
|
81
|
+
function writeMetaAttributes(span, meta) {
|
|
82
|
+
const { cache, CIRCUIT_BREAKER } = meta;
|
|
83
|
+
if (cache) {
|
|
84
|
+
span.setAttribute('tramvai.http-client.cache.forced', cache.forced);
|
|
85
|
+
span.setAttribute('tramvai.http-client.cache.enabled', cache.enabled);
|
|
86
|
+
span.setAttribute('tramvai.http-client.cache.enabled', cache.enabled);
|
|
87
|
+
span.setAttribute('tramvai.http-client.cache.memory.enabled', cache.memoryEnabled);
|
|
88
|
+
span.setAttribute('tramvai.http-client.cache.memory.force', cache.memoryForce);
|
|
89
|
+
span.setAttribute('tramvai.http-client.cache.memory.cache', cache.memoryCache);
|
|
90
|
+
span.setAttribute('tramvai.http-client.cache.memory.cache.outdated', cache.memoryCacheOutdated);
|
|
91
|
+
span.setAttribute('tramvai.http-client.cache.deduplicate.enabled', cache.deduplicateEnabled);
|
|
92
|
+
span.setAttribute('tramvai.http-client.cache.deduplicate.force', cache.deduplicateForce);
|
|
93
|
+
}
|
|
94
|
+
if (CIRCUIT_BREAKER) {
|
|
95
|
+
span.setAttribute('tramvai.http-client.circuit-breaker.open', CIRCUIT_BREAKER?.open);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
exports.providers = providers;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { trace, context } from '@opentelemetry/api';
|
|
2
|
+
import { provide } from '@tramvai/core';
|
|
3
|
+
import { LOGGER_INIT_HOOK } from '@tramvai/tokens-common';
|
|
4
|
+
|
|
5
|
+
const providers = [
|
|
6
|
+
provide({
|
|
7
|
+
provide: LOGGER_INIT_HOOK,
|
|
8
|
+
useValue: (loggerInstance) => {
|
|
9
|
+
loggerInstance.addExtension({
|
|
10
|
+
extend(logObj) {
|
|
11
|
+
const activeSpanContext = trace.getSpan(context.active())?.spanContext();
|
|
12
|
+
if (activeSpanContext) {
|
|
13
|
+
return {
|
|
14
|
+
...logObj,
|
|
15
|
+
spanId: activeSpanContext.spanId,
|
|
16
|
+
traceId: activeSpanContext.traceId,
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
return logObj;
|
|
20
|
+
},
|
|
21
|
+
});
|
|
22
|
+
},
|
|
23
|
+
}),
|
|
24
|
+
];
|
|
25
|
+
|
|
26
|
+
export { providers };
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var api = require('@opentelemetry/api');
|
|
6
|
+
var core = require('@tramvai/core');
|
|
7
|
+
var tokensCommon = require('@tramvai/tokens-common');
|
|
8
|
+
|
|
9
|
+
const providers = [
|
|
10
|
+
core.provide({
|
|
11
|
+
provide: tokensCommon.LOGGER_INIT_HOOK,
|
|
12
|
+
useValue: (loggerInstance) => {
|
|
13
|
+
loggerInstance.addExtension({
|
|
14
|
+
extend(logObj) {
|
|
15
|
+
const activeSpanContext = api.trace.getSpan(api.context.active())?.spanContext();
|
|
16
|
+
if (activeSpanContext) {
|
|
17
|
+
return {
|
|
18
|
+
...logObj,
|
|
19
|
+
spanId: activeSpanContext.spanId,
|
|
20
|
+
traceId: activeSpanContext.traceId,
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
return logObj;
|
|
24
|
+
},
|
|
25
|
+
});
|
|
26
|
+
},
|
|
27
|
+
}),
|
|
28
|
+
];
|
|
29
|
+
|
|
30
|
+
exports.providers = providers;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import { type Span } from '@opentelemetry/api';
|
|
3
|
+
declare const REQUEST_SPAN: unique symbol;
|
|
4
|
+
declare module 'fastify' {
|
|
5
|
+
interface FastifyRequest {
|
|
6
|
+
[REQUEST_SPAN]?: Span;
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
export declare const providers: (import("@tramvai/core").Provider<{
|
|
10
|
+
app: import("fastify").FastifyInstance<import("fastify").RawServerDefault, import("http").IncomingMessage, import("http").ServerResponse<import("http").IncomingMessage>, import("fastify").FastifyBaseLogger, import("fastify").FastifyTypeProviderDefault> & {
|
|
11
|
+
__type?: "base token" | undefined;
|
|
12
|
+
};
|
|
13
|
+
tracer: import("../tokens").TramvaiTracer & {
|
|
14
|
+
__type?: "base token" | undefined;
|
|
15
|
+
};
|
|
16
|
+
tracesExcludePaths: string & {
|
|
17
|
+
__type?: "multi token" | undefined;
|
|
18
|
+
};
|
|
19
|
+
}, import("@tramvai/tokens-server-private").FASTIFY_APP_INIT_HANDLER & {
|
|
20
|
+
__type?: "multi token" | undefined;
|
|
21
|
+
}> | import("@tramvai/core").Provider<{}, import("@tramvai/tokens-server-private").FASTIFY_APP_ERROR_HANDLER & {
|
|
22
|
+
__type?: "multi token" | undefined;
|
|
23
|
+
}>)[];
|
|
24
|
+
export {};
|
|
25
|
+
//# sourceMappingURL=server.d.ts.map
|
|
@@ -0,0 +1,119 @@
|
|
|
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';
|
|
2
|
+
import { propagation, ROOT_CONTEXT, SpanKind, SpanStatusCode } from '@opentelemetry/api';
|
|
3
|
+
import pathToRegexp from 'path-to-regexp';
|
|
4
|
+
import flatten from '@tinkoff/utils/array/flatten';
|
|
5
|
+
import { isNotFoundError, isHttpError } from '@tinkoff/errors';
|
|
6
|
+
import { provide } from '@tramvai/core';
|
|
7
|
+
import { UTILITY_SERVER_PATHS } from '@tramvai/tokens-server';
|
|
8
|
+
import { WEB_FASTIFY_APP_INIT_TOKEN, WEB_FASTIFY_APP_TOKEN, WEB_FASTIFY_APP_AFTER_ERROR_TOKEN } from '@tramvai/tokens-server-private';
|
|
9
|
+
import { OPENTELEMETRY_TRACER_TOKEN } from '../tokens.es.js';
|
|
10
|
+
|
|
11
|
+
const REQUEST_SPAN = Symbol('opentelemetry.tramvai.server.request.span');
|
|
12
|
+
const providers = [
|
|
13
|
+
provide({
|
|
14
|
+
provide: WEB_FASTIFY_APP_INIT_TOKEN,
|
|
15
|
+
useFactory: ({ app, tracer, tracesExcludePaths }) => {
|
|
16
|
+
return () => {
|
|
17
|
+
// todo copypaste from @tinkoff/measure-fastify-requests
|
|
18
|
+
const excludePatterns = flatten(tracesExcludePaths).map((p) => pathToRegexp(p));
|
|
19
|
+
app.addHook('onRequest', (req, reply, done) => {
|
|
20
|
+
// skip traces for healthchecks
|
|
21
|
+
if (excludePatterns.some((p) => p.test(req.url))) {
|
|
22
|
+
done();
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
// propagate context from incoming request
|
|
26
|
+
// https://opentelemetry.io/docs/languages/js/propagation/#manual-context-propagation
|
|
27
|
+
const activeContext = propagation.extract(ROOT_CONTEXT, req.headers);
|
|
28
|
+
const httpMethod = req.method;
|
|
29
|
+
// todo useful because always get `*`, rewrite with tramvai router route?
|
|
30
|
+
const httpRoute = req.routeOptions?.url
|
|
31
|
+
? req.routeOptions.url // since fastify@4.10.0
|
|
32
|
+
: req.routerPath;
|
|
33
|
+
const parsedUrl = new URL(`http://localhost${req.url}`);
|
|
34
|
+
// https://github.com/open-telemetry/semantic-conventions/blob/main/docs/http/http-spans.md#name
|
|
35
|
+
tracer.startActiveSpan(`${httpMethod} ${httpRoute === '*' ? 'APP' : httpRoute}`,
|
|
36
|
+
// https://github.com/open-telemetry/semantic-conventions/blob/main/docs/http/http-spans.md#http-server-semantic-conventions
|
|
37
|
+
{ kind: SpanKind.SERVER }, activeContext, (span) => {
|
|
38
|
+
req[REQUEST_SPAN] = span;
|
|
39
|
+
// todo: move custom tramvai attrs to constants
|
|
40
|
+
/**
|
|
41
|
+
* let's add some conventions for tramvai attributes:
|
|
42
|
+
* - `tramvai` prefix for all specific attributes in tramvai instrumentation
|
|
43
|
+
* - `tramvai.scope` second prefix to define module, e.g. `tramvai.scope: server`
|
|
44
|
+
* - `tramvai.*` second prefix for specific modules, e.g. `tramvai.server`
|
|
45
|
+
* - `tramvai.server.handler` - `app` value for pages handler, another possible values - `papi`, `request-limiter`
|
|
46
|
+
* - `tramvai.server.framework` - reserved for future, if we will add support for other server frameworks
|
|
47
|
+
*/
|
|
48
|
+
span.setAttribute('tramvai.scope', 'server');
|
|
49
|
+
span.setAttribute('tramvai.server.handler', 'app');
|
|
50
|
+
span.setAttribute('tramvai.server.framework', 'fastify');
|
|
51
|
+
// https://github.com/open-telemetry/semantic-conventions/blob/main/docs/attributes-registry/http.md
|
|
52
|
+
span.setAttribute(ATTR_HTTP_REQUEST_METHOD, httpMethod);
|
|
53
|
+
// route should have low-cardinality - https://github.com/open-telemetry/semantic-conventions/blob/main/docs/attributes-registry/http.md
|
|
54
|
+
span.setAttribute(ATTR_HTTP_ROUTE, httpRoute);
|
|
55
|
+
span.setAttribute(ATTR_URL_PATH, parsedUrl.pathname);
|
|
56
|
+
span.setAttribute(ATTR_URL_QUERY, parsedUrl.search.replace('?', ''));
|
|
57
|
+
span.setAttribute(ATTR_URL_SCHEME, parsedUrl.protocol.replace(':', ''));
|
|
58
|
+
span.setAttribute(ATTR_URL_FULL, parsedUrl.href);
|
|
59
|
+
done();
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
app.addHook('onResponse', (req, reply) => {
|
|
63
|
+
if (req[REQUEST_SPAN]) {
|
|
64
|
+
const span = req[REQUEST_SPAN];
|
|
65
|
+
if (reply.statusCode >= 400) ;
|
|
66
|
+
else {
|
|
67
|
+
span.setAttribute(ATTR_HTTP_RESPONSE_STATUS_CODE, reply.statusCode);
|
|
68
|
+
// todo req/res headers?
|
|
69
|
+
span.end();
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
};
|
|
74
|
+
},
|
|
75
|
+
deps: {
|
|
76
|
+
app: WEB_FASTIFY_APP_TOKEN,
|
|
77
|
+
tracer: OPENTELEMETRY_TRACER_TOKEN,
|
|
78
|
+
tracesExcludePaths: UTILITY_SERVER_PATHS,
|
|
79
|
+
},
|
|
80
|
+
}),
|
|
81
|
+
provide({
|
|
82
|
+
provide: WEB_FASTIFY_APP_AFTER_ERROR_TOKEN,
|
|
83
|
+
useFactory: (deps) => {
|
|
84
|
+
return (error, req, reply) => {
|
|
85
|
+
if (req[REQUEST_SPAN]) {
|
|
86
|
+
const span = req[REQUEST_SPAN];
|
|
87
|
+
let httpStatus;
|
|
88
|
+
// todo duplicated logic from packages/modules/server/src/server/error/prepareLogsForError.ts
|
|
89
|
+
if (isNotFoundError(error)) {
|
|
90
|
+
httpStatus = error.httpStatus || 404;
|
|
91
|
+
}
|
|
92
|
+
else if (isHttpError(error)) {
|
|
93
|
+
httpStatus = error.httpStatus || 500;
|
|
94
|
+
}
|
|
95
|
+
else {
|
|
96
|
+
httpStatus = error.statusCode || 500;
|
|
97
|
+
}
|
|
98
|
+
span.setAttribute(ATTR_HTTP_RESPONSE_STATUS_CODE, httpStatus);
|
|
99
|
+
// todo req/res headers?
|
|
100
|
+
// todo "error.type" attribute?
|
|
101
|
+
// do not set error status for incoming requests with 4xx status
|
|
102
|
+
// https://opentelemetry.io/docs/specs/semconv/http/http-spans/#status
|
|
103
|
+
if (httpStatus >= 500) {
|
|
104
|
+
span.recordException(error);
|
|
105
|
+
span.setStatus({
|
|
106
|
+
code: SpanStatusCode.ERROR,
|
|
107
|
+
message: error?.message ?? 'Unknown error',
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
span.end();
|
|
111
|
+
// todo RootErrorBoundary is out of scope, because it is rendered after `WEB_FASTIFY_APP_AFTER_ERROR_TOKEN` hooks
|
|
112
|
+
}
|
|
113
|
+
};
|
|
114
|
+
},
|
|
115
|
+
deps: {},
|
|
116
|
+
}),
|
|
117
|
+
];
|
|
118
|
+
|
|
119
|
+
export { providers };
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var semanticConventions = require('@opentelemetry/semantic-conventions');
|
|
6
|
+
var api = require('@opentelemetry/api');
|
|
7
|
+
var pathToRegexp = require('path-to-regexp');
|
|
8
|
+
var flatten = require('@tinkoff/utils/array/flatten');
|
|
9
|
+
var errors = require('@tinkoff/errors');
|
|
10
|
+
var core = require('@tramvai/core');
|
|
11
|
+
var tokensServer = require('@tramvai/tokens-server');
|
|
12
|
+
var tokensServerPrivate = require('@tramvai/tokens-server-private');
|
|
13
|
+
var tokens = require('../tokens.js');
|
|
14
|
+
|
|
15
|
+
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
16
|
+
|
|
17
|
+
var pathToRegexp__default = /*#__PURE__*/_interopDefaultLegacy(pathToRegexp);
|
|
18
|
+
var flatten__default = /*#__PURE__*/_interopDefaultLegacy(flatten);
|
|
19
|
+
|
|
20
|
+
const REQUEST_SPAN = Symbol('opentelemetry.tramvai.server.request.span');
|
|
21
|
+
const providers = [
|
|
22
|
+
core.provide({
|
|
23
|
+
provide: tokensServerPrivate.WEB_FASTIFY_APP_INIT_TOKEN,
|
|
24
|
+
useFactory: ({ app, tracer, tracesExcludePaths }) => {
|
|
25
|
+
return () => {
|
|
26
|
+
// todo copypaste from @tinkoff/measure-fastify-requests
|
|
27
|
+
const excludePatterns = flatten__default["default"](tracesExcludePaths).map((p) => pathToRegexp__default["default"](p));
|
|
28
|
+
app.addHook('onRequest', (req, reply, done) => {
|
|
29
|
+
// skip traces for healthchecks
|
|
30
|
+
if (excludePatterns.some((p) => p.test(req.url))) {
|
|
31
|
+
done();
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
// propagate context from incoming request
|
|
35
|
+
// https://opentelemetry.io/docs/languages/js/propagation/#manual-context-propagation
|
|
36
|
+
const activeContext = api.propagation.extract(api.ROOT_CONTEXT, req.headers);
|
|
37
|
+
const httpMethod = req.method;
|
|
38
|
+
// todo useful because always get `*`, rewrite with tramvai router route?
|
|
39
|
+
const httpRoute = req.routeOptions?.url
|
|
40
|
+
? req.routeOptions.url // since fastify@4.10.0
|
|
41
|
+
: req.routerPath;
|
|
42
|
+
const parsedUrl = new URL(`http://localhost${req.url}`);
|
|
43
|
+
// https://github.com/open-telemetry/semantic-conventions/blob/main/docs/http/http-spans.md#name
|
|
44
|
+
tracer.startActiveSpan(`${httpMethod} ${httpRoute === '*' ? 'APP' : httpRoute}`,
|
|
45
|
+
// https://github.com/open-telemetry/semantic-conventions/blob/main/docs/http/http-spans.md#http-server-semantic-conventions
|
|
46
|
+
{ kind: api.SpanKind.SERVER }, activeContext, (span) => {
|
|
47
|
+
req[REQUEST_SPAN] = span;
|
|
48
|
+
// todo: move custom tramvai attrs to constants
|
|
49
|
+
/**
|
|
50
|
+
* let's add some conventions for tramvai attributes:
|
|
51
|
+
* - `tramvai` prefix for all specific attributes in tramvai instrumentation
|
|
52
|
+
* - `tramvai.scope` second prefix to define module, e.g. `tramvai.scope: server`
|
|
53
|
+
* - `tramvai.*` second prefix for specific modules, e.g. `tramvai.server`
|
|
54
|
+
* - `tramvai.server.handler` - `app` value for pages handler, another possible values - `papi`, `request-limiter`
|
|
55
|
+
* - `tramvai.server.framework` - reserved for future, if we will add support for other server frameworks
|
|
56
|
+
*/
|
|
57
|
+
span.setAttribute('tramvai.scope', 'server');
|
|
58
|
+
span.setAttribute('tramvai.server.handler', 'app');
|
|
59
|
+
span.setAttribute('tramvai.server.framework', 'fastify');
|
|
60
|
+
// https://github.com/open-telemetry/semantic-conventions/blob/main/docs/attributes-registry/http.md
|
|
61
|
+
span.setAttribute(semanticConventions.ATTR_HTTP_REQUEST_METHOD, httpMethod);
|
|
62
|
+
// route should have low-cardinality - https://github.com/open-telemetry/semantic-conventions/blob/main/docs/attributes-registry/http.md
|
|
63
|
+
span.setAttribute(semanticConventions.ATTR_HTTP_ROUTE, httpRoute);
|
|
64
|
+
span.setAttribute(semanticConventions.ATTR_URL_PATH, parsedUrl.pathname);
|
|
65
|
+
span.setAttribute(semanticConventions.ATTR_URL_QUERY, parsedUrl.search.replace('?', ''));
|
|
66
|
+
span.setAttribute(semanticConventions.ATTR_URL_SCHEME, parsedUrl.protocol.replace(':', ''));
|
|
67
|
+
span.setAttribute(semanticConventions.ATTR_URL_FULL, parsedUrl.href);
|
|
68
|
+
done();
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
app.addHook('onResponse', (req, reply) => {
|
|
72
|
+
if (req[REQUEST_SPAN]) {
|
|
73
|
+
const span = req[REQUEST_SPAN];
|
|
74
|
+
if (reply.statusCode >= 400) ;
|
|
75
|
+
else {
|
|
76
|
+
span.setAttribute(semanticConventions.ATTR_HTTP_RESPONSE_STATUS_CODE, reply.statusCode);
|
|
77
|
+
// todo req/res headers?
|
|
78
|
+
span.end();
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
};
|
|
83
|
+
},
|
|
84
|
+
deps: {
|
|
85
|
+
app: tokensServerPrivate.WEB_FASTIFY_APP_TOKEN,
|
|
86
|
+
tracer: tokens.OPENTELEMETRY_TRACER_TOKEN,
|
|
87
|
+
tracesExcludePaths: tokensServer.UTILITY_SERVER_PATHS,
|
|
88
|
+
},
|
|
89
|
+
}),
|
|
90
|
+
core.provide({
|
|
91
|
+
provide: tokensServerPrivate.WEB_FASTIFY_APP_AFTER_ERROR_TOKEN,
|
|
92
|
+
useFactory: (deps) => {
|
|
93
|
+
return (error, req, reply) => {
|
|
94
|
+
if (req[REQUEST_SPAN]) {
|
|
95
|
+
const span = req[REQUEST_SPAN];
|
|
96
|
+
let httpStatus;
|
|
97
|
+
// todo duplicated logic from packages/modules/server/src/server/error/prepareLogsForError.ts
|
|
98
|
+
if (errors.isNotFoundError(error)) {
|
|
99
|
+
httpStatus = error.httpStatus || 404;
|
|
100
|
+
}
|
|
101
|
+
else if (errors.isHttpError(error)) {
|
|
102
|
+
httpStatus = error.httpStatus || 500;
|
|
103
|
+
}
|
|
104
|
+
else {
|
|
105
|
+
httpStatus = error.statusCode || 500;
|
|
106
|
+
}
|
|
107
|
+
span.setAttribute(semanticConventions.ATTR_HTTP_RESPONSE_STATUS_CODE, httpStatus);
|
|
108
|
+
// todo req/res headers?
|
|
109
|
+
// todo "error.type" attribute?
|
|
110
|
+
// do not set error status for incoming requests with 4xx status
|
|
111
|
+
// https://opentelemetry.io/docs/specs/semconv/http/http-spans/#status
|
|
112
|
+
if (httpStatus >= 500) {
|
|
113
|
+
span.recordException(error);
|
|
114
|
+
span.setStatus({
|
|
115
|
+
code: api.SpanStatusCode.ERROR,
|
|
116
|
+
message: error?.message ?? 'Unknown error',
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
span.end();
|
|
120
|
+
// todo RootErrorBoundary is out of scope, because it is rendered after `WEB_FASTIFY_APP_AFTER_ERROR_TOKEN` hooks
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
},
|
|
124
|
+
deps: {},
|
|
125
|
+
}),
|
|
126
|
+
];
|
|
127
|
+
|
|
128
|
+
exports.providers = providers;
|
package/lib/server.d.ts
ADDED
package/lib/server.es.js
ADDED
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { __decorate } from 'tslib';
|
|
2
|
+
import { Module, provide, commandLineListTokens, optional, APP_INFO_TOKEN } from '@tramvai/core';
|
|
3
|
+
import { NodeTracerProvider, SimpleSpanProcessor, ConsoleSpanExporter } from '@opentelemetry/sdk-trace-node';
|
|
4
|
+
import { Resource } from '@opentelemetry/resources';
|
|
5
|
+
import { ATTR_SERVICE_NAME } from '@opentelemetry/semantic-conventions';
|
|
6
|
+
import { LOGGER_TOKEN } from '@tramvai/tokens-common';
|
|
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
|
+
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
|
+
import { TramvaiTracerImpl } from './tracer/tracer.es.js';
|
|
10
|
+
import { providers } from './instrumentation/server.es.js';
|
|
11
|
+
import { providers as providers$1 } from './instrumentation/httpClient.es.js';
|
|
12
|
+
import { providers as providers$2 } from './instrumentation/logs.es.js';
|
|
13
|
+
|
|
14
|
+
let OpenTelemetryModule = class OpenTelemetryModule {
|
|
15
|
+
};
|
|
16
|
+
OpenTelemetryModule = __decorate([
|
|
17
|
+
Module({
|
|
18
|
+
imports: [],
|
|
19
|
+
providers: [
|
|
20
|
+
...providers,
|
|
21
|
+
...providers$1,
|
|
22
|
+
...providers$2,
|
|
23
|
+
provide({
|
|
24
|
+
provide: commandLineListTokens.init,
|
|
25
|
+
useFactory: ({ provider }) => {
|
|
26
|
+
return function initializeOpenTelemetryProvider() {
|
|
27
|
+
provider.register();
|
|
28
|
+
};
|
|
29
|
+
},
|
|
30
|
+
deps: {
|
|
31
|
+
provider: OPENTELEMETRY_PROVIDER_TOKEN,
|
|
32
|
+
},
|
|
33
|
+
}),
|
|
34
|
+
provide({
|
|
35
|
+
provide: commandLineListTokens.close,
|
|
36
|
+
useFactory: ({ provider, logger }) => {
|
|
37
|
+
return function shutdownOpenTelemetryProvider() {
|
|
38
|
+
const log = logger('opentelemetry');
|
|
39
|
+
provider.shutdown().catch((error) => {
|
|
40
|
+
log.error({
|
|
41
|
+
event: 'provider-shutdown-error',
|
|
42
|
+
error,
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
};
|
|
46
|
+
},
|
|
47
|
+
deps: {
|
|
48
|
+
provider: OPENTELEMETRY_PROVIDER_TOKEN,
|
|
49
|
+
logger: LOGGER_TOKEN,
|
|
50
|
+
},
|
|
51
|
+
}),
|
|
52
|
+
provide({
|
|
53
|
+
provide: OPENTELEMETRY_PROVIDER_TOKEN,
|
|
54
|
+
useFactory: ({ config }) => {
|
|
55
|
+
return new NodeTracerProvider(config);
|
|
56
|
+
},
|
|
57
|
+
deps: {
|
|
58
|
+
config: OPENTELEMETRY_PROVIDER_CONFIG_TOKEN,
|
|
59
|
+
},
|
|
60
|
+
}),
|
|
61
|
+
// todo maybe not needed?
|
|
62
|
+
provide({
|
|
63
|
+
provide: OPENTELEMETRY_PROVIDER_CONFIG_TOKEN,
|
|
64
|
+
useFactory: ({ resource, spanProcessors }) => {
|
|
65
|
+
return { resource, spanProcessors: spanProcessors ?? [] };
|
|
66
|
+
},
|
|
67
|
+
deps: {
|
|
68
|
+
resource: OPENTELEMETRY_PROVIDER_RESOURCE_TOKEN,
|
|
69
|
+
spanProcessors: optional(OPENTELEMETRY_PROVIDER_SPAN_PROCESSOR_TOKEN),
|
|
70
|
+
},
|
|
71
|
+
}),
|
|
72
|
+
provide({
|
|
73
|
+
provide: OPENTELEMETRY_PROVIDER_RESOURCE_TOKEN,
|
|
74
|
+
useFactory: ({ attributesList }) => {
|
|
75
|
+
const attributes = attributesList.reduce((acc, attribute) => {
|
|
76
|
+
return {
|
|
77
|
+
...acc,
|
|
78
|
+
...attribute,
|
|
79
|
+
};
|
|
80
|
+
}, {});
|
|
81
|
+
// todo async attributes
|
|
82
|
+
return new Resource(attributes);
|
|
83
|
+
},
|
|
84
|
+
deps: {
|
|
85
|
+
attributesList: OPENTELEMETRY_PROVIDER_RESOURCE_ATTRIBUTES_TOKEN,
|
|
86
|
+
},
|
|
87
|
+
}),
|
|
88
|
+
provide({
|
|
89
|
+
provide: OPENTELEMETRY_PROVIDER_RESOURCE_ATTRIBUTES_TOKEN,
|
|
90
|
+
useFactory: ({ appInfo }) => {
|
|
91
|
+
return {
|
|
92
|
+
[ATTR_SERVICE_NAME]: appInfo.appName,
|
|
93
|
+
};
|
|
94
|
+
},
|
|
95
|
+
deps: {
|
|
96
|
+
appInfo: APP_INFO_TOKEN,
|
|
97
|
+
},
|
|
98
|
+
}),
|
|
99
|
+
provide({
|
|
100
|
+
provide: OPENTELEMETRY_TRACER_TOKEN,
|
|
101
|
+
useFactory: ({ provider }) => {
|
|
102
|
+
const tracer = provider.getTracer('tramvai', '1.0.0');
|
|
103
|
+
return new TramvaiTracerImpl(tracer);
|
|
104
|
+
},
|
|
105
|
+
deps: {
|
|
106
|
+
provider: OPENTELEMETRY_PROVIDER_TOKEN,
|
|
107
|
+
},
|
|
108
|
+
}),
|
|
109
|
+
// todo open telemetry debug flag or wrap ConsoleSpanExporter in logger
|
|
110
|
+
...(process.env.NODE_ENV === 'development'
|
|
111
|
+
? [
|
|
112
|
+
provide({
|
|
113
|
+
provide: OPENTELEMETRY_PROVIDER_SPAN_PROCESSOR_TOKEN,
|
|
114
|
+
useFactory: () => {
|
|
115
|
+
return new SimpleSpanProcessor(new ConsoleSpanExporter());
|
|
116
|
+
},
|
|
117
|
+
}),
|
|
118
|
+
]
|
|
119
|
+
: []),
|
|
120
|
+
],
|
|
121
|
+
})
|
|
122
|
+
], OpenTelemetryModule);
|
|
123
|
+
// todo declareModule!
|
|
124
|
+
|
|
125
|
+
export { OpenTelemetryModule };
|
package/lib/server.js
ADDED
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var tslib = require('tslib');
|
|
6
|
+
var core = require('@tramvai/core');
|
|
7
|
+
var sdkTraceNode = require('@opentelemetry/sdk-trace-node');
|
|
8
|
+
var resources = require('@opentelemetry/resources');
|
|
9
|
+
var semanticConventions = require('@opentelemetry/semantic-conventions');
|
|
10
|
+
var tokensCommon = require('@tramvai/tokens-common');
|
|
11
|
+
var tokens = require('./tokens.js');
|
|
12
|
+
var tracer = require('./tracer/tracer.js');
|
|
13
|
+
var server = require('./instrumentation/server.js');
|
|
14
|
+
var httpClient = require('./instrumentation/httpClient.js');
|
|
15
|
+
var logs = require('./instrumentation/logs.js');
|
|
16
|
+
|
|
17
|
+
exports.OpenTelemetryModule = class OpenTelemetryModule {
|
|
18
|
+
};
|
|
19
|
+
exports.OpenTelemetryModule = tslib.__decorate([
|
|
20
|
+
core.Module({
|
|
21
|
+
imports: [],
|
|
22
|
+
providers: [
|
|
23
|
+
...server.providers,
|
|
24
|
+
...httpClient.providers,
|
|
25
|
+
...logs.providers,
|
|
26
|
+
core.provide({
|
|
27
|
+
provide: core.commandLineListTokens.init,
|
|
28
|
+
useFactory: ({ provider }) => {
|
|
29
|
+
return function initializeOpenTelemetryProvider() {
|
|
30
|
+
provider.register();
|
|
31
|
+
};
|
|
32
|
+
},
|
|
33
|
+
deps: {
|
|
34
|
+
provider: tokens.OPENTELEMETRY_PROVIDER_TOKEN,
|
|
35
|
+
},
|
|
36
|
+
}),
|
|
37
|
+
core.provide({
|
|
38
|
+
provide: core.commandLineListTokens.close,
|
|
39
|
+
useFactory: ({ provider, logger }) => {
|
|
40
|
+
return function shutdownOpenTelemetryProvider() {
|
|
41
|
+
const log = logger('opentelemetry');
|
|
42
|
+
provider.shutdown().catch((error) => {
|
|
43
|
+
log.error({
|
|
44
|
+
event: 'provider-shutdown-error',
|
|
45
|
+
error,
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
};
|
|
49
|
+
},
|
|
50
|
+
deps: {
|
|
51
|
+
provider: tokens.OPENTELEMETRY_PROVIDER_TOKEN,
|
|
52
|
+
logger: tokensCommon.LOGGER_TOKEN,
|
|
53
|
+
},
|
|
54
|
+
}),
|
|
55
|
+
core.provide({
|
|
56
|
+
provide: tokens.OPENTELEMETRY_PROVIDER_TOKEN,
|
|
57
|
+
useFactory: ({ config }) => {
|
|
58
|
+
return new sdkTraceNode.NodeTracerProvider(config);
|
|
59
|
+
},
|
|
60
|
+
deps: {
|
|
61
|
+
config: tokens.OPENTELEMETRY_PROVIDER_CONFIG_TOKEN,
|
|
62
|
+
},
|
|
63
|
+
}),
|
|
64
|
+
// todo maybe not needed?
|
|
65
|
+
core.provide({
|
|
66
|
+
provide: tokens.OPENTELEMETRY_PROVIDER_CONFIG_TOKEN,
|
|
67
|
+
useFactory: ({ resource, spanProcessors }) => {
|
|
68
|
+
return { resource, spanProcessors: spanProcessors ?? [] };
|
|
69
|
+
},
|
|
70
|
+
deps: {
|
|
71
|
+
resource: tokens.OPENTELEMETRY_PROVIDER_RESOURCE_TOKEN,
|
|
72
|
+
spanProcessors: core.optional(tokens.OPENTELEMETRY_PROVIDER_SPAN_PROCESSOR_TOKEN),
|
|
73
|
+
},
|
|
74
|
+
}),
|
|
75
|
+
core.provide({
|
|
76
|
+
provide: tokens.OPENTELEMETRY_PROVIDER_RESOURCE_TOKEN,
|
|
77
|
+
useFactory: ({ attributesList }) => {
|
|
78
|
+
const attributes = attributesList.reduce((acc, attribute) => {
|
|
79
|
+
return {
|
|
80
|
+
...acc,
|
|
81
|
+
...attribute,
|
|
82
|
+
};
|
|
83
|
+
}, {});
|
|
84
|
+
// todo async attributes
|
|
85
|
+
return new resources.Resource(attributes);
|
|
86
|
+
},
|
|
87
|
+
deps: {
|
|
88
|
+
attributesList: tokens.OPENTELEMETRY_PROVIDER_RESOURCE_ATTRIBUTES_TOKEN,
|
|
89
|
+
},
|
|
90
|
+
}),
|
|
91
|
+
core.provide({
|
|
92
|
+
provide: tokens.OPENTELEMETRY_PROVIDER_RESOURCE_ATTRIBUTES_TOKEN,
|
|
93
|
+
useFactory: ({ appInfo }) => {
|
|
94
|
+
return {
|
|
95
|
+
[semanticConventions.ATTR_SERVICE_NAME]: appInfo.appName,
|
|
96
|
+
};
|
|
97
|
+
},
|
|
98
|
+
deps: {
|
|
99
|
+
appInfo: core.APP_INFO_TOKEN,
|
|
100
|
+
},
|
|
101
|
+
}),
|
|
102
|
+
core.provide({
|
|
103
|
+
provide: tokens.OPENTELEMETRY_TRACER_TOKEN,
|
|
104
|
+
useFactory: ({ provider }) => {
|
|
105
|
+
const tracer$1 = provider.getTracer('tramvai', '1.0.0');
|
|
106
|
+
return new tracer.TramvaiTracerImpl(tracer$1);
|
|
107
|
+
},
|
|
108
|
+
deps: {
|
|
109
|
+
provider: tokens.OPENTELEMETRY_PROVIDER_TOKEN,
|
|
110
|
+
},
|
|
111
|
+
}),
|
|
112
|
+
// todo open telemetry debug flag or wrap ConsoleSpanExporter in logger
|
|
113
|
+
...(process.env.NODE_ENV === 'development'
|
|
114
|
+
? [
|
|
115
|
+
core.provide({
|
|
116
|
+
provide: tokens.OPENTELEMETRY_PROVIDER_SPAN_PROCESSOR_TOKEN,
|
|
117
|
+
useFactory: () => {
|
|
118
|
+
return new sdkTraceNode.SimpleSpanProcessor(new sdkTraceNode.ConsoleSpanExporter());
|
|
119
|
+
},
|
|
120
|
+
}),
|
|
121
|
+
]
|
|
122
|
+
: []),
|
|
123
|
+
],
|
|
124
|
+
})
|
|
125
|
+
], exports.OpenTelemetryModule);
|
|
126
|
+
// todo declareModule!
|
|
127
|
+
|
|
128
|
+
exports.OPENTELEMETRY_PROVIDER_CONFIG_TOKEN = tokens.OPENTELEMETRY_PROVIDER_CONFIG_TOKEN;
|
|
129
|
+
exports.OPENTELEMETRY_PROVIDER_RESOURCE_ATTRIBUTES_TOKEN = tokens.OPENTELEMETRY_PROVIDER_RESOURCE_ATTRIBUTES_TOKEN;
|
|
130
|
+
exports.OPENTELEMETRY_PROVIDER_RESOURCE_TOKEN = tokens.OPENTELEMETRY_PROVIDER_RESOURCE_TOKEN;
|
|
131
|
+
exports.OPENTELEMETRY_PROVIDER_SPAN_PROCESSOR_TOKEN = tokens.OPENTELEMETRY_PROVIDER_SPAN_PROCESSOR_TOKEN;
|
|
132
|
+
exports.OPENTELEMETRY_PROVIDER_TOKEN = tokens.OPENTELEMETRY_PROVIDER_TOKEN;
|
|
133
|
+
exports.OPENTELEMETRY_TRACER_TOKEN = tokens.OPENTELEMETRY_TRACER_TOKEN;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { createToken, Scope } from '@tinkoff/dippy';
|
|
2
|
+
|
|
3
|
+
const OPENTELEMETRY_PROVIDER_TOKEN = createToken('tramvai opentelemetry provider', { scope: Scope.SINGLETON });
|
|
4
|
+
const OPENTELEMETRY_PROVIDER_CONFIG_TOKEN = createToken('tramvai opentelemetry provider config', { scope: Scope.SINGLETON });
|
|
5
|
+
const OPENTELEMETRY_PROVIDER_SPAN_PROCESSOR_TOKEN = createToken('tramvai opentelemetry provider span processor', { multi: true, scope: Scope.SINGLETON });
|
|
6
|
+
const OPENTELEMETRY_PROVIDER_RESOURCE_TOKEN = createToken('tramvai opentelemetry provider resource', { scope: Scope.SINGLETON });
|
|
7
|
+
const OPENTELEMETRY_PROVIDER_RESOURCE_ATTRIBUTES_TOKEN = createToken('tramvai opentelemetry provider resource attributes', { multi: true, scope: Scope.SINGLETON });
|
|
8
|
+
const OPENTELEMETRY_TRACER_TOKEN = createToken('tramvai opentelemetry tracer', { scope: Scope.SINGLETON });
|
|
9
|
+
|
|
10
|
+
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 };
|
package/lib/tokens.d.ts
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { Context, Span, SpanOptions } from '@opentelemetry/api';
|
|
2
|
+
import type { SpanProcessor, TracerConfig, BasicTracerProvider } from '@opentelemetry/sdk-trace-node';
|
|
3
|
+
import type { Resource } from '@opentelemetry/resources';
|
|
4
|
+
/**
|
|
5
|
+
* API inspired by:
|
|
6
|
+
* - https://github.com/DataDog/dd-trace-js/blob/59e9a2a75f4256755b4e6c9951a0bdf8d39b4015/index.d.ts#L9
|
|
7
|
+
* - https://github.com/vercel/next.js/blob/9a1cd356dbafbfcf23d1b9ec05f772f766d05580/packages/next/src/server/lib/trace/tracer.ts#L74
|
|
8
|
+
*/
|
|
9
|
+
export interface TramvaiTracer {
|
|
10
|
+
startSpan(name: string, options?: SpanOptions, context?: Context): Span;
|
|
11
|
+
startActiveSpan<F extends (span: Span) => unknown>(name: string, fn: F): ReturnType<F>;
|
|
12
|
+
startActiveSpan<F extends (span: Span) => unknown>(name: string, options: SpanOptions, fn: F): ReturnType<F>;
|
|
13
|
+
startActiveSpan<F extends (span: Span) => unknown>(name: string, options: SpanOptions, context: Context, fn: F): ReturnType<F>;
|
|
14
|
+
getActiveSpan(): Span | undefined;
|
|
15
|
+
trace<T>(name: string, fn: (span: Span) => Promise<T>): Promise<T>;
|
|
16
|
+
trace<T>(name: string, fn: (span: Span) => T): T;
|
|
17
|
+
trace<T>(name: string, options: SpanOptions, fn: (span: Span) => Promise<T>): Promise<T>;
|
|
18
|
+
trace<T>(name: string, options: SpanOptions, fn: (span: Span) => T): T;
|
|
19
|
+
}
|
|
20
|
+
export declare const OPENTELEMETRY_PROVIDER_TOKEN: BasicTracerProvider & {
|
|
21
|
+
__type?: "base token" | undefined;
|
|
22
|
+
};
|
|
23
|
+
export declare const OPENTELEMETRY_PROVIDER_CONFIG_TOKEN: TracerConfig & {
|
|
24
|
+
__type?: "base token" | undefined;
|
|
25
|
+
};
|
|
26
|
+
export declare const OPENTELEMETRY_PROVIDER_SPAN_PROCESSOR_TOKEN: SpanProcessor & {
|
|
27
|
+
__type?: "multi token" | undefined;
|
|
28
|
+
};
|
|
29
|
+
export declare const OPENTELEMETRY_PROVIDER_RESOURCE_TOKEN: Resource & {
|
|
30
|
+
__type?: "base token" | undefined;
|
|
31
|
+
};
|
|
32
|
+
export declare const OPENTELEMETRY_PROVIDER_RESOURCE_ATTRIBUTES_TOKEN: import("@opentelemetry/api").Attributes & {
|
|
33
|
+
__type?: "multi token" | undefined;
|
|
34
|
+
};
|
|
35
|
+
export declare const OPENTELEMETRY_TRACER_TOKEN: TramvaiTracer & {
|
|
36
|
+
__type?: "base token" | undefined;
|
|
37
|
+
};
|
|
38
|
+
//# sourceMappingURL=tokens.d.ts.map
|
package/lib/tokens.es.js
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { createToken, Scope } from '@tinkoff/dippy';
|
|
2
|
+
|
|
3
|
+
const OPENTELEMETRY_PROVIDER_TOKEN = createToken('tramvai opentelemetry provider', { scope: Scope.SINGLETON });
|
|
4
|
+
const OPENTELEMETRY_PROVIDER_CONFIG_TOKEN = createToken('tramvai opentelemetry provider config', { scope: Scope.SINGLETON });
|
|
5
|
+
const OPENTELEMETRY_PROVIDER_SPAN_PROCESSOR_TOKEN = createToken('tramvai opentelemetry provider span processor', { multi: true, scope: Scope.SINGLETON });
|
|
6
|
+
const OPENTELEMETRY_PROVIDER_RESOURCE_TOKEN = createToken('tramvai opentelemetry provider resource', { scope: Scope.SINGLETON });
|
|
7
|
+
const OPENTELEMETRY_PROVIDER_RESOURCE_ATTRIBUTES_TOKEN = createToken('tramvai opentelemetry provider resource attributes', { multi: true, scope: Scope.SINGLETON });
|
|
8
|
+
const OPENTELEMETRY_TRACER_TOKEN = createToken('tramvai opentelemetry tracer', { scope: Scope.SINGLETON });
|
|
9
|
+
|
|
10
|
+
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 };
|
package/lib/tokens.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var dippy = require('@tinkoff/dippy');
|
|
6
|
+
|
|
7
|
+
const OPENTELEMETRY_PROVIDER_TOKEN = dippy.createToken('tramvai opentelemetry provider', { scope: dippy.Scope.SINGLETON });
|
|
8
|
+
const OPENTELEMETRY_PROVIDER_CONFIG_TOKEN = dippy.createToken('tramvai opentelemetry provider config', { scope: dippy.Scope.SINGLETON });
|
|
9
|
+
const OPENTELEMETRY_PROVIDER_SPAN_PROCESSOR_TOKEN = dippy.createToken('tramvai opentelemetry provider span processor', { multi: true, scope: dippy.Scope.SINGLETON });
|
|
10
|
+
const OPENTELEMETRY_PROVIDER_RESOURCE_TOKEN = dippy.createToken('tramvai opentelemetry provider resource', { scope: dippy.Scope.SINGLETON });
|
|
11
|
+
const OPENTELEMETRY_PROVIDER_RESOURCE_ATTRIBUTES_TOKEN = dippy.createToken('tramvai opentelemetry provider resource attributes', { multi: true, scope: dippy.Scope.SINGLETON });
|
|
12
|
+
const OPENTELEMETRY_TRACER_TOKEN = dippy.createToken('tramvai opentelemetry tracer', { scope: dippy.Scope.SINGLETON });
|
|
13
|
+
|
|
14
|
+
exports.OPENTELEMETRY_PROVIDER_CONFIG_TOKEN = OPENTELEMETRY_PROVIDER_CONFIG_TOKEN;
|
|
15
|
+
exports.OPENTELEMETRY_PROVIDER_RESOURCE_ATTRIBUTES_TOKEN = OPENTELEMETRY_PROVIDER_RESOURCE_ATTRIBUTES_TOKEN;
|
|
16
|
+
exports.OPENTELEMETRY_PROVIDER_RESOURCE_TOKEN = OPENTELEMETRY_PROVIDER_RESOURCE_TOKEN;
|
|
17
|
+
exports.OPENTELEMETRY_PROVIDER_SPAN_PROCESSOR_TOKEN = OPENTELEMETRY_PROVIDER_SPAN_PROCESSOR_TOKEN;
|
|
18
|
+
exports.OPENTELEMETRY_PROVIDER_TOKEN = OPENTELEMETRY_PROVIDER_TOKEN;
|
|
19
|
+
exports.OPENTELEMETRY_TRACER_TOKEN = OPENTELEMETRY_TRACER_TOKEN;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { Context, Span, SpanOptions, Tracer } from '@opentelemetry/api';
|
|
2
|
+
import type { TramvaiTracer } from '../tokens';
|
|
3
|
+
export declare class TramvaiTracerImpl implements TramvaiTracer {
|
|
4
|
+
private tracer;
|
|
5
|
+
constructor(tracer: Tracer);
|
|
6
|
+
startSpan(...args: any[]): Span;
|
|
7
|
+
startActiveSpan<F extends (span: Span) => unknown>(name: string, fn: F): ReturnType<F>;
|
|
8
|
+
startActiveSpan<F extends (span: Span) => unknown>(name: string, options: SpanOptions, fn: F): ReturnType<F>;
|
|
9
|
+
startActiveSpan<F extends (span: Span) => unknown>(name: string, options: SpanOptions, ctx: Context, fn: F): ReturnType<F>;
|
|
10
|
+
getActiveSpan(): Span | undefined;
|
|
11
|
+
trace<T>(name: string, fn: (span: Span) => Promise<T>): Promise<T>;
|
|
12
|
+
trace<T>(name: string, fn: (span: Span) => T): T;
|
|
13
|
+
trace<T>(name: string, options: SpanOptions, fn: (span: Span) => Promise<T>): Promise<T>;
|
|
14
|
+
trace<T>(name: string, options: SpanOptions, fn: (span: Span) => T): T;
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=tracer.d.ts.map
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import isPromise from '@tinkoff/utils/is/promise';
|
|
2
|
+
import { trace, context, ROOT_CONTEXT, SpanStatusCode } from '@opentelemetry/api';
|
|
3
|
+
|
|
4
|
+
/* eslint-disable prefer-destructuring */
|
|
5
|
+
function recordAndThrowError(span, error) {
|
|
6
|
+
span.recordException(error);
|
|
7
|
+
span.setStatus({
|
|
8
|
+
code: SpanStatusCode.ERROR,
|
|
9
|
+
message: error?.message ?? 'Unknown error',
|
|
10
|
+
});
|
|
11
|
+
span.end();
|
|
12
|
+
throw error;
|
|
13
|
+
}
|
|
14
|
+
class TramvaiTracerImpl {
|
|
15
|
+
constructor(tracer) {
|
|
16
|
+
this.tracer = tracer;
|
|
17
|
+
}
|
|
18
|
+
startSpan(...args) {
|
|
19
|
+
// @ts-expect-error
|
|
20
|
+
return this.tracer.startSpan(...args);
|
|
21
|
+
}
|
|
22
|
+
startActiveSpan(...args) {
|
|
23
|
+
// @ts-expect-error
|
|
24
|
+
return this.tracer.startActiveSpan(...args);
|
|
25
|
+
}
|
|
26
|
+
getActiveSpan() {
|
|
27
|
+
return trace.getSpan(context.active());
|
|
28
|
+
}
|
|
29
|
+
trace(...args) {
|
|
30
|
+
const name = args[0];
|
|
31
|
+
let fn;
|
|
32
|
+
let options;
|
|
33
|
+
if (args.length === 2) {
|
|
34
|
+
fn = args[1];
|
|
35
|
+
options = {};
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
fn = args[2];
|
|
39
|
+
options = args[1];
|
|
40
|
+
}
|
|
41
|
+
const activeSpan = trace.getSpan(context.active());
|
|
42
|
+
const spanContext = activeSpan ? trace.setSpan(context.active(), activeSpan) : undefined;
|
|
43
|
+
const ctx = spanContext ?? context.active() ?? ROOT_CONTEXT;
|
|
44
|
+
return this.startActiveSpan(name, options, ctx, (span) => {
|
|
45
|
+
try {
|
|
46
|
+
const result = fn(span);
|
|
47
|
+
// wrap promise fn, end span if promise is resolved or rejected
|
|
48
|
+
if (isPromise(result)) {
|
|
49
|
+
return result
|
|
50
|
+
.then((res) => {
|
|
51
|
+
span.end();
|
|
52
|
+
return res;
|
|
53
|
+
})
|
|
54
|
+
.catch((error) => {
|
|
55
|
+
recordAndThrowError(span, error);
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
// otherwise, end span immediately
|
|
59
|
+
span.end();
|
|
60
|
+
return result;
|
|
61
|
+
}
|
|
62
|
+
catch (error) {
|
|
63
|
+
recordAndThrowError(span, error);
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
/* eslint-enable prefer-destructuring */
|
|
69
|
+
|
|
70
|
+
export { TramvaiTracerImpl };
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var isPromise = require('@tinkoff/utils/is/promise');
|
|
6
|
+
var api = require('@opentelemetry/api');
|
|
7
|
+
|
|
8
|
+
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
9
|
+
|
|
10
|
+
var isPromise__default = /*#__PURE__*/_interopDefaultLegacy(isPromise);
|
|
11
|
+
|
|
12
|
+
/* eslint-disable prefer-destructuring */
|
|
13
|
+
function recordAndThrowError(span, error) {
|
|
14
|
+
span.recordException(error);
|
|
15
|
+
span.setStatus({
|
|
16
|
+
code: api.SpanStatusCode.ERROR,
|
|
17
|
+
message: error?.message ?? 'Unknown error',
|
|
18
|
+
});
|
|
19
|
+
span.end();
|
|
20
|
+
throw error;
|
|
21
|
+
}
|
|
22
|
+
class TramvaiTracerImpl {
|
|
23
|
+
constructor(tracer) {
|
|
24
|
+
this.tracer = tracer;
|
|
25
|
+
}
|
|
26
|
+
startSpan(...args) {
|
|
27
|
+
// @ts-expect-error
|
|
28
|
+
return this.tracer.startSpan(...args);
|
|
29
|
+
}
|
|
30
|
+
startActiveSpan(...args) {
|
|
31
|
+
// @ts-expect-error
|
|
32
|
+
return this.tracer.startActiveSpan(...args);
|
|
33
|
+
}
|
|
34
|
+
getActiveSpan() {
|
|
35
|
+
return api.trace.getSpan(api.context.active());
|
|
36
|
+
}
|
|
37
|
+
trace(...args) {
|
|
38
|
+
const name = args[0];
|
|
39
|
+
let fn;
|
|
40
|
+
let options;
|
|
41
|
+
if (args.length === 2) {
|
|
42
|
+
fn = args[1];
|
|
43
|
+
options = {};
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
fn = args[2];
|
|
47
|
+
options = args[1];
|
|
48
|
+
}
|
|
49
|
+
const activeSpan = api.trace.getSpan(api.context.active());
|
|
50
|
+
const spanContext = activeSpan ? api.trace.setSpan(api.context.active(), activeSpan) : undefined;
|
|
51
|
+
const ctx = spanContext ?? api.context.active() ?? api.ROOT_CONTEXT;
|
|
52
|
+
return this.startActiveSpan(name, options, ctx, (span) => {
|
|
53
|
+
try {
|
|
54
|
+
const result = fn(span);
|
|
55
|
+
// wrap promise fn, end span if promise is resolved or rejected
|
|
56
|
+
if (isPromise__default["default"](result)) {
|
|
57
|
+
return result
|
|
58
|
+
.then((res) => {
|
|
59
|
+
span.end();
|
|
60
|
+
return res;
|
|
61
|
+
})
|
|
62
|
+
.catch((error) => {
|
|
63
|
+
recordAndThrowError(span, error);
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
// otherwise, end span immediately
|
|
67
|
+
span.end();
|
|
68
|
+
return result;
|
|
69
|
+
}
|
|
70
|
+
catch (error) {
|
|
71
|
+
recordAndThrowError(span, error);
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
/* eslint-enable prefer-destructuring */
|
|
77
|
+
|
|
78
|
+
exports.TramvaiTracerImpl = TramvaiTracerImpl;
|
package/package.json
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@tramvai/module-opentelemetry",
|
|
3
|
+
"version": "5.14.9",
|
|
4
|
+
"description": "Интеграция OpenTelemetry",
|
|
5
|
+
"browser": "lib/browser.js",
|
|
6
|
+
"main": "lib/server.js",
|
|
7
|
+
"module": "lib/server.es.js",
|
|
8
|
+
"typings": "lib/server.d.d.ts",
|
|
9
|
+
"files": [
|
|
10
|
+
"lib"
|
|
11
|
+
],
|
|
12
|
+
"sideEffects": false,
|
|
13
|
+
"license": "Apache-2.0",
|
|
14
|
+
"repository": {
|
|
15
|
+
"type": "git",
|
|
16
|
+
"url": "git+ssh://git@github.com/tramvaijs/tramvai.git"
|
|
17
|
+
},
|
|
18
|
+
"scripts": {
|
|
19
|
+
"build": "tramvai-build --forPublish --preserveModules",
|
|
20
|
+
"watch": "tsc -w"
|
|
21
|
+
},
|
|
22
|
+
"publishConfig": {
|
|
23
|
+
"registry": "https://registry.npmjs.org/"
|
|
24
|
+
},
|
|
25
|
+
"dependencies": {
|
|
26
|
+
"@opentelemetry/api": "^1.9.0",
|
|
27
|
+
"@opentelemetry/resources": "^1.28.0",
|
|
28
|
+
"@opentelemetry/sdk-trace-node": "^1.28.0",
|
|
29
|
+
"@opentelemetry/semantic-conventions": "^1.28.0",
|
|
30
|
+
"path-to-regexp": "0.1.7",
|
|
31
|
+
"@tramvai/tokens-common": "5.14.9",
|
|
32
|
+
"@tramvai/tokens-metrics": "5.14.9",
|
|
33
|
+
"@tramvai/tokens-http-client": "5.14.9",
|
|
34
|
+
"@tramvai/tokens-server": "5.14.9",
|
|
35
|
+
"@tramvai/tokens-server-private": "5.14.9",
|
|
36
|
+
"@tinkoff/utils": "^2.1.2",
|
|
37
|
+
"@tinkoff/errors": "0.6.2"
|
|
38
|
+
},
|
|
39
|
+
"devDependencies": {},
|
|
40
|
+
"peerDependencies": {
|
|
41
|
+
"@tinkoff/dippy": "0.11.3",
|
|
42
|
+
"@tramvai/core": "5.14.9",
|
|
43
|
+
"tslib": "^2.4.0"
|
|
44
|
+
}
|
|
45
|
+
}
|