@stainlessdev/xray-emitter 0.3.1 → 0.4.0
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/{chunk-FGXXKIF7.js → chunk-447Z3SDN.js} +4 -4
- package/dist/{chunk-GYXI3DWB.js → chunk-7EKBXVZE.js} +59 -12
- package/dist/chunk-7EKBXVZE.js.map +1 -0
- package/dist/{chunk-NTIUR3OC.js → chunk-AKPTTC2I.js} +2 -2
- package/dist/{chunk-7KT6EPVZ.js → chunk-BKJO3FLI.js} +1 -1
- package/dist/{chunk-7KT6EPVZ.js.map → chunk-BKJO3FLI.js.map} +1 -1
- package/dist/{chunk-DNBARLGB.cjs → chunk-EPQTFPT7.cjs} +1 -1
- package/dist/{chunk-DNBARLGB.cjs.map → chunk-EPQTFPT7.cjs.map} +1 -1
- package/dist/{chunk-SUVCVINA.cjs → chunk-FZH3IY6R.cjs} +47 -47
- package/dist/{chunk-SUVCVINA.cjs.map → chunk-FZH3IY6R.cjs.map} +1 -1
- package/dist/{chunk-UJWD5CFA.cjs → chunk-IEWCR3GT.cjs} +86 -39
- package/dist/chunk-IEWCR3GT.cjs.map +1 -0
- package/dist/{chunk-CPHFCOA5.cjs → chunk-M6G4PEGF.cjs} +9 -9
- package/dist/{chunk-CPHFCOA5.cjs.map → chunk-M6G4PEGF.cjs.map} +1 -1
- package/dist/{chunk-55YD27PV.cjs → chunk-PIY7CFHY.cjs} +28 -28
- package/dist/{chunk-55YD27PV.cjs.map → chunk-PIY7CFHY.cjs.map} +1 -1
- package/dist/{chunk-DV3MVQBB.js → chunk-W42SQZKN.js} +4 -4
- package/dist/effect.cjs +19 -19
- package/dist/effect.d.cts +3 -3
- package/dist/effect.d.ts +3 -3
- package/dist/effect.js +4 -4
- package/dist/{emitter-Bi_m_w5h.d.cts → emitter-DKki0zYl.d.cts} +1 -1
- package/dist/{emitter-Dy7bRGTq.d.ts → emitter-DT-EuB8s.d.ts} +1 -1
- package/dist/express.cjs +7 -7
- package/dist/express.d.cts +2 -2
- package/dist/express.d.ts +2 -2
- package/dist/express.js +4 -4
- package/dist/fastify.cjs +10 -10
- package/dist/fastify.d.cts +2 -2
- package/dist/fastify.d.ts +2 -2
- package/dist/fastify.js +4 -4
- package/dist/fetch.cjs +5 -5
- package/dist/fetch.d.cts +2 -2
- package/dist/fetch.d.ts +2 -2
- package/dist/fetch.js +4 -4
- package/dist/hono.cjs +9 -9
- package/dist/hono.d.cts +3 -3
- package/dist/hono.d.ts +3 -3
- package/dist/hono.js +4 -4
- package/dist/index.cjs +3 -3
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/internal.cjs +3 -3
- package/dist/internal.d.cts +1 -1
- package/dist/internal.d.ts +1 -1
- package/dist/internal.js +2 -2
- package/dist/next.cjs +42 -8
- package/dist/next.cjs.map +1 -1
- package/dist/next.d.cts +3 -3
- package/dist/next.d.ts +3 -3
- package/dist/next.js +39 -5
- package/dist/next.js.map +1 -1
- package/dist/node.cjs +5 -5
- package/dist/node.d.cts +1 -1
- package/dist/node.d.ts +1 -1
- package/dist/node.js +4 -4
- package/dist/remix.cjs +7 -7
- package/dist/remix.d.cts +3 -3
- package/dist/remix.d.ts +3 -3
- package/dist/remix.js +4 -4
- package/dist/stub.cjs +121 -0
- package/dist/stub.cjs.map +1 -0
- package/dist/stub.d.cts +12 -0
- package/dist/stub.d.ts +12 -0
- package/dist/stub.js +121 -0
- package/dist/stub.js.map +1 -0
- package/dist/{types-BrKvhHbn.d.cts → types-C44Eg-i_.d.cts} +6 -2
- package/dist/{types-BrKvhHbn.d.ts → types-C44Eg-i_.d.ts} +6 -2
- package/package.json +10 -3
- package/dist/chunk-GYXI3DWB.js.map +0 -1
- package/dist/chunk-UJWD5CFA.cjs.map +0 -1
- /package/dist/{chunk-FGXXKIF7.js.map → chunk-447Z3SDN.js.map} +0 -0
- /package/dist/{chunk-NTIUR3OC.js.map → chunk-AKPTTC2I.js.map} +0 -0
- /package/dist/{chunk-DV3MVQBB.js.map → chunk-W42SQZKN.js.map} +0 -0
package/dist/node.cjs
CHANGED
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
|
|
4
4
|
|
|
5
|
-
var
|
|
6
|
-
require('./chunk-
|
|
7
|
-
require('./chunk-
|
|
8
|
-
require('./chunk-
|
|
5
|
+
var _chunkPIY7CFHYcjs = require('./chunk-PIY7CFHY.cjs');
|
|
6
|
+
require('./chunk-IEWCR3GT.cjs');
|
|
7
|
+
require('./chunk-M6G4PEGF.cjs');
|
|
8
|
+
require('./chunk-EPQTFPT7.cjs');
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
|
|
13
|
-
exports.createEmitter =
|
|
13
|
+
exports.createEmitter = _chunkPIY7CFHYcjs.createEmitter; exports.getXrayContext = _chunkPIY7CFHYcjs.getXrayContext; exports.wrapHttpHandler = _chunkPIY7CFHYcjs.wrapHttpHandler;
|
|
14
14
|
//# sourceMappingURL=node.cjs.map
|
package/dist/node.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { j as XrayRuntimeConfig, a as XrayEmitter, e as CaptureConfig, f as RedactionConfig, d as XrayContext, R as RequestLog } from './types-
|
|
1
|
+
import { j as XrayRuntimeConfig, a as XrayEmitter, e as CaptureConfig, f as RedactionConfig, d as XrayContext, R as RequestLog } from './types-C44Eg-i_.cjs';
|
|
2
2
|
import { IncomingMessage, ServerResponse } from 'node:http';
|
|
3
3
|
import '@opentelemetry/sdk-trace-base';
|
|
4
4
|
|
package/dist/node.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { j as XrayRuntimeConfig, a as XrayEmitter, e as CaptureConfig, f as RedactionConfig, d as XrayContext, R as RequestLog } from './types-
|
|
1
|
+
import { j as XrayRuntimeConfig, a as XrayEmitter, e as CaptureConfig, f as RedactionConfig, d as XrayContext, R as RequestLog } from './types-C44Eg-i_.js';
|
|
2
2
|
import { IncomingMessage, ServerResponse } from 'node:http';
|
|
3
3
|
import '@opentelemetry/sdk-trace-base';
|
|
4
4
|
|
package/dist/node.js
CHANGED
|
@@ -2,10 +2,10 @@ import {
|
|
|
2
2
|
createEmitter,
|
|
3
3
|
getXrayContext,
|
|
4
4
|
wrapHttpHandler
|
|
5
|
-
} from "./chunk-
|
|
6
|
-
import "./chunk-
|
|
7
|
-
import "./chunk-
|
|
8
|
-
import "./chunk-
|
|
5
|
+
} from "./chunk-447Z3SDN.js";
|
|
6
|
+
import "./chunk-7EKBXVZE.js";
|
|
7
|
+
import "./chunk-AKPTTC2I.js";
|
|
8
|
+
import "./chunk-BKJO3FLI.js";
|
|
9
9
|
export {
|
|
10
10
|
createEmitter,
|
|
11
11
|
getXrayContext,
|
package/dist/remix.cjs
CHANGED
|
@@ -2,14 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
|
|
4
4
|
|
|
5
|
-
var
|
|
6
|
-
require('./chunk-
|
|
7
|
-
require('./chunk-
|
|
8
|
-
require('./chunk-
|
|
5
|
+
var _chunkFZH3IY6Rcjs = require('./chunk-FZH3IY6R.cjs');
|
|
6
|
+
require('./chunk-IEWCR3GT.cjs');
|
|
7
|
+
require('./chunk-M6G4PEGF.cjs');
|
|
8
|
+
require('./chunk-EPQTFPT7.cjs');
|
|
9
9
|
|
|
10
10
|
// src/remix/remix.ts
|
|
11
11
|
function createEmitter2(config, options) {
|
|
12
|
-
const emitter =
|
|
12
|
+
const emitter = _chunkFZH3IY6Rcjs.createEmitter.call(void 0, config);
|
|
13
13
|
const wrap = ((handler) => wrapRemixRequestHandler(handler, emitter, options));
|
|
14
14
|
wrap.flush = emitter.flush;
|
|
15
15
|
wrap.shutdown = emitter.shutdown;
|
|
@@ -17,7 +17,7 @@ function createEmitter2(config, options) {
|
|
|
17
17
|
}
|
|
18
18
|
function wrapRemixRequestHandler(handler, xray, options) {
|
|
19
19
|
return (request, loadContext) => {
|
|
20
|
-
const wrapped =
|
|
20
|
+
const wrapped = _chunkFZH3IY6Rcjs.wrapFetchPreserve.call(void 0, (req) => handler(req, loadContext), xray, options);
|
|
21
21
|
return wrapped(request);
|
|
22
22
|
};
|
|
23
23
|
}
|
|
@@ -26,5 +26,5 @@ function wrapRemixRequestHandler(handler, xray, options) {
|
|
|
26
26
|
|
|
27
27
|
|
|
28
28
|
|
|
29
|
-
exports.createCoreEmitter =
|
|
29
|
+
exports.createCoreEmitter = _chunkFZH3IY6Rcjs.createEmitter; exports.createEmitter = createEmitter2; exports.getXrayContext = _chunkFZH3IY6Rcjs.getXrayContext; exports.wrapRemixRequestHandler = wrapRemixRequestHandler;
|
|
30
30
|
//# sourceMappingURL=remix.cjs.map
|
package/dist/remix.d.cts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { j as XrayRuntimeConfig, a as XrayEmitter } from './types-
|
|
2
|
-
export { e as CaptureConfig, f as RedactionConfig, R as RequestLog, X as XrayConfig, d as XrayContext } from './types-
|
|
3
|
-
export { c as createCoreEmitter } from './emitter-
|
|
1
|
+
import { j as XrayRuntimeConfig, a as XrayEmitter } from './types-C44Eg-i_.cjs';
|
|
2
|
+
export { e as CaptureConfig, f as RedactionConfig, R as RequestLog, X as XrayConfig, d as XrayContext } from './types-C44Eg-i_.cjs';
|
|
3
|
+
export { c as createCoreEmitter } from './emitter-DKki0zYl.cjs';
|
|
4
4
|
import { WrapOptions } from './fetch.cjs';
|
|
5
5
|
export { getXrayContext } from './fetch.cjs';
|
|
6
6
|
import '@opentelemetry/sdk-trace-base';
|
package/dist/remix.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { j as XrayRuntimeConfig, a as XrayEmitter } from './types-
|
|
2
|
-
export { e as CaptureConfig, f as RedactionConfig, R as RequestLog, X as XrayConfig, d as XrayContext } from './types-
|
|
3
|
-
export { c as createCoreEmitter } from './emitter-
|
|
1
|
+
import { j as XrayRuntimeConfig, a as XrayEmitter } from './types-C44Eg-i_.js';
|
|
2
|
+
export { e as CaptureConfig, f as RedactionConfig, R as RequestLog, X as XrayConfig, d as XrayContext } from './types-C44Eg-i_.js';
|
|
3
|
+
export { c as createCoreEmitter } from './emitter-DT-EuB8s.js';
|
|
4
4
|
import { WrapOptions } from './fetch.js';
|
|
5
5
|
export { getXrayContext } from './fetch.js';
|
|
6
6
|
import '@opentelemetry/sdk-trace-base';
|
package/dist/remix.js
CHANGED
|
@@ -2,10 +2,10 @@ import {
|
|
|
2
2
|
createEmitter,
|
|
3
3
|
getXrayContext,
|
|
4
4
|
wrapFetchPreserve
|
|
5
|
-
} from "./chunk-
|
|
6
|
-
import "./chunk-
|
|
7
|
-
import "./chunk-
|
|
8
|
-
import "./chunk-
|
|
5
|
+
} from "./chunk-W42SQZKN.js";
|
|
6
|
+
import "./chunk-7EKBXVZE.js";
|
|
7
|
+
import "./chunk-AKPTTC2I.js";
|
|
8
|
+
import "./chunk-BKJO3FLI.js";
|
|
9
9
|
|
|
10
10
|
// src/remix/remix.ts
|
|
11
11
|
function createEmitter2(config, options) {
|
package/dist/stub.cjs
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }// src/stub/stub.ts
|
|
2
|
+
var _http = require('http'); var _http2 = _interopRequireDefault(_http);
|
|
3
|
+
var _rootjs = require('@opentelemetry/otlp-transformer/build/src/generated/root.js'); var _rootjs2 = _interopRequireDefault(_rootjs);
|
|
4
|
+
var root = _rootjs2.default;
|
|
5
|
+
var ExportTraceServiceRequest = root.opentelemetry.proto.collector.trace.v1.ExportTraceServiceRequest;
|
|
6
|
+
function decodeAttributes(attrs) {
|
|
7
|
+
const result = {};
|
|
8
|
+
for (const attr of attrs) {
|
|
9
|
+
const v = attr.value;
|
|
10
|
+
if (v == null) continue;
|
|
11
|
+
if (v.stringValue != null) result[attr.key] = v.stringValue;
|
|
12
|
+
else if (v.intValue != null) result[attr.key] = Number(v.intValue);
|
|
13
|
+
else if (v.doubleValue != null) result[attr.key] = v.doubleValue;
|
|
14
|
+
else if (v.boolValue != null) result[attr.key] = v.boolValue;
|
|
15
|
+
else if (_optionalChain([v, 'access', _ => _.arrayValue, 'optionalAccess', _2 => _2.values])) {
|
|
16
|
+
result[attr.key] = v.arrayValue.values.map((item) => item.stringValue).filter((s) => s != null);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
return result;
|
|
20
|
+
}
|
|
21
|
+
function buildCapturedBody(bodyValue, encoding, truncated, sizeBytes) {
|
|
22
|
+
if (bodyValue == null) return void 0;
|
|
23
|
+
return {
|
|
24
|
+
bytes: _nullishCoalesce(sizeBytes, () => ( 0)),
|
|
25
|
+
encoding: _nullishCoalesce(encoding, () => ( "utf8")),
|
|
26
|
+
truncated: _nullishCoalesce(truncated, () => ( false)),
|
|
27
|
+
value: bodyValue
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
function collectHeaders(attrs, prefix) {
|
|
31
|
+
const headers = {};
|
|
32
|
+
let found = false;
|
|
33
|
+
for (const [key, value] of Object.entries(attrs)) {
|
|
34
|
+
if (key.startsWith(prefix)) {
|
|
35
|
+
found = true;
|
|
36
|
+
const headerName = key.slice(prefix.length);
|
|
37
|
+
headers[headerName] = value;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return found ? headers : void 0;
|
|
41
|
+
}
|
|
42
|
+
function spanToRequestLog(attrs) {
|
|
43
|
+
const method = attrs["http.request.method"];
|
|
44
|
+
if (method == null) return void 0;
|
|
45
|
+
return {
|
|
46
|
+
requestId: _nullishCoalesce(attrs["http.request.id"], () => ( "")),
|
|
47
|
+
serviceName: _nullishCoalesce(attrs["service.name"], () => ( "")),
|
|
48
|
+
method,
|
|
49
|
+
url: _nullishCoalesce(attrs["url.full"], () => ( "")),
|
|
50
|
+
route: attrs["http.route"],
|
|
51
|
+
statusCode: attrs["http.response.status_code"],
|
|
52
|
+
durationMs: 0,
|
|
53
|
+
requestHeaders: collectHeaders(attrs, "http.request.header."),
|
|
54
|
+
responseHeaders: collectHeaders(attrs, "http.response.header."),
|
|
55
|
+
requestBody: buildCapturedBody(
|
|
56
|
+
attrs["http.request.body"],
|
|
57
|
+
attrs["http.request.body.encoding"],
|
|
58
|
+
attrs["http.request.body.truncated"],
|
|
59
|
+
attrs["http.request.body.size"]
|
|
60
|
+
),
|
|
61
|
+
responseBody: buildCapturedBody(
|
|
62
|
+
attrs["http.response.body"],
|
|
63
|
+
attrs["http.response.body.encoding"],
|
|
64
|
+
attrs["http.response.body.truncated"],
|
|
65
|
+
attrs["http.response.body.size"]
|
|
66
|
+
),
|
|
67
|
+
tenantId: attrs["stainlessxray.tenant.id"],
|
|
68
|
+
userId: attrs["enduser.id"],
|
|
69
|
+
timestamp: ""
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
function decodeRequestLogs(body) {
|
|
73
|
+
const msg = ExportTraceServiceRequest.decode(body);
|
|
74
|
+
const obj = ExportTraceServiceRequest.toObject(msg, { defaults: true });
|
|
75
|
+
const logs = [];
|
|
76
|
+
for (const rs of _nullishCoalesce(obj.resourceSpans, () => ( []))) {
|
|
77
|
+
for (const ss of _nullishCoalesce(rs.scopeSpans, () => ( []))) {
|
|
78
|
+
for (const span of _nullishCoalesce(ss.spans, () => ( []))) {
|
|
79
|
+
const attrs = decodeAttributes(_nullishCoalesce(span.attributes, () => ( [])));
|
|
80
|
+
const log = spanToRequestLog(attrs);
|
|
81
|
+
if (log) logs.push(log);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return logs;
|
|
86
|
+
}
|
|
87
|
+
function createStub() {
|
|
88
|
+
return new Promise((resolve) => {
|
|
89
|
+
const requestLogs = [];
|
|
90
|
+
const server = _http2.default.createServer((req, res) => {
|
|
91
|
+
if (req.method === "POST" && req.url === "/v1/traces") {
|
|
92
|
+
const chunks = [];
|
|
93
|
+
req.on("data", (chunk) => chunks.push(chunk));
|
|
94
|
+
req.on("end", () => {
|
|
95
|
+
const body = Buffer.concat(chunks);
|
|
96
|
+
const logs = decodeRequestLogs(body);
|
|
97
|
+
requestLogs.push(...logs);
|
|
98
|
+
res.writeHead(200);
|
|
99
|
+
res.end();
|
|
100
|
+
});
|
|
101
|
+
} else {
|
|
102
|
+
res.writeHead(404);
|
|
103
|
+
res.end();
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
server.listen(0, "127.0.0.1", () => {
|
|
107
|
+
const addr = server.address();
|
|
108
|
+
resolve({
|
|
109
|
+
url: `http://127.0.0.1:${addr.port}`,
|
|
110
|
+
requestLogs,
|
|
111
|
+
close() {
|
|
112
|
+
return new Promise((resolve2) => server.close(() => resolve2()));
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
});
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
exports.createStub = createStub;
|
|
121
|
+
//# sourceMappingURL=stub.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["/home/runner/work/xray-emitter-js/xray-emitter-js/dist/stub.cjs","../src/stub/stub.ts"],"names":[],"mappings":"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","file":"/home/runner/work/xray-emitter-js/xray-emitter-js/dist/stub.cjs","sourcesContent":[null,"import http from 'node:http';\nimport type { RequestLog, CapturedBody } from '../core/types';\n\nimport _root from '@opentelemetry/otlp-transformer/build/src/generated/root.js';\n\n// The generated protobuf root has deeply nested namespaces that aren't\n// reflected in its type declarations.\nconst root = _root as any;\nconst ExportTraceServiceRequest =\n root.opentelemetry.proto.collector.trace.v1.ExportTraceServiceRequest;\n\nexport type { RequestLog };\n\nexport interface XrayStub {\n url: string;\n /** Request logs reconstructed from exported spans. */\n requestLogs: RequestLog[];\n close(): Promise<void>;\n}\n\ntype SpanAttributes = Record<string, string | number | boolean | string[]>;\n\nfunction decodeAttributes(attrs: any[]): SpanAttributes {\n const result: SpanAttributes = {};\n for (const attr of attrs) {\n const v = attr.value;\n if (v == null) continue;\n if (v.stringValue != null) result[attr.key] = v.stringValue;\n else if (v.intValue != null) result[attr.key] = Number(v.intValue);\n else if (v.doubleValue != null) result[attr.key] = v.doubleValue;\n else if (v.boolValue != null) result[attr.key] = v.boolValue;\n else if (v.arrayValue?.values) {\n result[attr.key] = v.arrayValue.values\n .map((item: any) => item.stringValue)\n .filter((s: any) => s != null);\n }\n }\n return result;\n}\n\nfunction buildCapturedBody(\n bodyValue: string | undefined,\n encoding: string | undefined,\n truncated: boolean | undefined,\n sizeBytes: number | undefined,\n): CapturedBody | undefined {\n if (bodyValue == null) return undefined;\n return {\n bytes: sizeBytes ?? 0,\n encoding: (encoding as 'utf8' | 'base64') ?? 'utf8',\n truncated: truncated ?? false,\n value: bodyValue,\n };\n}\n\nfunction collectHeaders(\n attrs: SpanAttributes,\n prefix: string,\n): Record<string, string | string[]> | undefined {\n const headers: Record<string, string | string[]> = {};\n let found = false;\n for (const [key, value] of Object.entries(attrs)) {\n if (key.startsWith(prefix)) {\n found = true;\n const headerName = key.slice(prefix.length);\n headers[headerName] = value as string | string[];\n }\n }\n return found ? headers : undefined;\n}\n\nfunction spanToRequestLog(attrs: SpanAttributes): RequestLog | undefined {\n const method = attrs['http.request.method'] as string | undefined;\n if (method == null) return undefined;\n\n return {\n requestId: (attrs['http.request.id'] as string) ?? '',\n serviceName: (attrs['service.name'] as string) ?? '',\n method,\n url: (attrs['url.full'] as string) ?? '',\n route: attrs['http.route'] as string | undefined,\n statusCode: attrs['http.response.status_code'] as number | undefined,\n durationMs: 0,\n requestHeaders: collectHeaders(attrs, 'http.request.header.'),\n responseHeaders: collectHeaders(attrs, 'http.response.header.'),\n requestBody: buildCapturedBody(\n attrs['http.request.body'] as string | undefined,\n attrs['http.request.body.encoding'] as string | undefined,\n attrs['http.request.body.truncated'] as boolean | undefined,\n attrs['http.request.body.size'] as number | undefined,\n ),\n responseBody: buildCapturedBody(\n attrs['http.response.body'] as string | undefined,\n attrs['http.response.body.encoding'] as string | undefined,\n attrs['http.response.body.truncated'] as boolean | undefined,\n attrs['http.response.body.size'] as number | undefined,\n ),\n tenantId: attrs['stainlessxray.tenant.id'] as string | undefined,\n userId: attrs['enduser.id'] as string | undefined,\n timestamp: '',\n };\n}\n\nfunction decodeRequestLogs(body: Buffer): RequestLog[] {\n const msg = ExportTraceServiceRequest.decode(body);\n const obj = ExportTraceServiceRequest.toObject(msg, { defaults: true });\n\n const logs: RequestLog[] = [];\n for (const rs of obj.resourceSpans ?? []) {\n for (const ss of rs.scopeSpans ?? []) {\n for (const span of ss.spans ?? []) {\n const attrs = decodeAttributes(span.attributes ?? []);\n const log = spanToRequestLog(attrs);\n if (log) logs.push(log);\n }\n }\n }\n return logs;\n}\n\nexport function createStub(): Promise<XrayStub> {\n return new Promise((resolve) => {\n const requestLogs: RequestLog[] = [];\n\n const server = http.createServer((req, res) => {\n if (req.method === 'POST' && req.url === '/v1/traces') {\n const chunks: Buffer[] = [];\n req.on('data', (chunk: Buffer) => chunks.push(chunk));\n req.on('end', () => {\n const body = Buffer.concat(chunks);\n const logs = decodeRequestLogs(body);\n requestLogs.push(...logs);\n\n res.writeHead(200);\n res.end();\n });\n } else {\n res.writeHead(404);\n res.end();\n }\n });\n\n server.listen(0, '127.0.0.1', () => {\n const addr = server.address() as import('node:net').AddressInfo;\n resolve({\n url: `http://127.0.0.1:${addr.port}`,\n requestLogs,\n close() {\n return new Promise((resolve) => server.close(() => resolve()));\n },\n });\n });\n });\n}\n"]}
|
package/dist/stub.d.cts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { R as RequestLog } from './types-C44Eg-i_.cjs';
|
|
2
|
+
import '@opentelemetry/sdk-trace-base';
|
|
3
|
+
|
|
4
|
+
interface XrayStub {
|
|
5
|
+
url: string;
|
|
6
|
+
/** Request logs reconstructed from exported spans. */
|
|
7
|
+
requestLogs: RequestLog[];
|
|
8
|
+
close(): Promise<void>;
|
|
9
|
+
}
|
|
10
|
+
declare function createStub(): Promise<XrayStub>;
|
|
11
|
+
|
|
12
|
+
export { RequestLog, type XrayStub, createStub };
|
package/dist/stub.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { R as RequestLog } from './types-C44Eg-i_.js';
|
|
2
|
+
import '@opentelemetry/sdk-trace-base';
|
|
3
|
+
|
|
4
|
+
interface XrayStub {
|
|
5
|
+
url: string;
|
|
6
|
+
/** Request logs reconstructed from exported spans. */
|
|
7
|
+
requestLogs: RequestLog[];
|
|
8
|
+
close(): Promise<void>;
|
|
9
|
+
}
|
|
10
|
+
declare function createStub(): Promise<XrayStub>;
|
|
11
|
+
|
|
12
|
+
export { RequestLog, type XrayStub, createStub };
|
package/dist/stub.js
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
// src/stub/stub.ts
|
|
2
|
+
import http from "http";
|
|
3
|
+
import _root from "@opentelemetry/otlp-transformer/build/src/generated/root.js";
|
|
4
|
+
var root = _root;
|
|
5
|
+
var ExportTraceServiceRequest = root.opentelemetry.proto.collector.trace.v1.ExportTraceServiceRequest;
|
|
6
|
+
function decodeAttributes(attrs) {
|
|
7
|
+
const result = {};
|
|
8
|
+
for (const attr of attrs) {
|
|
9
|
+
const v = attr.value;
|
|
10
|
+
if (v == null) continue;
|
|
11
|
+
if (v.stringValue != null) result[attr.key] = v.stringValue;
|
|
12
|
+
else if (v.intValue != null) result[attr.key] = Number(v.intValue);
|
|
13
|
+
else if (v.doubleValue != null) result[attr.key] = v.doubleValue;
|
|
14
|
+
else if (v.boolValue != null) result[attr.key] = v.boolValue;
|
|
15
|
+
else if (v.arrayValue?.values) {
|
|
16
|
+
result[attr.key] = v.arrayValue.values.map((item) => item.stringValue).filter((s) => s != null);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
return result;
|
|
20
|
+
}
|
|
21
|
+
function buildCapturedBody(bodyValue, encoding, truncated, sizeBytes) {
|
|
22
|
+
if (bodyValue == null) return void 0;
|
|
23
|
+
return {
|
|
24
|
+
bytes: sizeBytes ?? 0,
|
|
25
|
+
encoding: encoding ?? "utf8",
|
|
26
|
+
truncated: truncated ?? false,
|
|
27
|
+
value: bodyValue
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
function collectHeaders(attrs, prefix) {
|
|
31
|
+
const headers = {};
|
|
32
|
+
let found = false;
|
|
33
|
+
for (const [key, value] of Object.entries(attrs)) {
|
|
34
|
+
if (key.startsWith(prefix)) {
|
|
35
|
+
found = true;
|
|
36
|
+
const headerName = key.slice(prefix.length);
|
|
37
|
+
headers[headerName] = value;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return found ? headers : void 0;
|
|
41
|
+
}
|
|
42
|
+
function spanToRequestLog(attrs) {
|
|
43
|
+
const method = attrs["http.request.method"];
|
|
44
|
+
if (method == null) return void 0;
|
|
45
|
+
return {
|
|
46
|
+
requestId: attrs["http.request.id"] ?? "",
|
|
47
|
+
serviceName: attrs["service.name"] ?? "",
|
|
48
|
+
method,
|
|
49
|
+
url: attrs["url.full"] ?? "",
|
|
50
|
+
route: attrs["http.route"],
|
|
51
|
+
statusCode: attrs["http.response.status_code"],
|
|
52
|
+
durationMs: 0,
|
|
53
|
+
requestHeaders: collectHeaders(attrs, "http.request.header."),
|
|
54
|
+
responseHeaders: collectHeaders(attrs, "http.response.header."),
|
|
55
|
+
requestBody: buildCapturedBody(
|
|
56
|
+
attrs["http.request.body"],
|
|
57
|
+
attrs["http.request.body.encoding"],
|
|
58
|
+
attrs["http.request.body.truncated"],
|
|
59
|
+
attrs["http.request.body.size"]
|
|
60
|
+
),
|
|
61
|
+
responseBody: buildCapturedBody(
|
|
62
|
+
attrs["http.response.body"],
|
|
63
|
+
attrs["http.response.body.encoding"],
|
|
64
|
+
attrs["http.response.body.truncated"],
|
|
65
|
+
attrs["http.response.body.size"]
|
|
66
|
+
),
|
|
67
|
+
tenantId: attrs["stainlessxray.tenant.id"],
|
|
68
|
+
userId: attrs["enduser.id"],
|
|
69
|
+
timestamp: ""
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
function decodeRequestLogs(body) {
|
|
73
|
+
const msg = ExportTraceServiceRequest.decode(body);
|
|
74
|
+
const obj = ExportTraceServiceRequest.toObject(msg, { defaults: true });
|
|
75
|
+
const logs = [];
|
|
76
|
+
for (const rs of obj.resourceSpans ?? []) {
|
|
77
|
+
for (const ss of rs.scopeSpans ?? []) {
|
|
78
|
+
for (const span of ss.spans ?? []) {
|
|
79
|
+
const attrs = decodeAttributes(span.attributes ?? []);
|
|
80
|
+
const log = spanToRequestLog(attrs);
|
|
81
|
+
if (log) logs.push(log);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return logs;
|
|
86
|
+
}
|
|
87
|
+
function createStub() {
|
|
88
|
+
return new Promise((resolve) => {
|
|
89
|
+
const requestLogs = [];
|
|
90
|
+
const server = http.createServer((req, res) => {
|
|
91
|
+
if (req.method === "POST" && req.url === "/v1/traces") {
|
|
92
|
+
const chunks = [];
|
|
93
|
+
req.on("data", (chunk) => chunks.push(chunk));
|
|
94
|
+
req.on("end", () => {
|
|
95
|
+
const body = Buffer.concat(chunks);
|
|
96
|
+
const logs = decodeRequestLogs(body);
|
|
97
|
+
requestLogs.push(...logs);
|
|
98
|
+
res.writeHead(200);
|
|
99
|
+
res.end();
|
|
100
|
+
});
|
|
101
|
+
} else {
|
|
102
|
+
res.writeHead(404);
|
|
103
|
+
res.end();
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
server.listen(0, "127.0.0.1", () => {
|
|
107
|
+
const addr = server.address();
|
|
108
|
+
resolve({
|
|
109
|
+
url: `http://127.0.0.1:${addr.port}`,
|
|
110
|
+
requestLogs,
|
|
111
|
+
close() {
|
|
112
|
+
return new Promise((resolve2) => server.close(() => resolve2()));
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
});
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
export {
|
|
119
|
+
createStub
|
|
120
|
+
};
|
|
121
|
+
//# sourceMappingURL=stub.js.map
|
package/dist/stub.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/stub/stub.ts"],"sourcesContent":["import http from 'node:http';\nimport type { RequestLog, CapturedBody } from '../core/types';\n\nimport _root from '@opentelemetry/otlp-transformer/build/src/generated/root.js';\n\n// The generated protobuf root has deeply nested namespaces that aren't\n// reflected in its type declarations.\nconst root = _root as any;\nconst ExportTraceServiceRequest =\n root.opentelemetry.proto.collector.trace.v1.ExportTraceServiceRequest;\n\nexport type { RequestLog };\n\nexport interface XrayStub {\n url: string;\n /** Request logs reconstructed from exported spans. */\n requestLogs: RequestLog[];\n close(): Promise<void>;\n}\n\ntype SpanAttributes = Record<string, string | number | boolean | string[]>;\n\nfunction decodeAttributes(attrs: any[]): SpanAttributes {\n const result: SpanAttributes = {};\n for (const attr of attrs) {\n const v = attr.value;\n if (v == null) continue;\n if (v.stringValue != null) result[attr.key] = v.stringValue;\n else if (v.intValue != null) result[attr.key] = Number(v.intValue);\n else if (v.doubleValue != null) result[attr.key] = v.doubleValue;\n else if (v.boolValue != null) result[attr.key] = v.boolValue;\n else if (v.arrayValue?.values) {\n result[attr.key] = v.arrayValue.values\n .map((item: any) => item.stringValue)\n .filter((s: any) => s != null);\n }\n }\n return result;\n}\n\nfunction buildCapturedBody(\n bodyValue: string | undefined,\n encoding: string | undefined,\n truncated: boolean | undefined,\n sizeBytes: number | undefined,\n): CapturedBody | undefined {\n if (bodyValue == null) return undefined;\n return {\n bytes: sizeBytes ?? 0,\n encoding: (encoding as 'utf8' | 'base64') ?? 'utf8',\n truncated: truncated ?? false,\n value: bodyValue,\n };\n}\n\nfunction collectHeaders(\n attrs: SpanAttributes,\n prefix: string,\n): Record<string, string | string[]> | undefined {\n const headers: Record<string, string | string[]> = {};\n let found = false;\n for (const [key, value] of Object.entries(attrs)) {\n if (key.startsWith(prefix)) {\n found = true;\n const headerName = key.slice(prefix.length);\n headers[headerName] = value as string | string[];\n }\n }\n return found ? headers : undefined;\n}\n\nfunction spanToRequestLog(attrs: SpanAttributes): RequestLog | undefined {\n const method = attrs['http.request.method'] as string | undefined;\n if (method == null) return undefined;\n\n return {\n requestId: (attrs['http.request.id'] as string) ?? '',\n serviceName: (attrs['service.name'] as string) ?? '',\n method,\n url: (attrs['url.full'] as string) ?? '',\n route: attrs['http.route'] as string | undefined,\n statusCode: attrs['http.response.status_code'] as number | undefined,\n durationMs: 0,\n requestHeaders: collectHeaders(attrs, 'http.request.header.'),\n responseHeaders: collectHeaders(attrs, 'http.response.header.'),\n requestBody: buildCapturedBody(\n attrs['http.request.body'] as string | undefined,\n attrs['http.request.body.encoding'] as string | undefined,\n attrs['http.request.body.truncated'] as boolean | undefined,\n attrs['http.request.body.size'] as number | undefined,\n ),\n responseBody: buildCapturedBody(\n attrs['http.response.body'] as string | undefined,\n attrs['http.response.body.encoding'] as string | undefined,\n attrs['http.response.body.truncated'] as boolean | undefined,\n attrs['http.response.body.size'] as number | undefined,\n ),\n tenantId: attrs['stainlessxray.tenant.id'] as string | undefined,\n userId: attrs['enduser.id'] as string | undefined,\n timestamp: '',\n };\n}\n\nfunction decodeRequestLogs(body: Buffer): RequestLog[] {\n const msg = ExportTraceServiceRequest.decode(body);\n const obj = ExportTraceServiceRequest.toObject(msg, { defaults: true });\n\n const logs: RequestLog[] = [];\n for (const rs of obj.resourceSpans ?? []) {\n for (const ss of rs.scopeSpans ?? []) {\n for (const span of ss.spans ?? []) {\n const attrs = decodeAttributes(span.attributes ?? []);\n const log = spanToRequestLog(attrs);\n if (log) logs.push(log);\n }\n }\n }\n return logs;\n}\n\nexport function createStub(): Promise<XrayStub> {\n return new Promise((resolve) => {\n const requestLogs: RequestLog[] = [];\n\n const server = http.createServer((req, res) => {\n if (req.method === 'POST' && req.url === '/v1/traces') {\n const chunks: Buffer[] = [];\n req.on('data', (chunk: Buffer) => chunks.push(chunk));\n req.on('end', () => {\n const body = Buffer.concat(chunks);\n const logs = decodeRequestLogs(body);\n requestLogs.push(...logs);\n\n res.writeHead(200);\n res.end();\n });\n } else {\n res.writeHead(404);\n res.end();\n }\n });\n\n server.listen(0, '127.0.0.1', () => {\n const addr = server.address() as import('node:net').AddressInfo;\n resolve({\n url: `http://127.0.0.1:${addr.port}`,\n requestLogs,\n close() {\n return new Promise((resolve) => server.close(() => resolve()));\n },\n });\n });\n });\n}\n"],"mappings":";AAAA,OAAO,UAAU;AAGjB,OAAO,WAAW;AAIlB,IAAM,OAAO;AACb,IAAM,4BACJ,KAAK,cAAc,MAAM,UAAU,MAAM,GAAG;AAa9C,SAAS,iBAAiB,OAA8B;AACtD,QAAM,SAAyB,CAAC;AAChC,aAAW,QAAQ,OAAO;AACxB,UAAM,IAAI,KAAK;AACf,QAAI,KAAK,KAAM;AACf,QAAI,EAAE,eAAe,KAAM,QAAO,KAAK,GAAG,IAAI,EAAE;AAAA,aACvC,EAAE,YAAY,KAAM,QAAO,KAAK,GAAG,IAAI,OAAO,EAAE,QAAQ;AAAA,aACxD,EAAE,eAAe,KAAM,QAAO,KAAK,GAAG,IAAI,EAAE;AAAA,aAC5C,EAAE,aAAa,KAAM,QAAO,KAAK,GAAG,IAAI,EAAE;AAAA,aAC1C,EAAE,YAAY,QAAQ;AAC7B,aAAO,KAAK,GAAG,IAAI,EAAE,WAAW,OAC7B,IAAI,CAAC,SAAc,KAAK,WAAW,EACnC,OAAO,CAAC,MAAW,KAAK,IAAI;AAAA,IACjC;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,kBACP,WACA,UACA,WACA,WAC0B;AAC1B,MAAI,aAAa,KAAM,QAAO;AAC9B,SAAO;AAAA,IACL,OAAO,aAAa;AAAA,IACpB,UAAW,YAAkC;AAAA,IAC7C,WAAW,aAAa;AAAA,IACxB,OAAO;AAAA,EACT;AACF;AAEA,SAAS,eACP,OACA,QAC+C;AAC/C,QAAM,UAA6C,CAAC;AACpD,MAAI,QAAQ;AACZ,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,KAAK,GAAG;AAChD,QAAI,IAAI,WAAW,MAAM,GAAG;AAC1B,cAAQ;AACR,YAAM,aAAa,IAAI,MAAM,OAAO,MAAM;AAC1C,cAAQ,UAAU,IAAI;AAAA,IACxB;AAAA,EACF;AACA,SAAO,QAAQ,UAAU;AAC3B;AAEA,SAAS,iBAAiB,OAA+C;AACvE,QAAM,SAAS,MAAM,qBAAqB;AAC1C,MAAI,UAAU,KAAM,QAAO;AAE3B,SAAO;AAAA,IACL,WAAY,MAAM,iBAAiB,KAAgB;AAAA,IACnD,aAAc,MAAM,cAAc,KAAgB;AAAA,IAClD;AAAA,IACA,KAAM,MAAM,UAAU,KAAgB;AAAA,IACtC,OAAO,MAAM,YAAY;AAAA,IACzB,YAAY,MAAM,2BAA2B;AAAA,IAC7C,YAAY;AAAA,IACZ,gBAAgB,eAAe,OAAO,sBAAsB;AAAA,IAC5D,iBAAiB,eAAe,OAAO,uBAAuB;AAAA,IAC9D,aAAa;AAAA,MACX,MAAM,mBAAmB;AAAA,MACzB,MAAM,4BAA4B;AAAA,MAClC,MAAM,6BAA6B;AAAA,MACnC,MAAM,wBAAwB;AAAA,IAChC;AAAA,IACA,cAAc;AAAA,MACZ,MAAM,oBAAoB;AAAA,MAC1B,MAAM,6BAA6B;AAAA,MACnC,MAAM,8BAA8B;AAAA,MACpC,MAAM,yBAAyB;AAAA,IACjC;AAAA,IACA,UAAU,MAAM,yBAAyB;AAAA,IACzC,QAAQ,MAAM,YAAY;AAAA,IAC1B,WAAW;AAAA,EACb;AACF;AAEA,SAAS,kBAAkB,MAA4B;AACrD,QAAM,MAAM,0BAA0B,OAAO,IAAI;AACjD,QAAM,MAAM,0BAA0B,SAAS,KAAK,EAAE,UAAU,KAAK,CAAC;AAEtE,QAAM,OAAqB,CAAC;AAC5B,aAAW,MAAM,IAAI,iBAAiB,CAAC,GAAG;AACxC,eAAW,MAAM,GAAG,cAAc,CAAC,GAAG;AACpC,iBAAW,QAAQ,GAAG,SAAS,CAAC,GAAG;AACjC,cAAM,QAAQ,iBAAiB,KAAK,cAAc,CAAC,CAAC;AACpD,cAAM,MAAM,iBAAiB,KAAK;AAClC,YAAI,IAAK,MAAK,KAAK,GAAG;AAAA,MACxB;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAEO,SAAS,aAAgC;AAC9C,SAAO,IAAI,QAAQ,CAAC,YAAY;AAC9B,UAAM,cAA4B,CAAC;AAEnC,UAAM,SAAS,KAAK,aAAa,CAAC,KAAK,QAAQ;AAC7C,UAAI,IAAI,WAAW,UAAU,IAAI,QAAQ,cAAc;AACrD,cAAM,SAAmB,CAAC;AAC1B,YAAI,GAAG,QAAQ,CAAC,UAAkB,OAAO,KAAK,KAAK,CAAC;AACpD,YAAI,GAAG,OAAO,MAAM;AAClB,gBAAM,OAAO,OAAO,OAAO,MAAM;AACjC,gBAAM,OAAO,kBAAkB,IAAI;AACnC,sBAAY,KAAK,GAAG,IAAI;AAExB,cAAI,UAAU,GAAG;AACjB,cAAI,IAAI;AAAA,QACV,CAAC;AAAA,MACH,OAAO;AACL,YAAI,UAAU,GAAG;AACjB,YAAI,IAAI;AAAA,MACV;AAAA,IACF,CAAC;AAED,WAAO,OAAO,GAAG,aAAa,MAAM;AAClC,YAAM,OAAO,OAAO,QAAQ;AAC5B,cAAQ;AAAA,QACN,KAAK,oBAAoB,KAAK,IAAI;AAAA,QAClC;AAAA,QACA,QAAQ;AACN,iBAAO,IAAI,QAAQ,CAACA,aAAY,OAAO,MAAM,MAAMA,SAAQ,CAAC,CAAC;AAAA,QAC/D;AAAA,MACF,CAAC;AAAA,IACH,CAAC;AAAA,EACH,CAAC;AACH;","names":["resolve"]}
|
|
@@ -309,6 +309,10 @@ interface RequestLog {
|
|
|
309
309
|
* Custom attributes added via `setAttribute`.
|
|
310
310
|
*/
|
|
311
311
|
attributes?: Record<string, AttributeValue>;
|
|
312
|
+
/**
|
|
313
|
+
* Custom tags added via `setTag`.
|
|
314
|
+
*/
|
|
315
|
+
tags?: Record<string, AttributeValue>;
|
|
312
316
|
/**
|
|
313
317
|
* ISO timestamp for when request processing completed.
|
|
314
318
|
*/
|
|
@@ -346,9 +350,9 @@ interface XrayContext {
|
|
|
346
350
|
*/
|
|
347
351
|
setSessionId(id: string): void;
|
|
348
352
|
/**
|
|
349
|
-
*
|
|
353
|
+
* Set an arbitrary user-defined key/value tag on the request.
|
|
350
354
|
*/
|
|
351
|
-
|
|
355
|
+
setTag(key: string, value: AttributeValue): void;
|
|
352
356
|
/**
|
|
353
357
|
* Add a span event for the current request.
|
|
354
358
|
*/
|
|
@@ -309,6 +309,10 @@ interface RequestLog {
|
|
|
309
309
|
* Custom attributes added via `setAttribute`.
|
|
310
310
|
*/
|
|
311
311
|
attributes?: Record<string, AttributeValue>;
|
|
312
|
+
/**
|
|
313
|
+
* Custom tags added via `setTag`.
|
|
314
|
+
*/
|
|
315
|
+
tags?: Record<string, AttributeValue>;
|
|
312
316
|
/**
|
|
313
317
|
* ISO timestamp for when request processing completed.
|
|
314
318
|
*/
|
|
@@ -346,9 +350,9 @@ interface XrayContext {
|
|
|
346
350
|
*/
|
|
347
351
|
setSessionId(id: string): void;
|
|
348
352
|
/**
|
|
349
|
-
*
|
|
353
|
+
* Set an arbitrary user-defined key/value tag on the request.
|
|
350
354
|
*/
|
|
351
|
-
|
|
355
|
+
setTag(key: string, value: AttributeValue): void;
|
|
352
356
|
/**
|
|
353
357
|
* Add a span event for the current request.
|
|
354
358
|
*/
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stainlessdev/xray-emitter",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -56,6 +56,11 @@
|
|
|
56
56
|
"types": "./dist/effect.d.ts",
|
|
57
57
|
"import": "./dist/effect.js",
|
|
58
58
|
"require": "./dist/effect.cjs"
|
|
59
|
+
},
|
|
60
|
+
"./stub": {
|
|
61
|
+
"types": "./dist/stub.d.ts",
|
|
62
|
+
"import": "./dist/stub.js",
|
|
63
|
+
"require": "./dist/stub.cjs"
|
|
59
64
|
}
|
|
60
65
|
},
|
|
61
66
|
"files": [
|
|
@@ -65,6 +70,7 @@
|
|
|
65
70
|
"@opentelemetry/api": "^1.9.0",
|
|
66
71
|
"@opentelemetry/core": "^2.2.0",
|
|
67
72
|
"@opentelemetry/exporter-trace-otlp-proto": "^0.200.0",
|
|
73
|
+
"@opentelemetry/otlp-transformer": "^0.200.0",
|
|
68
74
|
"@opentelemetry/resources": "^2.2.0",
|
|
69
75
|
"@opentelemetry/sdk-trace-base": "^2.2.0",
|
|
70
76
|
"@opentelemetry/semantic-conventions": "^1.29.0"
|
|
@@ -73,8 +79,8 @@
|
|
|
73
79
|
"@effect/platform": "^0.94.0",
|
|
74
80
|
"@types/express": "^5.0.0",
|
|
75
81
|
"@types/node": "^20.19.29",
|
|
76
|
-
"esbuild": "^0.25.0",
|
|
77
82
|
"effect": "^3.19.0",
|
|
83
|
+
"esbuild": "^0.25.0",
|
|
78
84
|
"express": "^5.2.1",
|
|
79
85
|
"fastify": "^5.6.2",
|
|
80
86
|
"hono": "^4.11.4",
|
|
@@ -102,6 +108,7 @@
|
|
|
102
108
|
"example:hono": "pnpm --filter ./examples/hono start",
|
|
103
109
|
"example:next": "pnpm --filter ./examples/next-app start",
|
|
104
110
|
"example:node-http": "pnpm --filter ./examples/node-http start",
|
|
105
|
-
"example:remix": "pnpm --filter ./examples/remix-app start"
|
|
111
|
+
"example:remix": "pnpm --filter ./examples/remix-app start",
|
|
112
|
+
"examples:smoke": "./scripts/smoke-examples.sh"
|
|
106
113
|
}
|
|
107
114
|
}
|