Skip to content

Commit 49b032a

Browse files
authored
fix(sdk): serialization of Map in sub-objects of inputs and outputs (#323)
1 parent 5e0482e commit 49b032a

File tree

2 files changed

+35
-20
lines changed

2 files changed

+35
-20
lines changed

packages/traceloop-sdk/src/lib/tracing/decorators.ts

+26-11
Original file line numberDiff line numberDiff line change
@@ -79,15 +79,13 @@ function withEntity<
7979
) {
8080
span.setAttribute(
8181
SpanAttributes.TRACELOOP_ENTITY_INPUT,
82-
JSON.stringify({ args: [], kwargs: input[0] }),
82+
serialize({ args: [], kwargs: input[0] }),
8383
);
8484
} else {
8585
span.setAttribute(
8686
SpanAttributes.TRACELOOP_ENTITY_INPUT,
87-
JSON.stringify({
88-
args: input.map((arg) =>
89-
arg instanceof Map ? Array.from(arg.entries()) : arg,
90-
),
87+
serialize({
88+
args: input,
9189
kwargs: {},
9290
}),
9391
);
@@ -107,12 +105,13 @@ function withEntity<
107105
serialize(resolvedRes),
108106
);
109107
}
110-
return resolvedRes;
111108
} catch (error) {
112109
Telemetry.getInstance().logException(error);
113110
} finally {
114111
span.end();
115112
}
113+
114+
return resolvedRes;
116115
});
117116
}
118117
try {
@@ -122,12 +121,13 @@ function withEntity<
122121
serialize(res),
123122
);
124123
}
125-
return res;
126124
} catch (error) {
127125
Telemetry.getInstance().logException(error);
128126
} finally {
129127
span.end();
130128
}
129+
130+
return res;
131131
},
132132
),
133133
);
@@ -248,10 +248,25 @@ export function tool(
248248
return entity(TraceloopSpanKindValues.TOOL, config ?? {});
249249
}
250250

251-
function serialize(input: unknown): string {
251+
function cleanInput(input: unknown): unknown {
252252
if (input instanceof Map) {
253-
return JSON.stringify(Array.from(input.entries()));
254-
} else {
255-
return JSON.stringify(input);
253+
return Array.from(input.entries());
254+
} else if (Array.isArray(input)) {
255+
return input.map((value) => cleanInput(value));
256+
} else if (!input) {
257+
return input;
258+
} else if (typeof input === "object") {
259+
// serialize object one by one
260+
const output: any = {};
261+
Object.entries(input as any).forEach(([key, value]) => {
262+
output[key] = cleanInput(value);
263+
});
264+
return output;
256265
}
266+
267+
return input;
268+
}
269+
270+
function serialize(input: unknown): string {
271+
return JSON.stringify(cleanInput(input));
257272
}

packages/traceloop-sdk/test/decorators.test.ts

+9-9
Original file line numberDiff line numberDiff line change
@@ -233,10 +233,10 @@ describe("Test SDK Decorators", () => {
233233
class TestOpenAI {
234234
constructor(private model = "gpt-3.5-turbo") {}
235235

236-
@traceloop.workflow((thisArg, things) => ({
236+
@traceloop.workflow((thisArg, { things }) => ({
237237
name: `${(thisArg as TestOpenAI).model}_${(things as Map<string, string>).get("joke")}`,
238238
}))
239-
async chat(things: Map<string, string>) {
239+
async chat({ things }: { things: Map<string, string> }) {
240240
const generations: Map<string, string> = new Map();
241241
for await (const [key, value] of things) {
242242
const chatCompletion = await openai.chat.completions.create({
@@ -256,12 +256,12 @@ describe("Test SDK Decorators", () => {
256256
}
257257

258258
const testOpenAI = new TestOpenAI();
259-
const result = await testOpenAI.chat(
260-
new Map([
259+
const result = await testOpenAI.chat({
260+
things: new Map([
261261
["joke", "OpenTelemetry"],
262262
["fact", "JavaScript"],
263263
]),
264-
);
264+
});
265265

266266
const spans = memoryExporter.getFinishedSpans();
267267
const workflowName = "gpt-3.5-turbo_OpenTelemetry";
@@ -287,13 +287,13 @@ describe("Test SDK Decorators", () => {
287287
assert.strictEqual(
288288
workflowSpan.attributes[`${SpanAttributes.TRACELOOP_ENTITY_INPUT}`],
289289
JSON.stringify({
290-
args: [
291-
[
290+
args: [],
291+
kwargs: {
292+
things: [
292293
["joke", "OpenTelemetry"],
293294
["fact", "JavaScript"],
294295
],
295-
],
296-
kwargs: {},
296+
},
297297
}),
298298
);
299299
assert.strictEqual(

0 commit comments

Comments
 (0)