101101#endif
102102#include "ddtrace_arginfo.h"
103103#include "distributed_tracing_headers.h"
104+ #include "inferred_proxy_headers.h"
104105#include "live_debugger.h"
105106#include "agent_info.h"
106107
@@ -894,12 +895,14 @@ ZEND_METHOD(DDTrace_SpanLink, fromHeaders) {
894895
895896/* DDTrace\SpanData */
896897zend_class_entry * ddtrace_ce_span_data ;
898+ zend_class_entry * ddtrace_ce_inferred_span_data ;
897899zend_class_entry * ddtrace_ce_root_span_data ;
898900#if PHP_VERSION_ID >= 80000 && PHP_VERSION_ID < 80100
899901HashTable dd_root_span_data_duplicated_properties_table ;
900902#endif
901903zend_class_entry * ddtrace_ce_span_stack ;
902904zend_object_handlers ddtrace_span_data_handlers ;
905+ zend_object_handlers ddtrace_inferred_span_data_handlers ;
903906zend_object_handlers ddtrace_root_span_data_handlers ;
904907zend_object_handlers ddtrace_span_stack_handlers ;
905908
@@ -934,6 +937,11 @@ static zend_object *ddtrace_span_data_create(zend_class_entry *class_type) {
934937 return & span -> std ;
935938}
936939
940+ static zend_object * ddtrace_inferred_span_data_create (zend_class_entry * class_type ) {
941+ ddtrace_inferred_span_data * span = ecalloc (1 , sizeof (* span ));
942+ return dd_init_span_data_object (class_type , & span -> span , & ddtrace_inferred_span_data_handlers );
943+ }
944+
937945static zend_object * ddtrace_root_span_data_create (zend_class_entry * class_type ) {
938946 ddtrace_root_span_data * span = ecalloc (1 , sizeof (* span ));
939947 dd_init_span_data_object (class_type , & span -> span , & ddtrace_root_span_data_handlers );
@@ -1044,6 +1052,18 @@ static zend_object *ddtrace_span_data_clone_obj(zend_object *old_obj) {
10441052 return new_obj ;
10451053}
10461054
1055+ #if PHP_VERSION_ID < 80000
1056+ static zend_object * ddtrace_inferred_span_data_clone_obj (zval * old_zv ) {
1057+ zend_object * old_obj = Z_OBJ_P (old_zv );
1058+ #else
1059+ static zend_object * ddtrace_inferred_span_data_clone_obj (zend_object * old_obj ) {
1060+ #endif
1061+ zend_object * new_obj = ddtrace_inferred_span_data_create (old_obj -> ce );
1062+ zend_objects_clone_members (new_obj , old_obj );
1063+ return new_obj ;
1064+ }
1065+
1066+
10471067#if PHP_VERSION_ID < 80000
10481068static zend_object * ddtrace_root_span_data_clone_obj (zval * old_zv ) {
10491069 zend_object * old_obj = Z_OBJ_P (old_zv );
@@ -1242,6 +1262,14 @@ static void dd_register_span_data_ce(void) {
12421262 ddtrace_span_data_handlers .write_property = ddtrace_span_data_readonly ;
12431263 ddtrace_span_data_handlers .get_constructor = ddtrace_span_data_get_constructor ;
12441264
1265+ ddtrace_ce_inferred_span_data = register_class_DDTrace_InferredSpanData (ddtrace_ce_span_data );
1266+ ddtrace_ce_inferred_span_data -> create_object = ddtrace_inferred_span_data_create ;
1267+
1268+ memcpy (& ddtrace_inferred_span_data_handlers , & ddtrace_span_data_handlers , sizeof (zend_object_handlers ));
1269+ ddtrace_inferred_span_data_handlers .offset = XtOffsetOf (ddtrace_inferred_span_data , std );
1270+ ddtrace_inferred_span_data_handlers .clone_obj = ddtrace_inferred_span_data_clone_obj ;
1271+
1272+
12451273 ddtrace_ce_root_span_data = register_class_DDTrace_RootSpanData (ddtrace_ce_span_data );
12461274 ddtrace_ce_root_span_data -> create_object = ddtrace_root_span_data_create ;
12471275
@@ -1474,6 +1502,7 @@ static PHP_MINIT_FUNCTION(ddtrace) {
14741502 ddtrace_git_metadata_handlers .free_obj = ddtrace_free_obj_wrapper ;
14751503
14761504 ddtrace_engine_hooks_minit ();
1505+ ddtrace_init_proxy_info_map ();
14771506
14781507 ddtrace_integrations_minit ();
14791508 ddtrace_serializer_startup ();
@@ -1522,6 +1551,7 @@ static PHP_MSHUTDOWN_FUNCTION(ddtrace) {
15221551 ddtrace_log_mshutdown ();
15231552
15241553 ddtrace_engine_hooks_mshutdown ();
1554+ ddtrace_shutdown_proxy_info_map ();
15251555
15261556 ddtrace_shutdown_span_sampling_limiter ();
15271557 ddtrace_limiter_destroy ();
@@ -1575,6 +1605,7 @@ static void dd_initialize_request(void) {
15751605 DDTRACE_G (additional_global_tags ) = zend_new_array (0 );
15761606 DDTRACE_G (default_priority_sampling ) = DDTRACE_PRIORITY_SAMPLING_UNKNOWN ;
15771607 DDTRACE_G (propagated_priority_sampling ) = DDTRACE_PRIORITY_SAMPLING_UNSET ;
1608+ DDTRACE_G (inferred_span_created ) = false;
15781609 zend_hash_init (& DDTRACE_G (root_span_tags_preset ), 8 , unused , ZVAL_PTR_DTOR , 0 );
15791610 zend_hash_init (& DDTRACE_G (propagated_root_span_tags ), 8 , unused , ZVAL_PTR_DTOR , 0 );
15801611 zend_hash_init (& DDTRACE_G (tracestate_unknown_dd_keys ), 8 , unused , ZVAL_PTR_DTOR , 0 );
@@ -3100,36 +3131,22 @@ static bool dd_read_userspace_header(zai_str zai_header, const char *lowercase_h
31003131 return true;
31013132}
31023133
3103- static bool dd_read_array_header (zai_str zai_header , const char * lowercase_header , zend_string * * header_value , void * data ) {
3104- UNUSED (zai_header );
3105- zend_array * array = (zend_array * ) data ;
3106- zval * value = zend_hash_str_find (array , lowercase_header , strlen (lowercase_header ));
3107- if (!value ) {
3108- return false;
3109- }
3110-
3111- * header_value = zval_get_string (value );
3112- return true;
3113- }
3114-
3115- static ddtrace_distributed_tracing_result dd_parse_distributed_tracing_headers_function (INTERNAL_FUNCTION_PARAMETERS , bool * success ) {
3134+ static bool parse_tracing_headers_common (INTERNAL_FUNCTION_PARAMETERS , dd_fci_fcc_pair * func , bool * use_server_headers , zend_array * * array ) {
31163135 UNUSED (return_value );
3117-
3118- dd_fci_fcc_pair func ;
3119- bool use_server_headers = false;
3120- zend_array * array = NULL ;
3136+ * use_server_headers = false;
3137+ * array = NULL ;
31213138
31223139 ZEND_PARSE_PARAMETERS_START (1 , 1 )
31233140 DD_PARAM_PROLOGUE (0 , 0 );
31243141 if (Z_TYPE_P (_arg ) == IS_NULL ) {
3125- use_server_headers = true;
3126- } else if (UNEXPECTED (!zend_parse_arg_func (_arg , & func . fci , & func . fcc , false, & _error , true))) {
3142+ * use_server_headers = true;
3143+ } else if (UNEXPECTED (!zend_parse_arg_func (_arg , & func -> fci , & func -> fcc , false, & _error , true))) {
31273144 if (!_error ) {
31283145 zend_argument_type_error (1 , "must be a valid callback or of type array, %s given" , zend_zval_value_name (_arg ));
31293146 _error_code = ZPP_ERROR_FAILURE ;
31303147 break ;
31313148 } else if (Z_TYPE_P (_arg ) == IS_ARRAY ) {
3132- array = Z_ARR_P (_arg );
3149+ * array = Z_ARR_P (_arg );
31333150 efree (_error );
31343151 } else {
31353152 _error_code = ZPP_ERROR_WRONG_CALLBACK ;
@@ -3144,26 +3161,61 @@ static ddtrace_distributed_tracing_result dd_parse_distributed_tracing_headers_f
31443161#endif
31453162#endif
31463163 }
3147- ZEND_PARSE_PARAMETERS_END_EX (* success = false; return ( ddtrace_distributed_tracing_result ){ 0 } );
3164+ ZEND_PARSE_PARAMETERS_END_EX (return false );
31483165
3149- * success = true;
3150- if (!get_DD_TRACE_ENABLED ()) {
3166+ return true;
3167+ }
3168+
3169+ static ddtrace_distributed_tracing_result dd_parse_distributed_tracing_headers_function (INTERNAL_FUNCTION_PARAMETERS , bool * success ) {
3170+ dd_fci_fcc_pair func ;
3171+ bool use_server_headers ;
3172+ zend_array * array ;
3173+
3174+ * success = parse_tracing_headers_common (INTERNAL_FUNCTION_PARAM_PASSTHRU , & func , & use_server_headers , & array );
3175+ if (!* success || !get_DD_TRACE_ENABLED ()) {
31513176 return (ddtrace_distributed_tracing_result ){0 };
31523177 }
31533178
31543179 func .fci .param_count = 1 ;
31553180
31563181 if (array ) {
3157- return ddtrace_read_distributed_tracing_ids (dd_read_array_header , array );
3182+ return ddtrace_read_distributed_tracing_ids (ddtrace_read_array_header , array );
31583183 } else if (use_server_headers ) {
31593184 return ddtrace_read_distributed_tracing_ids (ddtrace_read_zai_header , & func );
31603185 } else {
31613186 return ddtrace_read_distributed_tracing_ids (dd_read_userspace_header , & func );
31623187 }
31633188}
31643189
3190+ static ddtrace_inferred_proxy_result dd_parse_inferred_proxy_headers_function (INTERNAL_FUNCTION_PARAMETERS , bool * success ) {
3191+ dd_fci_fcc_pair func ;
3192+ bool use_server_headers ;
3193+ zend_array * array ;
3194+
3195+ * success = parse_tracing_headers_common (INTERNAL_FUNCTION_PARAM_PASSTHRU , & func , & use_server_headers , & array );
3196+ if (!* success || !get_DD_TRACE_ENABLED () || !get_DD_TRACE_INFERRED_PROXY_SERVICES_ENABLED ()) {
3197+ return (ddtrace_inferred_proxy_result ){0 };
3198+ }
3199+
3200+ func .fci .param_count = 1 ;
3201+
3202+ if (array ) {
3203+ return ddtrace_read_inferred_proxy_headers (ddtrace_read_array_header , array );
3204+ } else if (use_server_headers ) {
3205+ return ddtrace_read_inferred_proxy_headers (ddtrace_read_zai_header , & func );
3206+ } else {
3207+ return ddtrace_read_inferred_proxy_headers (dd_read_userspace_header , & func );
3208+ }
3209+ }
3210+
31653211PHP_FUNCTION (DDTrace_consume_distributed_tracing_headers ) {
31663212 bool success ;
3213+
3214+ ddtrace_inferred_proxy_result inferred_result = dd_parse_inferred_proxy_headers_function (INTERNAL_FUNCTION_PARAM_PASSTHRU , & success );
3215+ if (success && get_DD_TRACE_ENABLED () && DDTRACE_G (active_stack )-> root_span && Z_TYPE (DDTRACE_G (active_stack )-> root_span -> property_inferred_span ) != IS_OBJECT ) {
3216+ ddtrace_open_inferred_span (& inferred_result , DDTRACE_G (active_stack )-> root_span );
3217+ }
3218+
31673219 ddtrace_distributed_tracing_result result = dd_parse_distributed_tracing_headers_function (INTERNAL_FUNCTION_PARAM_PASSTHRU , & success );
31683220 if (success && get_DD_TRACE_ENABLED ()) {
31693221 ddtrace_apply_distributed_tracing_result (& result , DDTRACE_G (active_stack )-> root_span );
0 commit comments