Skip to content

Commit 228102c

Browse files
committed
Fix conversion of non-utf8 sequences to AnyValue
> String values which are not valid Unicode sequences SHOULD be converted to AnyValue's bytes_value with the bytes representing the string in the original order and format of the source string.
1 parent bb07aca commit 228102c

File tree

3 files changed

+63
-1
lines changed

3 files changed

+63
-1
lines changed

src/Contrib/Otlp/AttributesConverter.php

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,12 +46,23 @@ public static function convertAnyValue($value): AnyValue
4646
$result->setDoubleValue($value);
4747
}
4848
if (is_string($value)) {
49-
$result->setStringValue($value);
49+
if (self::isUtf8($value)) {
50+
$result->setStringValue($value);
51+
} else {
52+
$result->setBytesValue($value);
53+
}
5054
}
5155

5256
return $result;
5357
}
5458

59+
private static function isUtf8(string $value): bool
60+
{
61+
return \extension_loaded('mbstring')
62+
? \mb_check_encoding($value, 'UTF-8')
63+
: !\preg_match('//u', $value);
64+
}
65+
5566
/**
5667
* Test whether an array is simple (non-KeyValue)
5768
*/

tests/Unit/Contrib/Otlp/AttributesConverterTest.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,13 @@ public static function basicTypesProvider(): array
3636
];
3737
}
3838

39+
public function test_convert_bytes(): void
40+
{
41+
$anyValue = AttributesConverter::convertAnyValue("\xe2");
42+
$this->assertTrue($anyValue->hasBytesValue());
43+
$this->assertSame("\xe2", $anyValue->getBytesValue());
44+
}
45+
3946
/**
4047
* @dataProvider arrayProvider
4148
*/

tests/Unit/Contrib/Otlp/SpanExporterTest.php

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,4 +104,48 @@ public function test_json_span_and_trace_id_hex_format(): void
104104
}
105105
TRACE, stream_get_contents($stream));
106106
}
107+
108+
public function test_json_invalid_utf8_sequence_is_encoded_as_bytes_value(): void
109+
{
110+
$stream = fopen('php://memory', 'a+b');
111+
$transport = new StreamTransport($stream, 'application/json');
112+
$exporter = new SpanExporter($transport);
113+
114+
$exporter->export([
115+
(new SpanData())
116+
->setContext(SpanContext::create('0af7651916cd43dd8448eb211c80319c', 'b7ad6b7169203331'))
117+
->addAttribute('invalid-utf8', "\xe2"),
118+
]);
119+
120+
fseek($stream, 0);
121+
$this->assertJsonStringEqualsJsonString(<<<TRACE
122+
{
123+
"resourceSpans": [
124+
{
125+
"resource": {},
126+
"scopeSpans": [
127+
{
128+
"scope": {},
129+
"spans": [
130+
{
131+
"traceId": "0af7651916cd43dd8448eb211c80319c",
132+
"spanId": "b7ad6b7169203331",
133+
"name": "test-span-data",
134+
"kind": 1,
135+
"startTimeUnixNano": "1505855794194009601",
136+
"endTimeUnixNano": "1505855799465726528",
137+
"status": {},
138+
"attributes": [{
139+
"key": "invalid-utf8",
140+
"value": {"bytesValue": "4g=="}
141+
}]
142+
}
143+
]
144+
}
145+
]
146+
}
147+
]
148+
}
149+
TRACE, stream_get_contents($stream));
150+
}
107151
}

0 commit comments

Comments
 (0)