@ryanzeng/nest-observe 0.1.1 → 0.1.3
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 +27 -1
- package/dist/index.d.mts +44 -17
- package/dist/index.d.ts +44 -17
- package/dist/index.js +353 -41
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +359 -43
- package/dist/index.mjs.map +1 -1
- package/dist/register.js +312 -43
- package/dist/register.js.map +1 -1
- package/dist/register.mjs +312 -43
- package/dist/register.mjs.map +1 -1
- package/package.json +19 -9
package/dist/register.mjs
CHANGED
|
@@ -91,15 +91,14 @@ function resolveObserveConfig(options = {}, env = process.env) {
|
|
|
91
91
|
allowedHeaders,
|
|
92
92
|
exportTimeoutMillis: positiveInteger(options.exportTimeoutMillis ?? env.OTEL_EXPORTER_OTLP_TIMEOUT, 1e4),
|
|
93
93
|
metricExportIntervalMillis: positiveInteger(options.metricExportIntervalMillis ?? env.OTEL_METRIC_EXPORT_INTERVAL, 6e4),
|
|
94
|
-
resourceAttributes
|
|
94
|
+
resourceAttributes,
|
|
95
|
+
diagnosticLogging: booleanValue(options.diagnosticLogging, true),
|
|
96
|
+
failFast: booleanValue(options.failFast, false)
|
|
95
97
|
};
|
|
96
98
|
if (options.exporters) result.exporters = options.exporters;
|
|
97
99
|
return result;
|
|
98
100
|
}
|
|
99
101
|
|
|
100
|
-
// src/exceptions/process-exception-capture.ts
|
|
101
|
-
import { trace, SpanStatusCode } from "@opentelemetry/api";
|
|
102
|
-
|
|
103
102
|
// src/security/redaction.ts
|
|
104
103
|
var REDACTED = "[REDACTED]";
|
|
105
104
|
var SENSITIVE_KEY = /(?:authorization|proxy-authorization|cookie|set-cookie|pass(?:word|wd)?|secret|token|api[-_]?key|phone|mobile)/i;
|
|
@@ -133,7 +132,115 @@ function redact(value) {
|
|
|
133
132
|
return visit(value, /* @__PURE__ */ new WeakSet());
|
|
134
133
|
}
|
|
135
134
|
|
|
135
|
+
// src/diagnostics.ts
|
|
136
|
+
function toError(value) {
|
|
137
|
+
if (value instanceof Error) return value;
|
|
138
|
+
if (typeof value === "string") return new Error(value);
|
|
139
|
+
try {
|
|
140
|
+
return new Error(JSON.stringify(value));
|
|
141
|
+
} catch {
|
|
142
|
+
return new Error(String(value));
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
function sanitizeError(error) {
|
|
146
|
+
const sanitized = new Error(redactText(error.message));
|
|
147
|
+
sanitized.name = error.name;
|
|
148
|
+
if (error.stack) sanitized.stack = redactText(error.stack);
|
|
149
|
+
return sanitized;
|
|
150
|
+
}
|
|
151
|
+
var ObserveDiagnostics = class {
|
|
152
|
+
constructor(logging, onError) {
|
|
153
|
+
this.logging = logging;
|
|
154
|
+
this.onError = onError;
|
|
155
|
+
}
|
|
156
|
+
logging;
|
|
157
|
+
onError;
|
|
158
|
+
currentStatus = "starting";
|
|
159
|
+
currentError;
|
|
160
|
+
failedSignals = /* @__PURE__ */ new Set();
|
|
161
|
+
reported = /* @__PURE__ */ new Set();
|
|
162
|
+
get status() {
|
|
163
|
+
return this.currentStatus;
|
|
164
|
+
}
|
|
165
|
+
get lastError() {
|
|
166
|
+
return this.currentError;
|
|
167
|
+
}
|
|
168
|
+
activate() {
|
|
169
|
+
if (this.currentStatus === "starting") this.currentStatus = "active";
|
|
170
|
+
}
|
|
171
|
+
inactive() {
|
|
172
|
+
this.currentStatus = "inactive";
|
|
173
|
+
}
|
|
174
|
+
stop() {
|
|
175
|
+
this.currentStatus = "stopped";
|
|
176
|
+
}
|
|
177
|
+
success(signal) {
|
|
178
|
+
this.failedSignals.delete(signal);
|
|
179
|
+
for (const fingerprint of this.reported) {
|
|
180
|
+
if (fingerprint.startsWith(`${signal}\0`)) this.reported.delete(fingerprint);
|
|
181
|
+
}
|
|
182
|
+
if (this.currentStatus === "degraded" && this.failedSignals.size === 0) {
|
|
183
|
+
this.currentStatus = "active";
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
failure(signal, stage, value) {
|
|
187
|
+
const error = sanitizeError(toError(value));
|
|
188
|
+
const event = { signal, stage, error, timestamp: Date.now() };
|
|
189
|
+
this.currentError = event;
|
|
190
|
+
this.failedSignals.add(signal);
|
|
191
|
+
if (this.currentStatus !== "inactive" && this.currentStatus !== "stopped") {
|
|
192
|
+
this.currentStatus = "degraded";
|
|
193
|
+
}
|
|
194
|
+
const fingerprint = `${signal}\0${stage}\0${error.name}\0${error.message}`;
|
|
195
|
+
if (this.reported.has(fingerprint)) return;
|
|
196
|
+
this.reported.add(fingerprint);
|
|
197
|
+
try {
|
|
198
|
+
this.onError?.(event);
|
|
199
|
+
} catch {
|
|
200
|
+
}
|
|
201
|
+
if (!this.logging) return;
|
|
202
|
+
try {
|
|
203
|
+
process.stderr.write(
|
|
204
|
+
`[nest-observe] ${signal} ${stage} failed: ${redactText(error.message)}
|
|
205
|
+
`
|
|
206
|
+
);
|
|
207
|
+
} catch {
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
};
|
|
211
|
+
function withExporterDiagnostics(exporter, signal, diagnostics) {
|
|
212
|
+
const delegate = exporter;
|
|
213
|
+
return new Proxy(exporter, {
|
|
214
|
+
get(target, property) {
|
|
215
|
+
if (property === "export") {
|
|
216
|
+
return (items, callback) => {
|
|
217
|
+
try {
|
|
218
|
+
delegate.export.call(target, items, (result) => {
|
|
219
|
+
if (result.code === 0) {
|
|
220
|
+
diagnostics.success(signal);
|
|
221
|
+
} else {
|
|
222
|
+
diagnostics.failure(
|
|
223
|
+
signal,
|
|
224
|
+
"export",
|
|
225
|
+
result.error ?? new Error(`${signal} export failed`)
|
|
226
|
+
);
|
|
227
|
+
}
|
|
228
|
+
callback(result);
|
|
229
|
+
});
|
|
230
|
+
} catch (error) {
|
|
231
|
+
diagnostics.failure(signal, "export", error);
|
|
232
|
+
throw error;
|
|
233
|
+
}
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
const value = Reflect.get(target, property, target);
|
|
237
|
+
return typeof value === "function" ? value.bind(target) : value;
|
|
238
|
+
}
|
|
239
|
+
});
|
|
240
|
+
}
|
|
241
|
+
|
|
136
242
|
// src/exceptions/process-exception-capture.ts
|
|
243
|
+
import { trace, SpanStatusCode } from "@opentelemetry/api";
|
|
137
244
|
function asError(value) {
|
|
138
245
|
return value instanceof Error ? value : new Error(String(value));
|
|
139
246
|
}
|
|
@@ -289,7 +396,7 @@ var NestMethodInstrumenter = class {
|
|
|
289
396
|
if (!descriptor || typeof original !== "function" || isTraceIgnored(original, type) || isTraceDecorated(original)) continue;
|
|
290
397
|
const existing = Reflect.get(target, methodName);
|
|
291
398
|
if (typeof existing === "function" && existing !== original && isTraceDecorated(existing)) continue;
|
|
292
|
-
const name = componentName
|
|
399
|
+
const name = typeof componentName === "symbol" ? String(componentName) : typeof componentName === "string" && componentName ? componentName : type.name || "Anonymous";
|
|
293
400
|
const attributes = {
|
|
294
401
|
[`nestjs.${kind}`]: name,
|
|
295
402
|
"nestjs.method": methodName
|
|
@@ -342,7 +449,7 @@ var CompatibleNestInstrumentation = class extends NestInstrumentation {
|
|
|
342
449
|
const instance = await original.apply(this, args);
|
|
343
450
|
try {
|
|
344
451
|
const wrapper = args[1];
|
|
345
|
-
if (!instance || typeof instance !== "object" || !wrapper?.metatype) return instance;
|
|
452
|
+
if (!instance || typeof instance !== "object" || !wrapper?.metatype || wrapper.inject !== void 0) return instance;
|
|
346
453
|
if (["InternalCoreModule", "ObserveModule", "DiscoveryModule"].includes(wrapper.host?.name ?? "")) {
|
|
347
454
|
return instance;
|
|
348
455
|
}
|
|
@@ -386,7 +493,8 @@ var SEVERITY = {
|
|
|
386
493
|
fatal: "FATAL"
|
|
387
494
|
};
|
|
388
495
|
function bodyValue(message) {
|
|
389
|
-
if (message instanceof Error)
|
|
496
|
+
if (message instanceof Error)
|
|
497
|
+
return redactText(message.stack ?? `${message.name}: ${message.message}`);
|
|
390
498
|
return redact(message);
|
|
391
499
|
}
|
|
392
500
|
var NestLoggerInstrumentation = class {
|
|
@@ -431,7 +539,8 @@ var NestLoggerInstrumentation = class {
|
|
|
431
539
|
disable() {
|
|
432
540
|
if (!this.enabled) return;
|
|
433
541
|
const prototype = ConsoleLogger.prototype;
|
|
434
|
-
for (const [method, original] of this.originals)
|
|
542
|
+
for (const [method, original] of this.originals)
|
|
543
|
+
prototype[method] = original;
|
|
435
544
|
this.originals.clear();
|
|
436
545
|
this.enabled = false;
|
|
437
546
|
}
|
|
@@ -494,9 +603,14 @@ var HttpRequestMetrics = class {
|
|
|
494
603
|
errorCount;
|
|
495
604
|
startedAt = /* @__PURE__ */ new WeakMap();
|
|
496
605
|
start(request) {
|
|
606
|
+
if (this.startedAt.has(request)) return false;
|
|
497
607
|
this.startedAt.set(request, process.hrtime.bigint());
|
|
608
|
+
return true;
|
|
498
609
|
}
|
|
499
610
|
record(request, response) {
|
|
611
|
+
const started = this.startedAt.get(request);
|
|
612
|
+
if (started === void 0) return false;
|
|
613
|
+
this.startedAt.delete(request);
|
|
500
614
|
const statusCode = Number.isFinite(response.statusCode) ? response.statusCode : 0;
|
|
501
615
|
const attributes = {
|
|
502
616
|
"service.name": this.serviceName,
|
|
@@ -505,12 +619,9 @@ var HttpRequestMetrics = class {
|
|
|
505
619
|
"http.response.status_code": statusCode
|
|
506
620
|
};
|
|
507
621
|
this.requestCount.add(1, attributes);
|
|
508
|
-
|
|
509
|
-
if (started !== void 0) {
|
|
510
|
-
this.requestDuration.record(Number(process.hrtime.bigint() - started) / 1e9, attributes);
|
|
511
|
-
this.startedAt.delete(request);
|
|
512
|
-
}
|
|
622
|
+
this.requestDuration.record(Number(process.hrtime.bigint() - started) / 1e9, attributes);
|
|
513
623
|
if (statusCode >= 500) this.errorCount.add(1, attributes);
|
|
624
|
+
return true;
|
|
514
625
|
}
|
|
515
626
|
};
|
|
516
627
|
|
|
@@ -601,8 +712,118 @@ import {
|
|
|
601
712
|
resourceFromAttributes
|
|
602
713
|
} from "@opentelemetry/resources";
|
|
603
714
|
import { hostname } from "os";
|
|
604
|
-
|
|
605
|
-
|
|
715
|
+
|
|
716
|
+
// package.json
|
|
717
|
+
var package_default = {
|
|
718
|
+
name: "@ryanzeng/nest-observe",
|
|
719
|
+
version: "0.1.3",
|
|
720
|
+
description: "Zero-config, vendor-neutral OpenTelemetry observability for NestJS",
|
|
721
|
+
keywords: [
|
|
722
|
+
"nestjs",
|
|
723
|
+
"opentelemetry",
|
|
724
|
+
"observability",
|
|
725
|
+
"otlp",
|
|
726
|
+
"tracing",
|
|
727
|
+
"metrics",
|
|
728
|
+
"logging"
|
|
729
|
+
],
|
|
730
|
+
license: "MIT",
|
|
731
|
+
homepage: "https://github.com/ryanzen9/nest-observe#readme",
|
|
732
|
+
bugs: {
|
|
733
|
+
url: "https://github.com/ryanzen9/nest-observe/issues"
|
|
734
|
+
},
|
|
735
|
+
repository: {
|
|
736
|
+
type: "git",
|
|
737
|
+
url: "git+https://github.com/ryanzen9/nest-observe.git"
|
|
738
|
+
},
|
|
739
|
+
packageManager: "pnpm@10.13.1",
|
|
740
|
+
sideEffects: [
|
|
741
|
+
"./dist/register.js",
|
|
742
|
+
"./dist/register.mjs"
|
|
743
|
+
],
|
|
744
|
+
main: "./dist/index.js",
|
|
745
|
+
module: "./dist/index.mjs",
|
|
746
|
+
types: "./dist/index.d.ts",
|
|
747
|
+
exports: {
|
|
748
|
+
".": {
|
|
749
|
+
import: {
|
|
750
|
+
types: "./dist/index.d.mts",
|
|
751
|
+
default: "./dist/index.mjs"
|
|
752
|
+
},
|
|
753
|
+
require: {
|
|
754
|
+
types: "./dist/index.d.ts",
|
|
755
|
+
default: "./dist/index.js"
|
|
756
|
+
}
|
|
757
|
+
},
|
|
758
|
+
"./register": {
|
|
759
|
+
import: {
|
|
760
|
+
types: "./dist/register.d.mts",
|
|
761
|
+
default: "./dist/register.mjs"
|
|
762
|
+
},
|
|
763
|
+
require: {
|
|
764
|
+
types: "./dist/register.d.ts",
|
|
765
|
+
default: "./dist/register.js"
|
|
766
|
+
}
|
|
767
|
+
}
|
|
768
|
+
},
|
|
769
|
+
files: [
|
|
770
|
+
"dist",
|
|
771
|
+
"README.md",
|
|
772
|
+
"CHANGELOG.md",
|
|
773
|
+
"LICENSE"
|
|
774
|
+
],
|
|
775
|
+
scripts: {
|
|
776
|
+
build: "tsup",
|
|
777
|
+
test: "vitest run",
|
|
778
|
+
"test:watch": "vitest",
|
|
779
|
+
typecheck: "tsc --noEmit",
|
|
780
|
+
check: "pnpm typecheck && pnpm test && pnpm build"
|
|
781
|
+
},
|
|
782
|
+
engines: {
|
|
783
|
+
node: ">=20"
|
|
784
|
+
},
|
|
785
|
+
peerDependencies: {
|
|
786
|
+
"@nestjs/common": ">=10 <13",
|
|
787
|
+
"@nestjs/core": ">=10 <13",
|
|
788
|
+
"reflect-metadata": ">=0.1.12 <1",
|
|
789
|
+
rxjs: "^7.1.0"
|
|
790
|
+
},
|
|
791
|
+
dependencies: {
|
|
792
|
+
"@opentelemetry/api": "^1.9.0",
|
|
793
|
+
"@opentelemetry/api-logs": "^0.221.0",
|
|
794
|
+
"@opentelemetry/exporter-logs-otlp-proto": "^0.221.0",
|
|
795
|
+
"@opentelemetry/exporter-metrics-otlp-proto": "^0.221.0",
|
|
796
|
+
"@opentelemetry/exporter-trace-otlp-proto": "^0.221.0",
|
|
797
|
+
"@opentelemetry/instrumentation": "^0.221.0",
|
|
798
|
+
"@opentelemetry/instrumentation-http": "^0.221.0",
|
|
799
|
+
"@opentelemetry/instrumentation-nestjs-core": "^0.67.0",
|
|
800
|
+
"@opentelemetry/resources": "^2.10.0",
|
|
801
|
+
"@opentelemetry/sdk-logs": "^0.221.0",
|
|
802
|
+
"@opentelemetry/sdk-metrics": "^2.10.0",
|
|
803
|
+
"@opentelemetry/sdk-trace-base": "^2.10.0",
|
|
804
|
+
"@opentelemetry/sdk-trace-node": "^2.10.0",
|
|
805
|
+
"@prisma/instrumentation": "^7.10.0"
|
|
806
|
+
},
|
|
807
|
+
devDependencies: {
|
|
808
|
+
"@nestjs/common": "^12.0.1",
|
|
809
|
+
"@nestjs/core": "^12.0.1",
|
|
810
|
+
"@nestjs/testing": "^12.0.1",
|
|
811
|
+
"@opentelemetry/sdk-trace-base": "^2.10.0",
|
|
812
|
+
"@types/node": "^24.0.0",
|
|
813
|
+
"reflect-metadata": "^0.2.2",
|
|
814
|
+
rxjs: "^7.8.2",
|
|
815
|
+
tsup: "^8.5.1",
|
|
816
|
+
typescript: "^5.9.3",
|
|
817
|
+
vitest: "^4.1.11"
|
|
818
|
+
},
|
|
819
|
+
publishConfig: {
|
|
820
|
+
access: "public"
|
|
821
|
+
}
|
|
822
|
+
};
|
|
823
|
+
|
|
824
|
+
// src/resource.ts
|
|
825
|
+
var SDK_NAME = package_default.name;
|
|
826
|
+
var SDK_VERSION = package_default.version;
|
|
606
827
|
function createObserveResource(config) {
|
|
607
828
|
return defaultResource().merge(
|
|
608
829
|
resourceFromAttributes({
|
|
@@ -659,14 +880,23 @@ var SpanRedactionProcessor = class {
|
|
|
659
880
|
|
|
660
881
|
// src/sdk.ts
|
|
661
882
|
var InactiveObserveHandle = class {
|
|
662
|
-
constructor(config) {
|
|
883
|
+
constructor(config, diagnostics) {
|
|
663
884
|
this.config = config;
|
|
885
|
+
this.diagnostics = diagnostics;
|
|
664
886
|
}
|
|
665
887
|
config;
|
|
888
|
+
diagnostics;
|
|
666
889
|
started = false;
|
|
667
890
|
tracerProvider = void 0;
|
|
668
891
|
meterProvider = void 0;
|
|
669
892
|
loggerProvider = void 0;
|
|
893
|
+
httpRequestMetrics = void 0;
|
|
894
|
+
get status() {
|
|
895
|
+
return this.diagnostics.status;
|
|
896
|
+
}
|
|
897
|
+
get lastError() {
|
|
898
|
+
return this.diagnostics.lastError;
|
|
899
|
+
}
|
|
670
900
|
forceFlush() {
|
|
671
901
|
return Promise.resolve();
|
|
672
902
|
}
|
|
@@ -675,52 +905,73 @@ var InactiveObserveHandle = class {
|
|
|
675
905
|
}
|
|
676
906
|
};
|
|
677
907
|
var ActiveObserveHandle = class {
|
|
678
|
-
constructor(config, tracerProvider, meterProvider, loggerProvider, runtimeMetrics, loggerInstrumentation, exceptionCapture, instrumentations) {
|
|
908
|
+
constructor(config, tracerProvider, meterProvider, loggerProvider, httpRequestMetrics, runtimeMetrics, loggerInstrumentation, exceptionCapture, instrumentations, diagnostics) {
|
|
679
909
|
this.config = config;
|
|
680
910
|
this.tracerProvider = tracerProvider;
|
|
681
911
|
this.meterProvider = meterProvider;
|
|
682
912
|
this.loggerProvider = loggerProvider;
|
|
913
|
+
this.httpRequestMetrics = httpRequestMetrics;
|
|
683
914
|
this.runtimeMetrics = runtimeMetrics;
|
|
684
915
|
this.loggerInstrumentation = loggerInstrumentation;
|
|
685
916
|
this.exceptionCapture = exceptionCapture;
|
|
686
917
|
this.instrumentations = instrumentations;
|
|
918
|
+
this.diagnostics = diagnostics;
|
|
687
919
|
}
|
|
688
920
|
config;
|
|
689
921
|
tracerProvider;
|
|
690
922
|
meterProvider;
|
|
691
923
|
loggerProvider;
|
|
924
|
+
httpRequestMetrics;
|
|
692
925
|
runtimeMetrics;
|
|
693
926
|
loggerInstrumentation;
|
|
694
927
|
exceptionCapture;
|
|
695
928
|
instrumentations;
|
|
929
|
+
diagnostics;
|
|
696
930
|
started = true;
|
|
697
931
|
stopped = false;
|
|
932
|
+
get status() {
|
|
933
|
+
return this.diagnostics.status;
|
|
934
|
+
}
|
|
935
|
+
get lastError() {
|
|
936
|
+
return this.diagnostics.lastError;
|
|
937
|
+
}
|
|
698
938
|
async forceFlush() {
|
|
699
|
-
await
|
|
700
|
-
this.tracerProvider
|
|
701
|
-
this.meterProvider
|
|
702
|
-
this.loggerProvider
|
|
703
|
-
]
|
|
939
|
+
await this.runSafely("forceFlush", [
|
|
940
|
+
...this.config.traces && this.tracerProvider ? [["traces", () => this.tracerProvider.forceFlush()]] : [],
|
|
941
|
+
...this.config.metrics && this.meterProvider ? [["metrics", () => this.meterProvider.forceFlush()]] : [],
|
|
942
|
+
...this.config.logs && this.loggerProvider ? [["logs", () => this.loggerProvider.forceFlush({ timeoutMillis: this.config.exportTimeoutMillis })]] : []
|
|
943
|
+
]);
|
|
704
944
|
}
|
|
705
945
|
async shutdown() {
|
|
706
946
|
if (this.stopped) return;
|
|
707
947
|
this.stopped = true;
|
|
708
948
|
this.loggerInstrumentation?.disable();
|
|
709
|
-
this.runtimeMetrics?.stop();
|
|
710
949
|
this.exceptionCapture.stop();
|
|
711
950
|
for (const instrumentation of this.instrumentations) {
|
|
712
951
|
try {
|
|
713
952
|
instrumentation.disable();
|
|
714
|
-
} catch {
|
|
953
|
+
} catch (error) {
|
|
954
|
+
this.diagnostics.failure("sdk", "shutdown", error);
|
|
715
955
|
}
|
|
716
956
|
}
|
|
717
957
|
await this.forceFlush();
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
this.
|
|
721
|
-
this.
|
|
722
|
-
|
|
958
|
+
this.runtimeMetrics?.stop();
|
|
959
|
+
await this.runSafely("shutdown", [
|
|
960
|
+
...this.tracerProvider ? [["traces", () => this.tracerProvider.shutdown()]] : [],
|
|
961
|
+
...this.meterProvider ? [["metrics", () => this.meterProvider.shutdown()]] : [],
|
|
962
|
+
...this.loggerProvider ? [["logs", () => this.loggerProvider.shutdown()]] : []
|
|
963
|
+
]);
|
|
723
964
|
if (activeRuntime === this) activeRuntime = void 0;
|
|
965
|
+
this.diagnostics.stop();
|
|
966
|
+
}
|
|
967
|
+
async runSafely(stage, operations) {
|
|
968
|
+
await Promise.all(operations.map(async ([signal, operation]) => {
|
|
969
|
+
try {
|
|
970
|
+
await operation();
|
|
971
|
+
} catch (error) {
|
|
972
|
+
this.diagnostics.failure(signal, stage, error);
|
|
973
|
+
}
|
|
974
|
+
}));
|
|
724
975
|
}
|
|
725
976
|
};
|
|
726
977
|
var activeRuntime;
|
|
@@ -731,12 +982,16 @@ function exporterConfig(url, config) {
|
|
|
731
982
|
timeoutMillis: config.exportTimeoutMillis
|
|
732
983
|
};
|
|
733
984
|
}
|
|
734
|
-
function createTraceProvider(config, resource) {
|
|
985
|
+
function createTraceProvider(config, resource, diagnostics) {
|
|
735
986
|
if (!config.traces && !config.metrics) return void 0;
|
|
736
987
|
const spanProcessors = [new SpanRedactionProcessor()];
|
|
737
988
|
if (config.traces) {
|
|
738
989
|
const exporter = config.exporters?.span ?? new OTLPTraceExporter(exporterConfig(config.endpoints.traces, config));
|
|
739
|
-
spanProcessors.push(new BatchSpanProcessor(
|
|
990
|
+
spanProcessors.push(new BatchSpanProcessor(withExporterDiagnostics(
|
|
991
|
+
exporter,
|
|
992
|
+
"traces",
|
|
993
|
+
diagnostics
|
|
994
|
+
), {
|
|
740
995
|
exportTimeoutMillis: config.exportTimeoutMillis,
|
|
741
996
|
maxQueueSize: 2048,
|
|
742
997
|
maxExportBatchSize: 512
|
|
@@ -751,14 +1006,18 @@ function createTraceProvider(config, resource) {
|
|
|
751
1006
|
provider.register();
|
|
752
1007
|
return provider;
|
|
753
1008
|
}
|
|
754
|
-
function createMeterProvider(config, resource) {
|
|
1009
|
+
function createMeterProvider(config, resource, diagnostics) {
|
|
755
1010
|
if (!config.metrics) return void 0;
|
|
756
1011
|
let reader;
|
|
757
1012
|
if (config.exporters?.metricReader) {
|
|
758
1013
|
reader = config.exporters.metricReader;
|
|
759
1014
|
} else {
|
|
760
1015
|
reader = new PeriodicExportingMetricReader({
|
|
761
|
-
exporter:
|
|
1016
|
+
exporter: withExporterDiagnostics(
|
|
1017
|
+
new OTLPMetricExporter(exporterConfig(config.endpoints.metrics, config)),
|
|
1018
|
+
"metrics",
|
|
1019
|
+
diagnostics
|
|
1020
|
+
),
|
|
762
1021
|
exportIntervalMillis: config.metricExportIntervalMillis,
|
|
763
1022
|
exportTimeoutMillis: Math.min(config.exportTimeoutMillis, config.metricExportIntervalMillis),
|
|
764
1023
|
cardinalityLimits: { default: 2e3, histogram: 2e3 }
|
|
@@ -776,13 +1035,13 @@ function createMeterProvider(config, resource) {
|
|
|
776
1035
|
metrics.setGlobalMeterProvider(provider);
|
|
777
1036
|
return provider;
|
|
778
1037
|
}
|
|
779
|
-
function createLoggerProvider(config, resource) {
|
|
1038
|
+
function createLoggerProvider(config, resource, diagnostics) {
|
|
780
1039
|
if (!config.logs) return void 0;
|
|
781
1040
|
const exporter = config.exporters?.log ?? new OTLPLogExporter(exporterConfig(config.endpoints.logs, config));
|
|
782
1041
|
const provider = new LoggerProvider({
|
|
783
1042
|
resource,
|
|
784
1043
|
processors: [new BatchLogRecordProcessor({
|
|
785
|
-
exporter,
|
|
1044
|
+
exporter: withExporterDiagnostics(exporter, "logs", diagnostics),
|
|
786
1045
|
exportTimeoutMillis: config.exportTimeoutMillis,
|
|
787
1046
|
maxQueueSize: 2048,
|
|
788
1047
|
maxExportBatchSize: 512
|
|
@@ -794,7 +1053,11 @@ function createLoggerProvider(config, resource) {
|
|
|
794
1053
|
function observe(options = {}) {
|
|
795
1054
|
if (activeRuntime?.started) return activeRuntime;
|
|
796
1055
|
const config = resolveObserveConfig(options);
|
|
797
|
-
|
|
1056
|
+
const diagnostics = new ObserveDiagnostics(config.diagnosticLogging, options.onError);
|
|
1057
|
+
if (!config.enabled) {
|
|
1058
|
+
diagnostics.inactive();
|
|
1059
|
+
return new InactiveObserveHandle(config, diagnostics);
|
|
1060
|
+
}
|
|
798
1061
|
let tracerProvider;
|
|
799
1062
|
let meterProvider;
|
|
800
1063
|
let loggerProvider;
|
|
@@ -804,10 +1067,11 @@ function observe(options = {}) {
|
|
|
804
1067
|
const instrumentations = [];
|
|
805
1068
|
try {
|
|
806
1069
|
const resource = createObserveResource(config);
|
|
807
|
-
meterProvider = createMeterProvider(config, resource);
|
|
1070
|
+
meterProvider = createMeterProvider(config, resource, diagnostics);
|
|
808
1071
|
const meter = meterProvider?.getMeter(SDK_NAME, SDK_VERSION);
|
|
809
|
-
|
|
810
|
-
|
|
1072
|
+
const httpRequestMetrics = meter ? new HttpRequestMetrics(meter, config.serviceName) : void 0;
|
|
1073
|
+
tracerProvider = createTraceProvider(config, resource, diagnostics);
|
|
1074
|
+
loggerProvider = createLoggerProvider(config, resource, diagnostics);
|
|
811
1075
|
runtimeMetrics = meter ? new RuntimeMetrics(meter) : void 0;
|
|
812
1076
|
runtimeMetrics?.start();
|
|
813
1077
|
const otelLogger = loggerProvider?.getLogger(SDK_NAME, SDK_VERSION);
|
|
@@ -822,7 +1086,6 @@ function observe(options = {}) {
|
|
|
822
1086
|
exceptionCapture.start();
|
|
823
1087
|
if (config.traces || config.metrics) {
|
|
824
1088
|
const safeHeaders = config.allowedHeaders.filter((header) => !isSensitiveKey(header));
|
|
825
|
-
const httpRequestMetrics = meter ? new HttpRequestMetrics(meter, config.serviceName) : void 0;
|
|
826
1089
|
instrumentations.push(new HttpInstrumentation({
|
|
827
1090
|
requireParentforOutgoingSpans: false,
|
|
828
1091
|
headersToSpanAttributes: {
|
|
@@ -866,14 +1129,18 @@ function observe(options = {}) {
|
|
|
866
1129
|
tracerProvider,
|
|
867
1130
|
meterProvider,
|
|
868
1131
|
loggerProvider,
|
|
1132
|
+
httpRequestMetrics,
|
|
869
1133
|
runtimeMetrics,
|
|
870
1134
|
loggerInstrumentation,
|
|
871
1135
|
exceptionCapture,
|
|
872
|
-
instrumentations
|
|
1136
|
+
instrumentations,
|
|
1137
|
+
diagnostics
|
|
873
1138
|
);
|
|
1139
|
+
diagnostics.activate();
|
|
874
1140
|
activeRuntime = runtime;
|
|
875
1141
|
return runtime;
|
|
876
|
-
} catch {
|
|
1142
|
+
} catch (error) {
|
|
1143
|
+
diagnostics.failure("sdk", "initialization", error);
|
|
877
1144
|
loggerInstrumentation?.disable();
|
|
878
1145
|
runtimeMetrics?.stop();
|
|
879
1146
|
exceptionCapture?.stop();
|
|
@@ -888,7 +1155,9 @@ function observe(options = {}) {
|
|
|
888
1155
|
meterProvider?.shutdown(),
|
|
889
1156
|
loggerProvider?.shutdown()
|
|
890
1157
|
].filter((item) => Boolean(item)));
|
|
891
|
-
|
|
1158
|
+
diagnostics.inactive();
|
|
1159
|
+
if (config.failFast) throw toError(error);
|
|
1160
|
+
return new InactiveObserveHandle(config, diagnostics);
|
|
892
1161
|
}
|
|
893
1162
|
}
|
|
894
1163
|
|