@pocket-tools/tracing 1.9.8 → 1.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{index.mjs → index.cjs} +103 -81
- package/dist/index.js +83 -101
- package/jest.config.ts +23 -0
- package/package.json +13 -2
- /package/dist/{index.d.mts → index.d.cts} +0 -0
|
@@ -1,52 +1,71 @@
|
|
|
1
|
+
var __create = Object.create;
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all)
|
|
9
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
|
+
};
|
|
11
|
+
var __copyProps = (to, from, except, desc) => {
|
|
12
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
13
|
+
for (let key of __getOwnPropNames(from))
|
|
14
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
15
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
16
|
+
}
|
|
17
|
+
return to;
|
|
18
|
+
};
|
|
19
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
20
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
21
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
22
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
23
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
24
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
25
|
+
mod
|
|
26
|
+
));
|
|
27
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
28
|
+
|
|
29
|
+
// src/index.ts
|
|
30
|
+
var index_exports = {};
|
|
31
|
+
__export(index_exports, {
|
|
32
|
+
AdditionalInstrumentation: () => AdditionalInstrumentation,
|
|
33
|
+
nodeSDKBuilder: () => nodeSDKBuilder
|
|
34
|
+
});
|
|
35
|
+
module.exports = __toCommonJS(index_exports);
|
|
36
|
+
|
|
1
37
|
// src/tracing.ts
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
import { OTLPMetricExporter as GRPCOTLPMetricExporter } from "@opentelemetry/exporter-metrics-otlp-grpc";
|
|
26
|
-
import { getNodeAutoInstrumentations } from "@opentelemetry/auto-instrumentations-node";
|
|
27
|
-
import {
|
|
28
|
-
envDetectorSync,
|
|
29
|
-
hostDetectorSync,
|
|
30
|
-
processDetectorSync
|
|
31
|
-
} from "@opentelemetry/resources";
|
|
32
|
-
import { awsEcsDetectorSync } from "@opentelemetry/resource-detector-aws";
|
|
33
|
-
import * as Sentry from "@sentry/node";
|
|
34
|
-
import {
|
|
35
|
-
BatchSpanProcessor,
|
|
36
|
-
ParentBasedSampler,
|
|
37
|
-
SamplingDecision
|
|
38
|
-
} from "@opentelemetry/sdk-trace-base";
|
|
39
|
-
import { AWSXRayPropagator } from "@opentelemetry/propagator-aws-xray";
|
|
40
|
-
import { AWSXRayIdGenerator } from "@opentelemetry/id-generator-aws-xray";
|
|
41
|
-
import { CompositePropagator } from "@opentelemetry/core";
|
|
38
|
+
var import_process = __toESM(require("process"), 1);
|
|
39
|
+
var import_sdk_node = require("@opentelemetry/sdk-node");
|
|
40
|
+
var import_api = require("@opentelemetry/api");
|
|
41
|
+
var import_instrumentation_knex = require("@opentelemetry/instrumentation-knex");
|
|
42
|
+
var import_exporter_trace_otlp_http = require("@opentelemetry/exporter-trace-otlp-http");
|
|
43
|
+
var import_exporter_trace_otlp_grpc = require("@opentelemetry/exporter-trace-otlp-grpc");
|
|
44
|
+
var import_exporter_logs_otlp_http = require("@opentelemetry/exporter-logs-otlp-http");
|
|
45
|
+
var import_exporter_logs_otlp_grpc = require("@opentelemetry/exporter-logs-otlp-grpc");
|
|
46
|
+
var import_instrumentation = require("@prisma/instrumentation");
|
|
47
|
+
var import_resources = require("@opentelemetry/resources");
|
|
48
|
+
var import_semantic_conventions = require("@opentelemetry/semantic-conventions");
|
|
49
|
+
var import_opentelemetry = require("@sentry/opentelemetry");
|
|
50
|
+
var import_sdk_metrics = require("@opentelemetry/sdk-metrics");
|
|
51
|
+
var import_exporter_metrics_otlp_http = require("@opentelemetry/exporter-metrics-otlp-http");
|
|
52
|
+
var import_exporter_metrics_otlp_grpc = require("@opentelemetry/exporter-metrics-otlp-grpc");
|
|
53
|
+
var import_auto_instrumentations_node = require("@opentelemetry/auto-instrumentations-node");
|
|
54
|
+
var import_resources2 = require("@opentelemetry/resources");
|
|
55
|
+
var import_resource_detector_aws = require("@opentelemetry/resource-detector-aws");
|
|
56
|
+
var Sentry = __toESM(require("@sentry/node"), 1);
|
|
57
|
+
var import_sdk_trace_base = require("@opentelemetry/sdk-trace-base");
|
|
58
|
+
var import_propagator_aws_xray = require("@opentelemetry/propagator-aws-xray");
|
|
59
|
+
var import_id_generator_aws_xray = require("@opentelemetry/id-generator-aws-xray");
|
|
60
|
+
var import_core = require("@opentelemetry/core");
|
|
42
61
|
var AdditionalInstrumentation = /* @__PURE__ */ ((AdditionalInstrumentation2) => {
|
|
43
62
|
AdditionalInstrumentation2["KNEX"] = "KNEX";
|
|
44
63
|
AdditionalInstrumentation2["PRISMA"] = "PRISMA";
|
|
45
64
|
return AdditionalInstrumentation2;
|
|
46
65
|
})(AdditionalInstrumentation || {});
|
|
47
66
|
var additionalInstrumentationConstructors = {
|
|
48
|
-
KNEX: KnexInstrumentation,
|
|
49
|
-
PRISMA: PrismaInstrumentation
|
|
67
|
+
KNEX: import_instrumentation_knex.KnexInstrumentation,
|
|
68
|
+
PRISMA: import_instrumentation.PrismaInstrumentation
|
|
50
69
|
};
|
|
51
70
|
var tracingDefaults = {
|
|
52
71
|
serviceName: "unknown",
|
|
@@ -65,9 +84,8 @@ function awaitAttributes(detector) {
|
|
|
65
84
|
* A function that returns a promise that resolves with the attributes
|
|
66
85
|
*/
|
|
67
86
|
async detect(config) {
|
|
68
|
-
var _a;
|
|
69
87
|
const resource = detector.detect(config);
|
|
70
|
-
await
|
|
88
|
+
await resource.waitForAsyncAttributes?.();
|
|
71
89
|
console.log("Detected resource: ", resource);
|
|
72
90
|
return resource;
|
|
73
91
|
}
|
|
@@ -80,32 +98,31 @@ var batchConfig = {
|
|
|
80
98
|
exportTimeoutMillis: 5e3
|
|
81
99
|
};
|
|
82
100
|
async function nodeSDKBuilder(config) {
|
|
83
|
-
var _a, _b, _c;
|
|
84
101
|
config = { ...tracingDefaults, ...config };
|
|
85
|
-
diag.setLogger(new DiagConsoleLogger(), DiagLogLevel.WARN);
|
|
86
|
-
const _resource = Resource.default().merge(
|
|
87
|
-
new Resource({
|
|
88
|
-
[ATTR_SERVICE_NAME]: config.serviceName,
|
|
89
|
-
[ATTR_SERVICE_VERSION]: config.release,
|
|
90
|
-
[SEMRESATTRS_DEPLOYMENT_ENVIRONMENT]:
|
|
102
|
+
import_api.diag.setLogger(new import_api.DiagConsoleLogger(), import_api.DiagLogLevel.WARN);
|
|
103
|
+
const _resource = import_resources.Resource.default().merge(
|
|
104
|
+
new import_resources.Resource({
|
|
105
|
+
[import_semantic_conventions.ATTR_SERVICE_NAME]: config.serviceName,
|
|
106
|
+
[import_semantic_conventions.ATTR_SERVICE_VERSION]: config.release,
|
|
107
|
+
[import_semantic_conventions.SEMRESATTRS_DEPLOYMENT_ENVIRONMENT]: import_process.default.env.ENVIRONMENT ?? import_process.default.env.NODE_ENV ?? "unknown"
|
|
91
108
|
})
|
|
92
109
|
);
|
|
93
|
-
const _traceExporter = config.protocol === "HTTP" ? new
|
|
110
|
+
const _traceExporter = config.protocol === "HTTP" ? new import_exporter_trace_otlp_http.OTLPTraceExporter({
|
|
94
111
|
//collector url
|
|
95
112
|
url: `${config.url}/v1/traces`
|
|
96
|
-
}) : new
|
|
97
|
-
const _metricReader = new PeriodicExportingMetricReader({
|
|
98
|
-
exporter: config.protocol === "HTTP" ? new
|
|
113
|
+
}) : new import_exporter_trace_otlp_grpc.OTLPTraceExporter({ url: config.url });
|
|
114
|
+
const _metricReader = new import_sdk_metrics.PeriodicExportingMetricReader({
|
|
115
|
+
exporter: config.protocol === "HTTP" ? new import_exporter_metrics_otlp_http.OTLPMetricExporter({
|
|
99
116
|
url: `${config.url}/v1/metrics`
|
|
100
|
-
}) : new
|
|
117
|
+
}) : new import_exporter_metrics_otlp_grpc.OTLPMetricExporter({ url: config.url }),
|
|
101
118
|
// once every 60 seconds, GCP supports 1 every 5 seconds for custom metrics https://cloud.google.com/monitoring/quotas#custom_metrics_quotas
|
|
102
119
|
// But lets just do 60 seconds for now as we figure it out
|
|
103
120
|
exportIntervalMillis: 1e4,
|
|
104
121
|
exportTimeoutMillis: 5e3
|
|
105
122
|
});
|
|
106
|
-
const _logExporter = config.protocol === "HTTP" ? new
|
|
123
|
+
const _logExporter = config.protocol === "HTTP" ? new import_exporter_logs_otlp_http.OTLPLogExporter({ url: `${config.url}/v1/logs` }) : new import_exporter_logs_otlp_grpc.OTLPLogExporter({ url: config.url });
|
|
107
124
|
const instrumentations = [
|
|
108
|
-
getNodeAutoInstrumentations({
|
|
125
|
+
(0, import_auto_instrumentations_node.getNodeAutoInstrumentations)({
|
|
109
126
|
"@opentelemetry/instrumentation-fs": {
|
|
110
127
|
// Disabling Filesystem instrumentation because it is very noisey and memory intense.
|
|
111
128
|
enabled: false,
|
|
@@ -119,8 +136,7 @@ async function nodeSDKBuilder(config) {
|
|
|
119
136
|
},
|
|
120
137
|
"@opentelemetry/instrumentation-http": {
|
|
121
138
|
ignoreIncomingRequestHook: (request) => {
|
|
122
|
-
|
|
123
|
-
if ((_a2 = request.url) == null ? void 0 : _a2.includes(".well-known/apollo/server-health")) {
|
|
139
|
+
if (request.url?.includes(".well-known/apollo/server-health")) {
|
|
124
140
|
return true;
|
|
125
141
|
}
|
|
126
142
|
return false;
|
|
@@ -145,21 +161,21 @@ async function nodeSDKBuilder(config) {
|
|
|
145
161
|
}
|
|
146
162
|
})
|
|
147
163
|
];
|
|
148
|
-
(
|
|
164
|
+
(config.additionalInstrumentations ?? []).forEach((instrumentation) => {
|
|
149
165
|
instrumentations.push(
|
|
150
166
|
new additionalInstrumentationConstructors[instrumentation]()
|
|
151
167
|
);
|
|
152
168
|
});
|
|
153
|
-
const sdk = new NodeSDK({
|
|
154
|
-
textMapPropagator: new CompositePropagator({
|
|
169
|
+
const sdk = new import_sdk_node.NodeSDK({
|
|
170
|
+
textMapPropagator: new import_core.CompositePropagator({
|
|
155
171
|
// The Propogators are run in the order they are added, and since we want the AWSXRAY to win,
|
|
156
172
|
// it must come last because it writes the parent context "sampled" data from the trace into the contexts
|
|
157
173
|
// We Keep Sentry in here, because it adds data that Sentry needs, we just don't want it to control the sample value.
|
|
158
|
-
propagators: [new SentryPropagator(), new AWSXRayPropagator()]
|
|
174
|
+
propagators: [new import_opentelemetry.SentryPropagator(), new import_propagator_aws_xray.AWSXRayPropagator()]
|
|
159
175
|
}),
|
|
160
176
|
instrumentations,
|
|
161
177
|
sampler: new SentryParentSampler({
|
|
162
|
-
root: new ParentBasedSampler({
|
|
178
|
+
root: new import_sdk_trace_base.ParentBasedSampler({
|
|
163
179
|
root: new UnleashSampler({
|
|
164
180
|
unleash: config.unleash,
|
|
165
181
|
flagName: config.flagName
|
|
@@ -169,31 +185,35 @@ async function nodeSDKBuilder(config) {
|
|
|
169
185
|
}),
|
|
170
186
|
contextManager: new Sentry.SentryContextManager(),
|
|
171
187
|
resource: _resource,
|
|
172
|
-
idGenerator: new AWSXRayIdGenerator(),
|
|
173
|
-
spanProcessors: [new BatchSpanProcessor(_traceExporter, batchConfig)],
|
|
188
|
+
idGenerator: new import_id_generator_aws_xray.AWSXRayIdGenerator(),
|
|
189
|
+
spanProcessors: [new import_sdk_trace_base.BatchSpanProcessor(_traceExporter, batchConfig)],
|
|
174
190
|
metricReader: _metricReader,
|
|
175
191
|
logRecordProcessors: [
|
|
176
|
-
new logs.BatchLogRecordProcessor(_logExporter, batchConfig)
|
|
192
|
+
new import_sdk_node.logs.BatchLogRecordProcessor(_logExporter, batchConfig)
|
|
177
193
|
],
|
|
178
194
|
// TODO: Remove after issue is fixed
|
|
179
195
|
// https://github.com/open-telemetry/opentelemetry-js/issues/4638
|
|
180
196
|
resourceDetectors: [
|
|
181
|
-
awaitAttributes(envDetectorSync),
|
|
182
|
-
awaitAttributes(hostDetectorSync),
|
|
183
|
-
awaitAttributes(processDetectorSync),
|
|
184
|
-
awaitAttributes(awsEcsDetectorSync)
|
|
197
|
+
awaitAttributes(import_resources2.envDetectorSync),
|
|
198
|
+
awaitAttributes(import_resources2.hostDetectorSync),
|
|
199
|
+
awaitAttributes(import_resources2.processDetectorSync),
|
|
200
|
+
awaitAttributes(import_resource_detector_aws.awsEcsDetectorSync)
|
|
185
201
|
]
|
|
186
202
|
});
|
|
187
203
|
sdk.start();
|
|
188
|
-
diag.info("Tracer successfully started");
|
|
204
|
+
import_api.diag.info("Tracer successfully started");
|
|
189
205
|
Sentry.validateOpenTelemetrySetup();
|
|
190
|
-
|
|
191
|
-
sdk.shutdown().then(() => diag.info("Tracing and Metrics terminated")).catch(
|
|
192
|
-
(error) => diag.error("Error terminating tracing and metrics", error)
|
|
193
|
-
).finally(() =>
|
|
206
|
+
import_process.default.on("SIGTERM", () => {
|
|
207
|
+
sdk.shutdown().then(() => import_api.diag.info("Tracing and Metrics terminated")).catch(
|
|
208
|
+
(error) => import_api.diag.error("Error terminating tracing and metrics", error)
|
|
209
|
+
).finally(() => import_process.default.exit(0));
|
|
194
210
|
});
|
|
195
211
|
}
|
|
196
212
|
var UnleashSampler = class _UnleashSampler {
|
|
213
|
+
_unleash;
|
|
214
|
+
_flagName;
|
|
215
|
+
_upperBound;
|
|
216
|
+
_ratio;
|
|
197
217
|
constructor(config) {
|
|
198
218
|
this._flagName = config.flagName;
|
|
199
219
|
this._unleash = config.unleash;
|
|
@@ -216,7 +236,7 @@ var UnleashSampler = class _UnleashSampler {
|
|
|
216
236
|
shouldSample(context, traceId, spanName, spanKind, attributes, links) {
|
|
217
237
|
this.updateFlagValue();
|
|
218
238
|
return {
|
|
219
|
-
decision: isValidTraceId(traceId) && this._accumulate(traceId) < this._upperBound ? SamplingDecision.RECORD_AND_SAMPLED : SamplingDecision.NOT_RECORD
|
|
239
|
+
decision: (0, import_api.isValidTraceId)(traceId) && this._accumulate(traceId) < this._upperBound ? import_sdk_trace_base.SamplingDecision.RECORD_AND_SAMPLED : import_sdk_trace_base.SamplingDecision.NOT_RECORD
|
|
220
240
|
};
|
|
221
241
|
}
|
|
222
242
|
updateFlagValue() {
|
|
@@ -253,6 +273,7 @@ var UnleashSampler = class _UnleashSampler {
|
|
|
253
273
|
}
|
|
254
274
|
};
|
|
255
275
|
var SentryParentSampler = class _SentryParentSampler {
|
|
276
|
+
_root;
|
|
256
277
|
constructor(config) {
|
|
257
278
|
this._root = config.root;
|
|
258
279
|
}
|
|
@@ -279,7 +300,7 @@ var SentryParentSampler = class _SentryParentSampler {
|
|
|
279
300
|
attributes,
|
|
280
301
|
links
|
|
281
302
|
);
|
|
282
|
-
return wrapSamplingDecision({
|
|
303
|
+
return (0, import_opentelemetry.wrapSamplingDecision)({
|
|
283
304
|
decision: decision.decision,
|
|
284
305
|
context,
|
|
285
306
|
spanAttributes: attributes
|
|
@@ -289,7 +310,8 @@ var SentryParentSampler = class _SentryParentSampler {
|
|
|
289
310
|
return _SentryParentSampler.name;
|
|
290
311
|
}
|
|
291
312
|
};
|
|
292
|
-
export
|
|
313
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
314
|
+
0 && (module.exports = {
|
|
293
315
|
AdditionalInstrumentation,
|
|
294
316
|
nodeSDKBuilder
|
|
295
|
-
};
|
|
317
|
+
});
|
package/dist/index.js
CHANGED
|
@@ -1,71 +1,52 @@
|
|
|
1
|
-
var __create = Object.create;
|
|
2
|
-
var __defProp = Object.defineProperty;
|
|
3
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
6
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
-
var __export = (target, all) => {
|
|
8
|
-
for (var name in all)
|
|
9
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
|
-
};
|
|
11
|
-
var __copyProps = (to, from, except, desc) => {
|
|
12
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
13
|
-
for (let key of __getOwnPropNames(from))
|
|
14
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
15
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
16
|
-
}
|
|
17
|
-
return to;
|
|
18
|
-
};
|
|
19
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
20
|
-
// If the importer is in node compatibility mode or this is not an ESM
|
|
21
|
-
// file that has been converted to a CommonJS file using a Babel-
|
|
22
|
-
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
23
|
-
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
24
|
-
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
25
|
-
mod
|
|
26
|
-
));
|
|
27
|
-
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
28
|
-
|
|
29
|
-
// src/index.ts
|
|
30
|
-
var src_exports = {};
|
|
31
|
-
__export(src_exports, {
|
|
32
|
-
AdditionalInstrumentation: () => AdditionalInstrumentation,
|
|
33
|
-
nodeSDKBuilder: () => nodeSDKBuilder
|
|
34
|
-
});
|
|
35
|
-
module.exports = __toCommonJS(src_exports);
|
|
36
|
-
|
|
37
1
|
// src/tracing.ts
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
2
|
+
import process from "process";
|
|
3
|
+
import { NodeSDK, logs } from "@opentelemetry/sdk-node";
|
|
4
|
+
import {
|
|
5
|
+
DiagConsoleLogger,
|
|
6
|
+
DiagLogLevel,
|
|
7
|
+
diag,
|
|
8
|
+
isValidTraceId
|
|
9
|
+
} from "@opentelemetry/api";
|
|
10
|
+
import { KnexInstrumentation } from "@opentelemetry/instrumentation-knex";
|
|
11
|
+
import { OTLPTraceExporter as HTTPOTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-http";
|
|
12
|
+
import { OTLPTraceExporter as GRPCOTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-grpc";
|
|
13
|
+
import { OTLPLogExporter as HTTPOTLPLogExporter } from "@opentelemetry/exporter-logs-otlp-http";
|
|
14
|
+
import { OTLPLogExporter as GRPCOTLPLogExporter } from "@opentelemetry/exporter-logs-otlp-grpc";
|
|
15
|
+
import { PrismaInstrumentation } from "@prisma/instrumentation";
|
|
16
|
+
import { Resource } from "@opentelemetry/resources";
|
|
17
|
+
import {
|
|
18
|
+
ATTR_SERVICE_NAME,
|
|
19
|
+
ATTR_SERVICE_VERSION,
|
|
20
|
+
SEMRESATTRS_DEPLOYMENT_ENVIRONMENT
|
|
21
|
+
} from "@opentelemetry/semantic-conventions";
|
|
22
|
+
import { SentryPropagator, wrapSamplingDecision } from "@sentry/opentelemetry";
|
|
23
|
+
import { PeriodicExportingMetricReader } from "@opentelemetry/sdk-metrics";
|
|
24
|
+
import { OTLPMetricExporter as HTTPOTLPMetricExporter } from "@opentelemetry/exporter-metrics-otlp-http";
|
|
25
|
+
import { OTLPMetricExporter as GRPCOTLPMetricExporter } from "@opentelemetry/exporter-metrics-otlp-grpc";
|
|
26
|
+
import { getNodeAutoInstrumentations } from "@opentelemetry/auto-instrumentations-node";
|
|
27
|
+
import {
|
|
28
|
+
envDetectorSync,
|
|
29
|
+
hostDetectorSync,
|
|
30
|
+
processDetectorSync
|
|
31
|
+
} from "@opentelemetry/resources";
|
|
32
|
+
import { awsEcsDetectorSync } from "@opentelemetry/resource-detector-aws";
|
|
33
|
+
import * as Sentry from "@sentry/node";
|
|
34
|
+
import {
|
|
35
|
+
BatchSpanProcessor,
|
|
36
|
+
ParentBasedSampler,
|
|
37
|
+
SamplingDecision
|
|
38
|
+
} from "@opentelemetry/sdk-trace-base";
|
|
39
|
+
import { AWSXRayPropagator } from "@opentelemetry/propagator-aws-xray";
|
|
40
|
+
import { AWSXRayIdGenerator } from "@opentelemetry/id-generator-aws-xray";
|
|
41
|
+
import { CompositePropagator } from "@opentelemetry/core";
|
|
61
42
|
var AdditionalInstrumentation = /* @__PURE__ */ ((AdditionalInstrumentation2) => {
|
|
62
43
|
AdditionalInstrumentation2["KNEX"] = "KNEX";
|
|
63
44
|
AdditionalInstrumentation2["PRISMA"] = "PRISMA";
|
|
64
45
|
return AdditionalInstrumentation2;
|
|
65
46
|
})(AdditionalInstrumentation || {});
|
|
66
47
|
var additionalInstrumentationConstructors = {
|
|
67
|
-
KNEX:
|
|
68
|
-
PRISMA:
|
|
48
|
+
KNEX: KnexInstrumentation,
|
|
49
|
+
PRISMA: PrismaInstrumentation
|
|
69
50
|
};
|
|
70
51
|
var tracingDefaults = {
|
|
71
52
|
serviceName: "unknown",
|
|
@@ -84,9 +65,8 @@ function awaitAttributes(detector) {
|
|
|
84
65
|
* A function that returns a promise that resolves with the attributes
|
|
85
66
|
*/
|
|
86
67
|
async detect(config) {
|
|
87
|
-
var _a;
|
|
88
68
|
const resource = detector.detect(config);
|
|
89
|
-
await
|
|
69
|
+
await resource.waitForAsyncAttributes?.();
|
|
90
70
|
console.log("Detected resource: ", resource);
|
|
91
71
|
return resource;
|
|
92
72
|
}
|
|
@@ -99,32 +79,31 @@ var batchConfig = {
|
|
|
99
79
|
exportTimeoutMillis: 5e3
|
|
100
80
|
};
|
|
101
81
|
async function nodeSDKBuilder(config) {
|
|
102
|
-
var _a, _b, _c;
|
|
103
82
|
config = { ...tracingDefaults, ...config };
|
|
104
|
-
|
|
105
|
-
const _resource =
|
|
106
|
-
new
|
|
107
|
-
[
|
|
108
|
-
[
|
|
109
|
-
[
|
|
83
|
+
diag.setLogger(new DiagConsoleLogger(), DiagLogLevel.WARN);
|
|
84
|
+
const _resource = Resource.default().merge(
|
|
85
|
+
new Resource({
|
|
86
|
+
[ATTR_SERVICE_NAME]: config.serviceName,
|
|
87
|
+
[ATTR_SERVICE_VERSION]: config.release,
|
|
88
|
+
[SEMRESATTRS_DEPLOYMENT_ENVIRONMENT]: process.env.ENVIRONMENT ?? process.env.NODE_ENV ?? "unknown"
|
|
110
89
|
})
|
|
111
90
|
);
|
|
112
|
-
const _traceExporter = config.protocol === "HTTP" ? new
|
|
91
|
+
const _traceExporter = config.protocol === "HTTP" ? new HTTPOTLPTraceExporter({
|
|
113
92
|
//collector url
|
|
114
93
|
url: `${config.url}/v1/traces`
|
|
115
|
-
}) : new
|
|
116
|
-
const _metricReader = new
|
|
117
|
-
exporter: config.protocol === "HTTP" ? new
|
|
94
|
+
}) : new GRPCOTLPTraceExporter({ url: config.url });
|
|
95
|
+
const _metricReader = new PeriodicExportingMetricReader({
|
|
96
|
+
exporter: config.protocol === "HTTP" ? new HTTPOTLPMetricExporter({
|
|
118
97
|
url: `${config.url}/v1/metrics`
|
|
119
|
-
}) : new
|
|
98
|
+
}) : new GRPCOTLPMetricExporter({ url: config.url }),
|
|
120
99
|
// once every 60 seconds, GCP supports 1 every 5 seconds for custom metrics https://cloud.google.com/monitoring/quotas#custom_metrics_quotas
|
|
121
100
|
// But lets just do 60 seconds for now as we figure it out
|
|
122
101
|
exportIntervalMillis: 1e4,
|
|
123
102
|
exportTimeoutMillis: 5e3
|
|
124
103
|
});
|
|
125
|
-
const _logExporter = config.protocol === "HTTP" ? new
|
|
104
|
+
const _logExporter = config.protocol === "HTTP" ? new HTTPOTLPLogExporter({ url: `${config.url}/v1/logs` }) : new GRPCOTLPLogExporter({ url: config.url });
|
|
126
105
|
const instrumentations = [
|
|
127
|
-
|
|
106
|
+
getNodeAutoInstrumentations({
|
|
128
107
|
"@opentelemetry/instrumentation-fs": {
|
|
129
108
|
// Disabling Filesystem instrumentation because it is very noisey and memory intense.
|
|
130
109
|
enabled: false,
|
|
@@ -138,8 +117,7 @@ async function nodeSDKBuilder(config) {
|
|
|
138
117
|
},
|
|
139
118
|
"@opentelemetry/instrumentation-http": {
|
|
140
119
|
ignoreIncomingRequestHook: (request) => {
|
|
141
|
-
|
|
142
|
-
if ((_a2 = request.url) == null ? void 0 : _a2.includes(".well-known/apollo/server-health")) {
|
|
120
|
+
if (request.url?.includes(".well-known/apollo/server-health")) {
|
|
143
121
|
return true;
|
|
144
122
|
}
|
|
145
123
|
return false;
|
|
@@ -164,21 +142,21 @@ async function nodeSDKBuilder(config) {
|
|
|
164
142
|
}
|
|
165
143
|
})
|
|
166
144
|
];
|
|
167
|
-
(
|
|
145
|
+
(config.additionalInstrumentations ?? []).forEach((instrumentation) => {
|
|
168
146
|
instrumentations.push(
|
|
169
147
|
new additionalInstrumentationConstructors[instrumentation]()
|
|
170
148
|
);
|
|
171
149
|
});
|
|
172
|
-
const sdk = new
|
|
173
|
-
textMapPropagator: new
|
|
150
|
+
const sdk = new NodeSDK({
|
|
151
|
+
textMapPropagator: new CompositePropagator({
|
|
174
152
|
// The Propogators are run in the order they are added, and since we want the AWSXRAY to win,
|
|
175
153
|
// it must come last because it writes the parent context "sampled" data from the trace into the contexts
|
|
176
154
|
// We Keep Sentry in here, because it adds data that Sentry needs, we just don't want it to control the sample value.
|
|
177
|
-
propagators: [new
|
|
155
|
+
propagators: [new SentryPropagator(), new AWSXRayPropagator()]
|
|
178
156
|
}),
|
|
179
157
|
instrumentations,
|
|
180
158
|
sampler: new SentryParentSampler({
|
|
181
|
-
root: new
|
|
159
|
+
root: new ParentBasedSampler({
|
|
182
160
|
root: new UnleashSampler({
|
|
183
161
|
unleash: config.unleash,
|
|
184
162
|
flagName: config.flagName
|
|
@@ -188,31 +166,35 @@ async function nodeSDKBuilder(config) {
|
|
|
188
166
|
}),
|
|
189
167
|
contextManager: new Sentry.SentryContextManager(),
|
|
190
168
|
resource: _resource,
|
|
191
|
-
idGenerator: new
|
|
192
|
-
spanProcessors: [new
|
|
169
|
+
idGenerator: new AWSXRayIdGenerator(),
|
|
170
|
+
spanProcessors: [new BatchSpanProcessor(_traceExporter, batchConfig)],
|
|
193
171
|
metricReader: _metricReader,
|
|
194
172
|
logRecordProcessors: [
|
|
195
|
-
new
|
|
173
|
+
new logs.BatchLogRecordProcessor(_logExporter, batchConfig)
|
|
196
174
|
],
|
|
197
175
|
// TODO: Remove after issue is fixed
|
|
198
176
|
// https://github.com/open-telemetry/opentelemetry-js/issues/4638
|
|
199
177
|
resourceDetectors: [
|
|
200
|
-
awaitAttributes(
|
|
201
|
-
awaitAttributes(
|
|
202
|
-
awaitAttributes(
|
|
203
|
-
awaitAttributes(
|
|
178
|
+
awaitAttributes(envDetectorSync),
|
|
179
|
+
awaitAttributes(hostDetectorSync),
|
|
180
|
+
awaitAttributes(processDetectorSync),
|
|
181
|
+
awaitAttributes(awsEcsDetectorSync)
|
|
204
182
|
]
|
|
205
183
|
});
|
|
206
184
|
sdk.start();
|
|
207
|
-
|
|
185
|
+
diag.info("Tracer successfully started");
|
|
208
186
|
Sentry.validateOpenTelemetrySetup();
|
|
209
|
-
|
|
210
|
-
sdk.shutdown().then(() =>
|
|
211
|
-
(error) =>
|
|
212
|
-
).finally(() =>
|
|
187
|
+
process.on("SIGTERM", () => {
|
|
188
|
+
sdk.shutdown().then(() => diag.info("Tracing and Metrics terminated")).catch(
|
|
189
|
+
(error) => diag.error("Error terminating tracing and metrics", error)
|
|
190
|
+
).finally(() => process.exit(0));
|
|
213
191
|
});
|
|
214
192
|
}
|
|
215
193
|
var UnleashSampler = class _UnleashSampler {
|
|
194
|
+
_unleash;
|
|
195
|
+
_flagName;
|
|
196
|
+
_upperBound;
|
|
197
|
+
_ratio;
|
|
216
198
|
constructor(config) {
|
|
217
199
|
this._flagName = config.flagName;
|
|
218
200
|
this._unleash = config.unleash;
|
|
@@ -235,7 +217,7 @@ var UnleashSampler = class _UnleashSampler {
|
|
|
235
217
|
shouldSample(context, traceId, spanName, spanKind, attributes, links) {
|
|
236
218
|
this.updateFlagValue();
|
|
237
219
|
return {
|
|
238
|
-
decision:
|
|
220
|
+
decision: isValidTraceId(traceId) && this._accumulate(traceId) < this._upperBound ? SamplingDecision.RECORD_AND_SAMPLED : SamplingDecision.NOT_RECORD
|
|
239
221
|
};
|
|
240
222
|
}
|
|
241
223
|
updateFlagValue() {
|
|
@@ -272,6 +254,7 @@ var UnleashSampler = class _UnleashSampler {
|
|
|
272
254
|
}
|
|
273
255
|
};
|
|
274
256
|
var SentryParentSampler = class _SentryParentSampler {
|
|
257
|
+
_root;
|
|
275
258
|
constructor(config) {
|
|
276
259
|
this._root = config.root;
|
|
277
260
|
}
|
|
@@ -298,7 +281,7 @@ var SentryParentSampler = class _SentryParentSampler {
|
|
|
298
281
|
attributes,
|
|
299
282
|
links
|
|
300
283
|
);
|
|
301
|
-
return
|
|
284
|
+
return wrapSamplingDecision({
|
|
302
285
|
decision: decision.decision,
|
|
303
286
|
context,
|
|
304
287
|
spanAttributes: attributes
|
|
@@ -308,8 +291,7 @@ var SentryParentSampler = class _SentryParentSampler {
|
|
|
308
291
|
return _SentryParentSampler.name;
|
|
309
292
|
}
|
|
310
293
|
};
|
|
311
|
-
|
|
312
|
-
0 && (module.exports = {
|
|
294
|
+
export {
|
|
313
295
|
AdditionalInstrumentation,
|
|
314
296
|
nodeSDKBuilder
|
|
315
|
-
}
|
|
297
|
+
};
|
package/jest.config.ts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { Config } from 'jest';
|
|
2
|
+
|
|
3
|
+
const config: Config = {
|
|
4
|
+
preset: 'ts-jest/presets/default-esm', // or other ESM presets
|
|
5
|
+
testEnvironment: 'node',
|
|
6
|
+
testMatch: ['**/?(*.)+(jest|spec).[jt]s?(x)'],
|
|
7
|
+
testPathIgnorePatterns: ['/dist/'],
|
|
8
|
+
moduleNameMapper: {
|
|
9
|
+
"^(\\.{1,2}/.*)\\.js$": "$1"
|
|
10
|
+
},
|
|
11
|
+
transform: {
|
|
12
|
+
['^.+.tsx?$']: [
|
|
13
|
+
'ts-jest',
|
|
14
|
+
{
|
|
15
|
+
tsconfig: '<rootDir>/tsconfig.json',
|
|
16
|
+
isolatedModules: true,
|
|
17
|
+
useESM: true,
|
|
18
|
+
},
|
|
19
|
+
],
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export default config;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pocket-tools/tracing",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.11.0",
|
|
4
4
|
"description": "Utilities for tracing",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"tracing"
|
|
@@ -11,6 +11,17 @@
|
|
|
11
11
|
},
|
|
12
12
|
"license": "Apache-2.0",
|
|
13
13
|
"author": "",
|
|
14
|
+
"type": "module",
|
|
15
|
+
"exports": {
|
|
16
|
+
"import": {
|
|
17
|
+
"types": "./dist/index.d.ts",
|
|
18
|
+
"import": "./dist/index.js"
|
|
19
|
+
},
|
|
20
|
+
"require": {
|
|
21
|
+
"types": "./dist/index.d.cts",
|
|
22
|
+
"require": "./dist/index.cjs"
|
|
23
|
+
}
|
|
24
|
+
},
|
|
14
25
|
"main": "dist/index.js",
|
|
15
26
|
"module": "dist/index.mjs",
|
|
16
27
|
"types": "dist/index.d.ts",
|
|
@@ -102,7 +113,7 @@
|
|
|
102
113
|
"ts-jest": "29.2.5",
|
|
103
114
|
"ts-node": "10.9.2",
|
|
104
115
|
"tsup": "8.3.5",
|
|
105
|
-
"typescript": "5.
|
|
116
|
+
"typescript": "5.7.2",
|
|
106
117
|
"@pocket-tools/eslint-config": "0.0.0",
|
|
107
118
|
"tsconfig": "0.0.0"
|
|
108
119
|
},
|
|
File without changes
|