Skip to content

Commit ca3de0b

Browse files
committed
add payload to the exporter
1 parent 347cb7f commit ca3de0b

4 files changed

Lines changed: 93 additions & 2 deletions

File tree

packages/agent/src/export/exporter.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,8 @@ export class OTLPExporter {
128128
const durationMs = event.metricName === "memory-leak" ? 0 : event.value;
129129

130130
return {
131-
traceId: crypto.randomBytes(16).toString("hex"),
131+
traceId:
132+
(event.payload.traceId as string | undefined) ?? crypto.randomBytes(16).toString("hex"),
132133
spanId: crypto.randomBytes(8).toString("hex"),
133134
name: event.metricName,
134135
kind: 1, // SPAN_KIND_INTERNAL

packages/agent/src/export/otlp-compatible-exporter.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,10 @@ export class OTLPCompatibleExporter {
5050
const nowNsStr = nowNs.toString();
5151

5252
const dataPoints = events.map((e) => ({
53-
attributes: [{ key: "metric.name", value: { stringValue: e.metricName } }],
53+
attributes: [
54+
{ key: "metric.name", value: { stringValue: e.metricName } },
55+
{ key: "argus.payload", value: { stringValue: JSON.stringify(e.payload) } },
56+
],
5457
startTimeUnixNano: nowNsStr,
5558
timeUnixNano: nowNsStr,
5659
asDouble: e.value,

packages/agent/tests/export/exporter.test.ts

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,42 @@ describe("OTLPExporter", () => {
3434
);
3535
});
3636

37+
it("uses traceId from payload when present instead of generating a random one", () => {
38+
const exporter = new OTLPExporter({
39+
endpointUrl: "https://localhost",
40+
key: "test",
41+
cert: "test",
42+
ca: "test",
43+
});
44+
45+
const knownTraceId = "a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4";
46+
const events: AggregatorEvent[] = [
47+
{ id: "1", metricName: "query", value: 50, payload: { traceId: knownTraceId } },
48+
];
49+
50+
const payload = exporter.formatToOTLP(events);
51+
const span = payload.resourceSpans[0].scopeSpans[0].spans[0];
52+
53+
assert.strictEqual(span.traceId, knownTraceId);
54+
});
55+
56+
it("falls back to a random traceId when payload has no traceId", () => {
57+
const exporter = new OTLPExporter({
58+
endpointUrl: "https://localhost",
59+
key: "test",
60+
cert: "test",
61+
ca: "test",
62+
});
63+
64+
const events: AggregatorEvent[] = [{ id: "1", metricName: "query", value: 50, payload: {} }];
65+
66+
const payload = exporter.formatToOTLP(events);
67+
const span = payload.resourceSpans[0].scopeSpans[0].spans[0];
68+
69+
assert.ok(span.traceId.length === 32, "fallback traceId must be 32 hex chars");
70+
assert.ok(/^[0-9a-f]+$/.test(span.traceId), "fallback traceId must be hex");
71+
});
72+
3773
// Bug: retry delay used retryDelayMs * attempt (linear) but JSDoc promised "doubles each attempt".
3874
// With maxRetries=3 the 3rd retry diverges: linear gives 300ms, exponential gives 400ms.
3975
it("should use exponential backoff — delay doubles each retry attempt", async () => {

packages/agent/tests/export/otlp-compatible-exporter.test.ts

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,57 @@ describe("OTLPCompatibleExporter", () => {
152152
}
153153
});
154154

155+
it("data points include argus.payload attribute with full event payload as JSON", async () => {
156+
let receivedBody = "";
157+
const server = http.createServer((req, res) => {
158+
let d = "";
159+
req.on("data", (c) => {
160+
d += String(c);
161+
});
162+
req.on("end", () => {
163+
receivedBody = d;
164+
res.writeHead(200).end();
165+
});
166+
});
167+
168+
await new Promise<void>((r) => server.listen(0, "127.0.0.1", r));
169+
const { port } = server.address() as { port: number };
170+
171+
try {
172+
const exporter = new OTLPCompatibleExporter({
173+
endpointUrl: `http://127.0.0.1:${port}/v1/metrics`,
174+
});
175+
const payload = { sanitizedQuery: "SELECT ?", suggestions: [{ message: "add index" }] };
176+
await exporter.export([makeEvent({ payload })]);
177+
178+
const parsed = JSON.parse(receivedBody) as {
179+
resourceMetrics: [
180+
{
181+
scopeMetrics: [
182+
{
183+
metrics: [
184+
{
185+
gauge: {
186+
dataPoints: {
187+
attributes: { key: string; value: { stringValue: string } }[];
188+
}[];
189+
};
190+
},
191+
];
192+
},
193+
];
194+
},
195+
];
196+
};
197+
const dp = parsed.resourceMetrics[0].scopeMetrics[0].metrics[0].gauge.dataPoints[0];
198+
const payloadAttr = dp.attributes.find((a) => a.key === "argus.payload");
199+
assert.ok(payloadAttr, "argus.payload attribute must be present");
200+
assert.deepStrictEqual(JSON.parse(payloadAttr.value.stringValue), payload);
201+
} finally {
202+
await new Promise<void>((r) => server.close(() => r()));
203+
}
204+
});
205+
155206
it("OTLP body contains service.name attribute", async () => {
156207
let receivedBody = "";
157208
const server = http.createServer((req, res) => {

0 commit comments

Comments
 (0)