Skip to content

Commit 5869a12

Browse files
authored
Add span field meta_struct (#2673)
Add new field meta_struct to the span. This new field is a map where its values are encoded to msgpack and then the resulting codification to msgpack binary
1 parent 8959058 commit 5869a12

8 files changed

Lines changed: 131 additions & 7 deletions

File tree

ext/ddtrace.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -708,6 +708,7 @@ static zend_object *dd_init_span_data_object(zend_class_entry *class_type, ddtra
708708
// Not handled in arginfo on these old versions
709709
array_init(&span->property_meta);
710710
array_init(&span->property_metrics);
711+
array_init(&span->property_meta_struct);
711712
array_init(&span->property_links);
712713
array_init(&span->property_peer_service_sources);
713714
#endif

ext/ddtrace.stub.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,13 @@ class SpanData {
9494
*/
9595
public string $version = "";
9696

97+
/**
98+
* @var string[] Meta struct can be used to send any data to the backend. The peculiarity of meta struct is
99+
* that the values are encoded with msgpack when sent to the agent. The values are first encoded to msgpack
100+
* and then, encoded again with msgpack to binary
101+
*/
102+
public array $meta_struct = [];
103+
97104
/**
98105
* @var string|null The type of request which can be set to: web, db, cache, or custom (Optional). Inherited
99106
* from parent.

ext/ddtrace_arginfo.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/* This is a generated file, edit the .stub.php file instead.
2-
* Stub hash: 190a99779c21033f0812df6365a7ebdd87057727 */
2+
* Stub hash: a92829eefe1ee642b3357f1eef2900f1336e462f */
33

44
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_DDTrace_trace_method, 0, 3, _IS_BOOL, 0)
55
ZEND_ARG_TYPE_INFO(0, className, IS_STRING, 0)
@@ -565,6 +565,12 @@ static zend_class_entry *register_class_DDTrace_SpanData(void)
565565
zend_declare_typed_property(class_entry, property_version_name, &property_version_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING));
566566
zend_string_release(property_version_name);
567567

568+
zval property_meta_struct_default_value;
569+
ZVAL_EMPTY_ARRAY(&property_meta_struct_default_value);
570+
zend_string *property_meta_struct_name = zend_string_init("meta_struct", sizeof("meta_struct") - 1, 1);
571+
zend_declare_typed_property(class_entry, property_meta_struct_name, &property_meta_struct_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_ARRAY));
572+
zend_string_release(property_meta_struct_name);
573+
568574
zval property_type_default_value;
569575
ZVAL_EMPTY_STRING(&property_type_default_value);
570576
zend_string *property_type_name = zend_string_init("type", sizeof("type") - 1, 1);

ext/serializer.c

Lines changed: 66 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,10 @@ static void mpack_write_utf8_lossy_cstr(mpack_writer_t *writer, const char *str,
6363
#define KEY_TRACE_ID "trace_id"
6464
#define KEY_SPAN_ID "span_id"
6565
#define KEY_PARENT_ID "parent_id"
66+
#define KEY_META_STRUCT "meta_struct"
6667

6768
static int msgpack_write_zval(mpack_writer_t *writer, zval *trace, int level);
69+
static void serialize_meta_struct(mpack_writer_t *writer, zval *trace);
6870

6971
static int write_hash_table(mpack_writer_t *writer, HashTable *ht, int level) {
7072
zval *tmp;
@@ -89,6 +91,7 @@ static int write_hash_table(mpack_writer_t *writer, HashTable *ht, int level) {
8991
ZEND_HASH_FOREACH_KEY_VAL_IND(ht, num_key, string_key, tmp) {
9092
// Writing the key, if associative
9193
bool zval_string_as_uint64 = false;
94+
bool is_meta_struct = false;
9295
if (is_assoc == 1) {
9396
char num_str_buf[MAX_ID_BUFSIZ], *key;
9497
size_t len;
@@ -105,11 +108,17 @@ static int write_hash_table(mpack_writer_t *writer, HashTable *ht, int level) {
105108
(0 == strcmp(KEY_TRACE_ID, key) || 0 == strcmp(KEY_SPAN_ID, key) || 0 == strcmp(KEY_PARENT_ID, key))) {
106109
zval_string_as_uint64 = true;
107110
}
111+
if (level <= 3 &&
112+
(0 == strcmp(KEY_META_STRUCT, key))) {
113+
is_meta_struct = true;
114+
}
108115
}
109116

110117
// Writing the value
111118
if (zval_string_as_uint64) {
112119
mpack_write_u64(writer, strtoull(Z_STRVAL_P(tmp), NULL, 10));
120+
} else if(is_meta_struct) {
121+
serialize_meta_struct(writer, tmp);
113122
} else if (msgpack_write_zval(writer, tmp, level) != 1) {
114123
return 0;
115124
}
@@ -128,7 +137,6 @@ static int msgpack_write_zval(mpack_writer_t *writer, zval *trace, int level) {
128137
if (Z_TYPE_P(trace) == IS_REFERENCE) {
129138
trace = Z_REFVAL_P(trace);
130139
}
131-
132140
switch (Z_TYPE_P(trace)) {
133141
case IS_ARRAY:
134142
if (write_hash_table(writer, Z_ARRVAL_P(trace), level + 1) != 1) {
@@ -159,6 +167,26 @@ static int msgpack_write_zval(mpack_writer_t *writer, zval *trace, int level) {
159167
return 1;
160168
}
161169

170+
static void serialize_meta_struct(mpack_writer_t *writer, zval *meta_struct) {
171+
zval *tmp;
172+
zend_string *string_key;
173+
174+
HashTable *ht = Z_ARRVAL_P(meta_struct);
175+
176+
mpack_start_map(writer, zend_hash_num_elements(ht));
177+
178+
ZEND_HASH_FOREACH_STR_KEY_VAL_IND(ht, string_key, tmp) {
179+
if (!string_key) {
180+
continue;
181+
}
182+
mpack_write_cstr(writer, ZSTR_VAL(string_key));
183+
mpack_write_bin(writer, Z_STRVAL_P(tmp), Z_STRLEN_P(tmp));
184+
}
185+
ZEND_HASH_FOREACH_END();
186+
187+
mpack_finish_map(writer);
188+
}
189+
162190
int ddtrace_serialize_simple_array_into_c_string(zval *trace, char **data_p, size_t *size_p) {
163191
// encode to memory buffer
164192
char *data;
@@ -1017,6 +1045,26 @@ static void dd_serialize_array_metrics_recursively(zend_array *target, zend_stri
10171045
dd_serialize_array_recursively(target, str, value, true);
10181046
}
10191047

1048+
static void dd_serialize_array_meta_struct_recursively(zend_array *target, zend_string *str, zval *value) {
1049+
char *data;
1050+
size_t size;
1051+
1052+
mpack_writer_t writer;
1053+
mpack_writer_init_growable(&writer, &data, &size);
1054+
int result = msgpack_write_zval(&writer, value, 5);
1055+
mpack_writer_destroy(&writer);
1056+
1057+
if (size == 0 || result == 0) {
1058+
return;
1059+
}
1060+
1061+
zval serialised;
1062+
ZVAL_STRINGL(&serialised, data, size);
1063+
1064+
zend_hash_update(target, str, &serialised);
1065+
free(data);
1066+
}
1067+
10201068
struct iter {
10211069
// caller owns key/value
10221070
bool (*next)(struct iter *self, zend_string **key, zend_string **value);
@@ -1426,7 +1474,6 @@ static zend_always_inline double strconv_parse_bool(zend_string *str) {
14261474

14271475
void ddtrace_serialize_span_to_array(ddtrace_span_data *span, zval *array) {
14281476
bool is_root_span = span->std.ce == ddtrace_ce_root_span_data;
1429-
14301477
zval *el;
14311478
zval zv;
14321479
el = &zv;
@@ -1794,6 +1841,23 @@ void ddtrace_serialize_span_to_array(ddtrace_span_data *span, zval *array) {
17941841
zend_array_destroy(Z_ARR(metrics_zv));
17951842
}
17961843

1844+
zend_array *meta_struct = ddtrace_property_array(&span->property_meta_struct);
1845+
zval meta_struct_zv;
1846+
array_init(&meta_struct_zv);
1847+
zend_string *ms_str_key;
1848+
zval *ms_val;
1849+
ZEND_HASH_FOREACH_STR_KEY_VAL_IND(meta_struct, ms_str_key, ms_val) {
1850+
if (ms_str_key) {
1851+
dd_serialize_array_meta_struct_recursively(Z_ARRVAL(meta_struct_zv), ms_str_key, ms_val);
1852+
}
1853+
}
1854+
ZEND_HASH_FOREACH_END();
1855+
if (zend_hash_num_elements(Z_ARR(meta_struct_zv))) {
1856+
zend_hash_str_add_new(Z_ARR_P(el), ZEND_STRL("meta_struct"), &meta_struct_zv);
1857+
} else {
1858+
zend_array_destroy(Z_ARR(meta_struct_zv));
1859+
}
1860+
17971861
add_next_index_zval(array, el);
17981862
}
17991863

ext/span.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ typedef union ddtrace_span_properties {
4545
zval property_service;
4646
zval property_env;
4747
zval property_version;
48+
zval property_meta_struct;
4849
zval property_type;
4950
zval property_meta;
5051
zval property_metrics;

tests/ext/active_span.phpt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ var_dump(DDTrace\active_span() == DDTrace\active_span());
2828
Hello, Datadog.
2929
greet tracer.
3030
bool(true)
31-
object(DDTrace\RootSpanData)#%d (18) {
31+
object(DDTrace\RootSpanData)#%d (19) {
3232
["name"]=>
3333
string(15) "active_span.php"
3434
["resource"]=>
@@ -39,6 +39,9 @@ object(DDTrace\RootSpanData)#%d (18) {
3939
string(0) ""
4040
["version"]=>
4141
string(0) ""
42+
["meta_struct"]=>
43+
array(0) {
44+
}
4245
["type"]=>
4346
string(3) "cli"
4447
["meta"]=>

tests/ext/meta_struct.phpt

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
--TEST--
2+
Add meta struct string
3+
--FILE--
4+
<?php
5+
function dd_trace_unserialize_trace_hex($meta_struct) {
6+
foreach($meta_struct as $key => $value) {
7+
$hex = [];
8+
$length = strlen($value);
9+
for ($i = 0; $i < $length; $i++) {
10+
$hex[] = bin2hex($value[$i]);
11+
}
12+
var_dump($key, implode(' ', $hex));
13+
}
14+
}
15+
16+
$span = DDTrace\start_span();
17+
$span->meta_struct["foo"] = "bar";
18+
$span->meta_struct["john"] = ["Doe"];
19+
DDTrace\close_span();
20+
21+
$spans = dd_trace_serialize_closed_spans();
22+
23+
foreach ($spans as $span)
24+
{
25+
dd_trace_unserialize_trace_hex($span["meta_struct"]);
26+
}
27+
28+
?>
29+
--EXPECTF--
30+
string(3) "foo"
31+
string(11) "a3 62 61 72"
32+
string(4) "john"
33+
string(14) "91 a3 44 6f 65"

tests/ext/sandbox/span_clone.phpt

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ var_dump(dd_trace_serialize_closed_spans());
2424

2525
?>
2626
--EXPECTF--
27-
object(DDTrace\RootSpanData)#%d (18) {
27+
object(DDTrace\RootSpanData)#%d (19) {
2828
["name"]=>
2929
string(3) "foo"
3030
["resource"]=>
@@ -35,6 +35,9 @@ object(DDTrace\RootSpanData)#%d (18) {
3535
string(0) ""
3636
["version"]=>
3737
string(0) ""
38+
["meta_struct"]=>
39+
array(0) {
40+
}
3841
["type"]=>
3942
string(3) "cli"
4043
["meta"]=>
@@ -82,7 +85,7 @@ object(DDTrace\RootSpanData)#%d (18) {
8285
["traceId"]=>
8386
string(32) "%s"
8487
}
85-
object(DDTrace\RootSpanData)#%d (18) {
88+
object(DDTrace\RootSpanData)#%d (19) {
8689
["name"]=>
8790
string(5) "dummy"
8891
["resource"]=>
@@ -93,6 +96,9 @@ object(DDTrace\RootSpanData)#%d (18) {
9396
string(0) ""
9497
["version"]=>
9598
string(0) ""
99+
["meta_struct"]=>
100+
array(0) {
101+
}
96102
["type"]=>
97103
string(3) "cli"
98104
["meta"]=>
@@ -127,7 +133,7 @@ object(DDTrace\RootSpanData)#%d (18) {
127133
NULL
128134
}
129135
["active"]=>
130-
object(DDTrace\RootSpanData)#%d (18) {
136+
object(DDTrace\RootSpanData)#%d (19) {
131137
["name"]=>
132138
string(3) "foo"
133139
["resource"]=>
@@ -138,6 +144,9 @@ object(DDTrace\RootSpanData)#%d (18) {
138144
string(0) ""
139145
["version"]=>
140146
string(0) ""
147+
["meta_struct"]=>
148+
array(0) {
149+
}
141150
["type"]=>
142151
string(3) "cli"
143152
["meta"]=>

0 commit comments

Comments
 (0)