@@ -942,24 +942,67 @@ static uint64_t _calc_sampling_key(zend_object *root_span, int status_code)
942942 return 0 ;
943943 }
944944
945+ zend_string * route_or_endpoint = NULL ;
946+ bool free_route_or_endpoint = false;
947+
945948 zval * route = zend_hash_str_find (Z_ARRVAL_P (meta ), ZEND_STRL ("http.route" ));
946- if (!route || Z_TYPE_P (route ) != IS_STRING ) {
947- mlog_g (dd_log_debug , "No http.route tag; not sampling" );
948- return 0 ;
949+ const bool has_http_route = route && Z_TYPE_P (route ) == IS_STRING ;
950+ if (has_http_route ) {
951+ route_or_endpoint = Z_STR_P (route );
952+ } else {
953+ // http.route is absent, check for http.endpoint
954+ zval * endpoint =
955+ zend_hash_str_find (Z_ARRVAL_P (meta ), ZEND_STRL ("http.endpoint" ));
956+ const bool has_http_endpoint =
957+ endpoint && Z_TYPE_P (endpoint ) == IS_STRING ;
958+ if (has_http_endpoint ) {
959+ // http.endpoint is already computed
960+ // Use it unless status code is 404
961+ #define HTTP_NOT_FOUND 404
962+ if (status_code == HTTP_NOT_FOUND ) {
963+ mlog_g (dd_log_debug ,
964+ "http.endpoint present but status is 404; not sampling" );
965+ } else {
966+ route_or_endpoint = Z_STR_P (endpoint );
967+ }
968+ } else {
969+ // http.endpoint not computed, compute it now without setting the
970+ // tag
971+ zval * url =
972+ zend_hash_str_find (Z_ARRVAL_P (meta ), ZEND_STRL ("http.url" ));
973+ const bool has_http_url = url && Z_TYPE_P (url ) == IS_STRING ;
974+ if (has_http_url ) {
975+ route_or_endpoint = dd_trace_guess_endpoint_from_url (
976+ Z_STRVAL_P (url ), Z_STRLEN_P (url ));
977+ if (route_or_endpoint ) {
978+ free_route_or_endpoint = true;
979+ } else {
980+ mlog_g (dd_log_debug ,
981+ "Failed to compute http.endpoint; not sampling" );
982+ }
983+ } else {
984+ mlog_g (dd_log_debug ,
985+ "No http.route, http.endpoint, or http.url; not sampling" );
986+ }
987+ }
988+ }
989+
990+ if (!route_or_endpoint ) {
991+ goto error ;
949992 }
950993
951994 zval * method =
952995 zend_hash_str_find (Z_ARRVAL_P (meta ), ZEND_STRL ("http.method" ));
953996 if (!method || Z_TYPE_P (method ) != IS_STRING ) {
954997 mlog_g (dd_log_debug , "No http.method tag; not sampling" );
955- return 0 ;
998+ goto error ;
956999 }
9571000
958- // use fnv-1a hash with: <http.route tag > NULL <http.method tag> NULL
1001+ // use fnv-1a hash with: <route_or_endpoint > NULL <http.method tag> NULL
9591002 // status_code
9601003
9611004 uint64_t hash = FNV_OFFSET_BASIS ;
962- hash = _hash_zend_string (hash , Z_STR_P ( route ) );
1005+ hash = _hash_zend_string (hash , route_or_endpoint );
9631006 hash *= FNV_PRIME ; // hash NUL byte
9641007 hash = _hash_zend_string (hash , Z_STR_P (method ));
9651008 hash *= FNV_PRIME ; // hash NUL byte
@@ -970,7 +1013,22 @@ static uint64_t _calc_sampling_key(zend_object *root_span, int status_code)
9701013 snprintf (status_str , sizeof (status_str ), "%d" , status_code );
9711014 hash = _hash_string (hash , status_str , status_len );
9721015
1016+ mlog_g (dd_log_debug ,
1017+ "Will use sampling key: %" PRIu64
1018+ " for route/endpoint %.*s, method %.*s, status %d" ,
1019+ hash , (int )ZSTR_LEN (route_or_endpoint ), ZSTR_VAL (route_or_endpoint ),
1020+ (int )ZSTR_LEN (Z_STR_P (method )), ZSTR_VAL (Z_STR_P (method )), status_code );
1021+
1022+ if (free_route_or_endpoint ) {
1023+ zend_string_release (route_or_endpoint );
1024+ }
9731025 return hash ;
1026+
1027+ error :
1028+ if (free_route_or_endpoint ) {
1029+ zend_string_release (route_or_endpoint );
1030+ }
1031+ return 0 ;
9741032}
9751033
9761034PHP_FUNCTION (datadog_appsec_testing_dump_req_lifecycle_state )
0 commit comments