@stainlessdev/xray-core 0.3.1 → 0.4.0-branch.bg-rework-exporters.8c5264b
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/dist/index.cjs +43 -128
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +4 -3
- package/dist/index.d.ts +4 -3
- package/dist/index.js +53 -131
- package/dist/index.js.map +1 -1
- package/dist/internal.d.cts +2 -1
- package/dist/internal.d.ts +2 -1
- package/dist/{types-D3Vzw_TA.d.cts → types-BA4cE85r.d.cts} +10 -8
- package/dist/{types-D3Vzw_TA.d.ts → types-BA4cE85r.d.ts} +10 -8
- package/package.json +1 -3
package/dist/index.js
CHANGED
|
@@ -118,13 +118,10 @@ var defaultRoute = {
|
|
|
118
118
|
normalize: true,
|
|
119
119
|
normalizer: normalizeRoutePattern
|
|
120
120
|
};
|
|
121
|
-
var DEFAULT_ENDPOINT_URL = "http://localhost:4318";
|
|
122
121
|
var defaultExporterBase = {
|
|
123
|
-
endpointUrl: DEFAULT_ENDPOINT_URL,
|
|
124
122
|
headers: {},
|
|
125
|
-
timeoutMs:
|
|
126
|
-
spanProcessor: "batch"
|
|
127
|
-
sampler: { type: "ratio", ratio: 1 }
|
|
123
|
+
timeoutMs: 3e4,
|
|
124
|
+
spanProcessor: "batch"
|
|
128
125
|
};
|
|
129
126
|
var XrayConfigError = class extends Error {
|
|
130
127
|
constructor(code, message) {
|
|
@@ -217,29 +214,23 @@ function normalizeExporter(endpointUrl, cfg) {
|
|
|
217
214
|
const resolvedEndpoint = normalizeExporterEndpoint(cfg?.endpointUrl ?? endpointUrl);
|
|
218
215
|
const rawHeaders = cfg?.headers ?? defaultExporterBase.headers ?? {};
|
|
219
216
|
const parsed = applyEndpointAuth(resolvedEndpoint, rawHeaders);
|
|
220
|
-
const enabled = cfg?.enabled ?? true;
|
|
221
217
|
const exporter = {
|
|
222
|
-
...defaultExporterBase,
|
|
223
|
-
...cfg,
|
|
224
|
-
enabled,
|
|
225
218
|
endpointUrl: parsed.endpointUrl,
|
|
226
219
|
headers: parsed.headers,
|
|
227
220
|
timeoutMs: cfg?.timeoutMs ?? defaultExporterBase.timeoutMs,
|
|
228
|
-
spanProcessor: cfg?.spanProcessor ?? defaultExporterBase.spanProcessor
|
|
229
|
-
sampler: cfg?.sampler ?? defaultExporterBase.sampler
|
|
221
|
+
spanProcessor: cfg?.spanProcessor ?? defaultExporterBase.spanProcessor
|
|
230
222
|
};
|
|
231
|
-
if (exporter.sampler.type === "ratio") {
|
|
232
|
-
const ratio = exporter.sampler.ratio ?? 1;
|
|
233
|
-
if (!Number.isFinite(ratio) || ratio < 0 || ratio > 1) {
|
|
234
|
-
throw new XrayConfigError("INVALID_EXPORTER", "sampler.ratio must be between 0 and 1");
|
|
235
|
-
}
|
|
236
|
-
exporter.sampler = { type: "ratio", ratio };
|
|
237
|
-
}
|
|
238
223
|
return exporter;
|
|
239
224
|
}
|
|
240
225
|
function normalizeExporterEndpoint(endpointUrl) {
|
|
241
226
|
const envUrl = typeof process !== "undefined" ? process.env?.["STAINLESS_XRAY_ENDPOINT_URL"] : void 0;
|
|
242
|
-
const resolved = endpointUrl ?? envUrl
|
|
227
|
+
const resolved = endpointUrl ?? envUrl;
|
|
228
|
+
if (!resolved || !resolved.trim()) {
|
|
229
|
+
throw new XrayConfigError(
|
|
230
|
+
"INVALID_CONFIG",
|
|
231
|
+
"endpointUrl is required (set endpointUrl or STAINLESS_XRAY_ENDPOINT_URL)"
|
|
232
|
+
);
|
|
233
|
+
}
|
|
243
234
|
const trimmed = resolved.trim();
|
|
244
235
|
const withoutTrailingSlash = trimmed.endsWith("/") ? trimmed.slice(0, -1) : trimmed;
|
|
245
236
|
if (withoutTrailingSlash.endsWith("/v1/traces")) {
|
|
@@ -667,6 +658,18 @@ function redactJsonPath(value, segments, replacement) {
|
|
|
667
658
|
}
|
|
668
659
|
}
|
|
669
660
|
|
|
661
|
+
// src/attributes.ts
|
|
662
|
+
import {
|
|
663
|
+
ATTR_HTTP_REQUEST_BODY_SIZE,
|
|
664
|
+
ATTR_HTTP_REQUEST_METHOD,
|
|
665
|
+
ATTR_HTTP_RESPONSE_BODY_SIZE,
|
|
666
|
+
ATTR_HTTP_RESPONSE_STATUS_CODE,
|
|
667
|
+
ATTR_HTTP_ROUTE,
|
|
668
|
+
ATTR_URL_FULL,
|
|
669
|
+
ATTR_URL_PATH,
|
|
670
|
+
ATTR_USER_ID
|
|
671
|
+
} from "@opentelemetry/semantic-conventions/incubating";
|
|
672
|
+
|
|
670
673
|
// src/attrkey.ts
|
|
671
674
|
var AttributeKeyRequestBody = "http.request.body";
|
|
672
675
|
var AttributeKeyRequestBodyEncoding = "http.request.body.encoding";
|
|
@@ -678,14 +681,6 @@ var AttributeKeyResponseBodyTruncated = "http.response.body.truncated";
|
|
|
678
681
|
var AttributeKeySpanDrop = "stainlessxray.internal.drop";
|
|
679
682
|
|
|
680
683
|
// src/attributes.ts
|
|
681
|
-
var attributeKeyEndUserId = "enduser.id";
|
|
682
|
-
var attributeKeyHttpRequestBodySize = "http.request.body.size";
|
|
683
|
-
var attributeKeyHttpRequestMethod = "http.request.method";
|
|
684
|
-
var attributeKeyHttpResponseBodySize = "http.response.body.size";
|
|
685
|
-
var attributeKeyHttpResponseStatusCode = "http.response.status_code";
|
|
686
|
-
var attributeKeyHttpRoute = "http.route";
|
|
687
|
-
var attributeKeyUrlPath = "url.path";
|
|
688
|
-
var attributeKeyUrlFull = "url.full";
|
|
689
684
|
function setHeaderAttributes(span, headers, prefix) {
|
|
690
685
|
if (!headers) {
|
|
691
686
|
return;
|
|
@@ -700,12 +695,12 @@ function setHeaderAttributes(span, headers, prefix) {
|
|
|
700
695
|
}
|
|
701
696
|
}
|
|
702
697
|
function setRequestAttributes(span, method, urlFull) {
|
|
703
|
-
span.setAttribute(
|
|
698
|
+
span.setAttribute(ATTR_HTTP_REQUEST_METHOD, method);
|
|
704
699
|
if (urlFull) {
|
|
705
|
-
span.setAttribute(
|
|
700
|
+
span.setAttribute(ATTR_URL_FULL, urlFull);
|
|
706
701
|
const path = extractPath(urlFull);
|
|
707
702
|
if (path) {
|
|
708
|
-
span.setAttribute(
|
|
703
|
+
span.setAttribute(ATTR_URL_PATH, path);
|
|
709
704
|
}
|
|
710
705
|
}
|
|
711
706
|
}
|
|
@@ -728,7 +723,7 @@ function setRequestBodyAttributes(span, body) {
|
|
|
728
723
|
}
|
|
729
724
|
}
|
|
730
725
|
function setRequestBodySizeAttribute(span, size) {
|
|
731
|
-
span.setAttribute(
|
|
726
|
+
span.setAttribute(ATTR_HTTP_REQUEST_BODY_SIZE, size);
|
|
732
727
|
}
|
|
733
728
|
function setResponseBodyAttributes(span, body) {
|
|
734
729
|
if (!body.value) {
|
|
@@ -741,18 +736,18 @@ function setResponseBodyAttributes(span, body) {
|
|
|
741
736
|
}
|
|
742
737
|
}
|
|
743
738
|
function setResponseBodySizeAttribute(span, size) {
|
|
744
|
-
span.setAttribute(
|
|
739
|
+
span.setAttribute(ATTR_HTTP_RESPONSE_BODY_SIZE, size);
|
|
745
740
|
}
|
|
746
741
|
function setResponseStatusAttribute(span, statusCode) {
|
|
747
|
-
span.setAttribute(
|
|
742
|
+
span.setAttribute(ATTR_HTTP_RESPONSE_STATUS_CODE, statusCode);
|
|
748
743
|
}
|
|
749
744
|
function setRouteAttribute(span, route) {
|
|
750
745
|
if (route) {
|
|
751
|
-
span.setAttribute(
|
|
746
|
+
span.setAttribute(ATTR_HTTP_ROUTE, route);
|
|
752
747
|
}
|
|
753
748
|
}
|
|
754
749
|
function setUserIdAttribute(span, userId) {
|
|
755
|
-
span.setAttribute(
|
|
750
|
+
span.setAttribute(ATTR_USER_ID, userId);
|
|
756
751
|
}
|
|
757
752
|
function setRequestIdAttribute(span, requestId) {
|
|
758
753
|
span.setAttribute(AttributeKeyRequestID, requestId);
|
|
@@ -765,14 +760,11 @@ import {
|
|
|
765
760
|
SpanKind,
|
|
766
761
|
SpanStatusCode
|
|
767
762
|
} from "@opentelemetry/api";
|
|
768
|
-
import { ExportResultCode } from "@opentelemetry/core";
|
|
769
763
|
import {
|
|
770
|
-
AlwaysOffSampler,
|
|
771
764
|
AlwaysOnSampler,
|
|
772
765
|
BasicTracerProvider,
|
|
773
766
|
BatchSpanProcessor,
|
|
774
|
-
SimpleSpanProcessor
|
|
775
|
-
TraceIdRatioBasedSampler
|
|
767
|
+
SimpleSpanProcessor
|
|
776
768
|
} from "@opentelemetry/sdk-trace-base";
|
|
777
769
|
import { resourceFromAttributes } from "@opentelemetry/resources";
|
|
778
770
|
import {
|
|
@@ -781,12 +773,8 @@ import {
|
|
|
781
773
|
ATTR_TELEMETRY_SDK_NAME,
|
|
782
774
|
ATTR_TELEMETRY_SDK_VERSION
|
|
783
775
|
} from "@opentelemetry/semantic-conventions";
|
|
784
|
-
import { JsonTraceSerializer, ProtobufTraceSerializer } from "@opentelemetry/otlp-transformer";
|
|
785
776
|
var defaultAttributeCountLimit = 128;
|
|
786
|
-
function createTracerProvider(config) {
|
|
787
|
-
if (!config.exporter.enabled || !config.exporter.endpointUrl) {
|
|
788
|
-
return null;
|
|
789
|
-
}
|
|
777
|
+
function createTracerProvider(config, exporter) {
|
|
790
778
|
if (config.exporter.endpointUrl.startsWith("http://")) {
|
|
791
779
|
diag.warn("xray: OTLP endpoint uses plaintext HTTP");
|
|
792
780
|
}
|
|
@@ -797,12 +785,6 @@ function createTracerProvider(config) {
|
|
|
797
785
|
[ATTR_TELEMETRY_SDK_NAME]: "stainless-xray",
|
|
798
786
|
[ATTR_TELEMETRY_SDK_VERSION]: sdkVersion()
|
|
799
787
|
});
|
|
800
|
-
const exporter = new FetchSpanExporter({
|
|
801
|
-
endpointUrl: config.exporter.endpointUrl,
|
|
802
|
-
headers: config.exporter.headers ?? {},
|
|
803
|
-
timeoutMillis: config.exporter.timeoutMs
|
|
804
|
-
});
|
|
805
|
-
const sampler = createSampler(config);
|
|
806
788
|
const spanProcessor = createSpanProcessor(config.exporter.spanProcessor, exporter);
|
|
807
789
|
const dropProcessor = new DropFilterSpanProcessor(spanProcessor);
|
|
808
790
|
const provider = new BasicTracerProvider({
|
|
@@ -812,7 +794,7 @@ function createTracerProvider(config) {
|
|
|
812
794
|
attributeValueLengthLimit
|
|
813
795
|
},
|
|
814
796
|
resource,
|
|
815
|
-
sampler,
|
|
797
|
+
sampler: new AlwaysOnSampler(),
|
|
816
798
|
spanLimits: {
|
|
817
799
|
attributeCountLimit: defaultAttributeCountLimit,
|
|
818
800
|
attributePerEventCountLimit: defaultAttributeCountLimit,
|
|
@@ -861,69 +843,6 @@ var DropFilterSpanProcessor = class {
|
|
|
861
843
|
return this.next.shutdown();
|
|
862
844
|
}
|
|
863
845
|
};
|
|
864
|
-
var FetchSpanExporter = class {
|
|
865
|
-
constructor(options) {
|
|
866
|
-
this.endpointUrl = options.endpointUrl;
|
|
867
|
-
this.headers = { ...options.headers };
|
|
868
|
-
this.timeoutMillis = options.timeoutMillis;
|
|
869
|
-
this.isShutdown = false;
|
|
870
|
-
const protobufSerializer = ProtobufTraceSerializer && typeof ProtobufTraceSerializer.serializeRequest === "function" ? ProtobufTraceSerializer : null;
|
|
871
|
-
this.serializer = protobufSerializer ?? JsonTraceSerializer;
|
|
872
|
-
this.contentType = protobufSerializer ? "application/x-protobuf" : "application/json";
|
|
873
|
-
}
|
|
874
|
-
export(spans, resultCallback) {
|
|
875
|
-
if (this.isShutdown) {
|
|
876
|
-
resultCallback({ code: ExportResultCode.FAILED });
|
|
877
|
-
return;
|
|
878
|
-
}
|
|
879
|
-
const payload = this.serializer.serializeRequest(spans);
|
|
880
|
-
if (!payload) {
|
|
881
|
-
resultCallback({
|
|
882
|
-
code: ExportResultCode.FAILED,
|
|
883
|
-
error: new Error("OTLP export failed: empty payload")
|
|
884
|
-
});
|
|
885
|
-
return;
|
|
886
|
-
}
|
|
887
|
-
const headers = {
|
|
888
|
-
...this.headers,
|
|
889
|
-
"Content-Type": this.contentType
|
|
890
|
-
};
|
|
891
|
-
const controller = typeof AbortController !== "undefined" ? new AbortController() : null;
|
|
892
|
-
let timeout;
|
|
893
|
-
if (controller) {
|
|
894
|
-
timeout = setTimeout(() => controller.abort(), this.timeoutMillis);
|
|
895
|
-
}
|
|
896
|
-
const doExport = async () => {
|
|
897
|
-
const response = await fetch(this.endpointUrl, {
|
|
898
|
-
method: "POST",
|
|
899
|
-
headers,
|
|
900
|
-
body: payload,
|
|
901
|
-
signal: controller?.signal
|
|
902
|
-
});
|
|
903
|
-
if (!response.ok) {
|
|
904
|
-
throw new Error(`OTLP export failed: ${response.status}`);
|
|
905
|
-
}
|
|
906
|
-
};
|
|
907
|
-
doExport().then(() => {
|
|
908
|
-
if (timeout) {
|
|
909
|
-
clearTimeout(timeout);
|
|
910
|
-
}
|
|
911
|
-
resultCallback({ code: ExportResultCode.SUCCESS });
|
|
912
|
-
}).catch((err) => {
|
|
913
|
-
if (timeout) {
|
|
914
|
-
clearTimeout(timeout);
|
|
915
|
-
}
|
|
916
|
-
diag.error("OTLP export failed", err);
|
|
917
|
-
resultCallback({ code: ExportResultCode.FAILED, error: err });
|
|
918
|
-
});
|
|
919
|
-
}
|
|
920
|
-
async forceFlush() {
|
|
921
|
-
return;
|
|
922
|
-
}
|
|
923
|
-
async shutdown() {
|
|
924
|
-
this.isShutdown = true;
|
|
925
|
-
}
|
|
926
|
-
};
|
|
927
846
|
function createSpanProcessor(mode, exporter) {
|
|
928
847
|
if (mode === "simple") {
|
|
929
848
|
return new SimpleSpanProcessor(exporter);
|
|
@@ -935,19 +854,9 @@ function createSpanProcessor(mode, exporter) {
|
|
|
935
854
|
exportTimeoutMillis: 3e4
|
|
936
855
|
});
|
|
937
856
|
}
|
|
938
|
-
function createSampler(config) {
|
|
939
|
-
const sampler = config.exporter.sampler;
|
|
940
|
-
if (sampler.type === "always_off") {
|
|
941
|
-
return new AlwaysOffSampler();
|
|
942
|
-
}
|
|
943
|
-
if (sampler.type === "ratio") {
|
|
944
|
-
return new TraceIdRatioBasedSampler(sampler.ratio ?? 1);
|
|
945
|
-
}
|
|
946
|
-
return new AlwaysOnSampler();
|
|
947
|
-
}
|
|
948
857
|
function sdkVersion() {
|
|
949
858
|
if (true) {
|
|
950
|
-
return "0.
|
|
859
|
+
return "0.4.0";
|
|
951
860
|
}
|
|
952
861
|
return "unknown";
|
|
953
862
|
}
|
|
@@ -976,16 +885,29 @@ function uuidv7() {
|
|
|
976
885
|
}
|
|
977
886
|
|
|
978
887
|
// src/emitter.ts
|
|
979
|
-
function createEmitter(config) {
|
|
888
|
+
function createEmitter(config, exporter) {
|
|
980
889
|
const resolved = normalizeConfig(config);
|
|
981
|
-
|
|
982
|
-
|
|
890
|
+
if (!exporter) {
|
|
891
|
+
throw new XrayConfigError(
|
|
892
|
+
"INVALID_CONFIG",
|
|
893
|
+
"exporter is required (use @stainlessdev/xray-node or @stainlessdev/xray-fetch)"
|
|
894
|
+
);
|
|
895
|
+
}
|
|
896
|
+
logWithLevel(resolved.logger, "info", resolved.logLevel, "xray: emitter configured", {
|
|
897
|
+
serviceName: resolved.serviceName,
|
|
898
|
+
environment: resolved.environment,
|
|
899
|
+
version: resolved.version,
|
|
900
|
+
exporterEndpoint: resolved.exporter.endpointUrl,
|
|
901
|
+
spanProcessor: resolved.exporter.spanProcessor
|
|
902
|
+
});
|
|
903
|
+
const tracerProvider = createTracerProvider(resolved, exporter);
|
|
904
|
+
const tracer = tracerFromProvider(tracerProvider);
|
|
983
905
|
return {
|
|
984
906
|
config: resolved,
|
|
985
907
|
startRequest: (req) => startRequest(resolved, tracer, req),
|
|
986
908
|
endRequest: (ctx, res, err) => endRequest(resolved, ctx, res, err),
|
|
987
|
-
flush: () => tracerProvider
|
|
988
|
-
shutdown: () => tracerProvider
|
|
909
|
+
flush: () => tracerProvider.forceFlush(),
|
|
910
|
+
shutdown: () => tracerProvider.shutdown()
|
|
989
911
|
};
|
|
990
912
|
}
|
|
991
913
|
function startRequest(config, tracer, req) {
|
|
@@ -996,7 +918,7 @@ function startRequest(config, tracer, req) {
|
|
|
996
918
|
if (req.route && config.route.normalize) {
|
|
997
919
|
req.route = config.route.normalizer ? config.route.normalizer(req.route) : normalizeRoutePattern(req.route);
|
|
998
920
|
}
|
|
999
|
-
const span =
|
|
921
|
+
const span = spanFromTracer(tracer, spanNameFromRequest(req));
|
|
1000
922
|
const context = {
|
|
1001
923
|
requestId,
|
|
1002
924
|
traceId: span?.spanContext().traceId,
|