Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,31 @@ describe('encodeAttributes', () => {
expect(warn).toHaveBeenCalled();
});

it('drops a null-prototype object without throwing', () => {
expect(() =>
encodeAttributes({ bad: Object.create(null) })
).not.toThrow();
expect(warn).toHaveBeenCalled();
});

it('drops a value whose toString throws without throwing', () => {
const bad = {
toString() {
throw new Error('boom');
}
};
Object.setPrototypeOf(bad, null);
expect(() => encodeAttributes({ bad })).not.toThrow();
expect(warn).toHaveBeenCalled();
});

it('drops a null-prototype object nested in an array without throwing', () => {
expect(() =>
encodeAttributes({ bad: [Object.create(null)] })
).not.toThrow();
expect(warn).toHaveBeenCalled();
});

it('drops unsupported root function', () => {
const result = encodeAttributes(() => {});
expect(result).toEqual({});
Expand Down
8 changes: 6 additions & 2 deletions packages/core/src/sdk/AttributesEncoding/defaultEncoders.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import {
} from './errorUtils';
import { encodeAttributesInPlace, sanitizeForJson } from './helpers';
import type { AttributeEncoder, Encodable } from './types';
import { warn } from './utils';
import { safeToString, warn } from './utils';

/** Primitives: keep them explicit so the full pipeline is used uniformly. */
export const stringEncoder: AttributeEncoder<string> = {
Expand Down Expand Up @@ -165,7 +165,11 @@ export const mapEncoder: AttributeEncoder<Map<unknown, unknown>> = {
value: sanitizeForJson(v, allEncoders)
});
} catch (err) {
warn(`Failed to encode Map key: ${k}. ERROR: ${String(err)}`);
warn(
`Failed to encode Map key: ${safeToString(
k
)}. ERROR: ${safeToString(err)}`
);
}
}

Expand Down
12 changes: 6 additions & 6 deletions packages/core/src/sdk/AttributesEncoding/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
*/

import type { AttributeEncoder, Encodable } from './types';
import { formatPathForLog, isPlainObject, warn } from './utils';
import { formatPathForLog, isPlainObject, safeToString, warn } from './utils';

const MAX_ATTRIBUTES = 256;

Expand Down Expand Up @@ -69,7 +69,7 @@ export function encodeAttributesInPlace(
warn(
`Dropped unsupported value in array at '${formatPathForLog(
path
)}': ${String(v)}`
)}': ${safeToString(v)}`
);
return undefined;
};
Expand All @@ -94,9 +94,9 @@ export function encodeAttributesInPlace(

// Unsupported
warn(
`Dropped unsupported value at '${formatPathForLog(path)}': ${String(
value
)}`
`Dropped unsupported value at '${formatPathForLog(
path
)}': ${safeToString(value)}`
);
}

Expand Down Expand Up @@ -138,7 +138,7 @@ export function applyEncoders(
return enc.encode(value as never);
}
} catch (err) {
warn(`Encoder error: ${String(err)}`);
warn(`Encoder error: ${safeToString(err)}`);
return undefined;
}
}
Expand Down
8 changes: 8 additions & 0 deletions packages/core/src/sdk/AttributesEncoding/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,14 @@ export function warn(text: string) {
InternalLog.log(`[ATTRIBUTES] ${text}`, SdkVerbosity.WARN);
}

export function safeToString(value: unknown): string {
try {
return String(value);
} catch {
return Object.prototype.toString.call(value);
}
}

export function isPlainObject(v: unknown): v is Record<string, unknown> {
return !!v && typeof v === 'object' && (v as any).constructor === Object;
}
Expand Down