@prairielearn/opentelemetry 1.11.3 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.mocharc.cjs +3 -0
- package/CHANGELOG.md +17 -0
- package/dist/commonjs-preloads.d.ts +1 -0
- package/dist/commonjs-preloads.js +43 -0
- package/dist/commonjs-preloads.js.map +1 -0
- package/dist/index.d.ts +5 -4
- package/dist/index.js +16 -27
- package/dist/index.js.map +1 -1
- package/dist/init.js +59 -63
- package/dist/init.js.map +1 -1
- package/dist/metrics.d.ts +2 -2
- package/dist/metrics.js +12 -23
- package/dist/metrics.js.map +1 -1
- package/dist/metrics.test.js +24 -52
- package/dist/metrics.test.js.map +1 -1
- package/dist/tracing.js +5 -9
- package/dist/tracing.js.map +1 -1
- package/dist/tracing.test.js +28 -30
- package/dist/tracing.test.js.map +1 -1
- package/package.json +31 -28
- package/src/commonjs-preloads.ts +42 -0
- package/src/index.ts +24 -12
- package/src/init.ts +27 -29
- package/src/metrics.test.ts +4 -4
- package/src/metrics.ts +2 -2
- package/src/tracing.test.ts +2 -2
package/.mocharc.cjs
ADDED
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,22 @@
|
|
|
1
1
|
# @prairielearn/opentelemetry
|
|
2
2
|
|
|
3
|
+
## 2.0.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 901fce8: Upgrade all JavaScript dependencies
|
|
8
|
+
- b697912: Fix CommonJS preloads of packages
|
|
9
|
+
|
|
10
|
+
## 2.0.0
|
|
11
|
+
|
|
12
|
+
### Major Changes
|
|
13
|
+
|
|
14
|
+
- 4f30b7e: Publish as native ESM
|
|
15
|
+
|
|
16
|
+
### Minor Changes
|
|
17
|
+
|
|
18
|
+
- c51f3aa: Upgrade all JavaScript dependencies; ensure packages loaded with ESM are instrumented
|
|
19
|
+
|
|
3
20
|
## 1.11.3
|
|
4
21
|
|
|
5
22
|
### Patch Changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { createRequire } from 'module';
|
|
2
|
+
// The packages below were determined by inspecting the implementation of each
|
|
3
|
+
// instrumentation package and finding which packages/files they're patching.
|
|
4
|
+
const PRELOAD_PACKAGES = [
|
|
5
|
+
// @opentelemetry/instrumentation-aws-sdk
|
|
6
|
+
'@aws-sdk/middleware-stack/dist/cjs/MiddlewareStack.js',
|
|
7
|
+
'@aws-sdk/middleware-stack/dist-cjs/MiddlewareStack.js',
|
|
8
|
+
'@aws-sdk/middleware-stack',
|
|
9
|
+
'@smithy/middleware-stack',
|
|
10
|
+
'@aws-sdk/smithy-client',
|
|
11
|
+
'aws-sdk/lib/core.js',
|
|
12
|
+
'aws-sdk',
|
|
13
|
+
// @opentelemetry/instrumentation-connect
|
|
14
|
+
'connect',
|
|
15
|
+
// @opentelemetry/instrumentation-dns
|
|
16
|
+
'dns',
|
|
17
|
+
'dns/promises',
|
|
18
|
+
// @opentelemetry/instrumentation-express
|
|
19
|
+
'express',
|
|
20
|
+
// @opentelemetry/instrumentation-http
|
|
21
|
+
'http',
|
|
22
|
+
'https',
|
|
23
|
+
// @opentelemetry/instrumentation-ioredis
|
|
24
|
+
'ioredis',
|
|
25
|
+
// @opentelemetry/instrumentation-postgres
|
|
26
|
+
'pg',
|
|
27
|
+
'pg-pool',
|
|
28
|
+
// @opentelemetry/instrumentation-redis
|
|
29
|
+
'redis',
|
|
30
|
+
];
|
|
31
|
+
const require = createRequire(import.meta.url);
|
|
32
|
+
for (const pkg of PRELOAD_PACKAGES) {
|
|
33
|
+
try {
|
|
34
|
+
require(pkg);
|
|
35
|
+
}
|
|
36
|
+
catch (e) {
|
|
37
|
+
// If the package is not found, it's fine, it just means that it wasn't
|
|
38
|
+
// installed. We'll throw any other errors.
|
|
39
|
+
if (e.code !== 'MODULE_NOT_FOUND')
|
|
40
|
+
throw e;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=commonjs-preloads.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"commonjs-preloads.js","sourceRoot":"","sources":["../src/commonjs-preloads.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAC;AAEvC,8EAA8E;AAC9E,6EAA6E;AAC7E,MAAM,gBAAgB,GAAG;IACvB,yCAAyC;IACzC,uDAAuD;IACvD,uDAAuD;IACvD,2BAA2B;IAC3B,0BAA0B;IAC1B,wBAAwB;IACxB,qBAAqB;IACrB,SAAS;IACT,yCAAyC;IACzC,SAAS;IACT,qCAAqC;IACrC,KAAK;IACL,cAAc;IACd,yCAAyC;IACzC,SAAS;IACT,sCAAsC;IACtC,MAAM;IACN,OAAO;IACP,yCAAyC;IACzC,SAAS;IACT,0CAA0C;IAC1C,IAAI;IACJ,SAAS;IACT,uCAAuC;IACvC,OAAO;CACR,CAAC;AAEF,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC/C,KAAK,MAAM,GAAG,IAAI,gBAAgB,EAAE,CAAC;IACnC,IAAI,CAAC;QACH,OAAO,CAAC,GAAG,CAAC,CAAC;IACf,CAAC;IAAC,OAAO,CAAM,EAAE,CAAC;QAChB,uEAAuE;QACvE,2CAA2C;QAC3C,IAAI,CAAC,CAAC,IAAI,KAAK,kBAAkB;YAAE,MAAM,CAAC,CAAC;IAC7C,CAAC;AACH,CAAC","sourcesContent":["import { createRequire } from 'module';\n\n// The packages below were determined by inspecting the implementation of each\n// instrumentation package and finding which packages/files they're patching.\nconst PRELOAD_PACKAGES = [\n // @opentelemetry/instrumentation-aws-sdk\n '@aws-sdk/middleware-stack/dist/cjs/MiddlewareStack.js',\n '@aws-sdk/middleware-stack/dist-cjs/MiddlewareStack.js',\n '@aws-sdk/middleware-stack',\n '@smithy/middleware-stack',\n '@aws-sdk/smithy-client',\n 'aws-sdk/lib/core.js',\n 'aws-sdk',\n // @opentelemetry/instrumentation-connect\n 'connect',\n // @opentelemetry/instrumentation-dns\n 'dns',\n 'dns/promises',\n // @opentelemetry/instrumentation-express\n 'express',\n // @opentelemetry/instrumentation-http\n 'http',\n 'https',\n // @opentelemetry/instrumentation-ioredis\n 'ioredis',\n // @opentelemetry/instrumentation-postgres\n 'pg',\n 'pg-pool',\n // @opentelemetry/instrumentation-redis\n 'redis',\n];\n\nconst require = createRequire(import.meta.url);\nfor (const pkg of PRELOAD_PACKAGES) {\n try {\n require(pkg);\n } catch (e: any) {\n // If the package is not found, it's fine, it just means that it wasn't\n // installed. We'll throw any other errors.\n if (e.code !== 'MODULE_NOT_FOUND') throw e;\n }\n}\n"]}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
export { trace, metrics, context, SpanStatusCode, ValueType, TraceFlags, Meter, Counter, Histogram, UpDownCounter, ObservableCounter, ObservableUpDownCounter, ObservableGauge, ObservableResult, } from '@opentelemetry/api';
|
|
1
|
+
export { trace, metrics, context, SpanStatusCode, ValueType, TraceFlags, type Meter, type Counter, type Histogram, type UpDownCounter, type ObservableCounter, type ObservableUpDownCounter, type ObservableGauge, type ObservableResult, } from '@opentelemetry/api';
|
|
2
2
|
export { suppressTracing } from '@opentelemetry/core';
|
|
3
|
-
export { init, shutdown, disableInstrumentations } from './init';
|
|
4
|
-
export { instrumented } from './tracing';
|
|
5
|
-
export { instrumentedWithMetrics, getCounter, getUpDownCounter, getHistogram, getObservableCounter, getObservableUpDownCounter, getObservableGauge, createObservableValueGauges,
|
|
3
|
+
export { init, shutdown, disableInstrumentations } from './init.js';
|
|
4
|
+
export { instrumented } from './tracing.js';
|
|
5
|
+
export { instrumentedWithMetrics, getCounter, getUpDownCounter, getHistogram, getObservableCounter, getObservableUpDownCounter, getObservableGauge, createObservableValueGauges, type CreateObservableValueGaugesOptions, } from './metrics.js';
|
|
6
|
+
import './commonjs-preloads.js';
|
package/dist/index.js
CHANGED
|
@@ -1,28 +1,17 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
var tracing_1 = require("./tracing");
|
|
18
|
-
Object.defineProperty(exports, "instrumented", { enumerable: true, get: function () { return tracing_1.instrumented; } });
|
|
19
|
-
var metrics_1 = require("./metrics");
|
|
20
|
-
Object.defineProperty(exports, "instrumentedWithMetrics", { enumerable: true, get: function () { return metrics_1.instrumentedWithMetrics; } });
|
|
21
|
-
Object.defineProperty(exports, "getCounter", { enumerable: true, get: function () { return metrics_1.getCounter; } });
|
|
22
|
-
Object.defineProperty(exports, "getUpDownCounter", { enumerable: true, get: function () { return metrics_1.getUpDownCounter; } });
|
|
23
|
-
Object.defineProperty(exports, "getHistogram", { enumerable: true, get: function () { return metrics_1.getHistogram; } });
|
|
24
|
-
Object.defineProperty(exports, "getObservableCounter", { enumerable: true, get: function () { return metrics_1.getObservableCounter; } });
|
|
25
|
-
Object.defineProperty(exports, "getObservableUpDownCounter", { enumerable: true, get: function () { return metrics_1.getObservableUpDownCounter; } });
|
|
26
|
-
Object.defineProperty(exports, "getObservableGauge", { enumerable: true, get: function () { return metrics_1.getObservableGauge; } });
|
|
27
|
-
Object.defineProperty(exports, "createObservableValueGauges", { enumerable: true, get: function () { return metrics_1.createObservableValueGauges; } });
|
|
1
|
+
export { trace, metrics, context, SpanStatusCode, ValueType, TraceFlags, } from '@opentelemetry/api';
|
|
2
|
+
export { suppressTracing } from '@opentelemetry/core';
|
|
3
|
+
export { init, shutdown, disableInstrumentations } from './init.js';
|
|
4
|
+
export { instrumented } from './tracing.js';
|
|
5
|
+
export { instrumentedWithMetrics, getCounter, getUpDownCounter, getHistogram, getObservableCounter, getObservableUpDownCounter, getObservableGauge, createObservableValueGauges, } from './metrics.js';
|
|
6
|
+
// Extremely stupid workaround for the fact that the OpenTelemetry instrumentations
|
|
7
|
+
// don't currently have robust support for ESM. This hack ensures that instrumented
|
|
8
|
+
// packages are loaded for the first time via CJS, which the OpenTelemetry
|
|
9
|
+
// instrumentation can intercept and patch. Subsequent imports can be ESM, but that
|
|
10
|
+
// doesn't matter because the instrumentation has already been applied.
|
|
11
|
+
//
|
|
12
|
+
// OpenTelemetry introduced experimental support for ESM in
|
|
13
|
+
// https://github.com/open-telemetry/opentelemetry-js/pull/3698. This requires
|
|
14
|
+
// the usage of `--experimental-loader` to load the instrumentations, which
|
|
15
|
+
// we currently want to avoid.
|
|
16
|
+
import './commonjs-preloads.js';
|
|
28
17
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,EACL,OAAO,EACP,OAAO,EACP,cAAc,EACd,SAAS,EACT,UAAU,GASX,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAEtD,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,uBAAuB,EAAE,MAAM,WAAW,CAAC;AACpE,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EACL,uBAAuB,EACvB,UAAU,EACV,gBAAgB,EAChB,YAAY,EACZ,oBAAoB,EACpB,0BAA0B,EAC1B,kBAAkB,EAClB,2BAA2B,GAE5B,MAAM,cAAc,CAAC;AAEtB,mFAAmF;AACnF,mFAAmF;AACnF,0EAA0E;AAC1E,mFAAmF;AACnF,uEAAuE;AACvE,EAAE;AACF,2DAA2D;AAC3D,8EAA8E;AAC9E,2EAA2E;AAC3E,8BAA8B;AAC9B,OAAO,wBAAwB,CAAC","sourcesContent":["export {\n trace,\n metrics,\n context,\n SpanStatusCode,\n ValueType,\n TraceFlags,\n type Meter,\n type Counter,\n type Histogram,\n type UpDownCounter,\n type ObservableCounter,\n type ObservableUpDownCounter,\n type ObservableGauge,\n type ObservableResult,\n} from '@opentelemetry/api';\nexport { suppressTracing } from '@opentelemetry/core';\n\nexport { init, shutdown, disableInstrumentations } from './init.js';\nexport { instrumented } from './tracing.js';\nexport {\n instrumentedWithMetrics,\n getCounter,\n getUpDownCounter,\n getHistogram,\n getObservableCounter,\n getObservableUpDownCounter,\n getObservableGauge,\n createObservableValueGauges,\n type CreateObservableValueGaugesOptions,\n} from './metrics.js';\n\n// Extremely stupid workaround for the fact that the OpenTelemetry instrumentations\n// don't currently have robust support for ESM. This hack ensures that instrumented\n// packages are loaded for the first time via CJS, which the OpenTelemetry\n// instrumentation can intercept and patch. Subsequent imports can be ESM, but that\n// doesn't matter because the instrumentation has already been applied.\n//\n// OpenTelemetry introduced experimental support for ESM in\n// https://github.com/open-telemetry/opentelemetry-js/pull/3698. This requires\n// the usage of `--experimental-loader` to load the instrumentations, which\n// we currently want to avoid.\nimport './commonjs-preloads.js';\n"]}
|
package/dist/init.js
CHANGED
|
@@ -1,33 +1,29 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
const instrumentation_pg_1 = require("@opentelemetry/instrumentation-pg");
|
|
22
|
-
const instrumentation_redis_1 = require("@opentelemetry/instrumentation-redis");
|
|
23
|
-
// Resource detectors go here.
|
|
24
|
-
const resource_detector_aws_1 = require("@opentelemetry/resource-detector-aws");
|
|
1
|
+
import { Metadata, credentials } from '@grpc/grpc-js';
|
|
2
|
+
import { metrics } from '@opentelemetry/api';
|
|
3
|
+
import { hrTimeToMilliseconds } from '@opentelemetry/core';
|
|
4
|
+
import { OTLPMetricExporter } from '@opentelemetry/exporter-metrics-otlp-grpc';
|
|
5
|
+
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-grpc';
|
|
6
|
+
import { OTLPTraceExporter as OTLPTraceExporterHttp } from '@opentelemetry/exporter-trace-otlp-http';
|
|
7
|
+
import { AwsInstrumentation } from '@opentelemetry/instrumentation-aws-sdk';
|
|
8
|
+
import { ConnectInstrumentation } from '@opentelemetry/instrumentation-connect';
|
|
9
|
+
import { DnsInstrumentation } from '@opentelemetry/instrumentation-dns';
|
|
10
|
+
import { ExpressLayerType, ExpressInstrumentation } from '@opentelemetry/instrumentation-express';
|
|
11
|
+
import { HttpInstrumentation } from '@opentelemetry/instrumentation-http';
|
|
12
|
+
import { IORedisInstrumentation } from '@opentelemetry/instrumentation-ioredis';
|
|
13
|
+
import { PgInstrumentation } from '@opentelemetry/instrumentation-pg';
|
|
14
|
+
import { RedisInstrumentation } from '@opentelemetry/instrumentation-redis';
|
|
15
|
+
import { awsEc2Detector } from '@opentelemetry/resource-detector-aws';
|
|
16
|
+
import { detectResourcesSync, processDetector, envDetector, Resource, } from '@opentelemetry/resources';
|
|
17
|
+
import { PeriodicExportingMetricReader, MeterProvider, ConsoleMetricExporter, AggregationTemporality, } from '@opentelemetry/sdk-metrics';
|
|
18
|
+
import { SimpleSpanProcessor, BatchSpanProcessor, ParentBasedSampler, TraceIdRatioBasedSampler, AlwaysOnSampler, AlwaysOffSampler, ConsoleSpanExporter, } from '@opentelemetry/sdk-trace-base';
|
|
19
|
+
import { NodeTracerProvider } from '@opentelemetry/sdk-trace-node';
|
|
20
|
+
import { SemanticResourceAttributes } from '@opentelemetry/semantic-conventions';
|
|
25
21
|
/**
|
|
26
22
|
* Extends `BatchSpanProcessor` to give it the ability to filter out spans
|
|
27
23
|
* before they're queued up to send. This enhances our sampling process so
|
|
28
24
|
* that we can filter spans _after_ they've been emitted.
|
|
29
25
|
*/
|
|
30
|
-
class FilterBatchSpanProcessor extends
|
|
26
|
+
class FilterBatchSpanProcessor extends BatchSpanProcessor {
|
|
31
27
|
filter;
|
|
32
28
|
constructor(exporter, filter) {
|
|
33
29
|
super(exporter);
|
|
@@ -57,27 +53,31 @@ function filter(span) {
|
|
|
57
53
|
// establishing a connection for the first time, which should happen only at
|
|
58
54
|
// bootup, or if a connection errors out. Those are the cases we're
|
|
59
55
|
// interested in, so we'll filter accordingly.
|
|
60
|
-
return
|
|
56
|
+
return hrTimeToMilliseconds(span.duration) > 1;
|
|
61
57
|
}
|
|
62
58
|
// Always return true so that we default to including a span.
|
|
63
59
|
return true;
|
|
64
60
|
}
|
|
61
|
+
// When adding new instrumentation here, add the corresponding packages to
|
|
62
|
+
// `commonjs-preloads.ts` so that we can ensure that they're loaded via CJS
|
|
63
|
+
// before anything tries to load them via CJS. This is necessary because the
|
|
64
|
+
// instrumentations can't hook into the ESM loader.
|
|
65
65
|
const instrumentations = [
|
|
66
|
-
new
|
|
67
|
-
new
|
|
68
|
-
new
|
|
69
|
-
new
|
|
66
|
+
new AwsInstrumentation(),
|
|
67
|
+
new ConnectInstrumentation(),
|
|
68
|
+
new DnsInstrumentation(),
|
|
69
|
+
new ExpressInstrumentation({
|
|
70
70
|
// We use a lot of middleware; it makes the traces way too noisy. If we
|
|
71
71
|
// want telemetry on a particular middleware, we should instrument it
|
|
72
72
|
// manually.
|
|
73
|
-
ignoreLayersType: [
|
|
73
|
+
ignoreLayersType: [ExpressLayerType.MIDDLEWARE],
|
|
74
74
|
ignoreLayers: [
|
|
75
75
|
// These don't provide useful information to us.
|
|
76
76
|
'router - /',
|
|
77
77
|
'request handler - /*',
|
|
78
78
|
],
|
|
79
79
|
}),
|
|
80
|
-
new
|
|
80
|
+
new HttpInstrumentation({
|
|
81
81
|
ignoreIncomingPaths: [
|
|
82
82
|
// socket.io requests are generally just long-polling; they don't add
|
|
83
83
|
// useful information for us.
|
|
@@ -87,8 +87,9 @@ const instrumentations = [
|
|
|
87
87
|
/\/pl\/webhooks\/ping/,
|
|
88
88
|
],
|
|
89
89
|
}),
|
|
90
|
-
new
|
|
91
|
-
new
|
|
90
|
+
new IORedisInstrumentation(),
|
|
91
|
+
new PgInstrumentation(),
|
|
92
|
+
new RedisInstrumentation(),
|
|
92
93
|
];
|
|
93
94
|
// Enable all instrumentations now, even though we haven't configured our
|
|
94
95
|
// span processors or trace exporters yet. We'll set those up later.
|
|
@@ -101,7 +102,7 @@ function getHoneycombMetadata(config, datasetSuffix = '') {
|
|
|
101
102
|
throw new Error('Missing Honeycomb API key');
|
|
102
103
|
if (!config.honeycombDataset)
|
|
103
104
|
throw new Error('Missing Honeycomb dataset');
|
|
104
|
-
const metadata = new
|
|
105
|
+
const metadata = new Metadata();
|
|
105
106
|
metadata.set('x-honeycomb-team', config.honeycombApiKey);
|
|
106
107
|
metadata.set('x-honeycomb-dataset', config.honeycombDataset + datasetSuffix);
|
|
107
108
|
return metadata;
|
|
@@ -114,18 +115,16 @@ function getTraceExporter(config) {
|
|
|
114
115
|
}
|
|
115
116
|
switch (config.openTelemetryExporter) {
|
|
116
117
|
case 'console':
|
|
117
|
-
return new
|
|
118
|
+
return new ConsoleSpanExporter();
|
|
118
119
|
case 'honeycomb':
|
|
119
|
-
return new
|
|
120
|
+
return new OTLPTraceExporter({
|
|
120
121
|
url: 'grpc://api.honeycomb.io:443/',
|
|
121
|
-
credentials:
|
|
122
|
+
credentials: credentials.createSsl(),
|
|
122
123
|
metadata: getHoneycombMetadata(config),
|
|
123
124
|
});
|
|
124
125
|
break;
|
|
125
126
|
case 'jaeger':
|
|
126
|
-
return new
|
|
127
|
-
url: process.env.OTEL_EXPORTER_JAEGER_ENDPOINT ?? 'grpc://localhost:4317/',
|
|
128
|
-
});
|
|
127
|
+
return new OTLPTraceExporterHttp();
|
|
129
128
|
default:
|
|
130
129
|
throw new Error(`Unknown OpenTelemetry exporter: ${config.openTelemetryExporter}`);
|
|
131
130
|
}
|
|
@@ -138,18 +137,18 @@ function getMetricExporter(config) {
|
|
|
138
137
|
}
|
|
139
138
|
switch (config.openTelemetryMetricExporter) {
|
|
140
139
|
case 'console':
|
|
141
|
-
return new
|
|
140
|
+
return new ConsoleMetricExporter();
|
|
142
141
|
case 'honeycomb':
|
|
143
|
-
return new
|
|
142
|
+
return new OTLPMetricExporter({
|
|
144
143
|
url: 'grpc://api.honeycomb.io:443/',
|
|
145
|
-
credentials:
|
|
144
|
+
credentials: credentials.createSsl(),
|
|
146
145
|
// Honeycomb recommends using a separate dataset for metrics, so we'll
|
|
147
146
|
// adopt the convention of appending '-metrics' to the dataset name.
|
|
148
147
|
metadata: getHoneycombMetadata(config, '-metrics'),
|
|
149
148
|
// Delta temporality means that sums, histograms, etc. will reset each
|
|
150
149
|
// time data is collected. This more closely matches how we want to
|
|
151
150
|
// observe our metrics than the default cumulative temporality.
|
|
152
|
-
temporalityPreference:
|
|
151
|
+
temporalityPreference: AggregationTemporality.DELTA,
|
|
153
152
|
});
|
|
154
153
|
default:
|
|
155
154
|
throw new Error(`Unknown OpenTelemetry metric exporter: ${config.openTelemetryMetricExporter}`);
|
|
@@ -167,7 +166,7 @@ function getSpanProcessor(config) {
|
|
|
167
166
|
return new FilterBatchSpanProcessor(traceExporter, filter);
|
|
168
167
|
}
|
|
169
168
|
case 'simple': {
|
|
170
|
-
return new
|
|
169
|
+
return new SimpleSpanProcessor(traceExporter);
|
|
171
170
|
}
|
|
172
171
|
default: {
|
|
173
172
|
throw new Error(`Unknown OpenTelemetry span processor: ${config.openTelemetrySpanProcessor}`);
|
|
@@ -179,7 +178,7 @@ function getSpanProcessor(config) {
|
|
|
179
178
|
* the correct metadata for the Honeycomb exporter. We don't actually have that
|
|
180
179
|
* information available until we've loaded our config.
|
|
181
180
|
*/
|
|
182
|
-
async function init(config) {
|
|
181
|
+
export async function init(config) {
|
|
183
182
|
if (!config.openTelemetryEnabled) {
|
|
184
183
|
// If not enabled, do nothing. We used to disable the instrumentations, but
|
|
185
184
|
// per maintainers, that can actually be problematic. See the comments on
|
|
@@ -195,16 +194,16 @@ async function init(config) {
|
|
|
195
194
|
let sampler;
|
|
196
195
|
switch (config.openTelemetrySamplerType ?? 'always-on') {
|
|
197
196
|
case 'always-on': {
|
|
198
|
-
sampler = new
|
|
197
|
+
sampler = new AlwaysOnSampler();
|
|
199
198
|
break;
|
|
200
199
|
}
|
|
201
200
|
case 'always-off': {
|
|
202
|
-
sampler = new
|
|
201
|
+
sampler = new AlwaysOffSampler();
|
|
203
202
|
break;
|
|
204
203
|
}
|
|
205
204
|
case 'trace-id-ratio': {
|
|
206
|
-
sampler = new
|
|
207
|
-
root: new
|
|
205
|
+
sampler = new ParentBasedSampler({
|
|
206
|
+
root: new TraceIdRatioBasedSampler(config.openTelemetrySampleRate),
|
|
208
207
|
});
|
|
209
208
|
break;
|
|
210
209
|
}
|
|
@@ -216,14 +215,14 @@ async function init(config) {
|
|
|
216
215
|
// asynchronously. We need to initialize our instrumentations first; only
|
|
217
216
|
// then can we actually start requiring all of our code that loads our config
|
|
218
217
|
// and ultimately tells us how to configure OpenTelemetry.
|
|
219
|
-
let resource =
|
|
220
|
-
detectors: [
|
|
218
|
+
let resource = detectResourcesSync({
|
|
219
|
+
detectors: [awsEc2Detector, processDetector, envDetector],
|
|
221
220
|
});
|
|
222
221
|
if (config.serviceName) {
|
|
223
|
-
resource = resource.merge(new
|
|
222
|
+
resource = resource.merge(new Resource({ [SemanticResourceAttributes.SERVICE_NAME]: config.serviceName }));
|
|
224
223
|
}
|
|
225
224
|
// Set up tracing instrumentation.
|
|
226
|
-
const nodeTracerProvider = new
|
|
225
|
+
const nodeTracerProvider = new NodeTracerProvider({
|
|
227
226
|
sampler,
|
|
228
227
|
resource,
|
|
229
228
|
});
|
|
@@ -236,36 +235,33 @@ async function init(config) {
|
|
|
236
235
|
tracerProvider = nodeTracerProvider;
|
|
237
236
|
// Set up metrics instrumentation if it's enabled.
|
|
238
237
|
if (metricExporter) {
|
|
239
|
-
const meterProvider = new
|
|
238
|
+
const meterProvider = new MeterProvider({
|
|
240
239
|
resource,
|
|
241
240
|
readers: [
|
|
242
|
-
new
|
|
241
|
+
new PeriodicExportingMetricReader({
|
|
243
242
|
exporter: metricExporter,
|
|
244
243
|
exportIntervalMillis: config.openTelemetryMetricExportIntervalMillis ?? 30_000,
|
|
245
244
|
}),
|
|
246
245
|
],
|
|
247
246
|
});
|
|
248
|
-
|
|
247
|
+
metrics.setGlobalMeterProvider(meterProvider);
|
|
249
248
|
}
|
|
250
249
|
}
|
|
251
|
-
exports.init = init;
|
|
252
250
|
/**
|
|
253
251
|
* Gracefully shuts down the OpenTelemetry instrumentation. Should be called
|
|
254
252
|
* when a `SIGTERM` signal is handled.
|
|
255
253
|
*/
|
|
256
|
-
async function shutdown() {
|
|
254
|
+
export async function shutdown() {
|
|
257
255
|
if (tracerProvider) {
|
|
258
256
|
await tracerProvider.shutdown();
|
|
259
257
|
tracerProvider = null;
|
|
260
258
|
}
|
|
261
259
|
}
|
|
262
|
-
exports.shutdown = shutdown;
|
|
263
260
|
/**
|
|
264
261
|
* Disables all OpenTelemetry instrumentations. This is useful for tests that
|
|
265
262
|
* need to access the unwrapped modules.
|
|
266
263
|
*/
|
|
267
|
-
function disableInstrumentations() {
|
|
264
|
+
export function disableInstrumentations() {
|
|
268
265
|
instrumentations.forEach((i) => i.disable());
|
|
269
266
|
}
|
|
270
|
-
exports.disableInstrumentations = disableInstrumentations;
|
|
271
267
|
//# sourceMappingURL=init.js.map
|
package/dist/init.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init.js","sourceRoot":"","sources":["../src/init.ts"],"names":[],"mappings":"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","sourcesContent":["import { Metadata, credentials } from '@grpc/grpc-js';\n\nimport { NodeTracerProvider } from '@opentelemetry/sdk-trace-node';\nimport {\n PeriodicExportingMetricReader,\n MeterProvider,\n PushMetricExporter,\n ConsoleMetricExporter,\n AggregationTemporality,\n} from '@opentelemetry/sdk-metrics';\nimport {\n SpanExporter,\n ReadableSpan,\n SpanProcessor,\n SimpleSpanProcessor,\n BatchSpanProcessor,\n ParentBasedSampler,\n TraceIdRatioBasedSampler,\n AlwaysOnSampler,\n AlwaysOffSampler,\n Sampler,\n ConsoleSpanExporter,\n} from '@opentelemetry/sdk-trace-base';\nimport {\n detectResourcesSync,\n processDetector,\n envDetector,\n Resource,\n} from '@opentelemetry/resources';\nimport { SemanticResourceAttributes } from '@opentelemetry/semantic-conventions';\nimport { metrics } from '@opentelemetry/api';\nimport { hrTimeToMilliseconds } from '@opentelemetry/core';\n\n// Exporters go here.\nimport { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-grpc';\nimport { OTLPMetricExporter } from '@opentelemetry/exporter-metrics-otlp-grpc';\n\n// Instrumentations go here.\nimport { AwsInstrumentation } from '@opentelemetry/instrumentation-aws-sdk';\nimport { ConnectInstrumentation } from '@opentelemetry/instrumentation-connect';\nimport { DnsInstrumentation } from '@opentelemetry/instrumentation-dns';\nimport { ExpressLayerType, ExpressInstrumentation } from '@opentelemetry/instrumentation-express';\nimport { HttpInstrumentation } from '@opentelemetry/instrumentation-http';\nimport { PgInstrumentation } from '@opentelemetry/instrumentation-pg';\nimport { RedisInstrumentation } from '@opentelemetry/instrumentation-redis';\n\n// Resource detectors go here.\nimport { awsEc2Detector } from '@opentelemetry/resource-detector-aws';\n\n/**\n * Extends `BatchSpanProcessor` to give it the ability to filter out spans\n * before they're queued up to send. This enhances our sampling process so\n * that we can filter spans _after_ they've been emitted.\n */\nclass FilterBatchSpanProcessor extends BatchSpanProcessor {\n private filter: (span: ReadableSpan) => boolean;\n\n constructor(exporter: SpanExporter, filter: (span: ReadableSpan) => boolean) {\n super(exporter);\n this.filter = filter;\n }\n\n /**\n * This is invoked after a span is \"finalized\". `super.onEnd` will queue up\n * the span to be exported, but if we don't call that, we can just drop the\n * span and the parent will be none the wiser!\n */\n onEnd(span: ReadableSpan) {\n if (!this.filter(span)) return;\n\n super.onEnd(span);\n }\n}\n\n/**\n * This will be used with our {@link FilterBatchSpanProcessor} to filter out\n * events that we're not interested in. This helps reduce our event volume\n * but still gives us fine-grained control over which events we keep.\n */\nfunction filter(span: ReadableSpan) {\n if (span.name === 'pg-pool.connect') {\n // Looking at historical data, this generally happens in under a millisecond,\n // precisely because we maintain a pool of long-lived connections. The only\n // time obtaining a client should take longer than that is if we're\n // establishing a connection for the first time, which should happen only at\n // bootup, or if a connection errors out. Those are the cases we're\n // interested in, so we'll filter accordingly.\n return hrTimeToMilliseconds(span.duration) > 1;\n }\n\n // Always return true so that we default to including a span.\n return true;\n}\n\nconst instrumentations = [\n new AwsInstrumentation(),\n new ConnectInstrumentation(),\n new DnsInstrumentation(),\n new ExpressInstrumentation({\n // We use a lot of middleware; it makes the traces way too noisy. If we\n // want telemetry on a particular middleware, we should instrument it\n // manually.\n ignoreLayersType: [ExpressLayerType.MIDDLEWARE],\n ignoreLayers: [\n // These don't provide useful information to us.\n 'router - /',\n 'request handler - /*',\n ],\n }),\n new HttpInstrumentation({\n ignoreIncomingPaths: [\n // socket.io requests are generally just long-polling; they don't add\n // useful information for us.\n /\\/socket.io\\//,\n // We get several of these per second; they just chew through our event quota.\n // They don't really do anything interesting anyways.\n /\\/pl\\/webhooks\\/ping/,\n ],\n }),\n new PgInstrumentation(),\n new RedisInstrumentation(),\n];\n\n// Enable all instrumentations now, even though we haven't configured our\n// span processors or trace exporters yet. We'll set those up later.\ninstrumentations.forEach((i) => {\n i.enable();\n});\n\nlet tracerProvider: NodeTracerProvider | null;\n\ninterface OpenTelemetryConfigEnabled {\n openTelemetryEnabled: boolean;\n openTelemetryExporter?: 'console' | 'honeycomb' | 'jaeger' | SpanExporter | null;\n openTelemetryMetricExporter?: 'console' | 'honeycomb' | PushMetricExporter | null;\n openTelemetryMetricExportIntervalMillis?: number;\n openTelemetrySamplerType: 'always-on' | 'always-off' | 'trace-id-ratio';\n openTelemetrySampleRate?: number;\n openTelemetrySpanProcessor?: 'batch' | 'simple' | SpanProcessor;\n honeycombApiKey?: string | null;\n honeycombDataset?: string | null;\n serviceName?: string;\n}\n\n// When we know for sure that OpenTelemetry is disabled, we won't require\n// any other attributes to be set.\ninterface OpenTelemetryConfigDisabled extends Partial<OpenTelemetryConfigEnabled> {\n openTelemetryEnabled: false;\n}\n\nexport type OpenTelemetryConfig = OpenTelemetryConfigEnabled | OpenTelemetryConfigDisabled;\n\nfunction getHoneycombMetadata(config: OpenTelemetryConfig, datasetSuffix = ''): Metadata {\n if (!config.honeycombApiKey) throw new Error('Missing Honeycomb API key');\n if (!config.honeycombDataset) throw new Error('Missing Honeycomb dataset');\n\n const metadata = new Metadata();\n\n metadata.set('x-honeycomb-team', config.honeycombApiKey);\n metadata.set('x-honeycomb-dataset', config.honeycombDataset + datasetSuffix);\n\n return metadata;\n}\n\nfunction getTraceExporter(config: OpenTelemetryConfig): SpanExporter | null {\n if (!config.openTelemetryExporter) return null;\n\n if (typeof config.openTelemetryExporter === 'object') {\n return config.openTelemetryExporter;\n }\n\n switch (config.openTelemetryExporter) {\n case 'console':\n return new ConsoleSpanExporter();\n case 'honeycomb':\n return new OTLPTraceExporter({\n url: 'grpc://api.honeycomb.io:443/',\n credentials: credentials.createSsl(),\n metadata: getHoneycombMetadata(config),\n });\n break;\n case 'jaeger':\n return new OTLPTraceExporter({\n url: process.env.OTEL_EXPORTER_JAEGER_ENDPOINT ?? 'grpc://localhost:4317/',\n });\n default:\n throw new Error(`Unknown OpenTelemetry exporter: ${config.openTelemetryExporter}`);\n }\n}\n\nfunction getMetricExporter(config: OpenTelemetryConfig): PushMetricExporter | null {\n if (!config.openTelemetryMetricExporter) return null;\n\n if (typeof config.openTelemetryMetricExporter === 'object') {\n return config.openTelemetryMetricExporter;\n }\n\n switch (config.openTelemetryMetricExporter) {\n case 'console':\n return new ConsoleMetricExporter();\n case 'honeycomb':\n return new OTLPMetricExporter({\n url: 'grpc://api.honeycomb.io:443/',\n credentials: credentials.createSsl(),\n // Honeycomb recommends using a separate dataset for metrics, so we'll\n // adopt the convention of appending '-metrics' to the dataset name.\n metadata: getHoneycombMetadata(config, '-metrics'),\n // Delta temporality means that sums, histograms, etc. will reset each\n // time data is collected. This more closely matches how we want to\n // observe our metrics than the default cumulative temporality.\n temporalityPreference: AggregationTemporality.DELTA,\n });\n default:\n throw new Error(\n `Unknown OpenTelemetry metric exporter: ${config.openTelemetryMetricExporter}`,\n );\n }\n}\n\nfunction getSpanProcessor(config: OpenTelemetryConfig): SpanProcessor | null {\n if (typeof config.openTelemetrySpanProcessor === 'object') {\n return config.openTelemetrySpanProcessor;\n }\n\n const traceExporter = getTraceExporter(config);\n if (!traceExporter) return null;\n\n switch (config.openTelemetrySpanProcessor ?? 'batch') {\n case 'batch': {\n return new FilterBatchSpanProcessor(traceExporter, filter);\n }\n case 'simple': {\n return new SimpleSpanProcessor(traceExporter);\n }\n default: {\n throw new Error(`Unknown OpenTelemetry span processor: ${config.openTelemetrySpanProcessor}`);\n }\n }\n}\n\n/**\n * Should be called once we've loaded our config; this will allow us to set up\n * the correct metadata for the Honeycomb exporter. We don't actually have that\n * information available until we've loaded our config.\n */\nexport async function init(config: OpenTelemetryConfig) {\n if (!config.openTelemetryEnabled) {\n // If not enabled, do nothing. We used to disable the instrumentations, but\n // per maintainers, that can actually be problematic. See the comments on\n // https://github.com/open-telemetry/opentelemetry-js-contrib/issues/970\n // The Express instrumentation also logs a benign error, which can be\n // confusing to users. There's a fix in progress if we want to switch back\n // to disabling instrumentations in the future:\n // https://github.com/open-telemetry/opentelemetry-js-contrib/pull/972\n return;\n }\n\n const metricExporter = getMetricExporter(config);\n const spanProcessor = getSpanProcessor(config);\n\n let sampler: Sampler;\n switch (config.openTelemetrySamplerType ?? 'always-on') {\n case 'always-on': {\n sampler = new AlwaysOnSampler();\n break;\n }\n case 'always-off': {\n sampler = new AlwaysOffSampler();\n break;\n }\n case 'trace-id-ratio': {\n sampler = new ParentBasedSampler({\n root: new TraceIdRatioBasedSampler(config.openTelemetrySampleRate),\n });\n break;\n }\n default:\n throw new Error(`Unknown OpenTelemetry sampler type: ${config.openTelemetrySamplerType}`);\n }\n\n // Much of this functionality is copied from `@opentelemetry/sdk-node`, but\n // we can't use the SDK directly because of the fact that we load our config\n // asynchronously. We need to initialize our instrumentations first; only\n // then can we actually start requiring all of our code that loads our config\n // and ultimately tells us how to configure OpenTelemetry.\n\n let resource = detectResourcesSync({\n detectors: [awsEc2Detector, processDetector, envDetector],\n });\n\n if (config.serviceName) {\n resource = resource.merge(\n new Resource({ [SemanticResourceAttributes.SERVICE_NAME]: config.serviceName }),\n );\n }\n\n // Set up tracing instrumentation.\n const nodeTracerProvider = new NodeTracerProvider({\n sampler,\n resource,\n });\n if (spanProcessor) {\n nodeTracerProvider.addSpanProcessor(spanProcessor);\n }\n nodeTracerProvider.register();\n instrumentations.forEach((i) => i.setTracerProvider(nodeTracerProvider));\n\n // Save the provider so we can shut it down later.\n tracerProvider = nodeTracerProvider;\n\n // Set up metrics instrumentation if it's enabled.\n if (metricExporter) {\n const meterProvider = new MeterProvider({\n resource,\n readers: [\n new PeriodicExportingMetricReader({\n exporter: metricExporter,\n exportIntervalMillis: config.openTelemetryMetricExportIntervalMillis ?? 30_000,\n }),\n ],\n });\n metrics.setGlobalMeterProvider(meterProvider);\n }\n}\n\n/**\n * Gracefully shuts down the OpenTelemetry instrumentation. Should be called\n * when a `SIGTERM` signal is handled.\n */\nexport async function shutdown(): Promise<void> {\n if (tracerProvider) {\n await tracerProvider.shutdown();\n tracerProvider = null;\n }\n}\n\n/**\n * Disables all OpenTelemetry instrumentations. This is useful for tests that\n * need to access the unwrapped modules.\n */\nexport function disableInstrumentations() {\n instrumentations.forEach((i) => i.disable());\n}\n"]}
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../src/init.ts"],"names":[],"mappings":"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","sourcesContent":["import { Metadata, credentials } from '@grpc/grpc-js';\nimport { metrics } from '@opentelemetry/api';\nimport { hrTimeToMilliseconds } from '@opentelemetry/core';\nimport { OTLPMetricExporter } from '@opentelemetry/exporter-metrics-otlp-grpc';\nimport { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-grpc';\nimport { OTLPTraceExporter as OTLPTraceExporterHttp } from '@opentelemetry/exporter-trace-otlp-http';\nimport { AwsInstrumentation } from '@opentelemetry/instrumentation-aws-sdk';\nimport { ConnectInstrumentation } from '@opentelemetry/instrumentation-connect';\nimport { DnsInstrumentation } from '@opentelemetry/instrumentation-dns';\nimport { ExpressLayerType, ExpressInstrumentation } from '@opentelemetry/instrumentation-express';\nimport { HttpInstrumentation } from '@opentelemetry/instrumentation-http';\nimport { IORedisInstrumentation } from '@opentelemetry/instrumentation-ioredis';\nimport { PgInstrumentation } from '@opentelemetry/instrumentation-pg';\nimport { RedisInstrumentation } from '@opentelemetry/instrumentation-redis';\nimport { awsEc2Detector } from '@opentelemetry/resource-detector-aws';\nimport {\n detectResourcesSync,\n processDetector,\n envDetector,\n Resource,\n} from '@opentelemetry/resources';\nimport {\n PeriodicExportingMetricReader,\n MeterProvider,\n PushMetricExporter,\n ConsoleMetricExporter,\n AggregationTemporality,\n} from '@opentelemetry/sdk-metrics';\nimport {\n SpanExporter,\n ReadableSpan,\n SpanProcessor,\n SimpleSpanProcessor,\n BatchSpanProcessor,\n ParentBasedSampler,\n TraceIdRatioBasedSampler,\n AlwaysOnSampler,\n AlwaysOffSampler,\n Sampler,\n ConsoleSpanExporter,\n} from '@opentelemetry/sdk-trace-base';\nimport { NodeTracerProvider } from '@opentelemetry/sdk-trace-node';\nimport { SemanticResourceAttributes } from '@opentelemetry/semantic-conventions';\n\n/**\n * Extends `BatchSpanProcessor` to give it the ability to filter out spans\n * before they're queued up to send. This enhances our sampling process so\n * that we can filter spans _after_ they've been emitted.\n */\nclass FilterBatchSpanProcessor extends BatchSpanProcessor {\n private filter: (span: ReadableSpan) => boolean;\n\n constructor(exporter: SpanExporter, filter: (span: ReadableSpan) => boolean) {\n super(exporter);\n this.filter = filter;\n }\n\n /**\n * This is invoked after a span is \"finalized\". `super.onEnd` will queue up\n * the span to be exported, but if we don't call that, we can just drop the\n * span and the parent will be none the wiser!\n */\n onEnd(span: ReadableSpan) {\n if (!this.filter(span)) return;\n\n super.onEnd(span);\n }\n}\n\n/**\n * This will be used with our {@link FilterBatchSpanProcessor} to filter out\n * events that we're not interested in. This helps reduce our event volume\n * but still gives us fine-grained control over which events we keep.\n */\nfunction filter(span: ReadableSpan) {\n if (span.name === 'pg-pool.connect') {\n // Looking at historical data, this generally happens in under a millisecond,\n // precisely because we maintain a pool of long-lived connections. The only\n // time obtaining a client should take longer than that is if we're\n // establishing a connection for the first time, which should happen only at\n // bootup, or if a connection errors out. Those are the cases we're\n // interested in, so we'll filter accordingly.\n return hrTimeToMilliseconds(span.duration) > 1;\n }\n\n // Always return true so that we default to including a span.\n return true;\n}\n\n// When adding new instrumentation here, add the corresponding packages to\n// `commonjs-preloads.ts` so that we can ensure that they're loaded via CJS\n// before anything tries to load them via CJS. This is necessary because the\n// instrumentations can't hook into the ESM loader.\nconst instrumentations = [\n new AwsInstrumentation(),\n new ConnectInstrumentation(),\n new DnsInstrumentation(),\n new ExpressInstrumentation({\n // We use a lot of middleware; it makes the traces way too noisy. If we\n // want telemetry on a particular middleware, we should instrument it\n // manually.\n ignoreLayersType: [ExpressLayerType.MIDDLEWARE],\n ignoreLayers: [\n // These don't provide useful information to us.\n 'router - /',\n 'request handler - /*',\n ],\n }),\n new HttpInstrumentation({\n ignoreIncomingPaths: [\n // socket.io requests are generally just long-polling; they don't add\n // useful information for us.\n /\\/socket.io\\//,\n // We get several of these per second; they just chew through our event quota.\n // They don't really do anything interesting anyways.\n /\\/pl\\/webhooks\\/ping/,\n ],\n }),\n new IORedisInstrumentation(),\n new PgInstrumentation(),\n new RedisInstrumentation(),\n];\n\n// Enable all instrumentations now, even though we haven't configured our\n// span processors or trace exporters yet. We'll set those up later.\ninstrumentations.forEach((i) => {\n i.enable();\n});\n\nlet tracerProvider: NodeTracerProvider | null;\n\ninterface OpenTelemetryConfigEnabled {\n openTelemetryEnabled: boolean;\n openTelemetryExporter?: 'console' | 'honeycomb' | 'jaeger' | SpanExporter | null;\n openTelemetryMetricExporter?: 'console' | 'honeycomb' | PushMetricExporter | null;\n openTelemetryMetricExportIntervalMillis?: number;\n openTelemetrySamplerType: 'always-on' | 'always-off' | 'trace-id-ratio';\n openTelemetrySampleRate?: number;\n openTelemetrySpanProcessor?: 'batch' | 'simple' | SpanProcessor;\n honeycombApiKey?: string | null;\n honeycombDataset?: string | null;\n serviceName?: string;\n}\n\n// When we know for sure that OpenTelemetry is disabled, we won't require\n// any other attributes to be set.\ninterface OpenTelemetryConfigDisabled extends Partial<OpenTelemetryConfigEnabled> {\n openTelemetryEnabled: false;\n}\n\nexport type OpenTelemetryConfig = OpenTelemetryConfigEnabled | OpenTelemetryConfigDisabled;\n\nfunction getHoneycombMetadata(config: OpenTelemetryConfig, datasetSuffix = ''): Metadata {\n if (!config.honeycombApiKey) throw new Error('Missing Honeycomb API key');\n if (!config.honeycombDataset) throw new Error('Missing Honeycomb dataset');\n\n const metadata = new Metadata();\n\n metadata.set('x-honeycomb-team', config.honeycombApiKey);\n metadata.set('x-honeycomb-dataset', config.honeycombDataset + datasetSuffix);\n\n return metadata;\n}\n\nfunction getTraceExporter(config: OpenTelemetryConfig): SpanExporter | null {\n if (!config.openTelemetryExporter) return null;\n\n if (typeof config.openTelemetryExporter === 'object') {\n return config.openTelemetryExporter;\n }\n\n switch (config.openTelemetryExporter) {\n case 'console':\n return new ConsoleSpanExporter();\n case 'honeycomb':\n return new OTLPTraceExporter({\n url: 'grpc://api.honeycomb.io:443/',\n credentials: credentials.createSsl(),\n metadata: getHoneycombMetadata(config),\n });\n break;\n case 'jaeger':\n return new OTLPTraceExporterHttp();\n default:\n throw new Error(`Unknown OpenTelemetry exporter: ${config.openTelemetryExporter}`);\n }\n}\n\nfunction getMetricExporter(config: OpenTelemetryConfig): PushMetricExporter | null {\n if (!config.openTelemetryMetricExporter) return null;\n\n if (typeof config.openTelemetryMetricExporter === 'object') {\n return config.openTelemetryMetricExporter;\n }\n\n switch (config.openTelemetryMetricExporter) {\n case 'console':\n return new ConsoleMetricExporter();\n case 'honeycomb':\n return new OTLPMetricExporter({\n url: 'grpc://api.honeycomb.io:443/',\n credentials: credentials.createSsl(),\n // Honeycomb recommends using a separate dataset for metrics, so we'll\n // adopt the convention of appending '-metrics' to the dataset name.\n metadata: getHoneycombMetadata(config, '-metrics'),\n // Delta temporality means that sums, histograms, etc. will reset each\n // time data is collected. This more closely matches how we want to\n // observe our metrics than the default cumulative temporality.\n temporalityPreference: AggregationTemporality.DELTA,\n });\n default:\n throw new Error(\n `Unknown OpenTelemetry metric exporter: ${config.openTelemetryMetricExporter}`,\n );\n }\n}\n\nfunction getSpanProcessor(config: OpenTelemetryConfig): SpanProcessor | null {\n if (typeof config.openTelemetrySpanProcessor === 'object') {\n return config.openTelemetrySpanProcessor;\n }\n\n const traceExporter = getTraceExporter(config);\n if (!traceExporter) return null;\n\n switch (config.openTelemetrySpanProcessor ?? 'batch') {\n case 'batch': {\n return new FilterBatchSpanProcessor(traceExporter, filter);\n }\n case 'simple': {\n return new SimpleSpanProcessor(traceExporter);\n }\n default: {\n throw new Error(`Unknown OpenTelemetry span processor: ${config.openTelemetrySpanProcessor}`);\n }\n }\n}\n\n/**\n * Should be called once we've loaded our config; this will allow us to set up\n * the correct metadata for the Honeycomb exporter. We don't actually have that\n * information available until we've loaded our config.\n */\nexport async function init(config: OpenTelemetryConfig) {\n if (!config.openTelemetryEnabled) {\n // If not enabled, do nothing. We used to disable the instrumentations, but\n // per maintainers, that can actually be problematic. See the comments on\n // https://github.com/open-telemetry/opentelemetry-js-contrib/issues/970\n // The Express instrumentation also logs a benign error, which can be\n // confusing to users. There's a fix in progress if we want to switch back\n // to disabling instrumentations in the future:\n // https://github.com/open-telemetry/opentelemetry-js-contrib/pull/972\n return;\n }\n\n const metricExporter = getMetricExporter(config);\n const spanProcessor = getSpanProcessor(config);\n\n let sampler: Sampler;\n switch (config.openTelemetrySamplerType ?? 'always-on') {\n case 'always-on': {\n sampler = new AlwaysOnSampler();\n break;\n }\n case 'always-off': {\n sampler = new AlwaysOffSampler();\n break;\n }\n case 'trace-id-ratio': {\n sampler = new ParentBasedSampler({\n root: new TraceIdRatioBasedSampler(config.openTelemetrySampleRate),\n });\n break;\n }\n default:\n throw new Error(`Unknown OpenTelemetry sampler type: ${config.openTelemetrySamplerType}`);\n }\n\n // Much of this functionality is copied from `@opentelemetry/sdk-node`, but\n // we can't use the SDK directly because of the fact that we load our config\n // asynchronously. We need to initialize our instrumentations first; only\n // then can we actually start requiring all of our code that loads our config\n // and ultimately tells us how to configure OpenTelemetry.\n\n let resource = detectResourcesSync({\n detectors: [awsEc2Detector, processDetector, envDetector],\n });\n\n if (config.serviceName) {\n resource = resource.merge(\n new Resource({ [SemanticResourceAttributes.SERVICE_NAME]: config.serviceName }),\n );\n }\n\n // Set up tracing instrumentation.\n const nodeTracerProvider = new NodeTracerProvider({\n sampler,\n resource,\n });\n if (spanProcessor) {\n nodeTracerProvider.addSpanProcessor(spanProcessor);\n }\n nodeTracerProvider.register();\n instrumentations.forEach((i) => i.setTracerProvider(nodeTracerProvider));\n\n // Save the provider so we can shut it down later.\n tracerProvider = nodeTracerProvider;\n\n // Set up metrics instrumentation if it's enabled.\n if (metricExporter) {\n const meterProvider = new MeterProvider({\n resource,\n readers: [\n new PeriodicExportingMetricReader({\n exporter: metricExporter,\n exportIntervalMillis: config.openTelemetryMetricExportIntervalMillis ?? 30_000,\n }),\n ],\n });\n metrics.setGlobalMeterProvider(meterProvider);\n }\n}\n\n/**\n * Gracefully shuts down the OpenTelemetry instrumentation. Should be called\n * when a `SIGTERM` signal is handled.\n */\nexport async function shutdown(): Promise<void> {\n if (tracerProvider) {\n await tracerProvider.shutdown();\n tracerProvider = null;\n }\n}\n\n/**\n * Disables all OpenTelemetry instrumentations. This is useful for tests that\n * need to access the unwrapped modules.\n */\nexport function disableInstrumentations() {\n instrumentations.forEach((i) => i.disable());\n}\n"]}
|
package/dist/metrics.d.ts
CHANGED
|
@@ -6,7 +6,7 @@ export declare function getObservableCounter(meter: Meter, name: string, options
|
|
|
6
6
|
export declare function getObservableUpDownCounter(meter: Meter, name: string, options?: MetricOptions): ObservableUpDownCounter<import("@opentelemetry/api").Attributes>;
|
|
7
7
|
export declare function getObservableGauge(meter: Meter, name: string, options?: MetricOptions): ObservableGauge<import("@opentelemetry/api").Attributes>;
|
|
8
8
|
export declare function instrumentedWithMetrics<T>(meter: Meter, name: string, fn: () => Promise<T> | T): Promise<T>;
|
|
9
|
-
export interface
|
|
9
|
+
export interface CreateObservableValueGaugesOptions extends MetricOptions {
|
|
10
10
|
interval: number;
|
|
11
11
|
}
|
|
12
12
|
/**
|
|
@@ -20,7 +20,7 @@ export interface createObservableValueGaugesOptions extends MetricOptions {
|
|
|
20
20
|
* - `${name}.max`
|
|
21
21
|
* - `${name}.avg`
|
|
22
22
|
*/
|
|
23
|
-
export declare function createObservableValueGauges(meter: Meter, name: string, options:
|
|
23
|
+
export declare function createObservableValueGauges(meter: Meter, name: string, options: CreateObservableValueGaugesOptions, observe: () => number): {
|
|
24
24
|
minGauge: ObservableGauge<import("@opentelemetry/api").Attributes>;
|
|
25
25
|
maxGauge: ObservableGauge<import("@opentelemetry/api").Attributes>;
|
|
26
26
|
averageGauge: ObservableGauge<import("@opentelemetry/api").Attributes>;
|
package/dist/metrics.js
CHANGED
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.createObservableValueGauges = exports.instrumentedWithMetrics = exports.getObservableGauge = exports.getObservableUpDownCounter = exports.getObservableCounter = exports.getUpDownCounter = exports.getCounter = exports.getHistogram = void 0;
|
|
4
|
-
const api_1 = require("@opentelemetry/api");
|
|
1
|
+
import { ValueType, } from '@opentelemetry/api';
|
|
5
2
|
const histogramCache = new WeakMap();
|
|
6
3
|
const counterCache = new WeakMap();
|
|
7
4
|
const upDownCounterCache = new WeakMap();
|
|
@@ -21,35 +18,29 @@ function getCachedMetric(cache, meter, name, create) {
|
|
|
21
18
|
}
|
|
22
19
|
return metric;
|
|
23
20
|
}
|
|
24
|
-
function getHistogram(meter, name, options) {
|
|
21
|
+
export function getHistogram(meter, name, options) {
|
|
25
22
|
return getCachedMetric(histogramCache, meter, name, () => meter.createHistogram(name, options));
|
|
26
23
|
}
|
|
27
|
-
|
|
28
|
-
function getCounter(meter, name, options) {
|
|
24
|
+
export function getCounter(meter, name, options) {
|
|
29
25
|
return getCachedMetric(counterCache, meter, name, () => meter.createCounter(name, options));
|
|
30
26
|
}
|
|
31
|
-
|
|
32
|
-
function getUpDownCounter(meter, name, options) {
|
|
27
|
+
export function getUpDownCounter(meter, name, options) {
|
|
33
28
|
return getCachedMetric(upDownCounterCache, meter, name, () => meter.createUpDownCounter(name, options));
|
|
34
29
|
}
|
|
35
|
-
|
|
36
|
-
function getObservableCounter(meter, name, options) {
|
|
30
|
+
export function getObservableCounter(meter, name, options) {
|
|
37
31
|
return getCachedMetric(observableCounterCache, meter, name, () => meter.createObservableCounter(name, options));
|
|
38
32
|
}
|
|
39
|
-
|
|
40
|
-
function getObservableUpDownCounter(meter, name, options) {
|
|
33
|
+
export function getObservableUpDownCounter(meter, name, options) {
|
|
41
34
|
return getCachedMetric(observableUpDownCounterCache, meter, name, () => meter.createObservableUpDownCounter(name, options));
|
|
42
35
|
}
|
|
43
|
-
|
|
44
|
-
function getObservableGauge(meter, name, options) {
|
|
36
|
+
export function getObservableGauge(meter, name, options) {
|
|
45
37
|
return getCachedMetric(observableGaugeCache, meter, name, () => meter.createObservableGauge(name, options));
|
|
46
38
|
}
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
const error = getCounter(meter, `${name}.error`, { valueType: api_1.ValueType.INT });
|
|
39
|
+
export async function instrumentedWithMetrics(meter, name, fn) {
|
|
40
|
+
const error = getCounter(meter, `${name}.error`, { valueType: ValueType.INT });
|
|
50
41
|
const histogram = getHistogram(meter, `${name}.duration`, {
|
|
51
42
|
unit: 'milliseconds',
|
|
52
|
-
valueType:
|
|
43
|
+
valueType: ValueType.DOUBLE,
|
|
53
44
|
});
|
|
54
45
|
const start = performance.now();
|
|
55
46
|
try {
|
|
@@ -63,7 +54,6 @@ async function instrumentedWithMetrics(meter, name, fn) {
|
|
|
63
54
|
histogram.record(performance.now() - start);
|
|
64
55
|
}
|
|
65
56
|
}
|
|
66
|
-
exports.instrumentedWithMetrics = instrumentedWithMetrics;
|
|
67
57
|
/**
|
|
68
58
|
* Creates a set of gauges that track the min, max, and average of a value over
|
|
69
59
|
* time. The value is observed on a regular interval.
|
|
@@ -75,7 +65,7 @@ exports.instrumentedWithMetrics = instrumentedWithMetrics;
|
|
|
75
65
|
* - `${name}.max`
|
|
76
66
|
* - `${name}.avg`
|
|
77
67
|
*/
|
|
78
|
-
function createObservableValueGauges(meter, name, options, observe) {
|
|
68
|
+
export function createObservableValueGauges(meter, name, options, observe) {
|
|
79
69
|
const { interval, ...metricOptions } = options;
|
|
80
70
|
let min = 0;
|
|
81
71
|
let max = 0;
|
|
@@ -99,7 +89,7 @@ function createObservableValueGauges(meter, name, options, observe) {
|
|
|
99
89
|
const averageGauge = getObservableGauge(meter, `${name}.avg`, {
|
|
100
90
|
...metricOptions,
|
|
101
91
|
// Average is always a double, even if the observed value is an int.
|
|
102
|
-
valueType:
|
|
92
|
+
valueType: ValueType.DOUBLE,
|
|
103
93
|
});
|
|
104
94
|
minGauge.addCallback((observableResult) => {
|
|
105
95
|
observableResult.observe(min);
|
|
@@ -117,5 +107,4 @@ function createObservableValueGauges(meter, name, options, observe) {
|
|
|
117
107
|
});
|
|
118
108
|
return { minGauge, maxGauge, averageGauge, stop: () => clearInterval(intervalId) };
|
|
119
109
|
}
|
|
120
|
-
exports.createObservableValueGauges = createObservableValueGauges;
|
|
121
110
|
//# sourceMappingURL=metrics.js.map
|