@ryanzeng/nest-observe 0.1.1 → 0.1.2
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 +42 -15
- package/dist/index.d.ts +42 -15
- package/dist/index.js +347 -37
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +353 -39
- package/dist/index.mjs.map +1 -1
- package/dist/register.js +313 -40
- package/dist/register.js.map +1 -1
- package/dist/register.mjs +313 -40
- 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
|
}
|
|
@@ -387,7 +494,13 @@ var SEVERITY = {
|
|
|
387
494
|
};
|
|
388
495
|
function bodyValue(message) {
|
|
389
496
|
if (message instanceof Error) return redactText(message.stack ?? `${message.name}: ${message.message}`);
|
|
390
|
-
|
|
497
|
+
const sanitized = redact(message);
|
|
498
|
+
if (sanitized === null || typeof sanitized !== "object") return sanitized;
|
|
499
|
+
try {
|
|
500
|
+
return JSON.stringify(sanitized, (_key, value) => typeof value === "bigint" ? value.toString() : value);
|
|
501
|
+
} catch {
|
|
502
|
+
return redactText(String(sanitized));
|
|
503
|
+
}
|
|
391
504
|
}
|
|
392
505
|
var NestLoggerInstrumentation = class {
|
|
393
506
|
constructor(emitter, resourceAttributes = {}) {
|
|
@@ -494,9 +607,14 @@ var HttpRequestMetrics = class {
|
|
|
494
607
|
errorCount;
|
|
495
608
|
startedAt = /* @__PURE__ */ new WeakMap();
|
|
496
609
|
start(request) {
|
|
610
|
+
if (this.startedAt.has(request)) return false;
|
|
497
611
|
this.startedAt.set(request, process.hrtime.bigint());
|
|
612
|
+
return true;
|
|
498
613
|
}
|
|
499
614
|
record(request, response) {
|
|
615
|
+
const started = this.startedAt.get(request);
|
|
616
|
+
if (started === void 0) return false;
|
|
617
|
+
this.startedAt.delete(request);
|
|
500
618
|
const statusCode = Number.isFinite(response.statusCode) ? response.statusCode : 0;
|
|
501
619
|
const attributes = {
|
|
502
620
|
"service.name": this.serviceName,
|
|
@@ -505,12 +623,9 @@ var HttpRequestMetrics = class {
|
|
|
505
623
|
"http.response.status_code": statusCode
|
|
506
624
|
};
|
|
507
625
|
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
|
-
}
|
|
626
|
+
this.requestDuration.record(Number(process.hrtime.bigint() - started) / 1e9, attributes);
|
|
513
627
|
if (statusCode >= 500) this.errorCount.add(1, attributes);
|
|
628
|
+
return true;
|
|
514
629
|
}
|
|
515
630
|
};
|
|
516
631
|
|
|
@@ -601,8 +716,118 @@ import {
|
|
|
601
716
|
resourceFromAttributes
|
|
602
717
|
} from "@opentelemetry/resources";
|
|
603
718
|
import { hostname } from "os";
|
|
604
|
-
|
|
605
|
-
|
|
719
|
+
|
|
720
|
+
// package.json
|
|
721
|
+
var package_default = {
|
|
722
|
+
name: "@ryanzeng/nest-observe",
|
|
723
|
+
version: "0.1.2",
|
|
724
|
+
description: "Zero-config, vendor-neutral OpenTelemetry observability for NestJS",
|
|
725
|
+
keywords: [
|
|
726
|
+
"nestjs",
|
|
727
|
+
"opentelemetry",
|
|
728
|
+
"observability",
|
|
729
|
+
"otlp",
|
|
730
|
+
"tracing",
|
|
731
|
+
"metrics",
|
|
732
|
+
"logging"
|
|
733
|
+
],
|
|
734
|
+
license: "MIT",
|
|
735
|
+
homepage: "https://github.com/ryanzen9/nest-observe#readme",
|
|
736
|
+
bugs: {
|
|
737
|
+
url: "https://github.com/ryanzen9/nest-observe/issues"
|
|
738
|
+
},
|
|
739
|
+
repository: {
|
|
740
|
+
type: "git",
|
|
741
|
+
url: "git+https://github.com/ryanzen9/nest-observe.git"
|
|
742
|
+
},
|
|
743
|
+
packageManager: "pnpm@10.13.1",
|
|
744
|
+
sideEffects: [
|
|
745
|
+
"./dist/register.js",
|
|
746
|
+
"./dist/register.mjs"
|
|
747
|
+
],
|
|
748
|
+
main: "./dist/index.js",
|
|
749
|
+
module: "./dist/index.mjs",
|
|
750
|
+
types: "./dist/index.d.ts",
|
|
751
|
+
exports: {
|
|
752
|
+
".": {
|
|
753
|
+
import: {
|
|
754
|
+
types: "./dist/index.d.mts",
|
|
755
|
+
default: "./dist/index.mjs"
|
|
756
|
+
},
|
|
757
|
+
require: {
|
|
758
|
+
types: "./dist/index.d.ts",
|
|
759
|
+
default: "./dist/index.js"
|
|
760
|
+
}
|
|
761
|
+
},
|
|
762
|
+
"./register": {
|
|
763
|
+
import: {
|
|
764
|
+
types: "./dist/register.d.mts",
|
|
765
|
+
default: "./dist/register.mjs"
|
|
766
|
+
},
|
|
767
|
+
require: {
|
|
768
|
+
types: "./dist/register.d.ts",
|
|
769
|
+
default: "./dist/register.js"
|
|
770
|
+
}
|
|
771
|
+
}
|
|
772
|
+
},
|
|
773
|
+
files: [
|
|
774
|
+
"dist",
|
|
775
|
+
"README.md",
|
|
776
|
+
"CHANGELOG.md",
|
|
777
|
+
"LICENSE"
|
|
778
|
+
],
|
|
779
|
+
scripts: {
|
|
780
|
+
build: "tsup",
|
|
781
|
+
test: "vitest run",
|
|
782
|
+
"test:watch": "vitest",
|
|
783
|
+
typecheck: "tsc --noEmit",
|
|
784
|
+
check: "pnpm typecheck && pnpm test && pnpm build"
|
|
785
|
+
},
|
|
786
|
+
engines: {
|
|
787
|
+
node: ">=20"
|
|
788
|
+
},
|
|
789
|
+
peerDependencies: {
|
|
790
|
+
"@nestjs/common": ">=10 <13",
|
|
791
|
+
"@nestjs/core": ">=10 <13",
|
|
792
|
+
"reflect-metadata": ">=0.1.12 <1",
|
|
793
|
+
rxjs: "^7.1.0"
|
|
794
|
+
},
|
|
795
|
+
dependencies: {
|
|
796
|
+
"@opentelemetry/api": "^1.9.0",
|
|
797
|
+
"@opentelemetry/api-logs": "^0.221.0",
|
|
798
|
+
"@opentelemetry/exporter-logs-otlp-proto": "^0.221.0",
|
|
799
|
+
"@opentelemetry/exporter-metrics-otlp-proto": "^0.221.0",
|
|
800
|
+
"@opentelemetry/exporter-trace-otlp-proto": "^0.221.0",
|
|
801
|
+
"@opentelemetry/instrumentation": "^0.221.0",
|
|
802
|
+
"@opentelemetry/instrumentation-http": "^0.221.0",
|
|
803
|
+
"@opentelemetry/instrumentation-nestjs-core": "^0.67.0",
|
|
804
|
+
"@opentelemetry/resources": "^2.10.0",
|
|
805
|
+
"@opentelemetry/sdk-logs": "^0.221.0",
|
|
806
|
+
"@opentelemetry/sdk-metrics": "^2.10.0",
|
|
807
|
+
"@opentelemetry/sdk-trace-base": "^2.10.0",
|
|
808
|
+
"@opentelemetry/sdk-trace-node": "^2.10.0",
|
|
809
|
+
"@prisma/instrumentation": "^7.10.0"
|
|
810
|
+
},
|
|
811
|
+
devDependencies: {
|
|
812
|
+
"@nestjs/common": "^12.0.1",
|
|
813
|
+
"@nestjs/core": "^12.0.1",
|
|
814
|
+
"@nestjs/testing": "^12.0.1",
|
|
815
|
+
"@opentelemetry/sdk-trace-base": "^2.10.0",
|
|
816
|
+
"@types/node": "^24.0.0",
|
|
817
|
+
"reflect-metadata": "^0.2.2",
|
|
818
|
+
rxjs: "^7.8.2",
|
|
819
|
+
tsup: "^8.5.1",
|
|
820
|
+
typescript: "^5.9.3",
|
|
821
|
+
vitest: "^4.1.11"
|
|
822
|
+
},
|
|
823
|
+
publishConfig: {
|
|
824
|
+
access: "public"
|
|
825
|
+
}
|
|
826
|
+
};
|
|
827
|
+
|
|
828
|
+
// src/resource.ts
|
|
829
|
+
var SDK_NAME = package_default.name;
|
|
830
|
+
var SDK_VERSION = package_default.version;
|
|
606
831
|
function createObserveResource(config) {
|
|
607
832
|
return defaultResource().merge(
|
|
608
833
|
resourceFromAttributes({
|
|
@@ -659,14 +884,23 @@ var SpanRedactionProcessor = class {
|
|
|
659
884
|
|
|
660
885
|
// src/sdk.ts
|
|
661
886
|
var InactiveObserveHandle = class {
|
|
662
|
-
constructor(config) {
|
|
887
|
+
constructor(config, diagnostics) {
|
|
663
888
|
this.config = config;
|
|
889
|
+
this.diagnostics = diagnostics;
|
|
664
890
|
}
|
|
665
891
|
config;
|
|
892
|
+
diagnostics;
|
|
666
893
|
started = false;
|
|
667
894
|
tracerProvider = void 0;
|
|
668
895
|
meterProvider = void 0;
|
|
669
896
|
loggerProvider = void 0;
|
|
897
|
+
httpRequestMetrics = void 0;
|
|
898
|
+
get status() {
|
|
899
|
+
return this.diagnostics.status;
|
|
900
|
+
}
|
|
901
|
+
get lastError() {
|
|
902
|
+
return this.diagnostics.lastError;
|
|
903
|
+
}
|
|
670
904
|
forceFlush() {
|
|
671
905
|
return Promise.resolve();
|
|
672
906
|
}
|
|
@@ -675,52 +909,73 @@ var InactiveObserveHandle = class {
|
|
|
675
909
|
}
|
|
676
910
|
};
|
|
677
911
|
var ActiveObserveHandle = class {
|
|
678
|
-
constructor(config, tracerProvider, meterProvider, loggerProvider, runtimeMetrics, loggerInstrumentation, exceptionCapture, instrumentations) {
|
|
912
|
+
constructor(config, tracerProvider, meterProvider, loggerProvider, httpRequestMetrics, runtimeMetrics, loggerInstrumentation, exceptionCapture, instrumentations, diagnostics) {
|
|
679
913
|
this.config = config;
|
|
680
914
|
this.tracerProvider = tracerProvider;
|
|
681
915
|
this.meterProvider = meterProvider;
|
|
682
916
|
this.loggerProvider = loggerProvider;
|
|
917
|
+
this.httpRequestMetrics = httpRequestMetrics;
|
|
683
918
|
this.runtimeMetrics = runtimeMetrics;
|
|
684
919
|
this.loggerInstrumentation = loggerInstrumentation;
|
|
685
920
|
this.exceptionCapture = exceptionCapture;
|
|
686
921
|
this.instrumentations = instrumentations;
|
|
922
|
+
this.diagnostics = diagnostics;
|
|
687
923
|
}
|
|
688
924
|
config;
|
|
689
925
|
tracerProvider;
|
|
690
926
|
meterProvider;
|
|
691
927
|
loggerProvider;
|
|
928
|
+
httpRequestMetrics;
|
|
692
929
|
runtimeMetrics;
|
|
693
930
|
loggerInstrumentation;
|
|
694
931
|
exceptionCapture;
|
|
695
932
|
instrumentations;
|
|
933
|
+
diagnostics;
|
|
696
934
|
started = true;
|
|
697
935
|
stopped = false;
|
|
936
|
+
get status() {
|
|
937
|
+
return this.diagnostics.status;
|
|
938
|
+
}
|
|
939
|
+
get lastError() {
|
|
940
|
+
return this.diagnostics.lastError;
|
|
941
|
+
}
|
|
698
942
|
async forceFlush() {
|
|
699
|
-
await
|
|
700
|
-
this.tracerProvider
|
|
701
|
-
this.meterProvider
|
|
702
|
-
this.loggerProvider
|
|
703
|
-
]
|
|
943
|
+
await this.runSafely("forceFlush", [
|
|
944
|
+
...this.config.traces && this.tracerProvider ? [["traces", () => this.tracerProvider.forceFlush()]] : [],
|
|
945
|
+
...this.config.metrics && this.meterProvider ? [["metrics", () => this.meterProvider.forceFlush()]] : [],
|
|
946
|
+
...this.config.logs && this.loggerProvider ? [["logs", () => this.loggerProvider.forceFlush({ timeoutMillis: this.config.exportTimeoutMillis })]] : []
|
|
947
|
+
]);
|
|
704
948
|
}
|
|
705
949
|
async shutdown() {
|
|
706
950
|
if (this.stopped) return;
|
|
707
951
|
this.stopped = true;
|
|
708
952
|
this.loggerInstrumentation?.disable();
|
|
709
|
-
this.runtimeMetrics?.stop();
|
|
710
953
|
this.exceptionCapture.stop();
|
|
711
954
|
for (const instrumentation of this.instrumentations) {
|
|
712
955
|
try {
|
|
713
956
|
instrumentation.disable();
|
|
714
|
-
} catch {
|
|
957
|
+
} catch (error) {
|
|
958
|
+
this.diagnostics.failure("sdk", "shutdown", error);
|
|
715
959
|
}
|
|
716
960
|
}
|
|
717
961
|
await this.forceFlush();
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
this.
|
|
721
|
-
this.
|
|
722
|
-
|
|
962
|
+
this.runtimeMetrics?.stop();
|
|
963
|
+
await this.runSafely("shutdown", [
|
|
964
|
+
...this.tracerProvider ? [["traces", () => this.tracerProvider.shutdown()]] : [],
|
|
965
|
+
...this.meterProvider ? [["metrics", () => this.meterProvider.shutdown()]] : [],
|
|
966
|
+
...this.loggerProvider ? [["logs", () => this.loggerProvider.shutdown()]] : []
|
|
967
|
+
]);
|
|
723
968
|
if (activeRuntime === this) activeRuntime = void 0;
|
|
969
|
+
this.diagnostics.stop();
|
|
970
|
+
}
|
|
971
|
+
async runSafely(stage, operations) {
|
|
972
|
+
await Promise.all(operations.map(async ([signal, operation]) => {
|
|
973
|
+
try {
|
|
974
|
+
await operation();
|
|
975
|
+
} catch (error) {
|
|
976
|
+
this.diagnostics.failure(signal, stage, error);
|
|
977
|
+
}
|
|
978
|
+
}));
|
|
724
979
|
}
|
|
725
980
|
};
|
|
726
981
|
var activeRuntime;
|
|
@@ -731,12 +986,16 @@ function exporterConfig(url, config) {
|
|
|
731
986
|
timeoutMillis: config.exportTimeoutMillis
|
|
732
987
|
};
|
|
733
988
|
}
|
|
734
|
-
function createTraceProvider(config, resource) {
|
|
989
|
+
function createTraceProvider(config, resource, diagnostics) {
|
|
735
990
|
if (!config.traces && !config.metrics) return void 0;
|
|
736
991
|
const spanProcessors = [new SpanRedactionProcessor()];
|
|
737
992
|
if (config.traces) {
|
|
738
993
|
const exporter = config.exporters?.span ?? new OTLPTraceExporter(exporterConfig(config.endpoints.traces, config));
|
|
739
|
-
spanProcessors.push(new BatchSpanProcessor(
|
|
994
|
+
spanProcessors.push(new BatchSpanProcessor(withExporterDiagnostics(
|
|
995
|
+
exporter,
|
|
996
|
+
"traces",
|
|
997
|
+
diagnostics
|
|
998
|
+
), {
|
|
740
999
|
exportTimeoutMillis: config.exportTimeoutMillis,
|
|
741
1000
|
maxQueueSize: 2048,
|
|
742
1001
|
maxExportBatchSize: 512
|
|
@@ -751,14 +1010,18 @@ function createTraceProvider(config, resource) {
|
|
|
751
1010
|
provider.register();
|
|
752
1011
|
return provider;
|
|
753
1012
|
}
|
|
754
|
-
function createMeterProvider(config, resource) {
|
|
1013
|
+
function createMeterProvider(config, resource, diagnostics) {
|
|
755
1014
|
if (!config.metrics) return void 0;
|
|
756
1015
|
let reader;
|
|
757
1016
|
if (config.exporters?.metricReader) {
|
|
758
1017
|
reader = config.exporters.metricReader;
|
|
759
1018
|
} else {
|
|
760
1019
|
reader = new PeriodicExportingMetricReader({
|
|
761
|
-
exporter:
|
|
1020
|
+
exporter: withExporterDiagnostics(
|
|
1021
|
+
new OTLPMetricExporter(exporterConfig(config.endpoints.metrics, config)),
|
|
1022
|
+
"metrics",
|
|
1023
|
+
diagnostics
|
|
1024
|
+
),
|
|
762
1025
|
exportIntervalMillis: config.metricExportIntervalMillis,
|
|
763
1026
|
exportTimeoutMillis: Math.min(config.exportTimeoutMillis, config.metricExportIntervalMillis),
|
|
764
1027
|
cardinalityLimits: { default: 2e3, histogram: 2e3 }
|
|
@@ -776,13 +1039,13 @@ function createMeterProvider(config, resource) {
|
|
|
776
1039
|
metrics.setGlobalMeterProvider(provider);
|
|
777
1040
|
return provider;
|
|
778
1041
|
}
|
|
779
|
-
function createLoggerProvider(config, resource) {
|
|
1042
|
+
function createLoggerProvider(config, resource, diagnostics) {
|
|
780
1043
|
if (!config.logs) return void 0;
|
|
781
1044
|
const exporter = config.exporters?.log ?? new OTLPLogExporter(exporterConfig(config.endpoints.logs, config));
|
|
782
1045
|
const provider = new LoggerProvider({
|
|
783
1046
|
resource,
|
|
784
1047
|
processors: [new BatchLogRecordProcessor({
|
|
785
|
-
exporter,
|
|
1048
|
+
exporter: withExporterDiagnostics(exporter, "logs", diagnostics),
|
|
786
1049
|
exportTimeoutMillis: config.exportTimeoutMillis,
|
|
787
1050
|
maxQueueSize: 2048,
|
|
788
1051
|
maxExportBatchSize: 512
|
|
@@ -794,7 +1057,11 @@ function createLoggerProvider(config, resource) {
|
|
|
794
1057
|
function observe(options = {}) {
|
|
795
1058
|
if (activeRuntime?.started) return activeRuntime;
|
|
796
1059
|
const config = resolveObserveConfig(options);
|
|
797
|
-
|
|
1060
|
+
const diagnostics = new ObserveDiagnostics(config.diagnosticLogging, options.onError);
|
|
1061
|
+
if (!config.enabled) {
|
|
1062
|
+
diagnostics.inactive();
|
|
1063
|
+
return new InactiveObserveHandle(config, diagnostics);
|
|
1064
|
+
}
|
|
798
1065
|
let tracerProvider;
|
|
799
1066
|
let meterProvider;
|
|
800
1067
|
let loggerProvider;
|
|
@@ -804,10 +1071,11 @@ function observe(options = {}) {
|
|
|
804
1071
|
const instrumentations = [];
|
|
805
1072
|
try {
|
|
806
1073
|
const resource = createObserveResource(config);
|
|
807
|
-
meterProvider = createMeterProvider(config, resource);
|
|
1074
|
+
meterProvider = createMeterProvider(config, resource, diagnostics);
|
|
808
1075
|
const meter = meterProvider?.getMeter(SDK_NAME, SDK_VERSION);
|
|
809
|
-
|
|
810
|
-
|
|
1076
|
+
const httpRequestMetrics = meter ? new HttpRequestMetrics(meter, config.serviceName) : void 0;
|
|
1077
|
+
tracerProvider = createTraceProvider(config, resource, diagnostics);
|
|
1078
|
+
loggerProvider = createLoggerProvider(config, resource, diagnostics);
|
|
811
1079
|
runtimeMetrics = meter ? new RuntimeMetrics(meter) : void 0;
|
|
812
1080
|
runtimeMetrics?.start();
|
|
813
1081
|
const otelLogger = loggerProvider?.getLogger(SDK_NAME, SDK_VERSION);
|
|
@@ -822,7 +1090,6 @@ function observe(options = {}) {
|
|
|
822
1090
|
exceptionCapture.start();
|
|
823
1091
|
if (config.traces || config.metrics) {
|
|
824
1092
|
const safeHeaders = config.allowedHeaders.filter((header) => !isSensitiveKey(header));
|
|
825
|
-
const httpRequestMetrics = meter ? new HttpRequestMetrics(meter, config.serviceName) : void 0;
|
|
826
1093
|
instrumentations.push(new HttpInstrumentation({
|
|
827
1094
|
requireParentforOutgoingSpans: false,
|
|
828
1095
|
headersToSpanAttributes: {
|
|
@@ -866,14 +1133,18 @@ function observe(options = {}) {
|
|
|
866
1133
|
tracerProvider,
|
|
867
1134
|
meterProvider,
|
|
868
1135
|
loggerProvider,
|
|
1136
|
+
httpRequestMetrics,
|
|
869
1137
|
runtimeMetrics,
|
|
870
1138
|
loggerInstrumentation,
|
|
871
1139
|
exceptionCapture,
|
|
872
|
-
instrumentations
|
|
1140
|
+
instrumentations,
|
|
1141
|
+
diagnostics
|
|
873
1142
|
);
|
|
1143
|
+
diagnostics.activate();
|
|
874
1144
|
activeRuntime = runtime;
|
|
875
1145
|
return runtime;
|
|
876
|
-
} catch {
|
|
1146
|
+
} catch (error) {
|
|
1147
|
+
diagnostics.failure("sdk", "initialization", error);
|
|
877
1148
|
loggerInstrumentation?.disable();
|
|
878
1149
|
runtimeMetrics?.stop();
|
|
879
1150
|
exceptionCapture?.stop();
|
|
@@ -888,7 +1159,9 @@ function observe(options = {}) {
|
|
|
888
1159
|
meterProvider?.shutdown(),
|
|
889
1160
|
loggerProvider?.shutdown()
|
|
890
1161
|
].filter((item) => Boolean(item)));
|
|
891
|
-
|
|
1162
|
+
diagnostics.inactive();
|
|
1163
|
+
if (config.failFast) throw toError(error);
|
|
1164
|
+
return new InactiveObserveHandle(config, diagnostics);
|
|
892
1165
|
}
|
|
893
1166
|
}
|
|
894
1167
|
|