@ryanzeng/nest-observe 0.1.0 → 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 +31 -1
- package/dist/index.d.mts +42 -15
- package/dist/index.d.ts +42 -15
- package/dist/index.js +379 -58
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +388 -60
- package/dist/index.mjs.map +1 -1
- package/dist/register.js +327 -52
- package/dist/register.js.map +1 -1
- package/dist/register.mjs +330 -52
- package/dist/register.mjs.map +1 -1
- package/package.json +19 -9
package/dist/register.js
CHANGED
|
@@ -93,15 +93,14 @@ function resolveObserveConfig(options = {}, env = process.env) {
|
|
|
93
93
|
allowedHeaders,
|
|
94
94
|
exportTimeoutMillis: positiveInteger(options.exportTimeoutMillis ?? env.OTEL_EXPORTER_OTLP_TIMEOUT, 1e4),
|
|
95
95
|
metricExportIntervalMillis: positiveInteger(options.metricExportIntervalMillis ?? env.OTEL_METRIC_EXPORT_INTERVAL, 6e4),
|
|
96
|
-
resourceAttributes
|
|
96
|
+
resourceAttributes,
|
|
97
|
+
diagnosticLogging: booleanValue(options.diagnosticLogging, true),
|
|
98
|
+
failFast: booleanValue(options.failFast, false)
|
|
97
99
|
};
|
|
98
100
|
if (options.exporters) result.exporters = options.exporters;
|
|
99
101
|
return result;
|
|
100
102
|
}
|
|
101
103
|
|
|
102
|
-
// src/exceptions/process-exception-capture.ts
|
|
103
|
-
var import_api = require("@opentelemetry/api");
|
|
104
|
-
|
|
105
104
|
// src/security/redaction.ts
|
|
106
105
|
var REDACTED = "[REDACTED]";
|
|
107
106
|
var SENSITIVE_KEY = /(?:authorization|proxy-authorization|cookie|set-cookie|pass(?:word|wd)?|secret|token|api[-_]?key|phone|mobile)/i;
|
|
@@ -135,7 +134,115 @@ function redact(value) {
|
|
|
135
134
|
return visit(value, /* @__PURE__ */ new WeakSet());
|
|
136
135
|
}
|
|
137
136
|
|
|
137
|
+
// src/diagnostics.ts
|
|
138
|
+
function toError(value) {
|
|
139
|
+
if (value instanceof Error) return value;
|
|
140
|
+
if (typeof value === "string") return new Error(value);
|
|
141
|
+
try {
|
|
142
|
+
return new Error(JSON.stringify(value));
|
|
143
|
+
} catch {
|
|
144
|
+
return new Error(String(value));
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
function sanitizeError(error) {
|
|
148
|
+
const sanitized = new Error(redactText(error.message));
|
|
149
|
+
sanitized.name = error.name;
|
|
150
|
+
if (error.stack) sanitized.stack = redactText(error.stack);
|
|
151
|
+
return sanitized;
|
|
152
|
+
}
|
|
153
|
+
var ObserveDiagnostics = class {
|
|
154
|
+
constructor(logging, onError) {
|
|
155
|
+
this.logging = logging;
|
|
156
|
+
this.onError = onError;
|
|
157
|
+
}
|
|
158
|
+
logging;
|
|
159
|
+
onError;
|
|
160
|
+
currentStatus = "starting";
|
|
161
|
+
currentError;
|
|
162
|
+
failedSignals = /* @__PURE__ */ new Set();
|
|
163
|
+
reported = /* @__PURE__ */ new Set();
|
|
164
|
+
get status() {
|
|
165
|
+
return this.currentStatus;
|
|
166
|
+
}
|
|
167
|
+
get lastError() {
|
|
168
|
+
return this.currentError;
|
|
169
|
+
}
|
|
170
|
+
activate() {
|
|
171
|
+
if (this.currentStatus === "starting") this.currentStatus = "active";
|
|
172
|
+
}
|
|
173
|
+
inactive() {
|
|
174
|
+
this.currentStatus = "inactive";
|
|
175
|
+
}
|
|
176
|
+
stop() {
|
|
177
|
+
this.currentStatus = "stopped";
|
|
178
|
+
}
|
|
179
|
+
success(signal) {
|
|
180
|
+
this.failedSignals.delete(signal);
|
|
181
|
+
for (const fingerprint of this.reported) {
|
|
182
|
+
if (fingerprint.startsWith(`${signal}\0`)) this.reported.delete(fingerprint);
|
|
183
|
+
}
|
|
184
|
+
if (this.currentStatus === "degraded" && this.failedSignals.size === 0) {
|
|
185
|
+
this.currentStatus = "active";
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
failure(signal, stage, value) {
|
|
189
|
+
const error = sanitizeError(toError(value));
|
|
190
|
+
const event = { signal, stage, error, timestamp: Date.now() };
|
|
191
|
+
this.currentError = event;
|
|
192
|
+
this.failedSignals.add(signal);
|
|
193
|
+
if (this.currentStatus !== "inactive" && this.currentStatus !== "stopped") {
|
|
194
|
+
this.currentStatus = "degraded";
|
|
195
|
+
}
|
|
196
|
+
const fingerprint = `${signal}\0${stage}\0${error.name}\0${error.message}`;
|
|
197
|
+
if (this.reported.has(fingerprint)) return;
|
|
198
|
+
this.reported.add(fingerprint);
|
|
199
|
+
try {
|
|
200
|
+
this.onError?.(event);
|
|
201
|
+
} catch {
|
|
202
|
+
}
|
|
203
|
+
if (!this.logging) return;
|
|
204
|
+
try {
|
|
205
|
+
process.stderr.write(
|
|
206
|
+
`[nest-observe] ${signal} ${stage} failed: ${redactText(error.message)}
|
|
207
|
+
`
|
|
208
|
+
);
|
|
209
|
+
} catch {
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
};
|
|
213
|
+
function withExporterDiagnostics(exporter, signal, diagnostics) {
|
|
214
|
+
const delegate = exporter;
|
|
215
|
+
return new Proxy(exporter, {
|
|
216
|
+
get(target, property) {
|
|
217
|
+
if (property === "export") {
|
|
218
|
+
return (items, callback) => {
|
|
219
|
+
try {
|
|
220
|
+
delegate.export.call(target, items, (result) => {
|
|
221
|
+
if (result.code === 0) {
|
|
222
|
+
diagnostics.success(signal);
|
|
223
|
+
} else {
|
|
224
|
+
diagnostics.failure(
|
|
225
|
+
signal,
|
|
226
|
+
"export",
|
|
227
|
+
result.error ?? new Error(`${signal} export failed`)
|
|
228
|
+
);
|
|
229
|
+
}
|
|
230
|
+
callback(result);
|
|
231
|
+
});
|
|
232
|
+
} catch (error) {
|
|
233
|
+
diagnostics.failure(signal, "export", error);
|
|
234
|
+
throw error;
|
|
235
|
+
}
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
const value = Reflect.get(target, property, target);
|
|
239
|
+
return typeof value === "function" ? value.bind(target) : value;
|
|
240
|
+
}
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
|
|
138
244
|
// src/exceptions/process-exception-capture.ts
|
|
245
|
+
var import_api = require("@opentelemetry/api");
|
|
139
246
|
function asError(value) {
|
|
140
247
|
return value instanceof Error ? value : new Error(String(value));
|
|
141
248
|
}
|
|
@@ -386,7 +493,13 @@ var SEVERITY = {
|
|
|
386
493
|
};
|
|
387
494
|
function bodyValue(message) {
|
|
388
495
|
if (message instanceof Error) return redactText(message.stack ?? `${message.name}: ${message.message}`);
|
|
389
|
-
|
|
496
|
+
const sanitized = redact(message);
|
|
497
|
+
if (sanitized === null || typeof sanitized !== "object") return sanitized;
|
|
498
|
+
try {
|
|
499
|
+
return JSON.stringify(sanitized, (_key, value) => typeof value === "bigint" ? value.toString() : value);
|
|
500
|
+
} catch {
|
|
501
|
+
return redactText(String(sanitized));
|
|
502
|
+
}
|
|
390
503
|
}
|
|
391
504
|
var NestLoggerInstrumentation = class {
|
|
392
505
|
constructor(emitter, resourceAttributes = {}) {
|
|
@@ -449,7 +562,7 @@ var SEVERITY_NUMBER = {
|
|
|
449
562
|
};
|
|
450
563
|
var OpenTelemetryLogEmitter = class {
|
|
451
564
|
logger;
|
|
452
|
-
constructor(name = "@
|
|
565
|
+
constructor(name = "@ryanzeng/nest-observe", version, logger) {
|
|
453
566
|
this.logger = logger ?? import_api_logs.logs.getLogger(name, version);
|
|
454
567
|
}
|
|
455
568
|
emit(record) {
|
|
@@ -493,9 +606,14 @@ var HttpRequestMetrics = class {
|
|
|
493
606
|
errorCount;
|
|
494
607
|
startedAt = /* @__PURE__ */ new WeakMap();
|
|
495
608
|
start(request) {
|
|
609
|
+
if (this.startedAt.has(request)) return false;
|
|
496
610
|
this.startedAt.set(request, process.hrtime.bigint());
|
|
611
|
+
return true;
|
|
497
612
|
}
|
|
498
613
|
record(request, response) {
|
|
614
|
+
const started = this.startedAt.get(request);
|
|
615
|
+
if (started === void 0) return false;
|
|
616
|
+
this.startedAt.delete(request);
|
|
499
617
|
const statusCode = Number.isFinite(response.statusCode) ? response.statusCode : 0;
|
|
500
618
|
const attributes = {
|
|
501
619
|
"service.name": this.serviceName,
|
|
@@ -504,12 +622,9 @@ var HttpRequestMetrics = class {
|
|
|
504
622
|
"http.response.status_code": statusCode
|
|
505
623
|
};
|
|
506
624
|
this.requestCount.add(1, attributes);
|
|
507
|
-
|
|
508
|
-
if (started !== void 0) {
|
|
509
|
-
this.requestDuration.record(Number(process.hrtime.bigint() - started) / 1e9, attributes);
|
|
510
|
-
this.startedAt.delete(request);
|
|
511
|
-
}
|
|
625
|
+
this.requestDuration.record(Number(process.hrtime.bigint() - started) / 1e9, attributes);
|
|
512
626
|
if (statusCode >= 500) this.errorCount.add(1, attributes);
|
|
627
|
+
return true;
|
|
513
628
|
}
|
|
514
629
|
};
|
|
515
630
|
|
|
@@ -595,21 +710,133 @@ var RuntimeMetrics = class {
|
|
|
595
710
|
};
|
|
596
711
|
|
|
597
712
|
// src/resource.ts
|
|
598
|
-
var import_node_os2 = require("os");
|
|
599
713
|
var import_resources = require("@opentelemetry/resources");
|
|
600
|
-
var
|
|
601
|
-
|
|
714
|
+
var import_node_os2 = require("os");
|
|
715
|
+
|
|
716
|
+
// package.json
|
|
717
|
+
var package_default = {
|
|
718
|
+
name: "@ryanzeng/nest-observe",
|
|
719
|
+
version: "0.1.2",
|
|
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;
|
|
602
827
|
function createObserveResource(config) {
|
|
603
|
-
return (0, import_resources.defaultResource)().merge(
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
828
|
+
return (0, import_resources.defaultResource)().merge(
|
|
829
|
+
(0, import_resources.resourceFromAttributes)({
|
|
830
|
+
...config.resourceAttributes,
|
|
831
|
+
"service.name": config.serviceName,
|
|
832
|
+
"service.version": config.serviceVersion,
|
|
833
|
+
"deployment.environment.name": config.environment,
|
|
834
|
+
"service.instance.id": config.instanceId,
|
|
835
|
+
"telemetry.sdk.name": SDK_NAME,
|
|
836
|
+
"telemetry.sdk.version": SDK_VERSION,
|
|
837
|
+
"host.name": config.resourceAttributes["host.name"] ?? (0, import_node_os2.hostname)()
|
|
838
|
+
})
|
|
839
|
+
);
|
|
613
840
|
}
|
|
614
841
|
|
|
615
842
|
// src/security/span-redaction-processor.ts
|
|
@@ -653,14 +880,23 @@ var SpanRedactionProcessor = class {
|
|
|
653
880
|
|
|
654
881
|
// src/sdk.ts
|
|
655
882
|
var InactiveObserveHandle = class {
|
|
656
|
-
constructor(config) {
|
|
883
|
+
constructor(config, diagnostics) {
|
|
657
884
|
this.config = config;
|
|
885
|
+
this.diagnostics = diagnostics;
|
|
658
886
|
}
|
|
659
887
|
config;
|
|
888
|
+
diagnostics;
|
|
660
889
|
started = false;
|
|
661
890
|
tracerProvider = void 0;
|
|
662
891
|
meterProvider = void 0;
|
|
663
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
|
+
}
|
|
664
900
|
forceFlush() {
|
|
665
901
|
return Promise.resolve();
|
|
666
902
|
}
|
|
@@ -669,52 +905,73 @@ var InactiveObserveHandle = class {
|
|
|
669
905
|
}
|
|
670
906
|
};
|
|
671
907
|
var ActiveObserveHandle = class {
|
|
672
|
-
constructor(config, tracerProvider, meterProvider, loggerProvider, runtimeMetrics, loggerInstrumentation, exceptionCapture, instrumentations) {
|
|
908
|
+
constructor(config, tracerProvider, meterProvider, loggerProvider, httpRequestMetrics, runtimeMetrics, loggerInstrumentation, exceptionCapture, instrumentations, diagnostics) {
|
|
673
909
|
this.config = config;
|
|
674
910
|
this.tracerProvider = tracerProvider;
|
|
675
911
|
this.meterProvider = meterProvider;
|
|
676
912
|
this.loggerProvider = loggerProvider;
|
|
913
|
+
this.httpRequestMetrics = httpRequestMetrics;
|
|
677
914
|
this.runtimeMetrics = runtimeMetrics;
|
|
678
915
|
this.loggerInstrumentation = loggerInstrumentation;
|
|
679
916
|
this.exceptionCapture = exceptionCapture;
|
|
680
917
|
this.instrumentations = instrumentations;
|
|
918
|
+
this.diagnostics = diagnostics;
|
|
681
919
|
}
|
|
682
920
|
config;
|
|
683
921
|
tracerProvider;
|
|
684
922
|
meterProvider;
|
|
685
923
|
loggerProvider;
|
|
924
|
+
httpRequestMetrics;
|
|
686
925
|
runtimeMetrics;
|
|
687
926
|
loggerInstrumentation;
|
|
688
927
|
exceptionCapture;
|
|
689
928
|
instrumentations;
|
|
929
|
+
diagnostics;
|
|
690
930
|
started = true;
|
|
691
931
|
stopped = false;
|
|
932
|
+
get status() {
|
|
933
|
+
return this.diagnostics.status;
|
|
934
|
+
}
|
|
935
|
+
get lastError() {
|
|
936
|
+
return this.diagnostics.lastError;
|
|
937
|
+
}
|
|
692
938
|
async forceFlush() {
|
|
693
|
-
await
|
|
694
|
-
this.tracerProvider
|
|
695
|
-
this.meterProvider
|
|
696
|
-
this.loggerProvider
|
|
697
|
-
]
|
|
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
|
+
]);
|
|
698
944
|
}
|
|
699
945
|
async shutdown() {
|
|
700
946
|
if (this.stopped) return;
|
|
701
947
|
this.stopped = true;
|
|
702
948
|
this.loggerInstrumentation?.disable();
|
|
703
|
-
this.runtimeMetrics?.stop();
|
|
704
949
|
this.exceptionCapture.stop();
|
|
705
950
|
for (const instrumentation of this.instrumentations) {
|
|
706
951
|
try {
|
|
707
952
|
instrumentation.disable();
|
|
708
|
-
} catch {
|
|
953
|
+
} catch (error) {
|
|
954
|
+
this.diagnostics.failure("sdk", "shutdown", error);
|
|
709
955
|
}
|
|
710
956
|
}
|
|
711
957
|
await this.forceFlush();
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
this.
|
|
715
|
-
this.
|
|
716
|
-
|
|
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
|
+
]);
|
|
717
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
|
+
}));
|
|
718
975
|
}
|
|
719
976
|
};
|
|
720
977
|
var activeRuntime;
|
|
@@ -725,12 +982,16 @@ function exporterConfig(url, config) {
|
|
|
725
982
|
timeoutMillis: config.exportTimeoutMillis
|
|
726
983
|
};
|
|
727
984
|
}
|
|
728
|
-
function createTraceProvider(config, resource) {
|
|
985
|
+
function createTraceProvider(config, resource, diagnostics) {
|
|
729
986
|
if (!config.traces && !config.metrics) return void 0;
|
|
730
987
|
const spanProcessors = [new SpanRedactionProcessor()];
|
|
731
988
|
if (config.traces) {
|
|
732
989
|
const exporter = config.exporters?.span ?? new import_exporter_trace_otlp_proto.OTLPTraceExporter(exporterConfig(config.endpoints.traces, config));
|
|
733
|
-
spanProcessors.push(new import_sdk_trace_base.BatchSpanProcessor(
|
|
990
|
+
spanProcessors.push(new import_sdk_trace_base.BatchSpanProcessor(withExporterDiagnostics(
|
|
991
|
+
exporter,
|
|
992
|
+
"traces",
|
|
993
|
+
diagnostics
|
|
994
|
+
), {
|
|
734
995
|
exportTimeoutMillis: config.exportTimeoutMillis,
|
|
735
996
|
maxQueueSize: 2048,
|
|
736
997
|
maxExportBatchSize: 512
|
|
@@ -745,14 +1006,18 @@ function createTraceProvider(config, resource) {
|
|
|
745
1006
|
provider.register();
|
|
746
1007
|
return provider;
|
|
747
1008
|
}
|
|
748
|
-
function createMeterProvider(config, resource) {
|
|
1009
|
+
function createMeterProvider(config, resource, diagnostics) {
|
|
749
1010
|
if (!config.metrics) return void 0;
|
|
750
1011
|
let reader;
|
|
751
1012
|
if (config.exporters?.metricReader) {
|
|
752
1013
|
reader = config.exporters.metricReader;
|
|
753
1014
|
} else {
|
|
754
1015
|
reader = new import_sdk_metrics.PeriodicExportingMetricReader({
|
|
755
|
-
exporter:
|
|
1016
|
+
exporter: withExporterDiagnostics(
|
|
1017
|
+
new import_exporter_metrics_otlp_proto.OTLPMetricExporter(exporterConfig(config.endpoints.metrics, config)),
|
|
1018
|
+
"metrics",
|
|
1019
|
+
diagnostics
|
|
1020
|
+
),
|
|
756
1021
|
exportIntervalMillis: config.metricExportIntervalMillis,
|
|
757
1022
|
exportTimeoutMillis: Math.min(config.exportTimeoutMillis, config.metricExportIntervalMillis),
|
|
758
1023
|
cardinalityLimits: { default: 2e3, histogram: 2e3 }
|
|
@@ -770,13 +1035,13 @@ function createMeterProvider(config, resource) {
|
|
|
770
1035
|
import_api5.metrics.setGlobalMeterProvider(provider);
|
|
771
1036
|
return provider;
|
|
772
1037
|
}
|
|
773
|
-
function createLoggerProvider(config, resource) {
|
|
1038
|
+
function createLoggerProvider(config, resource, diagnostics) {
|
|
774
1039
|
if (!config.logs) return void 0;
|
|
775
1040
|
const exporter = config.exporters?.log ?? new import_exporter_logs_otlp_proto.OTLPLogExporter(exporterConfig(config.endpoints.logs, config));
|
|
776
1041
|
const provider = new import_sdk_logs.LoggerProvider({
|
|
777
1042
|
resource,
|
|
778
1043
|
processors: [new import_sdk_logs.BatchLogRecordProcessor({
|
|
779
|
-
exporter,
|
|
1044
|
+
exporter: withExporterDiagnostics(exporter, "logs", diagnostics),
|
|
780
1045
|
exportTimeoutMillis: config.exportTimeoutMillis,
|
|
781
1046
|
maxQueueSize: 2048,
|
|
782
1047
|
maxExportBatchSize: 512
|
|
@@ -788,7 +1053,11 @@ function createLoggerProvider(config, resource) {
|
|
|
788
1053
|
function observe(options = {}) {
|
|
789
1054
|
if (activeRuntime?.started) return activeRuntime;
|
|
790
1055
|
const config = resolveObserveConfig(options);
|
|
791
|
-
|
|
1056
|
+
const diagnostics = new ObserveDiagnostics(config.diagnosticLogging, options.onError);
|
|
1057
|
+
if (!config.enabled) {
|
|
1058
|
+
diagnostics.inactive();
|
|
1059
|
+
return new InactiveObserveHandle(config, diagnostics);
|
|
1060
|
+
}
|
|
792
1061
|
let tracerProvider;
|
|
793
1062
|
let meterProvider;
|
|
794
1063
|
let loggerProvider;
|
|
@@ -798,10 +1067,11 @@ function observe(options = {}) {
|
|
|
798
1067
|
const instrumentations = [];
|
|
799
1068
|
try {
|
|
800
1069
|
const resource = createObserveResource(config);
|
|
801
|
-
meterProvider = createMeterProvider(config, resource);
|
|
1070
|
+
meterProvider = createMeterProvider(config, resource, diagnostics);
|
|
802
1071
|
const meter = meterProvider?.getMeter(SDK_NAME, SDK_VERSION);
|
|
803
|
-
|
|
804
|
-
|
|
1072
|
+
const httpRequestMetrics = meter ? new HttpRequestMetrics(meter, config.serviceName) : void 0;
|
|
1073
|
+
tracerProvider = createTraceProvider(config, resource, diagnostics);
|
|
1074
|
+
loggerProvider = createLoggerProvider(config, resource, diagnostics);
|
|
805
1075
|
runtimeMetrics = meter ? new RuntimeMetrics(meter) : void 0;
|
|
806
1076
|
runtimeMetrics?.start();
|
|
807
1077
|
const otelLogger = loggerProvider?.getLogger(SDK_NAME, SDK_VERSION);
|
|
@@ -816,7 +1086,6 @@ function observe(options = {}) {
|
|
|
816
1086
|
exceptionCapture.start();
|
|
817
1087
|
if (config.traces || config.metrics) {
|
|
818
1088
|
const safeHeaders = config.allowedHeaders.filter((header) => !isSensitiveKey(header));
|
|
819
|
-
const httpRequestMetrics = meter ? new HttpRequestMetrics(meter, config.serviceName) : void 0;
|
|
820
1089
|
instrumentations.push(new import_instrumentation_http.HttpInstrumentation({
|
|
821
1090
|
requireParentforOutgoingSpans: false,
|
|
822
1091
|
headersToSpanAttributes: {
|
|
@@ -860,14 +1129,18 @@ function observe(options = {}) {
|
|
|
860
1129
|
tracerProvider,
|
|
861
1130
|
meterProvider,
|
|
862
1131
|
loggerProvider,
|
|
1132
|
+
httpRequestMetrics,
|
|
863
1133
|
runtimeMetrics,
|
|
864
1134
|
loggerInstrumentation,
|
|
865
1135
|
exceptionCapture,
|
|
866
|
-
instrumentations
|
|
1136
|
+
instrumentations,
|
|
1137
|
+
diagnostics
|
|
867
1138
|
);
|
|
1139
|
+
diagnostics.activate();
|
|
868
1140
|
activeRuntime = runtime;
|
|
869
1141
|
return runtime;
|
|
870
|
-
} catch {
|
|
1142
|
+
} catch (error) {
|
|
1143
|
+
diagnostics.failure("sdk", "initialization", error);
|
|
871
1144
|
loggerInstrumentation?.disable();
|
|
872
1145
|
runtimeMetrics?.stop();
|
|
873
1146
|
exceptionCapture?.stop();
|
|
@@ -882,7 +1155,9 @@ function observe(options = {}) {
|
|
|
882
1155
|
meterProvider?.shutdown(),
|
|
883
1156
|
loggerProvider?.shutdown()
|
|
884
1157
|
].filter((item) => Boolean(item)));
|
|
885
|
-
|
|
1158
|
+
diagnostics.inactive();
|
|
1159
|
+
if (config.failFast) throw toError(error);
|
|
1160
|
+
return new InactiveObserveHandle(config, diagnostics);
|
|
886
1161
|
}
|
|
887
1162
|
}
|
|
888
1163
|
|