@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/index.js
CHANGED
|
@@ -32,6 +32,7 @@ __export(index_exports, {
|
|
|
32
32
|
CompatibleNestInstrumentation: () => CompatibleNestInstrumentation,
|
|
33
33
|
HttpRequestMetrics: () => HttpRequestMetrics,
|
|
34
34
|
IgnoreTrace: () => IgnoreTrace,
|
|
35
|
+
NestHttpMetricsInterceptor: () => NestHttpMetricsInterceptor,
|
|
35
36
|
NestLoggerInstrumentation: () => NestLoggerInstrumentation,
|
|
36
37
|
NestMethodInstrumenter: () => NestMethodInstrumenter,
|
|
37
38
|
OBSERVE_HANDLE: () => OBSERVE_HANDLE,
|
|
@@ -139,7 +140,9 @@ function resolveObserveConfig(options = {}, env = process.env) {
|
|
|
139
140
|
allowedHeaders,
|
|
140
141
|
exportTimeoutMillis: positiveInteger(options.exportTimeoutMillis ?? env.OTEL_EXPORTER_OTLP_TIMEOUT, 1e4),
|
|
141
142
|
metricExportIntervalMillis: positiveInteger(options.metricExportIntervalMillis ?? env.OTEL_METRIC_EXPORT_INTERVAL, 6e4),
|
|
142
|
-
resourceAttributes
|
|
143
|
+
resourceAttributes,
|
|
144
|
+
diagnosticLogging: booleanValue(options.diagnosticLogging, true),
|
|
145
|
+
failFast: booleanValue(options.failFast, false)
|
|
143
146
|
};
|
|
144
147
|
if (options.exporters) result.exporters = options.exporters;
|
|
145
148
|
return result;
|
|
@@ -335,7 +338,13 @@ var SEVERITY = {
|
|
|
335
338
|
};
|
|
336
339
|
function bodyValue(message) {
|
|
337
340
|
if (message instanceof Error) return redactText(message.stack ?? `${message.name}: ${message.message}`);
|
|
338
|
-
|
|
341
|
+
const sanitized = redact(message);
|
|
342
|
+
if (sanitized === null || typeof sanitized !== "object") return sanitized;
|
|
343
|
+
try {
|
|
344
|
+
return JSON.stringify(sanitized, (_key, value) => typeof value === "bigint" ? value.toString() : value);
|
|
345
|
+
} catch {
|
|
346
|
+
return redactText(String(sanitized));
|
|
347
|
+
}
|
|
339
348
|
}
|
|
340
349
|
var NestLoggerInstrumentation = class {
|
|
341
350
|
constructor(emitter, resourceAttributes = {}) {
|
|
@@ -569,9 +578,14 @@ var HttpRequestMetrics = class {
|
|
|
569
578
|
errorCount;
|
|
570
579
|
startedAt = /* @__PURE__ */ new WeakMap();
|
|
571
580
|
start(request) {
|
|
581
|
+
if (this.startedAt.has(request)) return false;
|
|
572
582
|
this.startedAt.set(request, process.hrtime.bigint());
|
|
583
|
+
return true;
|
|
573
584
|
}
|
|
574
585
|
record(request, response) {
|
|
586
|
+
const started = this.startedAt.get(request);
|
|
587
|
+
if (started === void 0) return false;
|
|
588
|
+
this.startedAt.delete(request);
|
|
575
589
|
const statusCode = Number.isFinite(response.statusCode) ? response.statusCode : 0;
|
|
576
590
|
const attributes = {
|
|
577
591
|
"service.name": this.serviceName,
|
|
@@ -580,12 +594,9 @@ var HttpRequestMetrics = class {
|
|
|
580
594
|
"http.response.status_code": statusCode
|
|
581
595
|
};
|
|
582
596
|
this.requestCount.add(1, attributes);
|
|
583
|
-
|
|
584
|
-
if (started !== void 0) {
|
|
585
|
-
this.requestDuration.record(Number(process.hrtime.bigint() - started) / 1e9, attributes);
|
|
586
|
-
this.startedAt.delete(request);
|
|
587
|
-
}
|
|
597
|
+
this.requestDuration.record(Number(process.hrtime.bigint() - started) / 1e9, attributes);
|
|
588
598
|
if (statusCode >= 500) this.errorCount.add(1, attributes);
|
|
599
|
+
return true;
|
|
589
600
|
}
|
|
590
601
|
};
|
|
591
602
|
|
|
@@ -674,6 +685,7 @@ var RuntimeMetrics = class {
|
|
|
674
685
|
var import_common2 = require("@nestjs/common");
|
|
675
686
|
var import_core = require("@nestjs/core");
|
|
676
687
|
var import_api7 = require("@opentelemetry/api");
|
|
688
|
+
var import_rxjs2 = require("rxjs");
|
|
677
689
|
|
|
678
690
|
// src/sdk.ts
|
|
679
691
|
var import_api_logs2 = require("@opentelemetry/api-logs");
|
|
@@ -689,6 +701,113 @@ var import_sdk_metrics = require("@opentelemetry/sdk-metrics");
|
|
|
689
701
|
var import_sdk_trace_base = require("@opentelemetry/sdk-trace-base");
|
|
690
702
|
var import_sdk_trace_node = require("@opentelemetry/sdk-trace-node");
|
|
691
703
|
|
|
704
|
+
// src/diagnostics.ts
|
|
705
|
+
function toError(value) {
|
|
706
|
+
if (value instanceof Error) return value;
|
|
707
|
+
if (typeof value === "string") return new Error(value);
|
|
708
|
+
try {
|
|
709
|
+
return new Error(JSON.stringify(value));
|
|
710
|
+
} catch {
|
|
711
|
+
return new Error(String(value));
|
|
712
|
+
}
|
|
713
|
+
}
|
|
714
|
+
function sanitizeError(error) {
|
|
715
|
+
const sanitized = new Error(redactText(error.message));
|
|
716
|
+
sanitized.name = error.name;
|
|
717
|
+
if (error.stack) sanitized.stack = redactText(error.stack);
|
|
718
|
+
return sanitized;
|
|
719
|
+
}
|
|
720
|
+
var ObserveDiagnostics = class {
|
|
721
|
+
constructor(logging, onError) {
|
|
722
|
+
this.logging = logging;
|
|
723
|
+
this.onError = onError;
|
|
724
|
+
}
|
|
725
|
+
logging;
|
|
726
|
+
onError;
|
|
727
|
+
currentStatus = "starting";
|
|
728
|
+
currentError;
|
|
729
|
+
failedSignals = /* @__PURE__ */ new Set();
|
|
730
|
+
reported = /* @__PURE__ */ new Set();
|
|
731
|
+
get status() {
|
|
732
|
+
return this.currentStatus;
|
|
733
|
+
}
|
|
734
|
+
get lastError() {
|
|
735
|
+
return this.currentError;
|
|
736
|
+
}
|
|
737
|
+
activate() {
|
|
738
|
+
if (this.currentStatus === "starting") this.currentStatus = "active";
|
|
739
|
+
}
|
|
740
|
+
inactive() {
|
|
741
|
+
this.currentStatus = "inactive";
|
|
742
|
+
}
|
|
743
|
+
stop() {
|
|
744
|
+
this.currentStatus = "stopped";
|
|
745
|
+
}
|
|
746
|
+
success(signal) {
|
|
747
|
+
this.failedSignals.delete(signal);
|
|
748
|
+
for (const fingerprint of this.reported) {
|
|
749
|
+
if (fingerprint.startsWith(`${signal}\0`)) this.reported.delete(fingerprint);
|
|
750
|
+
}
|
|
751
|
+
if (this.currentStatus === "degraded" && this.failedSignals.size === 0) {
|
|
752
|
+
this.currentStatus = "active";
|
|
753
|
+
}
|
|
754
|
+
}
|
|
755
|
+
failure(signal, stage, value) {
|
|
756
|
+
const error = sanitizeError(toError(value));
|
|
757
|
+
const event = { signal, stage, error, timestamp: Date.now() };
|
|
758
|
+
this.currentError = event;
|
|
759
|
+
this.failedSignals.add(signal);
|
|
760
|
+
if (this.currentStatus !== "inactive" && this.currentStatus !== "stopped") {
|
|
761
|
+
this.currentStatus = "degraded";
|
|
762
|
+
}
|
|
763
|
+
const fingerprint = `${signal}\0${stage}\0${error.name}\0${error.message}`;
|
|
764
|
+
if (this.reported.has(fingerprint)) return;
|
|
765
|
+
this.reported.add(fingerprint);
|
|
766
|
+
try {
|
|
767
|
+
this.onError?.(event);
|
|
768
|
+
} catch {
|
|
769
|
+
}
|
|
770
|
+
if (!this.logging) return;
|
|
771
|
+
try {
|
|
772
|
+
process.stderr.write(
|
|
773
|
+
`[nest-observe] ${signal} ${stage} failed: ${redactText(error.message)}
|
|
774
|
+
`
|
|
775
|
+
);
|
|
776
|
+
} catch {
|
|
777
|
+
}
|
|
778
|
+
}
|
|
779
|
+
};
|
|
780
|
+
function withExporterDiagnostics(exporter, signal, diagnostics) {
|
|
781
|
+
const delegate = exporter;
|
|
782
|
+
return new Proxy(exporter, {
|
|
783
|
+
get(target, property) {
|
|
784
|
+
if (property === "export") {
|
|
785
|
+
return (items, callback) => {
|
|
786
|
+
try {
|
|
787
|
+
delegate.export.call(target, items, (result) => {
|
|
788
|
+
if (result.code === 0) {
|
|
789
|
+
diagnostics.success(signal);
|
|
790
|
+
} else {
|
|
791
|
+
diagnostics.failure(
|
|
792
|
+
signal,
|
|
793
|
+
"export",
|
|
794
|
+
result.error ?? new Error(`${signal} export failed`)
|
|
795
|
+
);
|
|
796
|
+
}
|
|
797
|
+
callback(result);
|
|
798
|
+
});
|
|
799
|
+
} catch (error) {
|
|
800
|
+
diagnostics.failure(signal, "export", error);
|
|
801
|
+
throw error;
|
|
802
|
+
}
|
|
803
|
+
};
|
|
804
|
+
}
|
|
805
|
+
const value = Reflect.get(target, property, target);
|
|
806
|
+
return typeof value === "function" ? value.bind(target) : value;
|
|
807
|
+
}
|
|
808
|
+
});
|
|
809
|
+
}
|
|
810
|
+
|
|
692
811
|
// src/exceptions/process-exception-capture.ts
|
|
693
812
|
var import_api5 = require("@opentelemetry/api");
|
|
694
813
|
function asError(value) {
|
|
@@ -738,8 +857,118 @@ var ProcessExceptionCapture = class {
|
|
|
738
857
|
// src/resource.ts
|
|
739
858
|
var import_resources = require("@opentelemetry/resources");
|
|
740
859
|
var import_node_os2 = require("os");
|
|
741
|
-
|
|
742
|
-
|
|
860
|
+
|
|
861
|
+
// package.json
|
|
862
|
+
var package_default = {
|
|
863
|
+
name: "@ryanzeng/nest-observe",
|
|
864
|
+
version: "0.1.2",
|
|
865
|
+
description: "Zero-config, vendor-neutral OpenTelemetry observability for NestJS",
|
|
866
|
+
keywords: [
|
|
867
|
+
"nestjs",
|
|
868
|
+
"opentelemetry",
|
|
869
|
+
"observability",
|
|
870
|
+
"otlp",
|
|
871
|
+
"tracing",
|
|
872
|
+
"metrics",
|
|
873
|
+
"logging"
|
|
874
|
+
],
|
|
875
|
+
license: "MIT",
|
|
876
|
+
homepage: "https://github.com/ryanzen9/nest-observe#readme",
|
|
877
|
+
bugs: {
|
|
878
|
+
url: "https://github.com/ryanzen9/nest-observe/issues"
|
|
879
|
+
},
|
|
880
|
+
repository: {
|
|
881
|
+
type: "git",
|
|
882
|
+
url: "git+https://github.com/ryanzen9/nest-observe.git"
|
|
883
|
+
},
|
|
884
|
+
packageManager: "pnpm@10.13.1",
|
|
885
|
+
sideEffects: [
|
|
886
|
+
"./dist/register.js",
|
|
887
|
+
"./dist/register.mjs"
|
|
888
|
+
],
|
|
889
|
+
main: "./dist/index.js",
|
|
890
|
+
module: "./dist/index.mjs",
|
|
891
|
+
types: "./dist/index.d.ts",
|
|
892
|
+
exports: {
|
|
893
|
+
".": {
|
|
894
|
+
import: {
|
|
895
|
+
types: "./dist/index.d.mts",
|
|
896
|
+
default: "./dist/index.mjs"
|
|
897
|
+
},
|
|
898
|
+
require: {
|
|
899
|
+
types: "./dist/index.d.ts",
|
|
900
|
+
default: "./dist/index.js"
|
|
901
|
+
}
|
|
902
|
+
},
|
|
903
|
+
"./register": {
|
|
904
|
+
import: {
|
|
905
|
+
types: "./dist/register.d.mts",
|
|
906
|
+
default: "./dist/register.mjs"
|
|
907
|
+
},
|
|
908
|
+
require: {
|
|
909
|
+
types: "./dist/register.d.ts",
|
|
910
|
+
default: "./dist/register.js"
|
|
911
|
+
}
|
|
912
|
+
}
|
|
913
|
+
},
|
|
914
|
+
files: [
|
|
915
|
+
"dist",
|
|
916
|
+
"README.md",
|
|
917
|
+
"CHANGELOG.md",
|
|
918
|
+
"LICENSE"
|
|
919
|
+
],
|
|
920
|
+
scripts: {
|
|
921
|
+
build: "tsup",
|
|
922
|
+
test: "vitest run",
|
|
923
|
+
"test:watch": "vitest",
|
|
924
|
+
typecheck: "tsc --noEmit",
|
|
925
|
+
check: "pnpm typecheck && pnpm test && pnpm build"
|
|
926
|
+
},
|
|
927
|
+
engines: {
|
|
928
|
+
node: ">=20"
|
|
929
|
+
},
|
|
930
|
+
peerDependencies: {
|
|
931
|
+
"@nestjs/common": ">=10 <13",
|
|
932
|
+
"@nestjs/core": ">=10 <13",
|
|
933
|
+
"reflect-metadata": ">=0.1.12 <1",
|
|
934
|
+
rxjs: "^7.1.0"
|
|
935
|
+
},
|
|
936
|
+
dependencies: {
|
|
937
|
+
"@opentelemetry/api": "^1.9.0",
|
|
938
|
+
"@opentelemetry/api-logs": "^0.221.0",
|
|
939
|
+
"@opentelemetry/exporter-logs-otlp-proto": "^0.221.0",
|
|
940
|
+
"@opentelemetry/exporter-metrics-otlp-proto": "^0.221.0",
|
|
941
|
+
"@opentelemetry/exporter-trace-otlp-proto": "^0.221.0",
|
|
942
|
+
"@opentelemetry/instrumentation": "^0.221.0",
|
|
943
|
+
"@opentelemetry/instrumentation-http": "^0.221.0",
|
|
944
|
+
"@opentelemetry/instrumentation-nestjs-core": "^0.67.0",
|
|
945
|
+
"@opentelemetry/resources": "^2.10.0",
|
|
946
|
+
"@opentelemetry/sdk-logs": "^0.221.0",
|
|
947
|
+
"@opentelemetry/sdk-metrics": "^2.10.0",
|
|
948
|
+
"@opentelemetry/sdk-trace-base": "^2.10.0",
|
|
949
|
+
"@opentelemetry/sdk-trace-node": "^2.10.0",
|
|
950
|
+
"@prisma/instrumentation": "^7.10.0"
|
|
951
|
+
},
|
|
952
|
+
devDependencies: {
|
|
953
|
+
"@nestjs/common": "^12.0.1",
|
|
954
|
+
"@nestjs/core": "^12.0.1",
|
|
955
|
+
"@nestjs/testing": "^12.0.1",
|
|
956
|
+
"@opentelemetry/sdk-trace-base": "^2.10.0",
|
|
957
|
+
"@types/node": "^24.0.0",
|
|
958
|
+
"reflect-metadata": "^0.2.2",
|
|
959
|
+
rxjs: "^7.8.2",
|
|
960
|
+
tsup: "^8.5.1",
|
|
961
|
+
typescript: "^5.9.3",
|
|
962
|
+
vitest: "^4.1.11"
|
|
963
|
+
},
|
|
964
|
+
publishConfig: {
|
|
965
|
+
access: "public"
|
|
966
|
+
}
|
|
967
|
+
};
|
|
968
|
+
|
|
969
|
+
// src/resource.ts
|
|
970
|
+
var SDK_NAME = package_default.name;
|
|
971
|
+
var SDK_VERSION = package_default.version;
|
|
743
972
|
function createObserveResource(config) {
|
|
744
973
|
return (0, import_resources.defaultResource)().merge(
|
|
745
974
|
(0, import_resources.resourceFromAttributes)({
|
|
@@ -796,14 +1025,23 @@ var SpanRedactionProcessor = class {
|
|
|
796
1025
|
|
|
797
1026
|
// src/sdk.ts
|
|
798
1027
|
var InactiveObserveHandle = class {
|
|
799
|
-
constructor(config) {
|
|
1028
|
+
constructor(config, diagnostics) {
|
|
800
1029
|
this.config = config;
|
|
1030
|
+
this.diagnostics = diagnostics;
|
|
801
1031
|
}
|
|
802
1032
|
config;
|
|
1033
|
+
diagnostics;
|
|
803
1034
|
started = false;
|
|
804
1035
|
tracerProvider = void 0;
|
|
805
1036
|
meterProvider = void 0;
|
|
806
1037
|
loggerProvider = void 0;
|
|
1038
|
+
httpRequestMetrics = void 0;
|
|
1039
|
+
get status() {
|
|
1040
|
+
return this.diagnostics.status;
|
|
1041
|
+
}
|
|
1042
|
+
get lastError() {
|
|
1043
|
+
return this.diagnostics.lastError;
|
|
1044
|
+
}
|
|
807
1045
|
forceFlush() {
|
|
808
1046
|
return Promise.resolve();
|
|
809
1047
|
}
|
|
@@ -812,52 +1050,73 @@ var InactiveObserveHandle = class {
|
|
|
812
1050
|
}
|
|
813
1051
|
};
|
|
814
1052
|
var ActiveObserveHandle = class {
|
|
815
|
-
constructor(config, tracerProvider, meterProvider, loggerProvider, runtimeMetrics, loggerInstrumentation, exceptionCapture, instrumentations) {
|
|
1053
|
+
constructor(config, tracerProvider, meterProvider, loggerProvider, httpRequestMetrics, runtimeMetrics, loggerInstrumentation, exceptionCapture, instrumentations, diagnostics) {
|
|
816
1054
|
this.config = config;
|
|
817
1055
|
this.tracerProvider = tracerProvider;
|
|
818
1056
|
this.meterProvider = meterProvider;
|
|
819
1057
|
this.loggerProvider = loggerProvider;
|
|
1058
|
+
this.httpRequestMetrics = httpRequestMetrics;
|
|
820
1059
|
this.runtimeMetrics = runtimeMetrics;
|
|
821
1060
|
this.loggerInstrumentation = loggerInstrumentation;
|
|
822
1061
|
this.exceptionCapture = exceptionCapture;
|
|
823
1062
|
this.instrumentations = instrumentations;
|
|
1063
|
+
this.diagnostics = diagnostics;
|
|
824
1064
|
}
|
|
825
1065
|
config;
|
|
826
1066
|
tracerProvider;
|
|
827
1067
|
meterProvider;
|
|
828
1068
|
loggerProvider;
|
|
1069
|
+
httpRequestMetrics;
|
|
829
1070
|
runtimeMetrics;
|
|
830
1071
|
loggerInstrumentation;
|
|
831
1072
|
exceptionCapture;
|
|
832
1073
|
instrumentations;
|
|
1074
|
+
diagnostics;
|
|
833
1075
|
started = true;
|
|
834
1076
|
stopped = false;
|
|
1077
|
+
get status() {
|
|
1078
|
+
return this.diagnostics.status;
|
|
1079
|
+
}
|
|
1080
|
+
get lastError() {
|
|
1081
|
+
return this.diagnostics.lastError;
|
|
1082
|
+
}
|
|
835
1083
|
async forceFlush() {
|
|
836
|
-
await
|
|
837
|
-
this.tracerProvider
|
|
838
|
-
this.meterProvider
|
|
839
|
-
this.loggerProvider
|
|
840
|
-
]
|
|
1084
|
+
await this.runSafely("forceFlush", [
|
|
1085
|
+
...this.config.traces && this.tracerProvider ? [["traces", () => this.tracerProvider.forceFlush()]] : [],
|
|
1086
|
+
...this.config.metrics && this.meterProvider ? [["metrics", () => this.meterProvider.forceFlush()]] : [],
|
|
1087
|
+
...this.config.logs && this.loggerProvider ? [["logs", () => this.loggerProvider.forceFlush({ timeoutMillis: this.config.exportTimeoutMillis })]] : []
|
|
1088
|
+
]);
|
|
841
1089
|
}
|
|
842
1090
|
async shutdown() {
|
|
843
1091
|
if (this.stopped) return;
|
|
844
1092
|
this.stopped = true;
|
|
845
1093
|
this.loggerInstrumentation?.disable();
|
|
846
|
-
this.runtimeMetrics?.stop();
|
|
847
1094
|
this.exceptionCapture.stop();
|
|
848
1095
|
for (const instrumentation of this.instrumentations) {
|
|
849
1096
|
try {
|
|
850
1097
|
instrumentation.disable();
|
|
851
|
-
} catch {
|
|
1098
|
+
} catch (error) {
|
|
1099
|
+
this.diagnostics.failure("sdk", "shutdown", error);
|
|
852
1100
|
}
|
|
853
1101
|
}
|
|
854
1102
|
await this.forceFlush();
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
this.
|
|
858
|
-
this.
|
|
859
|
-
|
|
1103
|
+
this.runtimeMetrics?.stop();
|
|
1104
|
+
await this.runSafely("shutdown", [
|
|
1105
|
+
...this.tracerProvider ? [["traces", () => this.tracerProvider.shutdown()]] : [],
|
|
1106
|
+
...this.meterProvider ? [["metrics", () => this.meterProvider.shutdown()]] : [],
|
|
1107
|
+
...this.loggerProvider ? [["logs", () => this.loggerProvider.shutdown()]] : []
|
|
1108
|
+
]);
|
|
860
1109
|
if (activeRuntime === this) activeRuntime = void 0;
|
|
1110
|
+
this.diagnostics.stop();
|
|
1111
|
+
}
|
|
1112
|
+
async runSafely(stage, operations) {
|
|
1113
|
+
await Promise.all(operations.map(async ([signal, operation]) => {
|
|
1114
|
+
try {
|
|
1115
|
+
await operation();
|
|
1116
|
+
} catch (error) {
|
|
1117
|
+
this.diagnostics.failure(signal, stage, error);
|
|
1118
|
+
}
|
|
1119
|
+
}));
|
|
861
1120
|
}
|
|
862
1121
|
};
|
|
863
1122
|
var activeRuntime;
|
|
@@ -868,12 +1127,16 @@ function exporterConfig(url, config) {
|
|
|
868
1127
|
timeoutMillis: config.exportTimeoutMillis
|
|
869
1128
|
};
|
|
870
1129
|
}
|
|
871
|
-
function createTraceProvider(config, resource) {
|
|
1130
|
+
function createTraceProvider(config, resource, diagnostics) {
|
|
872
1131
|
if (!config.traces && !config.metrics) return void 0;
|
|
873
1132
|
const spanProcessors = [new SpanRedactionProcessor()];
|
|
874
1133
|
if (config.traces) {
|
|
875
1134
|
const exporter = config.exporters?.span ?? new import_exporter_trace_otlp_proto.OTLPTraceExporter(exporterConfig(config.endpoints.traces, config));
|
|
876
|
-
spanProcessors.push(new import_sdk_trace_base.BatchSpanProcessor(
|
|
1135
|
+
spanProcessors.push(new import_sdk_trace_base.BatchSpanProcessor(withExporterDiagnostics(
|
|
1136
|
+
exporter,
|
|
1137
|
+
"traces",
|
|
1138
|
+
diagnostics
|
|
1139
|
+
), {
|
|
877
1140
|
exportTimeoutMillis: config.exportTimeoutMillis,
|
|
878
1141
|
maxQueueSize: 2048,
|
|
879
1142
|
maxExportBatchSize: 512
|
|
@@ -888,14 +1151,18 @@ function createTraceProvider(config, resource) {
|
|
|
888
1151
|
provider.register();
|
|
889
1152
|
return provider;
|
|
890
1153
|
}
|
|
891
|
-
function createMeterProvider(config, resource) {
|
|
1154
|
+
function createMeterProvider(config, resource, diagnostics) {
|
|
892
1155
|
if (!config.metrics) return void 0;
|
|
893
1156
|
let reader;
|
|
894
1157
|
if (config.exporters?.metricReader) {
|
|
895
1158
|
reader = config.exporters.metricReader;
|
|
896
1159
|
} else {
|
|
897
1160
|
reader = new import_sdk_metrics.PeriodicExportingMetricReader({
|
|
898
|
-
exporter:
|
|
1161
|
+
exporter: withExporterDiagnostics(
|
|
1162
|
+
new import_exporter_metrics_otlp_proto.OTLPMetricExporter(exporterConfig(config.endpoints.metrics, config)),
|
|
1163
|
+
"metrics",
|
|
1164
|
+
diagnostics
|
|
1165
|
+
),
|
|
899
1166
|
exportIntervalMillis: config.metricExportIntervalMillis,
|
|
900
1167
|
exportTimeoutMillis: Math.min(config.exportTimeoutMillis, config.metricExportIntervalMillis),
|
|
901
1168
|
cardinalityLimits: { default: 2e3, histogram: 2e3 }
|
|
@@ -913,13 +1180,13 @@ function createMeterProvider(config, resource) {
|
|
|
913
1180
|
import_api6.metrics.setGlobalMeterProvider(provider);
|
|
914
1181
|
return provider;
|
|
915
1182
|
}
|
|
916
|
-
function createLoggerProvider(config, resource) {
|
|
1183
|
+
function createLoggerProvider(config, resource, diagnostics) {
|
|
917
1184
|
if (!config.logs) return void 0;
|
|
918
1185
|
const exporter = config.exporters?.log ?? new import_exporter_logs_otlp_proto.OTLPLogExporter(exporterConfig(config.endpoints.logs, config));
|
|
919
1186
|
const provider = new import_sdk_logs.LoggerProvider({
|
|
920
1187
|
resource,
|
|
921
1188
|
processors: [new import_sdk_logs.BatchLogRecordProcessor({
|
|
922
|
-
exporter,
|
|
1189
|
+
exporter: withExporterDiagnostics(exporter, "logs", diagnostics),
|
|
923
1190
|
exportTimeoutMillis: config.exportTimeoutMillis,
|
|
924
1191
|
maxQueueSize: 2048,
|
|
925
1192
|
maxExportBatchSize: 512
|
|
@@ -931,7 +1198,11 @@ function createLoggerProvider(config, resource) {
|
|
|
931
1198
|
function observe(options = {}) {
|
|
932
1199
|
if (activeRuntime?.started) return activeRuntime;
|
|
933
1200
|
const config = resolveObserveConfig(options);
|
|
934
|
-
|
|
1201
|
+
const diagnostics = new ObserveDiagnostics(config.diagnosticLogging, options.onError);
|
|
1202
|
+
if (!config.enabled) {
|
|
1203
|
+
diagnostics.inactive();
|
|
1204
|
+
return new InactiveObserveHandle(config, diagnostics);
|
|
1205
|
+
}
|
|
935
1206
|
let tracerProvider;
|
|
936
1207
|
let meterProvider;
|
|
937
1208
|
let loggerProvider;
|
|
@@ -941,10 +1212,11 @@ function observe(options = {}) {
|
|
|
941
1212
|
const instrumentations = [];
|
|
942
1213
|
try {
|
|
943
1214
|
const resource = createObserveResource(config);
|
|
944
|
-
meterProvider = createMeterProvider(config, resource);
|
|
1215
|
+
meterProvider = createMeterProvider(config, resource, diagnostics);
|
|
945
1216
|
const meter = meterProvider?.getMeter(SDK_NAME, SDK_VERSION);
|
|
946
|
-
|
|
947
|
-
|
|
1217
|
+
const httpRequestMetrics = meter ? new HttpRequestMetrics(meter, config.serviceName) : void 0;
|
|
1218
|
+
tracerProvider = createTraceProvider(config, resource, diagnostics);
|
|
1219
|
+
loggerProvider = createLoggerProvider(config, resource, diagnostics);
|
|
948
1220
|
runtimeMetrics = meter ? new RuntimeMetrics(meter) : void 0;
|
|
949
1221
|
runtimeMetrics?.start();
|
|
950
1222
|
const otelLogger = loggerProvider?.getLogger(SDK_NAME, SDK_VERSION);
|
|
@@ -959,7 +1231,6 @@ function observe(options = {}) {
|
|
|
959
1231
|
exceptionCapture.start();
|
|
960
1232
|
if (config.traces || config.metrics) {
|
|
961
1233
|
const safeHeaders = config.allowedHeaders.filter((header) => !isSensitiveKey(header));
|
|
962
|
-
const httpRequestMetrics = meter ? new HttpRequestMetrics(meter, config.serviceName) : void 0;
|
|
963
1234
|
instrumentations.push(new import_instrumentation_http.HttpInstrumentation({
|
|
964
1235
|
requireParentforOutgoingSpans: false,
|
|
965
1236
|
headersToSpanAttributes: {
|
|
@@ -1003,14 +1274,18 @@ function observe(options = {}) {
|
|
|
1003
1274
|
tracerProvider,
|
|
1004
1275
|
meterProvider,
|
|
1005
1276
|
loggerProvider,
|
|
1277
|
+
httpRequestMetrics,
|
|
1006
1278
|
runtimeMetrics,
|
|
1007
1279
|
loggerInstrumentation,
|
|
1008
1280
|
exceptionCapture,
|
|
1009
|
-
instrumentations
|
|
1281
|
+
instrumentations,
|
|
1282
|
+
diagnostics
|
|
1010
1283
|
);
|
|
1284
|
+
diagnostics.activate();
|
|
1011
1285
|
activeRuntime = runtime;
|
|
1012
1286
|
return runtime;
|
|
1013
|
-
} catch {
|
|
1287
|
+
} catch (error) {
|
|
1288
|
+
diagnostics.failure("sdk", "initialization", error);
|
|
1014
1289
|
loggerInstrumentation?.disable();
|
|
1015
1290
|
runtimeMetrics?.stop();
|
|
1016
1291
|
exceptionCapture?.stop();
|
|
@@ -1025,7 +1300,9 @@ function observe(options = {}) {
|
|
|
1025
1300
|
meterProvider?.shutdown(),
|
|
1026
1301
|
loggerProvider?.shutdown()
|
|
1027
1302
|
].filter((item) => Boolean(item)));
|
|
1028
|
-
|
|
1303
|
+
diagnostics.inactive();
|
|
1304
|
+
if (config.failFast) throw toError(error);
|
|
1305
|
+
return new InactiveObserveHandle(config, diagnostics);
|
|
1029
1306
|
}
|
|
1030
1307
|
}
|
|
1031
1308
|
function getObserveRuntime() {
|
|
@@ -1035,6 +1312,37 @@ function getObserveRuntime() {
|
|
|
1035
1312
|
// src/nest/observe.module.ts
|
|
1036
1313
|
var OBSERVE_OPTIONS = /* @__PURE__ */ Symbol("OBSERVE_OPTIONS");
|
|
1037
1314
|
var OBSERVE_HANDLE = /* @__PURE__ */ Symbol("OBSERVE_HANDLE");
|
|
1315
|
+
var NestHttpMetricsInterceptor = class {
|
|
1316
|
+
constructor(handle) {
|
|
1317
|
+
this.handle = handle;
|
|
1318
|
+
}
|
|
1319
|
+
handle;
|
|
1320
|
+
intercept(context3, next) {
|
|
1321
|
+
if (context3.getType() !== "http" || !this.handle.started || !this.handle.httpRequestMetrics) {
|
|
1322
|
+
return next.handle();
|
|
1323
|
+
}
|
|
1324
|
+
const http = context3.switchToHttp();
|
|
1325
|
+
const request = http.getRequest();
|
|
1326
|
+
const response = http.getResponse();
|
|
1327
|
+
const started = this.handle.httpRequestMetrics.start(request);
|
|
1328
|
+
const result = next.handle();
|
|
1329
|
+
if (!started) return result;
|
|
1330
|
+
const responseEventSource = response.raw ?? response;
|
|
1331
|
+
if (typeof responseEventSource.once === "function") {
|
|
1332
|
+
responseEventSource.once("finish", () => {
|
|
1333
|
+
this.handle.httpRequestMetrics?.record(request, response);
|
|
1334
|
+
});
|
|
1335
|
+
return result;
|
|
1336
|
+
}
|
|
1337
|
+
return result.pipe((0, import_rxjs2.finalize)(() => {
|
|
1338
|
+
this.handle.httpRequestMetrics?.record(request, response);
|
|
1339
|
+
}));
|
|
1340
|
+
}
|
|
1341
|
+
};
|
|
1342
|
+
NestHttpMetricsInterceptor = __decorateClass([
|
|
1343
|
+
(0, import_common2.Injectable)(),
|
|
1344
|
+
__decorateParam(0, (0, import_common2.Inject)(OBSERVE_HANDLE))
|
|
1345
|
+
], NestHttpMetricsInterceptor);
|
|
1038
1346
|
var NestObserveExplorer = class {
|
|
1039
1347
|
constructor(discovery, options, handle) {
|
|
1040
1348
|
this.discovery = discovery;
|
|
@@ -1088,6 +1396,7 @@ var ObserveModule = class {
|
|
|
1088
1396
|
providers: [
|
|
1089
1397
|
{ provide: OBSERVE_OPTIONS, useValue: options },
|
|
1090
1398
|
{ provide: OBSERVE_HANDLE, useFactory: () => observe(options) },
|
|
1399
|
+
{ provide: import_core.APP_INTERCEPTOR, useClass: NestHttpMetricsInterceptor },
|
|
1091
1400
|
NestObserveExplorer
|
|
1092
1401
|
],
|
|
1093
1402
|
exports: [OBSERVE_HANDLE]
|
|
@@ -1103,6 +1412,7 @@ ObserveModule = __decorateClass([
|
|
|
1103
1412
|
CompatibleNestInstrumentation,
|
|
1104
1413
|
HttpRequestMetrics,
|
|
1105
1414
|
IgnoreTrace,
|
|
1415
|
+
NestHttpMetricsInterceptor,
|
|
1106
1416
|
NestLoggerInstrumentation,
|
|
1107
1417
|
NestMethodInstrumenter,
|
|
1108
1418
|
OBSERVE_HANDLE,
|