@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.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 = {}) {
|
|
@@ -450,7 +563,7 @@ var SEVERITY_NUMBER = {
|
|
|
450
563
|
};
|
|
451
564
|
var OpenTelemetryLogEmitter = class {
|
|
452
565
|
logger;
|
|
453
|
-
constructor(name = "@
|
|
566
|
+
constructor(name = "@ryanzeng/nest-observe", version, logger) {
|
|
454
567
|
this.logger = logger ?? logs.getLogger(name, version);
|
|
455
568
|
}
|
|
456
569
|
emit(record) {
|
|
@@ -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
|
|
|
@@ -596,21 +711,136 @@ var RuntimeMetrics = class {
|
|
|
596
711
|
};
|
|
597
712
|
|
|
598
713
|
// src/resource.ts
|
|
714
|
+
import {
|
|
715
|
+
defaultResource,
|
|
716
|
+
resourceFromAttributes
|
|
717
|
+
} from "@opentelemetry/resources";
|
|
599
718
|
import { hostname } from "os";
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
var
|
|
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;
|
|
603
831
|
function createObserveResource(config) {
|
|
604
|
-
return defaultResource().merge(
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
832
|
+
return defaultResource().merge(
|
|
833
|
+
resourceFromAttributes({
|
|
834
|
+
...config.resourceAttributes,
|
|
835
|
+
"service.name": config.serviceName,
|
|
836
|
+
"service.version": config.serviceVersion,
|
|
837
|
+
"deployment.environment.name": config.environment,
|
|
838
|
+
"service.instance.id": config.instanceId,
|
|
839
|
+
"telemetry.sdk.name": SDK_NAME,
|
|
840
|
+
"telemetry.sdk.version": SDK_VERSION,
|
|
841
|
+
"host.name": config.resourceAttributes["host.name"] ?? hostname()
|
|
842
|
+
})
|
|
843
|
+
);
|
|
614
844
|
}
|
|
615
845
|
|
|
616
846
|
// src/security/span-redaction-processor.ts
|
|
@@ -654,14 +884,23 @@ var SpanRedactionProcessor = class {
|
|
|
654
884
|
|
|
655
885
|
// src/sdk.ts
|
|
656
886
|
var InactiveObserveHandle = class {
|
|
657
|
-
constructor(config) {
|
|
887
|
+
constructor(config, diagnostics) {
|
|
658
888
|
this.config = config;
|
|
889
|
+
this.diagnostics = diagnostics;
|
|
659
890
|
}
|
|
660
891
|
config;
|
|
892
|
+
diagnostics;
|
|
661
893
|
started = false;
|
|
662
894
|
tracerProvider = void 0;
|
|
663
895
|
meterProvider = void 0;
|
|
664
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
|
+
}
|
|
665
904
|
forceFlush() {
|
|
666
905
|
return Promise.resolve();
|
|
667
906
|
}
|
|
@@ -670,52 +909,73 @@ var InactiveObserveHandle = class {
|
|
|
670
909
|
}
|
|
671
910
|
};
|
|
672
911
|
var ActiveObserveHandle = class {
|
|
673
|
-
constructor(config, tracerProvider, meterProvider, loggerProvider, runtimeMetrics, loggerInstrumentation, exceptionCapture, instrumentations) {
|
|
912
|
+
constructor(config, tracerProvider, meterProvider, loggerProvider, httpRequestMetrics, runtimeMetrics, loggerInstrumentation, exceptionCapture, instrumentations, diagnostics) {
|
|
674
913
|
this.config = config;
|
|
675
914
|
this.tracerProvider = tracerProvider;
|
|
676
915
|
this.meterProvider = meterProvider;
|
|
677
916
|
this.loggerProvider = loggerProvider;
|
|
917
|
+
this.httpRequestMetrics = httpRequestMetrics;
|
|
678
918
|
this.runtimeMetrics = runtimeMetrics;
|
|
679
919
|
this.loggerInstrumentation = loggerInstrumentation;
|
|
680
920
|
this.exceptionCapture = exceptionCapture;
|
|
681
921
|
this.instrumentations = instrumentations;
|
|
922
|
+
this.diagnostics = diagnostics;
|
|
682
923
|
}
|
|
683
924
|
config;
|
|
684
925
|
tracerProvider;
|
|
685
926
|
meterProvider;
|
|
686
927
|
loggerProvider;
|
|
928
|
+
httpRequestMetrics;
|
|
687
929
|
runtimeMetrics;
|
|
688
930
|
loggerInstrumentation;
|
|
689
931
|
exceptionCapture;
|
|
690
932
|
instrumentations;
|
|
933
|
+
diagnostics;
|
|
691
934
|
started = true;
|
|
692
935
|
stopped = false;
|
|
936
|
+
get status() {
|
|
937
|
+
return this.diagnostics.status;
|
|
938
|
+
}
|
|
939
|
+
get lastError() {
|
|
940
|
+
return this.diagnostics.lastError;
|
|
941
|
+
}
|
|
693
942
|
async forceFlush() {
|
|
694
|
-
await
|
|
695
|
-
this.tracerProvider
|
|
696
|
-
this.meterProvider
|
|
697
|
-
this.loggerProvider
|
|
698
|
-
]
|
|
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
|
+
]);
|
|
699
948
|
}
|
|
700
949
|
async shutdown() {
|
|
701
950
|
if (this.stopped) return;
|
|
702
951
|
this.stopped = true;
|
|
703
952
|
this.loggerInstrumentation?.disable();
|
|
704
|
-
this.runtimeMetrics?.stop();
|
|
705
953
|
this.exceptionCapture.stop();
|
|
706
954
|
for (const instrumentation of this.instrumentations) {
|
|
707
955
|
try {
|
|
708
956
|
instrumentation.disable();
|
|
709
|
-
} catch {
|
|
957
|
+
} catch (error) {
|
|
958
|
+
this.diagnostics.failure("sdk", "shutdown", error);
|
|
710
959
|
}
|
|
711
960
|
}
|
|
712
961
|
await this.forceFlush();
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
this.
|
|
716
|
-
this.
|
|
717
|
-
|
|
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
|
+
]);
|
|
718
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
|
+
}));
|
|
719
979
|
}
|
|
720
980
|
};
|
|
721
981
|
var activeRuntime;
|
|
@@ -726,12 +986,16 @@ function exporterConfig(url, config) {
|
|
|
726
986
|
timeoutMillis: config.exportTimeoutMillis
|
|
727
987
|
};
|
|
728
988
|
}
|
|
729
|
-
function createTraceProvider(config, resource) {
|
|
989
|
+
function createTraceProvider(config, resource, diagnostics) {
|
|
730
990
|
if (!config.traces && !config.metrics) return void 0;
|
|
731
991
|
const spanProcessors = [new SpanRedactionProcessor()];
|
|
732
992
|
if (config.traces) {
|
|
733
993
|
const exporter = config.exporters?.span ?? new OTLPTraceExporter(exporterConfig(config.endpoints.traces, config));
|
|
734
|
-
spanProcessors.push(new BatchSpanProcessor(
|
|
994
|
+
spanProcessors.push(new BatchSpanProcessor(withExporterDiagnostics(
|
|
995
|
+
exporter,
|
|
996
|
+
"traces",
|
|
997
|
+
diagnostics
|
|
998
|
+
), {
|
|
735
999
|
exportTimeoutMillis: config.exportTimeoutMillis,
|
|
736
1000
|
maxQueueSize: 2048,
|
|
737
1001
|
maxExportBatchSize: 512
|
|
@@ -746,14 +1010,18 @@ function createTraceProvider(config, resource) {
|
|
|
746
1010
|
provider.register();
|
|
747
1011
|
return provider;
|
|
748
1012
|
}
|
|
749
|
-
function createMeterProvider(config, resource) {
|
|
1013
|
+
function createMeterProvider(config, resource, diagnostics) {
|
|
750
1014
|
if (!config.metrics) return void 0;
|
|
751
1015
|
let reader;
|
|
752
1016
|
if (config.exporters?.metricReader) {
|
|
753
1017
|
reader = config.exporters.metricReader;
|
|
754
1018
|
} else {
|
|
755
1019
|
reader = new PeriodicExportingMetricReader({
|
|
756
|
-
exporter:
|
|
1020
|
+
exporter: withExporterDiagnostics(
|
|
1021
|
+
new OTLPMetricExporter(exporterConfig(config.endpoints.metrics, config)),
|
|
1022
|
+
"metrics",
|
|
1023
|
+
diagnostics
|
|
1024
|
+
),
|
|
757
1025
|
exportIntervalMillis: config.metricExportIntervalMillis,
|
|
758
1026
|
exportTimeoutMillis: Math.min(config.exportTimeoutMillis, config.metricExportIntervalMillis),
|
|
759
1027
|
cardinalityLimits: { default: 2e3, histogram: 2e3 }
|
|
@@ -771,13 +1039,13 @@ function createMeterProvider(config, resource) {
|
|
|
771
1039
|
metrics.setGlobalMeterProvider(provider);
|
|
772
1040
|
return provider;
|
|
773
1041
|
}
|
|
774
|
-
function createLoggerProvider(config, resource) {
|
|
1042
|
+
function createLoggerProvider(config, resource, diagnostics) {
|
|
775
1043
|
if (!config.logs) return void 0;
|
|
776
1044
|
const exporter = config.exporters?.log ?? new OTLPLogExporter(exporterConfig(config.endpoints.logs, config));
|
|
777
1045
|
const provider = new LoggerProvider({
|
|
778
1046
|
resource,
|
|
779
1047
|
processors: [new BatchLogRecordProcessor({
|
|
780
|
-
exporter,
|
|
1048
|
+
exporter: withExporterDiagnostics(exporter, "logs", diagnostics),
|
|
781
1049
|
exportTimeoutMillis: config.exportTimeoutMillis,
|
|
782
1050
|
maxQueueSize: 2048,
|
|
783
1051
|
maxExportBatchSize: 512
|
|
@@ -789,7 +1057,11 @@ function createLoggerProvider(config, resource) {
|
|
|
789
1057
|
function observe(options = {}) {
|
|
790
1058
|
if (activeRuntime?.started) return activeRuntime;
|
|
791
1059
|
const config = resolveObserveConfig(options);
|
|
792
|
-
|
|
1060
|
+
const diagnostics = new ObserveDiagnostics(config.diagnosticLogging, options.onError);
|
|
1061
|
+
if (!config.enabled) {
|
|
1062
|
+
diagnostics.inactive();
|
|
1063
|
+
return new InactiveObserveHandle(config, diagnostics);
|
|
1064
|
+
}
|
|
793
1065
|
let tracerProvider;
|
|
794
1066
|
let meterProvider;
|
|
795
1067
|
let loggerProvider;
|
|
@@ -799,10 +1071,11 @@ function observe(options = {}) {
|
|
|
799
1071
|
const instrumentations = [];
|
|
800
1072
|
try {
|
|
801
1073
|
const resource = createObserveResource(config);
|
|
802
|
-
meterProvider = createMeterProvider(config, resource);
|
|
1074
|
+
meterProvider = createMeterProvider(config, resource, diagnostics);
|
|
803
1075
|
const meter = meterProvider?.getMeter(SDK_NAME, SDK_VERSION);
|
|
804
|
-
|
|
805
|
-
|
|
1076
|
+
const httpRequestMetrics = meter ? new HttpRequestMetrics(meter, config.serviceName) : void 0;
|
|
1077
|
+
tracerProvider = createTraceProvider(config, resource, diagnostics);
|
|
1078
|
+
loggerProvider = createLoggerProvider(config, resource, diagnostics);
|
|
806
1079
|
runtimeMetrics = meter ? new RuntimeMetrics(meter) : void 0;
|
|
807
1080
|
runtimeMetrics?.start();
|
|
808
1081
|
const otelLogger = loggerProvider?.getLogger(SDK_NAME, SDK_VERSION);
|
|
@@ -817,7 +1090,6 @@ function observe(options = {}) {
|
|
|
817
1090
|
exceptionCapture.start();
|
|
818
1091
|
if (config.traces || config.metrics) {
|
|
819
1092
|
const safeHeaders = config.allowedHeaders.filter((header) => !isSensitiveKey(header));
|
|
820
|
-
const httpRequestMetrics = meter ? new HttpRequestMetrics(meter, config.serviceName) : void 0;
|
|
821
1093
|
instrumentations.push(new HttpInstrumentation({
|
|
822
1094
|
requireParentforOutgoingSpans: false,
|
|
823
1095
|
headersToSpanAttributes: {
|
|
@@ -861,14 +1133,18 @@ function observe(options = {}) {
|
|
|
861
1133
|
tracerProvider,
|
|
862
1134
|
meterProvider,
|
|
863
1135
|
loggerProvider,
|
|
1136
|
+
httpRequestMetrics,
|
|
864
1137
|
runtimeMetrics,
|
|
865
1138
|
loggerInstrumentation,
|
|
866
1139
|
exceptionCapture,
|
|
867
|
-
instrumentations
|
|
1140
|
+
instrumentations,
|
|
1141
|
+
diagnostics
|
|
868
1142
|
);
|
|
1143
|
+
diagnostics.activate();
|
|
869
1144
|
activeRuntime = runtime;
|
|
870
1145
|
return runtime;
|
|
871
|
-
} catch {
|
|
1146
|
+
} catch (error) {
|
|
1147
|
+
diagnostics.failure("sdk", "initialization", error);
|
|
872
1148
|
loggerInstrumentation?.disable();
|
|
873
1149
|
runtimeMetrics?.stop();
|
|
874
1150
|
exceptionCapture?.stop();
|
|
@@ -883,7 +1159,9 @@ function observe(options = {}) {
|
|
|
883
1159
|
meterProvider?.shutdown(),
|
|
884
1160
|
loggerProvider?.shutdown()
|
|
885
1161
|
].filter((item) => Boolean(item)));
|
|
886
|
-
|
|
1162
|
+
diagnostics.inactive();
|
|
1163
|
+
if (config.failFast) throw toError(error);
|
|
1164
|
+
return new InactiveObserveHandle(config, diagnostics);
|
|
887
1165
|
}
|
|
888
1166
|
}
|
|
889
1167
|
|