Skip to content

Commit db03d25

Browse files
committed
Support serializing/deserializing empty arrays
1 parent 8977d25 commit db03d25

File tree

5 files changed

+64
-8
lines changed

5 files changed

+64
-8
lines changed

apps/webapp/app/utils/taskEvent.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {
55
isExceptionSpanEvent,
66
millisecondsToNanoseconds,
77
NULL_SENTINEL,
8+
EMPTY_ARRAY_SENTINEL,
89
SemanticInternalAttributes,
910
SpanEvent,
1011
SpanEvents,
@@ -446,6 +447,10 @@ export function rehydrateJson(json: Prisma.JsonValue): any {
446447
return null;
447448
}
448449

450+
if (json === EMPTY_ARRAY_SENTINEL) {
451+
return [];
452+
}
453+
449454
if (typeof json === "string") {
450455
return json;
451456
}

apps/webapp/app/v3/eventRepository.server.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {
55
ExceptionEventProperties,
66
ExceptionSpanEvent,
77
NULL_SENTINEL,
8+
EMPTY_ARRAY_SENTINEL,
89
PRIMARY_VARIANT,
910
SemanticInternalAttributes,
1011
SpanEvent,
@@ -1593,6 +1594,10 @@ function rehydrateJson(json: Prisma.JsonValue): any {
15931594
return null;
15941595
}
15951596

1597+
if (json === EMPTY_ARRAY_SENTINEL) {
1598+
return [];
1599+
}
1600+
15961601
if (typeof json === "string") {
15971602
return json;
15981603
}

packages/core/src/v3/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ export {
4444
primitiveValueOrflattenedAttributes,
4545
unflattenAttributes,
4646
NULL_SENTINEL,
47+
EMPTY_ARRAY_SENTINEL,
4748
} from "./utils/flattenAttributes.js";
4849
export { omit } from "./utils/omit.js";
4950
export {

packages/core/src/v3/utils/flattenAttributes.ts

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import { Attributes } from "@opentelemetry/api";
2+
import { debug } from "node:util";
23

34
export const NULL_SENTINEL = "$@null((";
5+
export const EMPTY_ARRAY_SENTINEL = "$@empty_array((";
46
export const CIRCULAR_REFERENCE_SENTINEL = "$@circular((";
57

68
export function flattenAttributes(
@@ -20,6 +22,11 @@ export function flattenAttributes(
2022
return result;
2123
}
2224

25+
if (Array.isArray(obj)) {
26+
result[prefix || ""] = EMPTY_ARRAY_SENTINEL;
27+
return result;
28+
}
29+
2330
if (typeof obj === "string") {
2431
result[prefix || ""] = obj;
2532
return result;
@@ -66,6 +73,10 @@ export function flattenAttributes(
6673
}
6774
}
6875
}
76+
77+
if (!value.length) {
78+
result[newPrefix] = EMPTY_ARRAY_SENTINEL;
79+
}
6980
} else if (isRecord(value)) {
7081
// update null check here
7182
Object.assign(result, flattenAttributes(value, newPrefix, seen));
@@ -98,7 +109,7 @@ export function unflattenAttributes(
98109
Object.keys(obj).length === 1 &&
99110
Object.keys(obj)[0] === ""
100111
) {
101-
return rehydrateNull(obj[""]) as any;
112+
return rehydrateEmptyValues(obj[""]) as any;
102113
}
103114

104115
if (Object.keys(obj).length === 0) {
@@ -150,7 +161,7 @@ export function unflattenAttributes(
150161
const lastPart = parts[parts.length - 1];
151162

152163
if (lastPart !== undefined) {
153-
current[lastPart] = rehydrateNull(rehydrateCircular(value));
164+
current[lastPart] = rehydrateEmptyValues(rehydrateCircular(value));
154165
}
155166
}
156167

@@ -201,10 +212,14 @@ export function primitiveValueOrflattenedAttributes(
201212
return attributes;
202213
}
203214

204-
function rehydrateNull(value: any): any {
215+
function rehydrateEmptyValues(value: any): any {
205216
if (value === NULL_SENTINEL) {
206217
return null;
207218
}
208219

220+
if (value === EMPTY_ARRAY_SENTINEL) {
221+
return [];
222+
}
223+
209224
return value;
210225
}

packages/core/test/flattenAttributes.test.ts

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,22 @@ describe("flattenAttributes", () => {
6161
expect(unflattenAttributes(result)).toEqual(input);
6262
});
6363

64+
it("flattens empty array attributes correctly", () => {
65+
const input: number[] = [];
66+
67+
const result = flattenAttributes(input);
68+
expect(result).toEqual({ "": "$@empty_array((" });
69+
expect(unflattenAttributes(result)).toEqual(input);
70+
});
71+
72+
it("flattens empty array child attributes correctly", () => {
73+
const input: number[] = [];
74+
75+
const result = flattenAttributes({ input });
76+
expect(result).toEqual({ input: "$@empty_array((" });
77+
expect(unflattenAttributes(result)).toEqual({ input });
78+
});
79+
6480
it("flattens complex objects correctly", () => {
6581
const obj = {
6682
level1: {
@@ -157,13 +173,13 @@ describe("flattenAttributes", () => {
157173
expect(flattenAttributes(obj, "retry.byStatus")).toEqual(expected);
158174
});
159175

160-
it("handles circular references correctly", () => {
176+
it("handles circular references correctly", () => {
161177
const user = { name: "Alice" };
162178
user["blogPosts"] = [{ title: "Post 1", author: user }]; // Circular reference
163179

164180
const result = flattenAttributes(user);
165181
expect(result).toEqual({
166-
"name": "Alice",
182+
name: "Alice",
167183
"blogPosts.[0].title": "Post 1",
168184
"blogPosts.[0].author": "$@circular((",
169185
});
@@ -175,7 +191,7 @@ describe("flattenAttributes", () => {
175191

176192
const result = flattenAttributes(user);
177193
expect(result).toEqual({
178-
"name": "Bob",
194+
name: "Bob",
179195
"friends.[0]": "$@circular((",
180196
});
181197
});
@@ -246,10 +262,24 @@ describe("unflattenAttributes", () => {
246262
};
247263
expect(unflattenAttributes(flattened)).toEqual(expected);
248264
});
249-
265+
266+
it("correctly reconstructs empty arrays", () => {
267+
const flattened = {
268+
"": "$@empty_array((",
269+
array1: "$@empty_array((",
270+
"array2.[0]": "$@empty_array((",
271+
};
272+
const expected = {
273+
"": [],
274+
array1: [],
275+
array2: [[]],
276+
};
277+
expect(unflattenAttributes(flattened)).toEqual(expected);
278+
});
279+
250280
it("rehydrates circular references correctly", () => {
251281
const flattened = {
252-
"name": "Alice",
282+
name: "Alice",
253283
"blogPosts.[0].title": "Post 1",
254284
"blogPosts.[0].author": "$@circular((",
255285
};

0 commit comments

Comments
 (0)