diff --git a/Makefile b/Makefile
index 666ccc07c8..b7f1e536ed 100644
--- a/Makefile
+++ b/Makefile
@@ -981,6 +981,7 @@ TEST_WEB_82 := \
test_web_laravel_9x \
test_web_laravel_10x \
test_web_laravel_latest \
+ test_web_apigw \
test_web_laravel_octane_latest \
test_web_lumen_81 \
test_web_lumen_90 \
@@ -1042,6 +1043,7 @@ TEST_WEB_83 := \
test_web_laravel_9x \
test_web_laravel_10x \
test_web_laravel_latest \
+ test_web_apigw \
test_web_laravel_octane_latest \
test_web_lumen_81 \
test_web_lumen_90 \
@@ -1311,6 +1313,8 @@ test_integrations_sqlsrv: global_test_run_dependencies
$(eval TEST_EXTRA_INI=)
test_integrations_swoole_5: global_test_run_dependencies
$(call run_tests_debug,--testsuite=swoole-test)
+test_web_apigw: global_test_run_dependencies tests/Frameworks/Laravel/Latest/composer.lock-php$(PHP_MAJOR_MINOR) tests/Frameworks/Laravel/Octane/Latest/composer.lock-php$(PHP_MAJOR_MINOR) tests/Frameworks/Roadrunner/Version_2/composer.lock-php$(PHP_MAJOR_MINOR)
+ $(call run_tests_debug,--testsuite=api-gateway-test)
test_web_cakephp_28: global_test_run_dependencies tests/Frameworks/CakePHP/Version_2_8/composer.lock-php$(PHP_MAJOR_MINOR)
$(call run_tests_debug,--testsuite=cakephp-28-test)
test_web_cakephp_310: global_test_run_dependencies tests/Frameworks/CakePHP/Version_3_10/composer.lock-php$(PHP_MAJOR_MINOR)
diff --git a/config.m4 b/config.m4
index 241f81657b..96ee803147 100644
--- a/config.m4
+++ b/config.m4
@@ -187,6 +187,7 @@ if test "$PHP_DDTRACE" != "no"; then
ext/handlers_kafka.c \
ext/handlers_pcntl.c \
ext/handlers_signal.c \
+ ext/inferred_proxy_headers.c \
ext/integrations/exec_integration.c \
ext/integrations/integrations.c \
ext/ip_extraction.c \
diff --git a/config.w32 b/config.w32
index dc151bd508..7addf079fe 100644
--- a/config.w32
+++ b/config.w32
@@ -39,6 +39,7 @@ if (PHP_DDTRACE != 'no') {
DDTRACE_EXT_SOURCES += " handlers_internal.c";
DDTRACE_EXT_SOURCES += " handlers_kafka.c";
DDTRACE_EXT_SOURCES += " handlers_pcntl.c";
+ DDTRACE_EXT_SOURCES += " inferred_proxy_headers.c";
DDTRACE_EXT_SOURCES += " ip_extraction.c";
DDTRACE_EXT_SOURCES += " standalone_limiter.c";
DDTRACE_EXT_SOURCES += " live_debugger.c";
diff --git a/ext/configuration.h b/ext/configuration.h
index 970b97f212..55ba9847b5 100644
--- a/ext/configuration.h
+++ b/ext/configuration.h
@@ -238,6 +238,7 @@ enum ddtrace_sampling_rules_format {
CONFIG(SET, DD_DYNAMIC_INSTRUMENTATION_REDACTED_IDENTIFIERS, "", .ini_change = zai_config_system_ini_change) \
CONFIG(BOOL, DD_EXPERIMENTAL_APPSEC_STANDALONE_ENABLED, "false") \
CONFIG(SET, DD_DYNAMIC_INSTRUMENTATION_REDACTED_TYPES, "", .ini_change = zai_config_system_ini_change) \
+ CONFIG(BOOL, DD_TRACE_INFERRED_PROXY_SERVICES_ENABLED, "false") \
DD_INTEGRATIONS
#ifndef _WIN32
diff --git a/ext/ddtrace.c b/ext/ddtrace.c
index e256d1aeae..2b759bfed8 100644
--- a/ext/ddtrace.c
+++ b/ext/ddtrace.c
@@ -100,6 +100,7 @@
#endif
#include "ddtrace_arginfo.h"
#include "distributed_tracing_headers.h"
+#include "inferred_proxy_headers.h"
#include "live_debugger.h"
#include "agent_info.h"
@@ -374,11 +375,19 @@ bool ddtrace_alter_sampling_rules_file_config(zval *old_value, zval *new_value,
return dd_save_sampling_rules_file_config(Z_STR_P(new_value), PHP_INI_USER, PHP_INI_STAGE_RUNTIME);
}
-static inline void dd_alter_prop(size_t prop_offset, zval *old_value, zval *new_value, zend_string *new_str) {
+static inline void dd_alter_prop_common(size_t prop_offset, zval *old_value, zval *new_value, zend_string *new_str, bool skip_inferred) {
UNUSED(old_value, new_str);
ddtrace_span_properties *pspan = ddtrace_active_span_props();
while (pspan) {
+ if (skip_inferred) {
+ ddtrace_span_data *span = SPANDATA(pspan);
+ if (span->type == DDTRACE_INFERRED_SPAN) {
+ pspan = pspan->parent; // It should be NULL, but just in case...
+ continue;
+ }
+ }
+
zval *property = (zval *) (prop_offset + (char *) pspan), garbage = *property;
ZVAL_COPY(property, new_value);
zval_ptr_dtor(&garbage);
@@ -386,8 +395,20 @@ static inline void dd_alter_prop(size_t prop_offset, zval *old_value, zval *new_
}
}
+static inline void dd_alter_prop(size_t prop_offset, zval *old_value, zval *new_value, zend_string *new_str) {
+ dd_alter_prop_common(prop_offset, old_value, new_value, new_str, false);
+}
+
+static inline void dd_alter_prop_skip_inferred_span(size_t prop_offset, zval *old_value, zval *new_value, zend_string *new_str) {
+ dd_alter_prop_common(prop_offset, old_value, new_value, new_str, true);
+}
+
bool ddtrace_alter_dd_service(zval *old_value, zval *new_value, zend_string *new_str) {
- dd_alter_prop(XtOffsetOf(ddtrace_span_properties, property_service), old_value, new_value, new_str);
+ if (get_DD_TRACE_INFERRED_PROXY_SERVICES_ENABLED()) {
+ dd_alter_prop_skip_inferred_span(XtOffsetOf(ddtrace_span_properties, property_service), old_value, new_value, new_str);
+ } else {
+ dd_alter_prop(XtOffsetOf(ddtrace_span_properties, property_service), old_value, new_value, new_str);
+ }
if (DDTRACE_G(request_initialized)) {
ddtrace_sidecar_submit_root_span_data_direct(NULL, new_str, get_DD_ENV(), get_DD_VERSION());
}
@@ -932,6 +953,7 @@ static zend_object *ddtrace_root_span_data_create(zend_class_entry *class_type)
array_init(&span->property_propagated_tags);
array_init(&span->property_tracestate_tags);
#endif
+ span->inferred_root = NULL;
return &span->std;
}
@@ -1459,6 +1481,8 @@ static PHP_MINIT_FUNCTION(ddtrace) {
ddtrace_minit_remote_config();
ddtrace_appsec_minit();
+ ddtrace_init_proxy_info_map();
+
return SUCCESS;
}
@@ -1612,6 +1636,10 @@ static void dd_initialize_request(void) {
ddtrace_distributed_tracing_result distributed_result = ddtrace_read_distributed_tracing_ids(ddtrace_read_zai_header, NULL);
ddtrace_apply_distributed_tracing_result(&distributed_result, NULL);
+ if (get_DD_TRACE_INFERRED_PROXY_SERVICES_ENABLED()) {
+ ddtrace_infer_proxy_services();
+ }
+
if (get_DD_TRACE_GENERATE_ROOT_SPAN()) {
ddtrace_push_root_span();
}
@@ -2693,6 +2721,10 @@ PHP_FUNCTION(DDTrace_root_span) {
}
dd_ensure_root_span();
ddtrace_root_span_data *span = DDTRACE_G(active_stack)->root_span;
+ if (span && span->type == DDTRACE_INFERRED_SPAN) {
+ span = span->inferred_root;
+ }
+
if (span) {
RETURN_OBJ_COPY(&span->std);
}
@@ -2736,6 +2768,25 @@ PHP_FUNCTION(DDTrace_start_trace_span) {
dd_start_span(INTERNAL_FUNCTION_PARAM_PASSTHRU);
}
+/* {{{ proto RootSpanData|null DDTrace\start_inferred_span(array $headers) */
+PHP_FUNCTION(DDTrace_start_inferred_span) {
+ zval *headers_zv = NULL;
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "a", &headers_zv) != SUCCESS) {
+ RETURN_THROWS();
+ }
+ zend_array *headers = Z_ARRVAL_P(headers_zv);
+
+ if (!get_DD_TRACE_ENABLED() || !get_DD_TRACE_INFERRED_PROXY_SERVICES_ENABLED()) {
+ RETURN_NULL();
+ }
+
+ ddtrace_root_span_data *root_span = ddtrace_open_inferred_span(headers);
+ if (root_span) {
+ RETURN_OBJ_COPY(&root_span->std);
+ }
+ RETURN_NULL();
+}
+
static void dd_set_span_finish_time(ddtrace_span_data *span, double finish_time_seconds) {
// we do not expose the monotonic time here, so do not use it as reference time to calculate difference
uint64_t start_time = span->start;
@@ -3065,18 +3116,6 @@ static bool dd_read_userspace_header(zai_str zai_header, const char *lowercase_h
return true;
}
-static bool dd_read_array_header(zai_str zai_header, const char *lowercase_header, zend_string **header_value, void *data) {
- UNUSED(zai_header);
- zend_array *array = (zend_array *) data;
- zval *value = zend_hash_str_find(array, lowercase_header, strlen(lowercase_header));
- if (!value) {
- return false;
- }
-
- *header_value = zval_get_string(value);
- return true;
-}
-
static ddtrace_distributed_tracing_result dd_parse_distributed_tracing_headers_function(INTERNAL_FUNCTION_PARAMETERS, bool *success) {
UNUSED(return_value);
@@ -3119,7 +3158,7 @@ static ddtrace_distributed_tracing_result dd_parse_distributed_tracing_headers_f
func.fci.param_count = 1;
if (array) {
- return ddtrace_read_distributed_tracing_ids(dd_read_array_header, array);
+ return ddtrace_read_distributed_tracing_ids(ddtrace_read_array_header, array);
} else if (use_server_headers) {
return ddtrace_read_distributed_tracing_ids(ddtrace_read_zai_header, &func);
} else {
diff --git a/ext/ddtrace.stub.php b/ext/ddtrace.stub.php
index 066b759dc5..5b0bb3fbb9 100644
--- a/ext/ddtrace.stub.php
+++ b/ext/ddtrace.stub.php
@@ -545,6 +545,12 @@ function update_span_duration(SpanData $span, float $finishTime = 0): false|null
*/
function start_trace_span(float $startTime = 0): SpanData {}
+ /**
+ * @internal
+ * @return RootSpanData|null The newly created inferred root span, or 'null' if headers extraction failed.
+ */
+ function start_inferred_span(array $headers): RootSpanData|null {}
+
/**
* Get the active stack
*
diff --git a/ext/ddtrace_arginfo.h b/ext/ddtrace_arginfo.h
index d616d445e9..3ee782d054 100644
--- a/ext/ddtrace_arginfo.h
+++ b/ext/ddtrace_arginfo.h
@@ -1,5 +1,5 @@
/* This is a generated file, edit the .stub.php file instead.
- * Stub hash: 5edec61a2b1ae22c8473ffbd3c509df6196abbae */
+ * Stub hash: 2ef1574e246f5a5c696b74152169237fad040333 */
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_DDTrace_trace_method, 0, 3, _IS_BOOL, 0)
ZEND_ARG_TYPE_INFO(0, className, IS_STRING, 0)
@@ -65,6 +65,10 @@ ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_DDTrace_start_trace_span, 0, 0, D
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, startTime, IS_DOUBLE, 0, "0")
ZEND_END_ARG_INFO()
+ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_DDTrace_start_inferred_span, 0, 1, DDTrace\\RootSpanData, 1)
+ ZEND_ARG_TYPE_INFO(0, headers, IS_ARRAY, 0)
+ZEND_END_ARG_INFO()
+
ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_DDTrace_active_stack, 0, 0, DDTrace\\SpanStack, 1)
ZEND_END_ARG_INFO()
@@ -318,6 +322,7 @@ ZEND_FUNCTION(DDTrace_start_span);
ZEND_FUNCTION(DDTrace_close_span);
ZEND_FUNCTION(DDTrace_update_span_duration);
ZEND_FUNCTION(DDTrace_start_trace_span);
+ZEND_FUNCTION(DDTrace_start_inferred_span);
ZEND_FUNCTION(DDTrace_active_stack);
ZEND_FUNCTION(DDTrace_create_stack);
ZEND_FUNCTION(DDTrace_switch_stack);
@@ -402,6 +407,7 @@ static const zend_function_entry ext_functions[] = {
ZEND_RAW_FENTRY(ZEND_NS_NAME("DDTrace", "close_span"), zif_DDTrace_close_span, arginfo_DDTrace_close_span, 0, NULL, NULL)
ZEND_RAW_FENTRY(ZEND_NS_NAME("DDTrace", "update_span_duration"), zif_DDTrace_update_span_duration, arginfo_DDTrace_update_span_duration, 0, NULL, NULL)
ZEND_RAW_FENTRY(ZEND_NS_NAME("DDTrace", "start_trace_span"), zif_DDTrace_start_trace_span, arginfo_DDTrace_start_trace_span, 0, NULL, NULL)
+ ZEND_RAW_FENTRY(ZEND_NS_NAME("DDTrace", "start_inferred_span"), zif_DDTrace_start_inferred_span, arginfo_DDTrace_start_inferred_span, 0, NULL, NULL)
ZEND_RAW_FENTRY(ZEND_NS_NAME("DDTrace", "active_stack"), zif_DDTrace_active_stack, arginfo_DDTrace_active_stack, 0, NULL, NULL)
ZEND_RAW_FENTRY(ZEND_NS_NAME("DDTrace", "create_stack"), zif_DDTrace_create_stack, arginfo_DDTrace_create_stack, 0, NULL, NULL)
ZEND_RAW_FENTRY(ZEND_NS_NAME("DDTrace", "switch_stack"), zif_DDTrace_switch_stack, arginfo_DDTrace_switch_stack, 0, NULL, NULL)
diff --git a/ext/distributed_tracing_headers.c b/ext/distributed_tracing_headers.c
index f54a4d06e4..f338a90adb 100644
--- a/ext/distributed_tracing_headers.c
+++ b/ext/distributed_tracing_headers.c
@@ -522,3 +522,15 @@ bool ddtrace_read_zai_header(zai_str zai_header, const char *lowercase_header, z
*header_value = zend_string_copy(*header_value);
return true;
}
+
+bool ddtrace_read_array_header(zai_str zai_header, const char *lowercase_header, zend_string **header_value, void *data) {
+ UNUSED(zai_header);
+ zend_array *array = (zend_array *) data;
+ zval *value = zend_hash_str_find(array, lowercase_header, strlen(lowercase_header));
+ if (!value) {
+ return false;
+ }
+
+ *header_value = zval_get_string(value);
+ return true;
+}
diff --git a/ext/distributed_tracing_headers.h b/ext/distributed_tracing_headers.h
index b69120cdf2..29747bc541 100644
--- a/ext/distributed_tracing_headers.h
+++ b/ext/distributed_tracing_headers.h
@@ -22,5 +22,6 @@ typedef bool (ddtrace_read_header)(zai_str zai_header, const char *lowercase_hea
ddtrace_distributed_tracing_result ddtrace_read_distributed_tracing_ids(ddtrace_read_header *read_header, void *data);
void ddtrace_apply_distributed_tracing_result(ddtrace_distributed_tracing_result *result, ddtrace_root_span_data *span);
bool ddtrace_read_zai_header(zai_str zai_header, const char *lowercase_header, zend_string **header_value, void *data);
+bool ddtrace_read_array_header(zai_str zai_header, const char *lowercase_header, zend_string **header_value, void *data);
#endif // DD_DISTRIBUTED_TRACING_HEADERS_H
diff --git a/ext/inferred_proxy_headers.c b/ext/inferred_proxy_headers.c
new file mode 100644
index 0000000000..8f917de401
--- /dev/null
+++ b/ext/inferred_proxy_headers.c
@@ -0,0 +1,46 @@
+#include "inferred_proxy_headers.h"
+
+ZEND_EXTERN_MODULE_GLOBALS(ddtrace);
+
+static HashTable proxy_info_map;
+
+void ddtrace_add_proxy_info(const char *system, const char *span_name, const char *component) {
+ ddtrace_proxy_info *info = pemalloc(sizeof(ddtrace_proxy_info), 1);
+ info->span_name = span_name;
+ info->component = component;
+ zend_hash_str_add_ptr(&proxy_info_map, system, strlen(system), info);
+}
+
+static void dd_proxy_info_dtor(zval *zv) {
+ pefree(Z_PTR_P(zv), 1);
+}
+
+void ddtrace_init_proxy_info_map(void) {
+ zend_hash_init(&proxy_info_map, 8, NULL, (dtor_func_t)dd_proxy_info_dtor, 1);
+
+ ddtrace_add_proxy_info("aws-apigateway", "aws.apigateway", "aws-apigateway");
+
+ // Add more proxies using ddtrace_add_proxy_info
+}
+
+ddtrace_inferred_proxy_result ddtrace_read_inferred_proxy_headers(ddtrace_read_header *read_header, void *data) {
+ ddtrace_inferred_proxy_result result = {0};
+
+ read_header((zai_str)ZAI_STRL("X_DD_PROXY"), "x-dd-proxy", &result.system, data);
+ read_header((zai_str)ZAI_STRL("X_DD_PROXY_REQUEST_TIME_MS"), "x-dd-proxy-request-time-ms", &result.start_time_ms, data);
+
+ if (!result.system || !result.start_time_ms) {
+ return result;
+ }
+
+ read_header((zai_str)ZAI_STRL("X_DD_PROXY_PATH"), "x-dd-proxy-path", &result.path, data);
+ read_header((zai_str)ZAI_STRL("X_DD_PROXY_HTTPMETHOD"), "x-dd-proxy-httpmethod", &result.http_method, data);
+ read_header((zai_str)ZAI_STRL("X_DD_PROXY_DOMAIN_NAME"), "x-dd-proxy-domain-name", &result.domain, data);
+ read_header((zai_str)ZAI_STRL("X_DD_PROXY_STAGE"), "x-dd-proxy-stage", &result.stage, data);
+
+ return result;
+}
+
+const ddtrace_proxy_info* ddtrace_get_proxy_info(zend_string *system) {
+ return zend_hash_find_ptr(&proxy_info_map, system);
+}
diff --git a/ext/inferred_proxy_headers.h b/ext/inferred_proxy_headers.h
new file mode 100644
index 0000000000..20cfb30fcb
--- /dev/null
+++ b/ext/inferred_proxy_headers.h
@@ -0,0 +1,25 @@
+#ifndef DD_INFERRED_PROXY_HEADERS_H
+#define DD_INFERRED_PROXY_HEADERS_H
+
+#include "ddtrace.h"
+#include "distributed_tracing_headers.h"
+
+typedef struct {
+ zend_string *system;
+ zend_string *start_time_ms;
+ zend_string *path;
+ zend_string *http_method;
+ zend_string *domain;
+ zend_string *stage;
+} ddtrace_inferred_proxy_result;
+
+typedef struct {
+ const char *span_name;
+ const char *component;
+} ddtrace_proxy_info;
+
+ddtrace_inferred_proxy_result ddtrace_read_inferred_proxy_headers(ddtrace_read_header *read_header, void *data);
+const ddtrace_proxy_info* ddtrace_get_proxy_info(zend_string *system);
+void ddtrace_init_proxy_info_map(void);
+
+#endif // DD_INFERRED_PROXY_HEADERS_H
\ No newline at end of file
diff --git a/ext/serializer.c b/ext/serializer.c
index 463756ee99..c123c6925d 100644
--- a/ext/serializer.c
+++ b/ext/serializer.c
@@ -678,9 +678,13 @@ static void dd_set_entrypoint_root_span_props(struct superglob_equiv *data, ddtr
}
void ddtrace_inherit_span_properties(ddtrace_span_data *span, ddtrace_span_data *parent) {
- zval *prop_service = &span->property_service;
- zval_ptr_dtor(prop_service);
- ZVAL_COPY(prop_service, &parent->property_service);
+ ddtrace_root_span_data *root = span->stack->root_span;
+ if (&root->span != parent || root->type != DDTRACE_INFERRED_SPAN) {
+ zval *prop_service = &span->property_service;
+ zval_ptr_dtor(prop_service);
+ ZVAL_COPY(prop_service, &parent->property_service);
+ }
+
zval *prop_type = &span->property_type;
zval_ptr_dtor(prop_type);
ZVAL_COPY(prop_type, &parent->property_type);
@@ -737,6 +741,24 @@ zend_string *ddtrace_active_service_name(void) {
return ddtrace_default_service_name();
}
+void dd_set_entrypoint_root_span_props_from_globals(ddtrace_root_span_data *span) {
+ struct superglob_equiv data = {0};
+ {
+ zval *_server_zv = &PG(http_globals)[TRACK_VARS_SERVER];
+ if (Z_TYPE_P(_server_zv) == IS_ARRAY || zend_is_auto_global_str(ZEND_STRL("_SERVER"))) {
+ data.server = Z_ARRVAL_P(_server_zv);
+ }
+ }
+ {
+ zval *_post_zv = &PG(http_globals)[TRACK_VARS_POST];
+ if (Z_TYPE_P(_post_zv) == IS_ARRAY || zend_is_auto_global_str(ZEND_STRL("_POST"))) {
+ data.post = Z_ARRVAL_P(_post_zv);
+ }
+ }
+
+ dd_set_entrypoint_root_span_props(&data, span);
+}
+
void ddtrace_set_root_span_properties(ddtrace_root_span_data *span) {
ddtrace_update_root_id_properties(span);
@@ -759,22 +781,8 @@ void ddtrace_set_root_span_properties(ddtrace_root_span_data *span) {
ZVAL_STR(&zv, encoded_id);
zend_hash_str_add_new(meta, ZEND_STRL("runtime-id"), &zv);
- if (ddtrace_span_is_entrypoint_root(&span->span)) {
- struct superglob_equiv data = {0};
- {
- zval *_server_zv = &PG(http_globals)[TRACK_VARS_SERVER];
- if (Z_TYPE_P(_server_zv) == IS_ARRAY || zend_is_auto_global_str(ZEND_STRL("_SERVER"))) {
- data.server = Z_ARRVAL_P(_server_zv);
- }
- }
- {
- zval *_post_zv = &PG(http_globals)[TRACK_VARS_POST];
- if (Z_TYPE_P(_post_zv) == IS_ARRAY || zend_is_auto_global_str(ZEND_STRL("_POST"))) {
- data.post = Z_ARRVAL_P(_post_zv);
- }
- }
-
- dd_set_entrypoint_root_span_props(&data, span);
+ if (ddtrace_span_is_entrypoint_root(&span->span) && span->type != DDTRACE_INFERRED_SPAN) {
+ dd_set_entrypoint_root_span_props_from_globals(span);
}
if (get_DD_TRACE_REPORT_HOSTNAME()) {
@@ -1173,6 +1181,13 @@ static void _serialize_meta(zval *el, ddtrace_span_data *span, zend_string *serv
zval *exception_zv = &span->property_exception;
bool has_exception = Z_TYPE_P(exception_zv) == IS_OBJECT && instanceof_function(Z_OBJCE_P(exception_zv), zend_ce_throwable);
+ if (!has_exception && span->std.ce == ddtrace_ce_root_span_data) { // inherit exception on inferred span from child root
+ ddtrace_root_span_data *root = ROOTSPANDATA(&span->std);
+ if (root->inferred_root) { // Can't check for DDTRACE_INFERRED_SPAN because the span is now closed
+ exception_zv = &root->inferred_root->span.property_exception;
+ has_exception = Z_TYPE_P(exception_zv) == IS_OBJECT && instanceof_function(Z_OBJCE_P(exception_zv), zend_ce_throwable);
+ }
+ }
if (has_exception) {
ignore_error = false;
enum dd_exception exception_type = DD_EXCEPTION_THROWN;
diff --git a/ext/serializer.h b/ext/serializer.h
index 3c5f3cb87b..58a64d0005 100644
--- a/ext/serializer.h
+++ b/ext/serializer.h
@@ -11,6 +11,7 @@ void ddtrace_serialize_span_to_array(ddtrace_span_data *span, zval *array);
void ddtrace_save_active_error_to_metadata(void);
void ddtrace_set_global_span_properties(ddtrace_span_data *span);
+void dd_set_entrypoint_root_span_props_from_globals(ddtrace_root_span_data *span);
void ddtrace_set_root_span_properties(ddtrace_root_span_data *span);
void ddtrace_update_root_id_properties(ddtrace_root_span_data *span);
void ddtrace_inherit_span_properties(ddtrace_span_data *span, ddtrace_span_data *parent);
diff --git a/ext/span.c b/ext/span.c
index 0ea3b2457a..1e657def23 100644
--- a/ext/span.c
+++ b/ext/span.c
@@ -18,6 +18,7 @@
#include "user_request.h"
#include "zend_types.h"
#include "sidecar.h"
+#include "inferred_proxy_headers.h"
#define USE_REALTIME_CLOCK 0
#define USE_MONOTONIC_CLOCK 1
@@ -165,8 +166,10 @@ ddtrace_span_data *ddtrace_open_span(enum ddtrace_span_dataype type) {
// ensure dtor can be called again
GC_DEL_FLAGS(&stack->std, IS_OBJ_DESTRUCTOR_CALLED);
+ ddtrace_root_span_data *rsd = DDTRACE_G(active_stack)->root_span;
+ bool child_of_inferred_span = rsd != NULL && rsd->type == DDTRACE_INFERRED_SPAN && rsd->inferred_root == NULL;
bool root_span = DDTRACE_G(active_stack)->root_span == NULL;
- ddtrace_span_data *span = ddtrace_init_span(type, root_span ? ddtrace_ce_root_span_data : ddtrace_ce_span_data);
+ ddtrace_span_data *span = ddtrace_init_span(type, (root_span || child_of_inferred_span) ? ddtrace_ce_root_span_data : ddtrace_ce_span_data);
// All open spans hold a ref to their stack
ZVAL_OBJ_COPY(&span->property_stack, &stack->std);
@@ -204,6 +207,23 @@ ddtrace_span_data *ddtrace_open_span(enum ddtrace_span_dataype type) {
span->parent = NULL;
ddtrace_set_root_span_properties(root);
+ } else if (child_of_inferred_span) {
+ ddtrace_root_span_data *root = ROOTSPANDATA(&span->std);
+ DDTRACE_G(active_stack)->root_span->inferred_root = root;
+
+ root->trace_id = DDTRACE_G(active_stack)->root_span->trace_id;
+ root->parent_id = DDTRACE_G(active_stack)->root_span->span.span_id;
+ ZVAL_OBJ(&span->property_parent, &DDTRACE_G(active_stack)->root_span->span.std);
+ ddtrace_inherit_span_properties(span, &DDTRACE_G(active_stack)->root_span->span);
+ dd_set_entrypoint_root_span_props_from_globals(root);
+
+ zval *prop_name = &span->property_name;
+ zval_ptr_dtor(prop_name);
+ ZVAL_STR(prop_name, ddtrace_default_service_name());
+
+ zval *prop_service = &span->property_service;
+ zval_ptr_dtor(prop_service);
+ ZVAL_STR_COPY(prop_service, ZSTR_LEN(get_DD_SERVICE()) ? get_DD_SERVICE() : Z_STR_P(prop_name));
} else {
// do not copy the parent, it was active span before, just transfer that reference
ZVAL_OBJ(&span->property_parent, &parent_span->std);
@@ -374,6 +394,13 @@ void ddtrace_push_root_span(void) {
GC_DELREF(&span->std);
}
+ddtrace_span_data *ddtrace_push_inferred_root_span(void) {
+ ddtrace_span_data *span = ddtrace_open_span(DDTRACE_INFERRED_SPAN);
+ // We opened the span, but are not going to hold a reference to it directly - the stack will manage it.
+ GC_DELREF(&span->std);
+ return span;
+}
+
DDTRACE_PUBLIC zend_object *ddtrace_get_root_span()
{
if (!DDTRACE_G(active_stack)) {
@@ -658,7 +685,7 @@ void ddtrace_close_all_open_spans(bool force_close_root_span) {
ddtrace_span_data *span;
while (stack->active && (span = SPANDATA(stack->active))->stack == stack) {
LOG(SPAN_TRACE, "Automatically finishing the next span (in shutdown or force flush requested)");
- if (get_DD_AUTOFINISH_SPANS() || (force_close_root_span && span->type == DDTRACE_AUTOROOT_SPAN)) {
+ if (get_DD_AUTOFINISH_SPANS() || (force_close_root_span && (span->type == DDTRACE_AUTOROOT_SPAN || span->type == DDTRACE_INFERRED_SPAN))) {
dd_trace_stop_span_time(span);
ddtrace_close_span(span);
} else {
@@ -796,3 +823,78 @@ zend_string *ddtrace_trace_id_as_hex_string(ddtrace_trace_id id) {
snprintf(ZSTR_VAL(str), 33, "%016" PRIx64 "%016" PRIx64, id.high, id.low);
return str;
}
+
+static void free_inferred_proxy_result(ddtrace_inferred_proxy_result *result) {
+ zend_string_release(result->system);
+ zend_string_release(result->start_time_ms);
+ if (result->http_method) zend_string_release(result->http_method);
+ if (result->path) zend_string_release(result->path);
+ if (result->domain) zend_string_release(result->domain);
+ if (result->stage) zend_string_release(result->stage);
+}
+
+
+ddtrace_root_span_data *ddtrace_open_inferred_span(zend_array *headers) {
+ ddtrace_read_header *read_header = headers ? ddtrace_read_array_header : ddtrace_read_zai_header;
+ ddtrace_inferred_proxy_result result = ddtrace_read_inferred_proxy_headers(read_header, headers);
+
+ if (!result.system || !result.start_time_ms) {
+ free_inferred_proxy_result(&result);
+ return NULL;
+ }
+
+ const ddtrace_proxy_info *proxy_info = ddtrace_get_proxy_info(result.system);
+ if (!proxy_info) {
+ zend_string_release(result.system);
+ zend_string_release(result.start_time_ms);
+ return NULL;
+ }
+
+ ddtrace_span_data *span = ddtrace_push_inferred_root_span();
+
+ zval_ptr_dtor(&span->property_name);
+ ZVAL_STR(&span->property_name, zend_string_init(proxy_info->span_name, strlen(proxy_info->span_name), 0));
+
+ zval_ptr_dtor(&span->property_resource);
+ if (result.http_method && result.path) {
+ ZVAL_STR(&span->property_resource, strpprintf(0, "%s %s", ZSTR_VAL(result.http_method), ZSTR_VAL(result.path)));
+ }
+
+ span->start = ZEND_ATOL(ZSTR_VAL(result.start_time_ms)) * 1000000;
+ span->duration_start = zend_hrtime() - (ddtrace_nanoseconds_realtime() - span->start);
+
+ zval zv;
+
+ if (result.domain) {
+ ZVAL_STR_COPY(&zv, result.domain);
+ ddtrace_assign_variable(&span->property_service, &zv);
+ }
+
+ zend_array *meta = ddtrace_property_array(&span->property_meta);
+
+ if (result.http_method) {
+ ZVAL_STR_COPY(&zv, result.http_method);
+ zend_hash_str_add_new(meta, ZEND_STRL("http.method"), &zv);
+ }
+
+ if (result.domain && result.path) {
+ ZVAL_STR(&zv, strpprintf(0, "%s%s", ZSTR_VAL(result.domain), ZSTR_VAL(result.path)));
+ zend_hash_str_add_new(meta, ZEND_STRL("http.url"), &zv);
+ }
+
+ if (result.stage) {
+ ZVAL_STR_COPY(&zv, result.stage);
+ zend_hash_str_add_new(meta, ZEND_STRL("stage"), &zv);
+ }
+
+ add_assoc_long(&span->property_meta, "_dd.inferred_span", 1);
+ add_assoc_string(&span->property_meta, "component", proxy_info->component);
+
+ free_inferred_proxy_result(&result);
+
+ return ROOTSPANDATA(&span->std);
+}
+
+void ddtrace_infer_proxy_services(void) {
+ ddtrace_open_inferred_span(NULL);
+}
diff --git a/ext/span.h b/ext/span.h
index c664ead825..8545faa025 100644
--- a/ext/span.h
+++ b/ext/span.h
@@ -23,6 +23,7 @@ enum ddtrace_span_dataype {
DDTRACE_INTERNAL_SPAN,
DDTRACE_USER_SPAN,
DDTRACE_AUTOROOT_SPAN,
+ DDTRACE_INFERRED_SPAN,
DDTRACE_SPAN_CLOSED,
};
@@ -107,6 +108,7 @@ struct ddtrace_root_span_data {
ddtrace_rule_result sampling_rule;
bool explicit_sampling_priority;
enum ddtrace_trace_limited trace_is_limited;
+ struct ddtrace_root_span_data *inferred_root; // Only used when inferring proxy services (type: DDTRACE_INFERRED_SPAN)
union {
ddtrace_span_data;
@@ -211,6 +213,7 @@ ddtrace_span_data *ddtrace_init_dummy_span(void);
ddtrace_span_stack *ddtrace_init_span_stack(void);
ddtrace_span_stack *ddtrace_init_root_span_stack(void);
void ddtrace_push_root_span(void);
+ddtrace_span_data *ddtrace_push_inferred_root_span(void);
ddtrace_span_data *ddtrace_active_span(void);
static inline ddtrace_span_properties *ddtrace_active_span_props(void) {
@@ -241,6 +244,8 @@ zend_string *ddtrace_span_id_as_string(uint64_t id);
zend_string *ddtrace_trace_id_as_string(ddtrace_trace_id id);
zend_string *ddtrace_span_id_as_hex_string(uint64_t id);
zend_string *ddtrace_trace_id_as_hex_string(ddtrace_trace_id id);
+ddtrace_root_span_data *ddtrace_open_inferred_span(zend_array *headers);
+void ddtrace_infer_proxy_services(void);
bool ddtrace_span_alter_root_span_config(zval *old_value, zval *new_value, zend_string *new_str);
@@ -250,7 +255,9 @@ static inline bool ddtrace_span_is_dropped(ddtrace_span_data *span) {
static inline bool ddtrace_span_is_entrypoint_root(ddtrace_span_data *span) {
// The parent stack of a true top-level stack does never have a parent stack itself
- return span->std.ce == ddtrace_ce_root_span_data && (!span->stack->parent_stack || !span->stack->parent_stack->parent_stack);
+ return span->std.ce == ddtrace_ce_root_span_data
+ && (!span->stack->parent_stack || !span->stack->parent_stack->parent_stack)
+ && (!span->root || !span->root->inferred_root || &span->root->inferred_root->span != span);
}
#endif // DD_SPAN_H
diff --git a/src/DDTrace/Integrations/Roadrunner/RoadrunnerIntegration.php b/src/DDTrace/Integrations/Roadrunner/RoadrunnerIntegration.php
index 27b2b8a0bf..6941c7c4f5 100644
--- a/src/DDTrace/Integrations/Roadrunner/RoadrunnerIntegration.php
+++ b/src/DDTrace/Integrations/Roadrunner/RoadrunnerIntegration.php
@@ -137,15 +137,17 @@ public function init(): int
$recCall = 0;
\DDTrace\install_hook('Spiral\RoadRunner\Http\HttpWorker::waitRequest',
- function () use (&$activeSpan, &$suppressResponse) {
+ function () use (&$inferredSpan, &$activeSpan, &$suppressResponse) {
if ($activeSpan) {
\DDTrace\close_spans_until($activeSpan);
\DDTrace\close_span();
+ dd_trace_close_all_spans_and_flush();
}
$activeSpan = null;
+ $inferredSpan = null;
$suppressResponse = null;
},
- function (HookData $hook) use (&$activeSpan, &$suppressResponse, $integration, $service, &$recCall) {
+ function (HookData $hook) use (&$inferredSpan, &$activeSpan, &$suppressResponse, $integration, $service, &$recCall) {
/** @var ?\Spiral\RoadRunner\Http\Request $retval */
$retval = $hook->returned;
if (!$retval && !$hook->exception) {
@@ -155,7 +157,22 @@ function (HookData $hook) use (&$activeSpan, &$suppressResponse, $integration, $
return;
}
- $activeSpan = \DDTrace\start_trace_span();
+ $headers = [];
+ if ($retval) {
+ foreach ($retval->headers as $headername => $header) {
+ $header = implode(", ", $header);
+ $headers[strtolower($headername)] = $header;
+ }
+ }
+
+ $inferredProxyServicesEnabled = \dd_trace_env_config('DD_TRACE_INFERRED_PROXY_SERVICES_ENABLED');
+ $inferredSpan = null;
+ if ($inferredProxyServicesEnabled && $headers) {
+ $inferredSpan = \DDTrace\start_inferred_span($headers);
+ }
+ $hook->data['inferredSpan'] = $inferredSpan;
+
+ $activeSpan = $inferredSpan ? \DDTrace\start_span() : \DDTrace\start_trace_span();
$activeSpan->service = $service;
$activeSpan->name = "web.request";
@@ -165,26 +182,32 @@ function (HookData $hook) use (&$activeSpan, &$suppressResponse, $integration, $
$integration->addTraceAnalyticsIfEnabled($activeSpan);
if ($hook->exception) {
$activeSpan->exception = $hook->exception;
+ if ($inferredSpan) {
+ $inferredSpan->exception = $hook->exception;
+ }
\DDTrace\close_span();
+ if ($inferredSpan) {
+ dd_trace_close_all_spans_and_flush();
+ }
$activeSpan = null;
+ $inferredSpan = null;
} else {
- $headers = [];
- foreach ($retval->headers as $headername => $header) {
- $header = implode(", ", $header);
- $headers[strtolower($headername)] = $header;
- }
\DDTrace\consume_distributed_tracing_headers(function ($headername) use ($headers) {
return $headers[$headername] ?? null;
});
- $res = notify_start($activeSpan, RoadrunnerIntegration::build_req_spec($retval), $retval->body);
+ $res = notify_start($inferredSpan ?: $activeSpan, RoadrunnerIntegration::build_req_spec($retval), $retval->body);
if ($res) {
// block on start
RoadrunnerIntegration::ensure_headers_map_fmt($res['headers']);
$this->respond($res['status'], $res['body'] ?? '', $res['headers']);
\DDTrace\close_span();
+ if ($inferredSpan) {
+ dd_trace_close_all_spans_and_flush();
+ }
$activeSpan = null;
+ $inferredSpan = null;
if ($recCall++ > 128) {
// too many recursive calls. Exit so that the worker can be restarted
@@ -199,7 +222,7 @@ function (HookData $hook) use (&$activeSpan, &$suppressResponse, $integration, $
} else {
$thiz = $this;
// to support block midrequest
- set_blocking_function($activeSpan,
+ set_blocking_function($inferredSpan ?: $activeSpan,
static function ($res) use (&$activeSpan, &$suppressResponse, $thiz) {
RoadrunnerIntegration::ensure_headers_map_fmt($res['headers']);
$thiz->respond($res['status'], $res['body'] ?? '', $res['headers']);
@@ -210,7 +233,7 @@ static function ($res) use (&$activeSpan, &$suppressResponse, $thiz) {
}
});
- $respondBefore = function (HookData $hook) use (&$activeSpan, &$suppressResponse) {
+ $respondBefore = function (HookData $hook) use (&$inferredSpan, &$activeSpan, &$suppressResponse) {
$hook->disableJitInlining();
if (!$activeSpan || count($hook->args) < 3) {
return;
@@ -237,7 +260,7 @@ static function ($res) use (&$activeSpan, &$suppressResponse, $thiz) {
// send arbitrary addresses.
$body = null;
}
- $blocking = notify_commit($activeSpan, $hook->args[0], $hook->args[2], $body);
+ $blocking = notify_commit($inferredSpan ?: $activeSpan, $hook->args[0], $hook->args[2], $body);
if ($blocking) {
$hook->args[0] = $blocking['status'];
$hook->args[1] = $blocking['body'];
@@ -246,7 +269,7 @@ static function ($res) use (&$activeSpan, &$suppressResponse, $thiz) {
}
};
- $respondAfter = function (HookData $hook) use (&$activeSpan, &$suppressResponse) {
+ $respondAfter = function (HookData $hook) use (&$inferredSpan, &$activeSpan, &$suppressResponse) {
if (!$activeSpan || count($hook->args) < 3) {
return;
}
@@ -257,8 +280,14 @@ static function ($res) use (&$activeSpan, &$suppressResponse, $thiz) {
$activeSpan->meta[Tag::COMPONENT] = RoadrunnerIntegration::NAME;
if ($hook->exception && empty($activeSpan->exception)) {
$activeSpan->exception = $hook->exception;
+ if ($inferredSpan) {
+ $inferredSpan->exception = $hook->exception;
+ }
} elseif ($status >= 500 && $ex = \DDTrace\find_active_exception()) {
$activeSpan->exception = $ex;
+ if ($inferredSpan) {
+ $inferredSpan->exception = $ex;
+ }
}
};
diff --git a/src/DDTrace/Integrations/Swoole/SwooleIntegration.php b/src/DDTrace/Integrations/Swoole/SwooleIntegration.php
index 06a01d2256..a0aafd81d5 100644
--- a/src/DDTrace/Integrations/Swoole/SwooleIntegration.php
+++ b/src/DDTrace/Integrations/Swoole/SwooleIntegration.php
@@ -14,6 +14,7 @@
use function DDTrace\consume_distributed_tracing_headers;
use function DDTrace\extract_ip_from_headers;
use function DDTrace\Internal\handle_fork;
+use function DDTrace\set_distributed_tracing_context;
class SwooleIntegration extends Integration
{
@@ -34,7 +35,18 @@ public function instrumentRequestStart(callable $callback, SwooleIntegration $in
\DDTrace\install_hook(
$callback,
function (HookData $hook) use ($integration, $server, $scheme) {
- $rootSpan = $hook->span(new SpanStack());
+ $args = $hook->args;
+ /** @var Request $request */
+ $request = $args[0];
+
+ $inferredProxyServicesEnabled = \dd_trace_env_config('DD_TRACE_INFERRED_PROXY_SERVICES_ENABLED');
+ $inferredSpan = null;
+ if ($inferredProxyServicesEnabled) {
+ $inferredSpan = \DDTrace\start_inferred_span($request->header);
+ }
+ $hook->data['inferredSpan'] = $inferredSpan;
+
+ $rootSpan = $hook->span($inferredSpan ?: new SpanStack());
$rootSpan->name = "web.request";
$rootSpan->service = \ddtrace_config_app_name('swoole');
$rootSpan->type = Type::WEB_SERVLET;
@@ -42,10 +54,6 @@ function (HookData $hook) use ($integration, $server, $scheme) {
$rootSpan->meta[Tag::SPAN_KIND] = Tag::SPAN_KIND_VALUE_SERVER;
$integration->addTraceAnalyticsIfEnabled($rootSpan);
- $args = $hook->args;
- /** @var Request $request */
- $request = $args[0];
-
$headers = [];
$allowedHeaders = \dd_trace_env_config('DD_TRACE_HEADER_TAGS');
foreach ($request->header as $name => $value) {
@@ -102,6 +110,16 @@ function (HookData $hook) use ($integration, $server, $scheme) {
$rootSpan->meta[Tag::HTTP_URL] = Normalizer::uriNormalizeincomingPath($url);
unset($rootSpan->meta['closure.declaration']);
+ },
+ function (HookData $hook) {
+ $inferredSpan = $hook->data['inferredSpan'];
+ if ($inferredSpan) {
+ $autofinishConfig = ini_get('datadog.autofinish_spans');
+ ini_set('datadog.autofinish_spans', 'true');
+ \DDTrace\switch_stack($inferredSpan);
+ dd_trace_close_all_spans_and_flush();
+ ini_set('datadog.autofinish_spans', $autofinishConfig);
+ }
}
);
}
@@ -175,7 +193,9 @@ function ($response, $scope, $args) use ($integration) {
&& ((int)$rootSpan->meta[Tag::HTTP_STATUS_CODE]) >= 500
&& $ex = \DDTrace\find_active_exception()
) {
- $rootSpan->exception = $ex;
+ do {
+ $rootSpan->exception = $ex;
+ } while ($rootSpan = $rootSpan->parent);
}
}
);
diff --git a/tests/Frameworks/Laravel/Latest/.env b/tests/Frameworks/Laravel/Latest/.env
index 1047bb0413..fb543cfb09 100644
--- a/tests/Frameworks/Laravel/Latest/.env
+++ b/tests/Frameworks/Laravel/Latest/.env
@@ -20,11 +20,11 @@ LOG_DEPRECATIONS_CHANNEL=null
LOG_LEVEL=debug
DB_CONNECTION=mysql
-DB_HOST=127.0.0.1
+DB_HOST=mysql_integration
DB_PORT=3306
-DB_DATABASE=laravel
-DB_USERNAME=root
-DB_PASSWORD=
+DB_DATABASE=laravel11
+DB_USERNAME=test
+DB_PASSWORD=test
SESSION_DRIVER=file
SESSION_LIFETIME=120
diff --git a/tests/Integrations/CLI/Laravel/Latest/CommonScenariosTest.php b/tests/Integrations/CLI/Laravel/Latest/CommonScenariosTest.php
index a317486761..58f04c6162 100644
--- a/tests/Integrations/CLI/Laravel/Latest/CommonScenariosTest.php
+++ b/tests/Integrations/CLI/Laravel/Latest/CommonScenariosTest.php
@@ -8,6 +8,11 @@
class CommonScenariosTest extends \DDTrace\Tests\Integrations\CLI\Laravel\V10_X\CommonScenariosTest
{
+ protected function getScriptLocation()
+ {
+ return __DIR__ . '/../../../../Frameworks/Laravel/Latest/artisan';
+ }
+
public function testCommandWithNoArguments()
{
$this->retrieveDumpedData();
diff --git a/tests/Integrations/Laravel/APIGWTest.php b/tests/Integrations/Laravel/APIGWTest.php
new file mode 100644
index 0000000000..873bf75f73
--- /dev/null
+++ b/tests/Integrations/Laravel/APIGWTest.php
@@ -0,0 +1,68 @@
+ 'laravel_test_app',
+ 'DD_SERVICE' => 'my_service',
+ 'DD_ENV' => 'local-test',
+ 'DD_VERSION' => '1.0',
+ 'DD_TRACE_INFERRED_PROXY_SERVICES_ENABLED' => 'true',
+ ]);
+ }
+
+ public function testLaravelInferredProxy()
+ {
+ $this->tracesFromWebRequestSnapshot(function () {
+ $this->call(
+ GetSpec::create(
+ 'A simple GET request returning a string',
+ '/simple?key=value&pwd=should_redact',
+ [
+ 'x-dd-proxy: aws-apigateway',
+ 'x-dd-proxy-request-time-ms: 1739261376000',
+ 'x-dd-proxy-path: /test',
+ 'x-dd-proxy-httpmethod: GET',
+ 'x-dd-proxy-domain-name: example.com',
+ 'x-dd-proxy-stage: aws-prod',
+ ]
+ )
+ );
+ });
+ }
+
+ public function testLaravelInferredProxyException()
+ {
+ $this->tracesFromWebRequestSnapshot(function () {
+ $this->call(
+ GetSpec::create(
+ 'A GET throwing an exception',
+ '/error?key=value&pwd=should_redact',
+ [
+ 'x-dd-proxy: aws-apigateway',
+ 'x-dd-proxy-request-time-ms: 1739261376000',
+ 'x-dd-proxy-path: /test',
+ 'x-dd-proxy-httpmethod: GET',
+ 'x-dd-proxy-domain-name: example.com',
+ 'x-dd-proxy-stage: aws-prod',
+ ]
+ )
+ );
+ });
+ }
+}
\ No newline at end of file
diff --git a/tests/Integrations/Laravel/Latest/CommonScenariosTest.php b/tests/Integrations/Laravel/Latest/CommonScenariosTest.php
index d5262ba8a4..045deed71d 100644
--- a/tests/Integrations/Laravel/Latest/CommonScenariosTest.php
+++ b/tests/Integrations/Laravel/Latest/CommonScenariosTest.php
@@ -4,6 +4,8 @@
class CommonScenariosTest extends \DDTrace\Tests\Integrations\Laravel\V9_x\CommonScenariosTest
{
+ public static $database = "laravel11";
+
public static function getAppIndexScript()
{
return __DIR__ . '/../../../Frameworks/Laravel/Latest/public/index.php';
diff --git a/tests/Integrations/Laravel/Octane/APIGWTest.php b/tests/Integrations/Laravel/Octane/APIGWTest.php
new file mode 100644
index 0000000000..e62c90bdf6
--- /dev/null
+++ b/tests/Integrations/Laravel/Octane/APIGWTest.php
@@ -0,0 +1,150 @@
+ 'laravel_test_app',
+ 'DD_SERVICE' => 'swoole_test_app',
+ 'DD_TRACE_CLI_ENABLED' => 'true',
+ 'PHP_INI_SCAN_DIR' => ':' . dirname(self::getAppIndexScript()),
+ 'DD_ENV' => 'local-test',
+ 'DD_VERSION' => '1.0',
+ 'DD_TRACE_INFERRED_PROXY_SERVICES_ENABLED' => 'true',
+ 'DD_TRACE_HEADER_TAGS' => 'x-dd-proxy-domain-name,x-dd-proxy,x-dd-proxy-httpmethod,x-dd-proxy-path,x-dd-proxy-request-time-ms,x-dd-proxy-stage',
+ ]);
+ }
+
+ public function testInferredProxy()
+ {
+ $until = function ($request) {
+ $body = $request["body"] ?? [];
+ $traces = empty($body) ? [[]] : json_decode($body, true);
+
+ foreach ($traces as $trace) {
+ foreach ($trace as $span) {
+ if ($span
+ && isset($span["name"])
+ && $span["name"] === "laravel.request"
+ && (str_contains($span["resource"], 'App\\Http\\Controllers') || $span["resource"] === 'GET /does_not_exist')
+ ) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ };
+
+ $traces = $this->tracesFromWebRequest(function () {
+ $this->call(
+ GetSpec::create(
+ 'A simple GET request returning a string',
+ '/simple?key=value&pwd=should_redact',
+ [
+ 'x-dd-proxy: aws-apigateway',
+ 'x-dd-proxy-request-time-ms: 1739261376000',
+ 'x-dd-proxy-path: /test',
+ 'x-dd-proxy-httpmethod: GET',
+ 'x-dd-proxy-domain-name: example.com',
+ 'x-dd-proxy-stage: aws-prod',
+ ]
+ )
+ );
+ }, null, $until);
+
+ $apigwTrace = null;
+ foreach ($traces as $trace) {
+ if ($trace[0]["name"] === "aws.apigateway") {
+ $apigwTrace = $trace;
+ break;
+ }
+ }
+
+ $this->snapshotFromTraces([$apigwTrace]);
+ }
+
+ public function testInferredProxyException()
+ {
+ $until = function ($request) {
+ $body = $request["body"] ?? [];
+ $traces = empty($body) ? [[]] : json_decode($body, true);
+
+ foreach ($traces as $trace) {
+ foreach ($trace as $span) {
+ if ($span
+ && isset($span["name"])
+ && $span["name"] === "laravel.request"
+ && (str_contains($span["resource"], 'App\\Http\\Controllers') || $span["resource"] === 'GET /does_not_exist')
+ ) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ };
+
+ $traces = $this->tracesFromWebRequest(function () {
+ $this->call(
+ GetSpec::create(
+ 'A GET throwing an exception',
+ '/error?key=value&pwd=should_redact',
+ [
+ 'x-dd-proxy: aws-apigateway',
+ 'x-dd-proxy-request-time-ms: 1739261376000',
+ 'x-dd-proxy-path: /test',
+ 'x-dd-proxy-httpmethod: GET',
+ 'x-dd-proxy-domain-name: example.com',
+ 'x-dd-proxy-stage: aws-prod',
+ ]
+ )
+ );
+ }, null, $until);
+
+ $apigwTrace = null;
+ foreach ($traces as $trace) {
+ if ($trace[0]["name"] === "aws.apigateway") {
+ $apigwTrace = $trace;
+ break;
+ }
+ }
+
+ $this->snapshotFromTraces([$apigwTrace]);
+ }
+}
\ No newline at end of file
diff --git a/tests/Integrations/Roadrunner/APIGWTest.php b/tests/Integrations/Roadrunner/APIGWTest.php
new file mode 100644
index 0000000000..8bec3ff722
--- /dev/null
+++ b/tests/Integrations/Roadrunner/APIGWTest.php
@@ -0,0 +1,86 @@
+ 'roadrunner_test_app',
+ 'DD_TRACE_CLI_ENABLED' => 'true',
+ 'DD_ENV' => 'local-test',
+ 'DD_VERSION' => '1.0',
+ 'DD_TRACE_INFERRED_PROXY_SERVICES_ENABLED' => 'true',
+ 'DD_TRACE_HEADER_TAGS' => 'x-dd-proxy-domain-name,x-dd-proxy,x-dd-proxy-httpmethod,x-dd-proxy-path,x-dd-proxy-request-time-ms,x-dd-proxy-stage',
+ ]);
+ }
+
+ public function testInferredProxy()
+ {
+ $traces = $this->tracesFromWebRequest(function () {
+ $this->call(
+ GetSpec::create(
+ 'A simple GET request returning a string',
+ '/simple?key=value&pwd=should_redact',
+ [
+ 'x-dd-proxy: aws-apigateway',
+ 'x-dd-proxy-request-time-ms: 1739261376000',
+ 'x-dd-proxy-path: /test',
+ 'x-dd-proxy-httpmethod: GET',
+ 'x-dd-proxy-domain-name: example.com',
+ 'x-dd-proxy-stage: aws-prod',
+ ]
+ )
+ );
+ });
+
+ $this->snapshotFromTraces($traces);
+ }
+
+ public function testInferredProxyException()
+ {
+ $traces = $this->tracesFromWebRequest(function () {
+ $this->call(
+ GetSpec::create(
+ 'A GET throwing an exception',
+ '/error?key=value&pwd=should_redact',
+ [
+ 'x-dd-proxy: aws-apigateway',
+ 'x-dd-proxy-request-time-ms: 1739261376000',
+ 'x-dd-proxy-path: /test',
+ 'x-dd-proxy-httpmethod: GET',
+ 'x-dd-proxy-domain-name: example.com',
+ 'x-dd-proxy-stage: aws-prod',
+ ]
+ )
+ );
+ });
+
+ $this->snapshotFromTraces($traces);
+ }
+}
diff --git a/tests/ext/inferred_proxy/alter_service.phpt b/tests/ext/inferred_proxy/alter_service.phpt
new file mode 100644
index 0000000000..be589fc18d
--- /dev/null
+++ b/tests/ext/inferred_proxy/alter_service.phpt
@@ -0,0 +1,126 @@
+--TEST--
+Inferred span's service shouldn't change on ini_change of datadog.service
+--ENV--
+DD_TRACE_AUTO_FLUSH_ENABLED=0
+DD_TRACE_GENERATE_ROOT_SPAN=0
+DD_AUTOFINISH_SPANS=1
+DD_SERVICE=aws-server
+DD_ENV=local-prod
+DD_VERSION=1.0
+
+DD_TRACE_DEBUG=0
+
+DD_TRACE_INFERRED_PROXY_SERVICES_ENABLED=1
+HTTP_X_DD_PROXY=aws-apigateway
+HTTP_X_DD_PROXY_REQUEST_TIME_MS=100
+HTTP_X_DD_PROXY_PATH=/test
+HTTP_X_DD_PROXY_HTTPMETHOD=GET
+HTTP_X_DD_PROXY_DOMAIN_NAME=example.com
+HTTP_X_DD_PROXY_STAGE=aws-prod
+
+METHOD=GET
+SERVER_NAME=localhost:8888
+SCRIPT_NAME=/foo.php
+REQUEST_URI=/foo
+
+DD_AGENT_HOST=request-replayer
+DD_TRACE_AGENT_PORT=80
+DD_TRACE_AGENT_FLUSH_AFTER_N_REQUESTS=1
+DD_TRACE_AGENT_FLUSH_INTERVAL=666
+DD_INSTRUMENTATION_TELEMETRY_ENABLED=0
+
+DD_TRACE_DEBUG_PRNG_SEED=42
+--GET--
+foo=bar
+--FILE--
+name = "child";
+
+dd_trace_close_all_spans_and_flush(); // Simulates end of request
+
+$body = json_decode($rr->waitForDataAndReplay()["body"], true);
+echo json_encode($body, JSON_PRETTY_PRINT);
+?>
+--EXPECTF--
+[
+ [
+ {
+ "trace_id": "13930160852258120406",
+ "span_id": "13930160852258120406",
+ "start": 100000000,
+ "duration": %d,
+ "name": "aws.apigateway",
+ "resource": "GET \/test",
+ "service": "example.com",
+ "type": "web",
+ "meta": {
+ "runtime-id": "%s",
+ "http.method": "GET",
+ "http.url": "example.com\/test",
+ "stage": "aws-prod",
+ "_dd.inferred_span": "1",
+ "component": "aws-apigateway",
+ "_dd.p.dm": "-0",
+ "env": "local-prod",
+ "version": "1.0",
+ "http.status_code": "200",
+ "_dd.p.tid": "%s"
+ },
+ "metrics": {
+ "process_id": %d,
+ "_dd.agent_psr": 1,
+ "_sampling_priority_v1": 1,
+ "php.compilation.total_time_ms": %f,
+ "php.memory.peak_usage_bytes": %d,
+ "php.memory.peak_real_usage_bytes": %d
+ }
+ },
+ {
+ "trace_id": "13930160852258120406",
+ "span_id": "11788048577503494824",
+ "parent_id": "13930160852258120406",
+ "start": 120000000,
+ "duration": %d,
+ "name": "web.request",
+ "resource": "GET \/foo",
+ "service": "my_service",
+ "type": "web",
+ "meta": {
+ "http.url": "http:\/\/localhost:8888\/foo",
+ "http.method": "GET",
+ "env": "local-prod",
+ "version": "1.0",
+ "_dd.p.tid": "%s",
+ "_dd.base_service": "example.com"
+ },
+ "metrics": {
+ "_sampling_priority_v1": 1
+ }
+ },
+ {
+ "trace_id": "13930160852258120406",
+ "span_id": "13874630024467741450",
+ "parent_id": "11788048577503494824",
+ "start": 130000000,
+ "duration": %d,
+ "name": "child",
+ "resource": "child",
+ "service": "my_service",
+ "type": "web",
+ "meta": {
+ "env": "local-prod",
+ "version": "1.0",
+ "_dd.base_service": "example.com"
+ }
+ }
+ ]
+]
\ No newline at end of file
diff --git a/tests/ext/inferred_proxy/basic_test.phpt b/tests/ext/inferred_proxy/basic_test.phpt
new file mode 100644
index 0000000000..06b26a30f3
--- /dev/null
+++ b/tests/ext/inferred_proxy/basic_test.phpt
@@ -0,0 +1,127 @@
+--TEST--
+Should create parent and child spans for a 200
+--ENV--
+DD_TRACE_AUTO_FLUSH_ENABLED=0
+DD_TRACE_GENERATE_ROOT_SPAN=0
+DD_AUTOFINISH_SPANS=1
+DD_SERVICE=aws-server
+DD_ENV=local-prod
+DD_VERSION=1.0
+
+DD_TRACE_DEBUG=0
+
+DD_TRACE_INFERRED_PROXY_SERVICES_ENABLED=1
+HTTP_X_DD_PROXY=aws-apigateway
+HTTP_X_DD_PROXY_REQUEST_TIME_MS=100
+HTTP_X_DD_PROXY_PATH=/test
+HTTP_X_DD_PROXY_HTTPMETHOD=GET
+HTTP_X_DD_PROXY_DOMAIN_NAME=example.com
+HTTP_X_DD_PROXY_STAGE=aws-prod
+
+METHOD=GET
+SERVER_NAME=localhost:8888
+SCRIPT_NAME=/foo.php
+REQUEST_URI=/foo
+
+DD_AGENT_HOST=request-replayer
+DD_TRACE_AGENT_PORT=80
+DD_TRACE_AGENT_FLUSH_AFTER_N_REQUESTS=1
+DD_TRACE_AGENT_FLUSH_INTERVAL=666
+DD_INSTRUMENTATION_TELEMETRY_ENABLED=0
+
+DD_TRACE_DEBUG_PRNG_SEED=42
+--GET--
+foo=bar
+--FILE--
+name = "child";
+
+\DDTrace\root_span()->meta['foo'] = 'bar'; // It MUST set it on $parent
+
+dd_trace_close_all_spans_and_flush(); // Simulates end of request
+
+$body = json_decode($rr->waitForDataAndReplay()["body"], true);
+echo json_encode($body, JSON_PRETTY_PRINT);
+?>
+--EXPECTF--
+[
+ [
+ {
+ "trace_id": "13930160852258120406",
+ "span_id": "13930160852258120406",
+ "start": 100000000,
+ "duration": %d,
+ "name": "aws.apigateway",
+ "resource": "GET \/test",
+ "service": "example.com",
+ "type": "web",
+ "meta": {
+ "runtime-id": "%s",
+ "http.method": "GET",
+ "http.url": "example.com\/test",
+ "stage": "aws-prod",
+ "_dd.inferred_span": "1",
+ "component": "aws-apigateway",
+ "_dd.p.dm": "-0",
+ "env": "local-prod",
+ "version": "1.0",
+ "http.status_code": "200",
+ "_dd.p.tid": "%s"
+ },
+ "metrics": {
+ "process_id": %d,
+ "_dd.agent_psr": 1,
+ "_sampling_priority_v1": 1,
+ "php.compilation.total_time_ms": %f,
+ "php.memory.peak_usage_bytes": %d,
+ "php.memory.peak_real_usage_bytes": %d
+ }
+ },
+ {
+ "trace_id": "13930160852258120406",
+ "span_id": "11788048577503494824",
+ "parent_id": "13930160852258120406",
+ "start": 120000000,
+ "duration": %d,
+ "name": "web.request",
+ "resource": "GET \/foo",
+ "service": "aws-server",
+ "type": "web",
+ "meta": {
+ "http.url": "http:\/\/localhost:8888\/foo",
+ "http.method": "GET",
+ "foo": "bar",
+ "env": "local-prod",
+ "version": "1.0",
+ "_dd.p.tid": "%s",
+ "_dd.base_service": "example.com"
+ },
+ "metrics": {
+ "_sampling_priority_v1": 1
+ }
+ },
+ {
+ "trace_id": "13930160852258120406",
+ "span_id": "13874630024467741450",
+ "parent_id": "11788048577503494824",
+ "start": 130000000,
+ "duration": %d,
+ "name": "child",
+ "resource": "child",
+ "service": "aws-server",
+ "type": "web",
+ "meta": {
+ "env": "local-prod",
+ "version": "1.0",
+ "_dd.base_service": "example.com"
+ }
+ }
+ ]
+]
\ No newline at end of file
diff --git a/tests/ext/inferred_proxy/distributed_tracing.phpt b/tests/ext/inferred_proxy/distributed_tracing.phpt
new file mode 100644
index 0000000000..0f0c5c6b4b
--- /dev/null
+++ b/tests/ext/inferred_proxy/distributed_tracing.phpt
@@ -0,0 +1,133 @@
+--TEST--
+Span creation with distributed context
+--ENV--
+DD_TRACE_AUTO_FLUSH_ENABLED=0
+DD_TRACE_GENERATE_ROOT_SPAN=0
+DD_AUTOFINISH_SPANS=1
+DD_SERVICE=aws-server
+DD_ENV=local-prod
+DD_VERSION=1.0
+
+DD_TRACE_DEBUG=0
+
+DD_TRACE_INFERRED_PROXY_SERVICES_ENABLED=1
+HTTP_X_DD_PROXY=aws-apigateway
+HTTP_X_DD_PROXY_REQUEST_TIME_MS=100
+HTTP_X_DD_PROXY_PATH=/test
+HTTP_X_DD_PROXY_HTTPMETHOD=GET
+HTTP_X_DD_PROXY_DOMAIN_NAME=example.com
+HTTP_X_DD_PROXY_STAGE=aws-prod
+
+HTTP_X_DATADOG_TRACE_ID=1
+HTTP_X_DATADOG_PARENT_ID=2
+HTTP_X_DATADOG_ORIGIN=rum
+HTTP_X_DATADOG_SAMPLING_PRIORITY=2
+
+METHOD=GET
+SERVER_NAME=localhost:8888
+SCRIPT_NAME=/foo.php
+REQUEST_URI=/foo
+
+DD_AGENT_HOST=request-replayer
+DD_TRACE_AGENT_PORT=80
+DD_TRACE_AGENT_FLUSH_AFTER_N_REQUESTS=1
+DD_TRACE_AGENT_FLUSH_INTERVAL=666
+DD_INSTRUMENTATION_TELEMETRY_ENABLED=0
+
+DD_TRACE_DEBUG_PRNG_SEED=42
+--GET--
+foo=bar
+--FILE--
+name = "child";
+
+\DDTrace\root_span()->meta['foo'] = 'bar'; // It MUST set it on $parent
+
+dd_trace_close_all_spans_and_flush(); // Simulates end of request
+
+$body = json_decode($rr->waitForDataAndReplay()["body"], true);
+echo json_encode($body, JSON_PRETTY_PRINT);
+?>
+--EXPECTF--
+[
+ [
+ {
+ "trace_id": "1",
+ "span_id": "13930160852258120406",
+ "parent_id": "2",
+ "start": 100000000,
+ "duration": %d,
+ "name": "aws.apigateway",
+ "resource": "GET \/test",
+ "service": "example.com",
+ "type": "web",
+ "meta": {
+ "_dd.p.dm": "-0",
+ "runtime-id": "%s",
+ "http.method": "GET",
+ "http.url": "example.com\/test",
+ "stage": "aws-prod",
+ "_dd.inferred_span": "1",
+ "component": "aws-apigateway",
+ "env": "local-prod",
+ "version": "1.0",
+ "http.status_code": "200",
+ "_dd.origin": "rum"
+ },
+ "metrics": {
+ "process_id": %d,
+ "_sampling_priority_v1": 2,
+ "php.compilation.total_time_ms": %f,
+ "php.memory.peak_usage_bytes": %d,
+ "php.memory.peak_real_usage_bytes": %d
+ }
+ },
+ {
+ "trace_id": "1",
+ "span_id": "11788048577503494824",
+ "parent_id": "13930160852258120406",
+ "start": 120000000,
+ "duration": %d,
+ "name": "web.request",
+ "resource": "GET \/foo",
+ "service": "aws-server",
+ "type": "web",
+ "meta": {
+ "http.url": "http:\/\/localhost:8888\/foo",
+ "http.method": "GET",
+ "foo": "bar",
+ "env": "local-prod",
+ "version": "1.0",
+ "_dd.origin": "rum",
+ "_dd.base_service": "example.com"
+ },
+ "metrics": {
+ "_sampling_priority_v1": 2
+ }
+ },
+ {
+ "trace_id": "1",
+ "span_id": "13874630024467741450",
+ "parent_id": "11788048577503494824",
+ "start": 130000000,
+ "duration": %d,
+ "name": "child",
+ "resource": "child",
+ "service": "aws-server",
+ "type": "web",
+ "meta": {
+ "env": "local-prod",
+ "version": "1.0",
+ "_dd.origin": "rum",
+ "_dd.base_service": "example.com"
+ }
+ }
+ ]
+]
\ No newline at end of file
diff --git a/tests/ext/inferred_proxy/error_propagated.phpt b/tests/ext/inferred_proxy/error_propagated.phpt
new file mode 100644
index 0000000000..e2d0c8043d
--- /dev/null
+++ b/tests/ext/inferred_proxy/error_propagated.phpt
@@ -0,0 +1,128 @@
+--TEST--
+Should create parent and child spans for error
+--ENV--
+DD_TRACE_AUTO_FLUSH_ENABLED=0
+DD_TRACE_GENERATE_ROOT_SPAN=0
+DD_AUTOFINISH_SPANS=1
+DD_SERVICE=aws-server
+DD_ENV=local-prod
+DD_VERSION=1.0
+
+DD_TRACE_DEBUG=0
+
+DD_TRACE_INFERRED_PROXY_SERVICES_ENABLED=1
+HTTP_X_DD_PROXY=aws-apigateway
+HTTP_X_DD_PROXY_REQUEST_TIME_MS=100
+HTTP_X_DD_PROXY_PATH=/test
+HTTP_X_DD_PROXY_HTTPMETHOD=GET
+HTTP_X_DD_PROXY_DOMAIN_NAME=example.com
+HTTP_X_DD_PROXY_STAGE=aws-prod
+
+METHOD=GET
+SERVER_NAME=localhost:8888
+SCRIPT_NAME=/foo.php
+REQUEST_URI=/foo
+
+DD_AGENT_HOST=request-replayer
+DD_TRACE_AGENT_PORT=80
+DD_TRACE_AGENT_FLUSH_AFTER_N_REQUESTS=1
+DD_TRACE_AGENT_FLUSH_INTERVAL=666
+DD_INSTRUMENTATION_TELEMETRY_ENABLED=0
+
+DD_TRACE_DEBUG_PRNG_SEED=42
+--GET--
+foo=bar
+--FILE--
+name = 'request';
+});
+
+try {
+ oops();
+} catch (\Exception $e) {
+ //
+}
+
+dd_trace_close_all_spans_and_flush(); // Simulates end of request
+
+$body = json_decode($rr->waitForDataAndReplay()["body"], true);
+echo json_encode($body, JSON_PRETTY_PRINT);
+?>
+--EXPECTF--
+[
+ [
+ {
+ "trace_id": "13930160852258120406",
+ "span_id": "13930160852258120406",
+ "start": 100000000,
+ "duration": %d,
+ "name": "aws.apigateway",
+ "resource": "GET \/test",
+ "service": "example.com",
+ "type": "web",
+ "error": 1,
+ "meta": {
+ "runtime-id": "%s",
+ "http.method": "GET",
+ "http.url": "example.com\/test",
+ "stage": "aws-prod",
+ "_dd.inferred_span": "1",
+ "component": "aws-apigateway",
+ "_dd.p.dm": "-0",
+ "env": "local-prod",
+ "version": "1.0",
+ "error.message": "Uncaught Exception (500): An exception occurred in %s\/build_extension\/tests\/ext\/inferred_proxy\/error_propagated.php:10",
+ "error.type": "Exception",
+ "error.stack": "#0 %s\/tmp\/build_extension\/tests\/ext\/inferred_proxy\/error_propagated.php(18): oops()\n#1 {main}",
+ "http.status_code": "500",
+ "_dd.p.tid": "%s"
+ },
+ "metrics": {
+ "process_id": %d,
+ "_dd.agent_psr": 1,
+ "_sampling_priority_v1": 1,
+ "php.compilation.total_time_ms": %f,
+ "php.memory.peak_usage_bytes": %d,
+ "php.memory.peak_real_usage_bytes": %d
+ }
+ },
+ {
+ "trace_id": "13930160852258120406",
+ "span_id": "11788048577503494824",
+ "parent_id": "13930160852258120406",
+ "start": %d,
+ "duration": %d,
+ "name": "request",
+ "resource": "GET \/foo",
+ "service": "aws-server",
+ "type": "web",
+ "error": 1,
+ "meta": {
+ "http.url": "http:\/\/localhost:8888\/foo",
+ "http.method": "GET",
+ "env": "local-prod",
+ "version": "1.0",
+ "error.message": "Uncaught Exception (500): An exception occurred in %s\/tmp\/build_extension\/tests\/ext\/inferred_proxy\/error_propagated.php:10",
+ "error.type": "Exception",
+ "error.stack": "#0 %s\/tmp\/build_extension\/tests\/ext\/inferred_proxy\/error_propagated.php(18): oops()\n#1 {main}",
+ "_dd.p.tid": "%s",
+ "_dd.base_service": "example.com"
+ },
+ "metrics": {
+ "_sampling_priority_v1": 1
+ }
+ }
+ ]
+]
\ No newline at end of file
diff --git a/tests/ext/inferred_proxy/incomplete_headers.phpt b/tests/ext/inferred_proxy/incomplete_headers.phpt
new file mode 100644
index 0000000000..254f88b3e2
--- /dev/null
+++ b/tests/ext/inferred_proxy/incomplete_headers.phpt
@@ -0,0 +1,93 @@
+--TEST--
+An Inferred Span should not be created on missing headers
+--ENV--
+DD_TRACE_AUTO_FLUSH_ENABLED=0
+DD_TRACE_GENERATE_ROOT_SPAN=0
+DD_AUTOFINISH_SPANS=1
+DD_SERVICE=aws-server
+DD_ENV=local-prod
+DD_VERSION=1.0
+
+DD_TRACE_DEBUG=0
+
+DD_TRACE_INFERRED_PROXY_SERVICES_ENABLED=1
+HTTP_X_DD_PROXY=aws-apigateway
+
+METHOD=GET
+SERVER_NAME=localhost:8888
+SCRIPT_NAME=/foo.php
+REQUEST_URI=/foo
+
+DD_AGENT_HOST=request-replayer
+DD_TRACE_AGENT_PORT=80
+DD_TRACE_AGENT_FLUSH_AFTER_N_REQUESTS=1
+DD_TRACE_AGENT_FLUSH_INTERVAL=666
+DD_INSTRUMENTATION_TELEMETRY_ENABLED=0
+
+DD_TRACE_DEBUG_PRNG_SEED=42
+--GET--
+foo=bar
+--FILE--
+name = "child";
+
+dd_trace_close_all_spans_and_flush(); // Simulates end of request
+
+$body = json_decode($rr->waitForDataAndReplay()["body"], true);
+echo json_encode($body, JSON_PRETTY_PRINT);
+?>
+--EXPECTF--
+[
+ [
+ {
+ "trace_id": "13930160852258120406",
+ "span_id": "13930160852258120406",
+ "start": 120000000,
+ "duration": %d,
+ "name": "web.request",
+ "resource": "GET \/foo",
+ "service": "aws-server",
+ "type": "web",
+ "meta": {
+ "runtime-id": "%s",
+ "http.url": "http:\/\/localhost:8888\/foo",
+ "http.method": "GET",
+ "_dd.p.dm": "-0",
+ "env": "local-prod",
+ "version": "1.0",
+ "http.status_code": "200",
+ "_dd.p.tid": "%s"
+ },
+ "metrics": {
+ "process_id": %d,
+ "_dd.agent_psr": 1,
+ "_sampling_priority_v1": 1,
+ "php.compilation.total_time_ms": %f,
+ "php.memory.peak_usage_bytes": %f,
+ "php.memory.peak_real_usage_bytes": %f
+ }
+ },
+ {
+ "trace_id": "13930160852258120406",
+ "span_id": "11788048577503494824",
+ "parent_id": "13930160852258120406",
+ "start": 130000000,
+ "duration": %d,
+ "name": "child",
+ "resource": "child",
+ "service": "aws-server",
+ "type": "web",
+ "meta": {
+ "env": "local-prod",
+ "version": "1.0"
+ }
+ }
+ ]
+]
\ No newline at end of file
diff --git a/tests/phpunit.xml b/tests/phpunit.xml
index c44f1f70f5..2c8f53df4f 100644
--- a/tests/phpunit.xml
+++ b/tests/phpunit.xml
@@ -73,6 +73,11 @@
./Integrations/Laravel/Octane/Latest
+
+ ./Integrations/Laravel/APIGWTest.php
+ ./Integrations/Laravel/Octane/APIGWTest.php
+ ./Integrations/Roadrunner/APIGWTest.php
+
./OpenTelemetry/Integration/Context/Fiber
./OpenTelemetry/Unit/API
diff --git a/tests/snapshots/tests.integrations.laravel.apigw_test.test_laravel_inferred_proxy.json b/tests/snapshots/tests.integrations.laravel.apigw_test.test_laravel_inferred_proxy.json
new file mode 100644
index 0000000000..20c7419bd9
--- /dev/null
+++ b/tests/snapshots/tests.integrations.laravel.apigw_test.test_laravel_inferred_proxy.json
@@ -0,0 +1,381 @@
+[[
+ {
+ "name": "aws.apigateway",
+ "service": "example.com",
+ "resource": "GET /test",
+ "trace_id": 0,
+ "span_id": 1,
+ "parent_id": 16608282385995297226,
+ "type": "web",
+ "meta": {
+ "_dd.inferred_span": "1",
+ "_dd.p.dm": "-0",
+ "_dd.p.tid": "67b5998500000000",
+ "component": "aws-apigateway",
+ "env": "local-test",
+ "http.method": "GET",
+ "http.status_code": "200",
+ "http.url": "example.com/test",
+ "runtime-id": "696b2e43-4025-464d-8b9b-1ce63ba78d6e",
+ "stage": "aws-prod",
+ "version": "1.0"
+ },
+ "metrics": {
+ "_sampling_priority_v1": 1.0
+ }
+ },
+ {
+ "name": "laravel.request",
+ "service": "my_service",
+ "resource": "App\\Http\\Controllers\\CommonSpecsController@simple simple_route",
+ "trace_id": 0,
+ "span_id": 2,
+ "parent_id": 1,
+ "type": "web",
+ "meta": {
+ "_dd.base_service": "example.com",
+ "_dd.p.tid": "67b5998500000000",
+ "component": "laravel",
+ "env": "local-test",
+ "http.method": "GET",
+ "http.route": "simple",
+ "http.url": "http://localhost/simple?key=value&",
+ "laravel.route.action": "App\\Http\\Controllers\\CommonSpecsController@simple",
+ "laravel.route.name": "simple_route",
+ "span.kind": "server",
+ "version": "1.0"
+ },
+ "metrics": {
+ "_sampling_priority_v1": 1.0
+ }
+ },
+ {
+ "name": "laravel.event.handle",
+ "service": "my_service",
+ "resource": "bootstrapping: Illuminate\\Foundation\\Bootstrap\\LoadEnvironmentVariables",
+ "trace_id": 0,
+ "span_id": 3,
+ "parent_id": 2,
+ "type": "web",
+ "meta": {
+ "_dd.base_service": "example.com",
+ "component": "laravel",
+ "env": "local-test",
+ "version": "1.0"
+ }
+ },
+ {
+ "name": "laravel.event.handle",
+ "service": "my_service",
+ "resource": "bootstrapped: Illuminate\\Foundation\\Bootstrap\\LoadEnvironmentVariables",
+ "trace_id": 0,
+ "span_id": 4,
+ "parent_id": 2,
+ "type": "web",
+ "meta": {
+ "_dd.base_service": "example.com",
+ "component": "laravel",
+ "env": "local-test",
+ "version": "1.0"
+ }
+ },
+ {
+ "name": "laravel.event.handle",
+ "service": "my_service",
+ "resource": "bootstrapping: Illuminate\\Foundation\\Bootstrap\\LoadConfiguration",
+ "trace_id": 0,
+ "span_id": 5,
+ "parent_id": 2,
+ "type": "web",
+ "meta": {
+ "_dd.base_service": "example.com",
+ "component": "laravel",
+ "env": "local-test",
+ "version": "1.0"
+ }
+ },
+ {
+ "name": "laravel.event.handle",
+ "service": "my_service",
+ "resource": "bootstrapped: Illuminate\\Foundation\\Bootstrap\\LoadConfiguration",
+ "trace_id": 0,
+ "span_id": 6,
+ "parent_id": 2,
+ "type": "web",
+ "meta": {
+ "_dd.base_service": "example.com",
+ "component": "laravel",
+ "env": "local-test",
+ "version": "1.0"
+ }
+ },
+ {
+ "name": "laravel.event.handle",
+ "service": "my_service",
+ "resource": "bootstrapping: Illuminate\\Foundation\\Bootstrap\\HandleExceptions",
+ "trace_id": 0,
+ "span_id": 7,
+ "parent_id": 2,
+ "type": "web",
+ "meta": {
+ "_dd.base_service": "example.com",
+ "component": "laravel",
+ "env": "local-test",
+ "version": "1.0"
+ }
+ },
+ {
+ "name": "laravel.event.handle",
+ "service": "my_service",
+ "resource": "bootstrapped: Illuminate\\Foundation\\Bootstrap\\HandleExceptions",
+ "trace_id": 0,
+ "span_id": 8,
+ "parent_id": 2,
+ "type": "web",
+ "meta": {
+ "_dd.base_service": "example.com",
+ "component": "laravel",
+ "env": "local-test",
+ "version": "1.0"
+ }
+ },
+ {
+ "name": "laravel.event.handle",
+ "service": "my_service",
+ "resource": "bootstrapping: Illuminate\\Foundation\\Bootstrap\\RegisterFacades",
+ "trace_id": 0,
+ "span_id": 9,
+ "parent_id": 2,
+ "type": "web",
+ "meta": {
+ "_dd.base_service": "example.com",
+ "component": "laravel",
+ "env": "local-test",
+ "version": "1.0"
+ }
+ },
+ {
+ "name": "laravel.event.handle",
+ "service": "my_service",
+ "resource": "bootstrapped: Illuminate\\Foundation\\Bootstrap\\RegisterFacades",
+ "trace_id": 0,
+ "span_id": 10,
+ "parent_id": 2,
+ "type": "web",
+ "meta": {
+ "_dd.base_service": "example.com",
+ "component": "laravel",
+ "env": "local-test",
+ "version": "1.0"
+ }
+ },
+ {
+ "name": "laravel.event.handle",
+ "service": "my_service",
+ "resource": "bootstrapping: Illuminate\\Foundation\\Bootstrap\\RegisterProviders",
+ "trace_id": 0,
+ "span_id": 11,
+ "parent_id": 2,
+ "type": "web",
+ "meta": {
+ "_dd.base_service": "example.com",
+ "component": "laravel",
+ "env": "local-test",
+ "version": "1.0"
+ }
+ },
+ {
+ "name": "laravel.provider.load",
+ "service": "my_service",
+ "resource": "Illuminate\\Foundation\\ProviderRepository::load",
+ "trace_id": 0,
+ "span_id": 12,
+ "parent_id": 2,
+ "type": "web",
+ "meta": {
+ "_dd.base_service": "example.com",
+ "component": "laravel",
+ "env": "local-test",
+ "version": "1.0"
+ }
+ },
+ {
+ "name": "laravel.event.handle",
+ "service": "my_service",
+ "resource": "bootstrapped: Illuminate\\Foundation\\Bootstrap\\RegisterProviders",
+ "trace_id": 0,
+ "span_id": 13,
+ "parent_id": 2,
+ "type": "web",
+ "meta": {
+ "_dd.base_service": "example.com",
+ "component": "laravel",
+ "env": "local-test",
+ "version": "1.0"
+ }
+ },
+ {
+ "name": "laravel.event.handle",
+ "service": "my_service",
+ "resource": "bootstrapping: Illuminate\\Foundation\\Bootstrap\\BootProviders",
+ "trace_id": 0,
+ "span_id": 14,
+ "parent_id": 2,
+ "type": "web",
+ "meta": {
+ "_dd.base_service": "example.com",
+ "component": "laravel",
+ "env": "local-test",
+ "version": "1.0"
+ }
+ },
+ {
+ "name": "laravel.event.handle",
+ "service": "my_service",
+ "resource": "bootstrapped: Illuminate\\Foundation\\Bootstrap\\BootProviders",
+ "trace_id": 0,
+ "span_id": 15,
+ "parent_id": 2,
+ "type": "web",
+ "meta": {
+ "_dd.base_service": "example.com",
+ "component": "laravel",
+ "env": "local-test",
+ "version": "1.0"
+ }
+ },
+ {
+ "name": "laravel.event.handle",
+ "service": "my_service",
+ "resource": "Illuminate\\Routing\\Events\\Routing",
+ "trace_id": 0,
+ "span_id": 16,
+ "parent_id": 2,
+ "type": "web",
+ "meta": {
+ "_dd.base_service": "example.com",
+ "component": "laravel",
+ "env": "local-test",
+ "version": "1.0"
+ }
+ },
+ {
+ "name": "laravel.event.handle",
+ "service": "my_service",
+ "resource": "Illuminate\\Routing\\Events\\RouteMatched",
+ "trace_id": 0,
+ "span_id": 17,
+ "parent_id": 2,
+ "type": "web",
+ "meta": {
+ "_dd.base_service": "example.com",
+ "component": "laravel",
+ "env": "local-test",
+ "version": "1.0"
+ }
+ },
+ {
+ "name": "laravel.action",
+ "service": "my_service",
+ "resource": "simple",
+ "trace_id": 0,
+ "span_id": 18,
+ "parent_id": 2,
+ "type": "web",
+ "meta": {
+ "_dd.base_service": "example.com",
+ "component": "laravel",
+ "env": "local-test",
+ "version": "1.0"
+ }
+ },
+ {
+ "name": "laravel.event.handle",
+ "service": "my_service",
+ "resource": "Illuminate\\Routing\\Events\\PreparingResponse",
+ "trace_id": 0,
+ "span_id": 19,
+ "parent_id": 2,
+ "type": "web",
+ "meta": {
+ "_dd.base_service": "example.com",
+ "component": "laravel",
+ "env": "local-test",
+ "version": "1.0"
+ }
+ },
+ {
+ "name": "laravel.event.handle",
+ "service": "my_service",
+ "resource": "Illuminate\\Routing\\Events\\ResponsePrepared",
+ "trace_id": 0,
+ "span_id": 20,
+ "parent_id": 2,
+ "type": "web",
+ "meta": {
+ "_dd.base_service": "example.com",
+ "component": "laravel",
+ "env": "local-test",
+ "version": "1.0"
+ }
+ },
+ {
+ "name": "laravel.event.handle",
+ "service": "my_service",
+ "resource": "Illuminate\\Routing\\Events\\PreparingResponse",
+ "trace_id": 0,
+ "span_id": 21,
+ "parent_id": 2,
+ "type": "web",
+ "meta": {
+ "_dd.base_service": "example.com",
+ "component": "laravel",
+ "env": "local-test",
+ "version": "1.0"
+ }
+ },
+ {
+ "name": "laravel.event.handle",
+ "service": "my_service",
+ "resource": "Illuminate\\Routing\\Events\\ResponsePrepared",
+ "trace_id": 0,
+ "span_id": 22,
+ "parent_id": 2,
+ "type": "web",
+ "meta": {
+ "_dd.base_service": "example.com",
+ "component": "laravel",
+ "env": "local-test",
+ "version": "1.0"
+ }
+ },
+ {
+ "name": "laravel.event.handle",
+ "service": "my_service",
+ "resource": "Illuminate\\Foundation\\Http\\Events\\RequestHandled",
+ "trace_id": 0,
+ "span_id": 23,
+ "parent_id": 2,
+ "type": "web",
+ "meta": {
+ "_dd.base_service": "example.com",
+ "component": "laravel",
+ "env": "local-test",
+ "version": "1.0"
+ }
+ },
+ {
+ "name": "laravel.event.handle",
+ "service": "my_service",
+ "resource": "Illuminate\\Foundation\\Events\\Terminating",
+ "trace_id": 0,
+ "span_id": 24,
+ "parent_id": 2,
+ "type": "web",
+ "meta": {
+ "_dd.base_service": "example.com",
+ "component": "laravel",
+ "env": "local-test",
+ "version": "1.0"
+ }
+ }]]
diff --git a/tests/snapshots/tests.integrations.laravel.apigw_test.test_laravel_inferred_proxy_exception.json b/tests/snapshots/tests.integrations.laravel.apigw_test.test_laravel_inferred_proxy_exception.json
new file mode 100644
index 0000000000..ed8b71ce04
--- /dev/null
+++ b/tests/snapshots/tests.integrations.laravel.apigw_test.test_laravel_inferred_proxy_exception.json
@@ -0,0 +1,378 @@
+[[
+ {
+ "name": "aws.apigateway",
+ "service": "example.com",
+ "resource": "GET /test",
+ "trace_id": 0,
+ "span_id": 1,
+ "parent_id": 3960688414599440033,
+ "type": "web",
+ "error": 1,
+ "meta": {
+ "_dd.inferred_span": "1",
+ "_dd.p.dm": "-0",
+ "_dd.p.tid": "67b5998f00000000",
+ "component": "aws-apigateway",
+ "env": "local-test",
+ "error.message": "Uncaught Exception (500): Controller error in /home/circleci/app/tests/Frameworks/Laravel/Latest/app/Http/Controllers/CommonSpecsController.php:19",
+ "error.stack": "#0 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Routing/ControllerDispatcher.php(47): App\\Http\\Controllers\\CommonSpecsController->error()\n#1 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Routing/Route.php(266): Illuminate\\Routing\\ControllerDispatcher->dispatch()\n#2 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Routing/Route.php(212): Illuminate\\Routing\\Route->runController()\n#3 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Routing/Router.php(808): Illuminate\\Routing\\Route->run()\n#4 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(170): Illuminate\\Routing\\Router->Illuminate\\Routing\\{closure}()\n#5 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Routing/Middleware/SubstituteBindings.php(51): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()\n#6 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(209): Illuminate\\Routing\\Middleware\\SubstituteBindings->handle()\n#7 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/VerifyCsrfToken.php(88): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()\n#8 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(209): Illuminate\\Foundation\\Http\\Middleware\\VerifyCsrfToken->handle()\n#9 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/View/Middleware/ShareErrorsFromSession.php(49): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()\n#10 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(209): Illuminate\\View\\Middleware\\ShareErrorsFromSession->handle()\n#11 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Session/Middleware/StartSession.php(121): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()\n#12 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Session/Middleware/StartSession.php(64): Illuminate\\Session\\Middleware\\StartSession->handleStatefulRequest()\n#13 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(209): Illuminate\\Session\\Middleware\\StartSession->handle()\n#14 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Cookie/Middleware/AddQueuedCookiesToResponse.php(37): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()\n#15 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(209): Illuminate\\Cookie\\Middleware\\AddQueuedCookiesToResponse->handle()\n#16 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Cookie/Middleware/EncryptCookies.php(75): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()\n#17 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(209): Illuminate\\Cookie\\Middleware\\EncryptCookies->handle()\n#18 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(127): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()\n#19 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Routing/Router.php(807): Illuminate\\Pipeline\\Pipeline->then()\n#20 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Routing/Router.php(786): Illuminate\\Routing\\Router->runRouteWithinStack()\n#21 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Routing/Router.php(750): Illuminate\\Routing\\Router->runRoute()\n#22 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Routing/Router.php(739): Illuminate\\Routing\\Router->dispatchToRoute()\n#23 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(201): Illuminate\\Routing\\Router->dispatch()\n#24 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(170): Illuminate\\Foundation\\Http\\Kernel->Illuminate\\Foundation\\Http\\{closure}()\n#25 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TransformsRequest.php(21): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()\n#26 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/ConvertEmptyStringsToNull.php(31): Illuminate\\Foundation\\Http\\Middleware\\TransformsRequest->handle()\n#27 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(209): Illuminate\\Foundation\\Http\\Middleware\\ConvertEmptyStringsToNull->handle()\n#28 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TransformsRequest.php(21): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()\n#29 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TrimStrings.php(51): Illuminate\\Foundation\\Http\\Middleware\\TransformsRequest->handle()\n#30 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(209): Illuminate\\Foundation\\Http\\Middleware\\TrimStrings->handle()\n#31 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Http/Middleware/ValidatePostSize.php(27): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()\n#32 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(209): Illuminate\\Http\\Middleware\\ValidatePostSize->handle()\n#33 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/PreventRequestsDuringMaintenance.php(110): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()\n#34 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(209): Illuminate\\Foundation\\Http\\Middleware\\PreventRequestsDuringMaintenance->handle()\n#35 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Http/Middleware/HandleCors.php(49): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()\n#36 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(209): Illuminate\\Http\\Middleware\\HandleCors->handle()\n#37 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Http/Middleware/TrustProxies.php(58): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()\n#38 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(209): Illuminate\\Http\\Middleware\\TrustProxies->handle()\n#39 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/InvokeDeferredCallbacks.php(22): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()\n#40 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(209): Illuminate\\Foundation\\Http\\Middleware\\InvokeDeferredCallbacks->handle()\n#41 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(127): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()\n#42 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(176): Illuminate\\Pipeline\\Pipeline->then()\n#43 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(145): Illuminate\\Foundation\\Http\\Kernel->sendRequestThroughRouter()\n#44 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Foundation/Application.php(1216): Illuminate\\Foundation\\Http\\Kernel->handle()\n#45 /home/circleci/app/tests/Frameworks/Laravel/Latest/public/index.php(17): Illuminate\\Foundation\\Application->handleRequest()\n#46 {main}",
+ "error.type": "Exception",
+ "http.method": "GET",
+ "http.status_code": "500",
+ "http.url": "example.com/test",
+ "runtime-id": "696b2e43-4025-464d-8b9b-1ce63ba78d6e",
+ "stage": "aws-prod",
+ "version": "1.0"
+ },
+ "metrics": {
+ "_sampling_priority_v1": 1.0
+ }
+ },
+ {
+ "name": "laravel.request",
+ "service": "my_service",
+ "resource": "App\\Http\\Controllers\\CommonSpecsController@error unnamed_route",
+ "trace_id": 0,
+ "span_id": 2,
+ "parent_id": 1,
+ "type": "web",
+ "error": 1,
+ "meta": {
+ "_dd.base_service": "example.com",
+ "_dd.p.tid": "67b5998f00000000",
+ "component": "laravel",
+ "env": "local-test",
+ "error.message": "Uncaught Exception (500): Controller error in /home/circleci/app/tests/Frameworks/Laravel/Latest/app/Http/Controllers/CommonSpecsController.php:19",
+ "error.stack": "#0 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Routing/ControllerDispatcher.php(47): App\\Http\\Controllers\\CommonSpecsController->error()\n#1 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Routing/Route.php(266): Illuminate\\Routing\\ControllerDispatcher->dispatch()\n#2 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Routing/Route.php(212): Illuminate\\Routing\\Route->runController()\n#3 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Routing/Router.php(808): Illuminate\\Routing\\Route->run()\n#4 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(170): Illuminate\\Routing\\Router->Illuminate\\Routing\\{closure}()\n#5 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Routing/Middleware/SubstituteBindings.php(51): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()\n#6 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(209): Illuminate\\Routing\\Middleware\\SubstituteBindings->handle()\n#7 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/VerifyCsrfToken.php(88): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()\n#8 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(209): Illuminate\\Foundation\\Http\\Middleware\\VerifyCsrfToken->handle()\n#9 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/View/Middleware/ShareErrorsFromSession.php(49): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()\n#10 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(209): Illuminate\\View\\Middleware\\ShareErrorsFromSession->handle()\n#11 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Session/Middleware/StartSession.php(121): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()\n#12 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Session/Middleware/StartSession.php(64): Illuminate\\Session\\Middleware\\StartSession->handleStatefulRequest()\n#13 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(209): Illuminate\\Session\\Middleware\\StartSession->handle()\n#14 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Cookie/Middleware/AddQueuedCookiesToResponse.php(37): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()\n#15 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(209): Illuminate\\Cookie\\Middleware\\AddQueuedCookiesToResponse->handle()\n#16 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Cookie/Middleware/EncryptCookies.php(75): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()\n#17 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(209): Illuminate\\Cookie\\Middleware\\EncryptCookies->handle()\n#18 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(127): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()\n#19 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Routing/Router.php(807): Illuminate\\Pipeline\\Pipeline->then()\n#20 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Routing/Router.php(786): Illuminate\\Routing\\Router->runRouteWithinStack()\n#21 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Routing/Router.php(750): Illuminate\\Routing\\Router->runRoute()\n#22 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Routing/Router.php(739): Illuminate\\Routing\\Router->dispatchToRoute()\n#23 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(201): Illuminate\\Routing\\Router->dispatch()\n#24 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(170): Illuminate\\Foundation\\Http\\Kernel->Illuminate\\Foundation\\Http\\{closure}()\n#25 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TransformsRequest.php(21): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()\n#26 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/ConvertEmptyStringsToNull.php(31): Illuminate\\Foundation\\Http\\Middleware\\TransformsRequest->handle()\n#27 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(209): Illuminate\\Foundation\\Http\\Middleware\\ConvertEmptyStringsToNull->handle()\n#28 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TransformsRequest.php(21): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()\n#29 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TrimStrings.php(51): Illuminate\\Foundation\\Http\\Middleware\\TransformsRequest->handle()\n#30 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(209): Illuminate\\Foundation\\Http\\Middleware\\TrimStrings->handle()\n#31 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Http/Middleware/ValidatePostSize.php(27): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()\n#32 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(209): Illuminate\\Http\\Middleware\\ValidatePostSize->handle()\n#33 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/PreventRequestsDuringMaintenance.php(110): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()\n#34 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(209): Illuminate\\Foundation\\Http\\Middleware\\PreventRequestsDuringMaintenance->handle()\n#35 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Http/Middleware/HandleCors.php(49): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()\n#36 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(209): Illuminate\\Http\\Middleware\\HandleCors->handle()\n#37 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Http/Middleware/TrustProxies.php(58): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()\n#38 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(209): Illuminate\\Http\\Middleware\\TrustProxies->handle()\n#39 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/InvokeDeferredCallbacks.php(22): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()\n#40 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(209): Illuminate\\Foundation\\Http\\Middleware\\InvokeDeferredCallbacks->handle()\n#41 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(127): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()\n#42 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(176): Illuminate\\Pipeline\\Pipeline->then()\n#43 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(145): Illuminate\\Foundation\\Http\\Kernel->sendRequestThroughRouter()\n#44 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Foundation/Application.php(1216): Illuminate\\Foundation\\Http\\Kernel->handle()\n#45 /home/circleci/app/tests/Frameworks/Laravel/Latest/public/index.php(17): Illuminate\\Foundation\\Application->handleRequest()\n#46 {main}",
+ "error.type": "Exception",
+ "http.method": "GET",
+ "http.route": "error",
+ "http.url": "http://localhost/error?key=value&",
+ "laravel.route.action": "App\\Http\\Controllers\\CommonSpecsController@error",
+ "laravel.route.name": "unnamed_route",
+ "span.kind": "server",
+ "version": "1.0"
+ },
+ "metrics": {
+ "_sampling_priority_v1": 1.0
+ }
+ },
+ {
+ "name": "laravel.event.handle",
+ "service": "my_service",
+ "resource": "bootstrapping: Illuminate\\Foundation\\Bootstrap\\LoadEnvironmentVariables",
+ "trace_id": 0,
+ "span_id": 3,
+ "parent_id": 2,
+ "type": "web",
+ "meta": {
+ "_dd.base_service": "example.com",
+ "component": "laravel",
+ "env": "local-test",
+ "version": "1.0"
+ }
+ },
+ {
+ "name": "laravel.event.handle",
+ "service": "my_service",
+ "resource": "bootstrapped: Illuminate\\Foundation\\Bootstrap\\LoadEnvironmentVariables",
+ "trace_id": 0,
+ "span_id": 4,
+ "parent_id": 2,
+ "type": "web",
+ "meta": {
+ "_dd.base_service": "example.com",
+ "component": "laravel",
+ "env": "local-test",
+ "version": "1.0"
+ }
+ },
+ {
+ "name": "laravel.event.handle",
+ "service": "my_service",
+ "resource": "bootstrapping: Illuminate\\Foundation\\Bootstrap\\LoadConfiguration",
+ "trace_id": 0,
+ "span_id": 5,
+ "parent_id": 2,
+ "type": "web",
+ "meta": {
+ "_dd.base_service": "example.com",
+ "component": "laravel",
+ "env": "local-test",
+ "version": "1.0"
+ }
+ },
+ {
+ "name": "laravel.event.handle",
+ "service": "my_service",
+ "resource": "bootstrapped: Illuminate\\Foundation\\Bootstrap\\LoadConfiguration",
+ "trace_id": 0,
+ "span_id": 6,
+ "parent_id": 2,
+ "type": "web",
+ "meta": {
+ "_dd.base_service": "example.com",
+ "component": "laravel",
+ "env": "local-test",
+ "version": "1.0"
+ }
+ },
+ {
+ "name": "laravel.event.handle",
+ "service": "my_service",
+ "resource": "bootstrapping: Illuminate\\Foundation\\Bootstrap\\HandleExceptions",
+ "trace_id": 0,
+ "span_id": 7,
+ "parent_id": 2,
+ "type": "web",
+ "meta": {
+ "_dd.base_service": "example.com",
+ "component": "laravel",
+ "env": "local-test",
+ "version": "1.0"
+ }
+ },
+ {
+ "name": "laravel.event.handle",
+ "service": "my_service",
+ "resource": "bootstrapped: Illuminate\\Foundation\\Bootstrap\\HandleExceptions",
+ "trace_id": 0,
+ "span_id": 8,
+ "parent_id": 2,
+ "type": "web",
+ "meta": {
+ "_dd.base_service": "example.com",
+ "component": "laravel",
+ "env": "local-test",
+ "version": "1.0"
+ }
+ },
+ {
+ "name": "laravel.event.handle",
+ "service": "my_service",
+ "resource": "bootstrapping: Illuminate\\Foundation\\Bootstrap\\RegisterFacades",
+ "trace_id": 0,
+ "span_id": 9,
+ "parent_id": 2,
+ "type": "web",
+ "meta": {
+ "_dd.base_service": "example.com",
+ "component": "laravel",
+ "env": "local-test",
+ "version": "1.0"
+ }
+ },
+ {
+ "name": "laravel.event.handle",
+ "service": "my_service",
+ "resource": "bootstrapped: Illuminate\\Foundation\\Bootstrap\\RegisterFacades",
+ "trace_id": 0,
+ "span_id": 10,
+ "parent_id": 2,
+ "type": "web",
+ "meta": {
+ "_dd.base_service": "example.com",
+ "component": "laravel",
+ "env": "local-test",
+ "version": "1.0"
+ }
+ },
+ {
+ "name": "laravel.event.handle",
+ "service": "my_service",
+ "resource": "bootstrapping: Illuminate\\Foundation\\Bootstrap\\RegisterProviders",
+ "trace_id": 0,
+ "span_id": 11,
+ "parent_id": 2,
+ "type": "web",
+ "meta": {
+ "_dd.base_service": "example.com",
+ "component": "laravel",
+ "env": "local-test",
+ "version": "1.0"
+ }
+ },
+ {
+ "name": "laravel.provider.load",
+ "service": "my_service",
+ "resource": "Illuminate\\Foundation\\ProviderRepository::load",
+ "trace_id": 0,
+ "span_id": 12,
+ "parent_id": 2,
+ "type": "web",
+ "meta": {
+ "_dd.base_service": "example.com",
+ "component": "laravel",
+ "env": "local-test",
+ "version": "1.0"
+ }
+ },
+ {
+ "name": "laravel.event.handle",
+ "service": "my_service",
+ "resource": "bootstrapped: Illuminate\\Foundation\\Bootstrap\\RegisterProviders",
+ "trace_id": 0,
+ "span_id": 13,
+ "parent_id": 2,
+ "type": "web",
+ "meta": {
+ "_dd.base_service": "example.com",
+ "component": "laravel",
+ "env": "local-test",
+ "version": "1.0"
+ }
+ },
+ {
+ "name": "laravel.event.handle",
+ "service": "my_service",
+ "resource": "bootstrapping: Illuminate\\Foundation\\Bootstrap\\BootProviders",
+ "trace_id": 0,
+ "span_id": 14,
+ "parent_id": 2,
+ "type": "web",
+ "meta": {
+ "_dd.base_service": "example.com",
+ "component": "laravel",
+ "env": "local-test",
+ "version": "1.0"
+ }
+ },
+ {
+ "name": "laravel.event.handle",
+ "service": "my_service",
+ "resource": "bootstrapped: Illuminate\\Foundation\\Bootstrap\\BootProviders",
+ "trace_id": 0,
+ "span_id": 15,
+ "parent_id": 2,
+ "type": "web",
+ "meta": {
+ "_dd.base_service": "example.com",
+ "component": "laravel",
+ "env": "local-test",
+ "version": "1.0"
+ }
+ },
+ {
+ "name": "laravel.event.handle",
+ "service": "my_service",
+ "resource": "Illuminate\\Routing\\Events\\Routing",
+ "trace_id": 0,
+ "span_id": 16,
+ "parent_id": 2,
+ "type": "web",
+ "meta": {
+ "_dd.base_service": "example.com",
+ "component": "laravel",
+ "env": "local-test",
+ "version": "1.0"
+ }
+ },
+ {
+ "name": "laravel.event.handle",
+ "service": "my_service",
+ "resource": "Illuminate\\Routing\\Events\\RouteMatched",
+ "trace_id": 0,
+ "span_id": 17,
+ "parent_id": 2,
+ "type": "web",
+ "meta": {
+ "_dd.base_service": "example.com",
+ "component": "laravel",
+ "env": "local-test",
+ "version": "1.0"
+ }
+ },
+ {
+ "name": "laravel.action",
+ "service": "my_service",
+ "resource": "error",
+ "trace_id": 0,
+ "span_id": 18,
+ "parent_id": 2,
+ "type": "web",
+ "error": 1,
+ "meta": {
+ "_dd.base_service": "example.com",
+ "component": "laravel",
+ "env": "local-test",
+ "error.message": "Thrown Exception (500): Controller error in /home/circleci/app/tests/Frameworks/Laravel/Latest/app/Http/Controllers/CommonSpecsController.php:19",
+ "error.stack": "#0 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Routing/ControllerDispatcher.php(47): App\\Http\\Controllers\\CommonSpecsController->error()\n#1 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Routing/Route.php(266): Illuminate\\Routing\\ControllerDispatcher->dispatch()\n#2 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Routing/Route.php(212): Illuminate\\Routing\\Route->runController()\n#3 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Routing/Router.php(808): Illuminate\\Routing\\Route->run()\n#4 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(170): Illuminate\\Routing\\Router->Illuminate\\Routing\\{closure}()\n#5 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Routing/Middleware/SubstituteBindings.php(51): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()\n#6 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(209): Illuminate\\Routing\\Middleware\\SubstituteBindings->handle()\n#7 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/VerifyCsrfToken.php(88): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()\n#8 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(209): Illuminate\\Foundation\\Http\\Middleware\\VerifyCsrfToken->handle()\n#9 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/View/Middleware/ShareErrorsFromSession.php(49): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()\n#10 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(209): Illuminate\\View\\Middleware\\ShareErrorsFromSession->handle()\n#11 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Session/Middleware/StartSession.php(121): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()\n#12 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Session/Middleware/StartSession.php(64): Illuminate\\Session\\Middleware\\StartSession->handleStatefulRequest()\n#13 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(209): Illuminate\\Session\\Middleware\\StartSession->handle()\n#14 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Cookie/Middleware/AddQueuedCookiesToResponse.php(37): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()\n#15 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(209): Illuminate\\Cookie\\Middleware\\AddQueuedCookiesToResponse->handle()\n#16 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Cookie/Middleware/EncryptCookies.php(75): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()\n#17 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(209): Illuminate\\Cookie\\Middleware\\EncryptCookies->handle()\n#18 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(127): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()\n#19 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Routing/Router.php(807): Illuminate\\Pipeline\\Pipeline->then()\n#20 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Routing/Router.php(786): Illuminate\\Routing\\Router->runRouteWithinStack()\n#21 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Routing/Router.php(750): Illuminate\\Routing\\Router->runRoute()\n#22 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Routing/Router.php(739): Illuminate\\Routing\\Router->dispatchToRoute()\n#23 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(201): Illuminate\\Routing\\Router->dispatch()\n#24 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(170): Illuminate\\Foundation\\Http\\Kernel->Illuminate\\Foundation\\Http\\{closure}()\n#25 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TransformsRequest.php(21): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()\n#26 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/ConvertEmptyStringsToNull.php(31): Illuminate\\Foundation\\Http\\Middleware\\TransformsRequest->handle()\n#27 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(209): Illuminate\\Foundation\\Http\\Middleware\\ConvertEmptyStringsToNull->handle()\n#28 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TransformsRequest.php(21): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()\n#29 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TrimStrings.php(51): Illuminate\\Foundation\\Http\\Middleware\\TransformsRequest->handle()\n#30 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(209): Illuminate\\Foundation\\Http\\Middleware\\TrimStrings->handle()\n#31 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Http/Middleware/ValidatePostSize.php(27): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()\n#32 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(209): Illuminate\\Http\\Middleware\\ValidatePostSize->handle()\n#33 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/PreventRequestsDuringMaintenance.php(110): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()\n#34 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(209): Illuminate\\Foundation\\Http\\Middleware\\PreventRequestsDuringMaintenance->handle()\n#35 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Http/Middleware/HandleCors.php(49): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()\n#36 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(209): Illuminate\\Http\\Middleware\\HandleCors->handle()\n#37 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Http/Middleware/TrustProxies.php(58): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()\n#38 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(209): Illuminate\\Http\\Middleware\\TrustProxies->handle()\n#39 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/InvokeDeferredCallbacks.php(22): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()\n#40 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(209): Illuminate\\Foundation\\Http\\Middleware\\InvokeDeferredCallbacks->handle()\n#41 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(127): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()\n#42 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(176): Illuminate\\Pipeline\\Pipeline->then()\n#43 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(145): Illuminate\\Foundation\\Http\\Kernel->sendRequestThroughRouter()\n#44 /home/circleci/app/tests/Frameworks/Laravel/Latest/vendor/laravel/framework/src/Illuminate/Foundation/Application.php(1216): Illuminate\\Foundation\\Http\\Kernel->handle()\n#45 /home/circleci/app/tests/Frameworks/Laravel/Latest/public/index.php(17): Illuminate\\Foundation\\Application->handleRequest()\n#46 {main}",
+ "error.type": "Exception",
+ "version": "1.0"
+ }
+ },
+ {
+ "name": "laravel.event.handle",
+ "service": "my_service",
+ "resource": "Illuminate\\Log\\Events\\MessageLogged",
+ "trace_id": 0,
+ "span_id": 19,
+ "parent_id": 2,
+ "type": "web",
+ "meta": {
+ "_dd.base_service": "example.com",
+ "component": "laravel",
+ "env": "local-test",
+ "version": "1.0"
+ }
+ },
+ {
+ "name": "laravel.event.handle",
+ "service": "my_service",
+ "resource": "Illuminate\\Routing\\Events\\PreparingResponse",
+ "trace_id": 0,
+ "span_id": 20,
+ "parent_id": 2,
+ "type": "web",
+ "meta": {
+ "_dd.base_service": "example.com",
+ "component": "laravel",
+ "env": "local-test",
+ "version": "1.0"
+ }
+ },
+ {
+ "name": "laravel.event.handle",
+ "service": "my_service",
+ "resource": "Illuminate\\Routing\\Events\\ResponsePrepared",
+ "trace_id": 0,
+ "span_id": 21,
+ "parent_id": 2,
+ "type": "web",
+ "meta": {
+ "_dd.base_service": "example.com",
+ "component": "laravel",
+ "env": "local-test",
+ "version": "1.0"
+ }
+ },
+ {
+ "name": "laravel.event.handle",
+ "service": "my_service",
+ "resource": "Illuminate\\Foundation\\Http\\Events\\RequestHandled",
+ "trace_id": 0,
+ "span_id": 22,
+ "parent_id": 2,
+ "type": "web",
+ "meta": {
+ "_dd.base_service": "example.com",
+ "component": "laravel",
+ "env": "local-test",
+ "version": "1.0"
+ }
+ },
+ {
+ "name": "laravel.event.handle",
+ "service": "my_service",
+ "resource": "Illuminate\\Foundation\\Events\\Terminating",
+ "trace_id": 0,
+ "span_id": 23,
+ "parent_id": 2,
+ "type": "web",
+ "meta": {
+ "_dd.base_service": "example.com",
+ "component": "laravel",
+ "env": "local-test",
+ "version": "1.0"
+ }
+ }]]
diff --git a/tests/snapshots/tests.integrations.laravel.octane.apigw_test.test_inferred_proxy.json b/tests/snapshots/tests.integrations.laravel.octane.apigw_test.test_inferred_proxy.json
new file mode 100644
index 0000000000..664f34ff48
--- /dev/null
+++ b/tests/snapshots/tests.integrations.laravel.octane.apigw_test.test_inferred_proxy.json
@@ -0,0 +1,237 @@
+[[
+ {
+ "name": "aws.apigateway",
+ "service": "example.com",
+ "resource": "GET /test",
+ "trace_id": 0,
+ "span_id": 1,
+ "parent_id": 15744600919684174002,
+ "type": "cli",
+ "meta": {
+ "_dd.inferred_span": "1",
+ "_dd.p.dm": "0",
+ "_dd.p.tid": "67b5c8a600000000",
+ "component": "aws-apigateway",
+ "env": "local-test",
+ "http.method": "GET",
+ "http.url": "example.com/test",
+ "runtime-id": "f17d43eb-d9ba-4756-b37a-8dab181a4319",
+ "stage": "aws-prod",
+ "version": "1.0"
+ },
+ "metrics": {
+ "_sampling_priority_v1": 1
+ }
+ },
+ {
+ "name": "laravel.request",
+ "service": "swoole_test_app",
+ "resource": "App\\Http\\Controllers\\CommonSpecsController@simple simple_route",
+ "trace_id": 0,
+ "span_id": 2,
+ "parent_id": 1,
+ "type": "web",
+ "meta": {
+ "_dd.base_service": "example.com",
+ "_dd.p.tid": "67b5c8a600000000",
+ "component": "laravel",
+ "env": "local-test",
+ "http.method": "GET",
+ "http.request.headers.x-dd-proxy": "aws-apigateway",
+ "http.request.headers.x-dd-proxy-domain-name": "example.com",
+ "http.request.headers.x-dd-proxy-httpmethod": "GET",
+ "http.request.headers.x-dd-proxy-path": "/test",
+ "http.request.headers.x-dd-proxy-request-time-ms": "1739261376000",
+ "http.request.headers.x-dd-proxy-stage": "aws-prod",
+ "http.route": "simple",
+ "http.status_code": "200",
+ "http.url": "http://localhost/simple?key=value&",
+ "laravel.route.action": "App\\Http\\Controllers\\CommonSpecsController@simple",
+ "laravel.route.name": "simple_route",
+ "span.kind": "server",
+ "version": "1.0"
+ },
+ "metrics": {
+ "_sampling_priority_v1": 1
+ }
+ },
+ {
+ "name": "laravel.event.handle",
+ "service": "swoole_test_app",
+ "resource": "Laravel\\Octane\\Events\\RequestReceived",
+ "trace_id": 0,
+ "span_id": 3,
+ "parent_id": 2,
+ "type": "web",
+ "meta": {
+ "_dd.base_service": "example.com",
+ "component": "laravel",
+ "env": "local-test",
+ "version": "1.0"
+ }
+ },
+ {
+ "name": "laravel.event.handle",
+ "service": "swoole_test_app",
+ "resource": "Illuminate\\Routing\\Events\\Routing",
+ "trace_id": 0,
+ "span_id": 4,
+ "parent_id": 2,
+ "type": "web",
+ "meta": {
+ "_dd.base_service": "example.com",
+ "component": "laravel",
+ "env": "local-test",
+ "version": "1.0"
+ }
+ },
+ {
+ "name": "laravel.event.handle",
+ "service": "swoole_test_app",
+ "resource": "Illuminate\\Routing\\Events\\RouteMatched",
+ "trace_id": 0,
+ "span_id": 5,
+ "parent_id": 2,
+ "type": "web",
+ "meta": {
+ "_dd.base_service": "example.com",
+ "component": "laravel",
+ "env": "local-test",
+ "version": "1.0"
+ }
+ },
+ {
+ "name": "laravel.action",
+ "service": "swoole_test_app",
+ "resource": "simple",
+ "trace_id": 0,
+ "span_id": 6,
+ "parent_id": 2,
+ "type": "web",
+ "meta": {
+ "_dd.base_service": "example.com",
+ "component": "laravel",
+ "env": "local-test",
+ "version": "1.0"
+ }
+ },
+ {
+ "name": "laravel.event.handle",
+ "service": "swoole_test_app",
+ "resource": "Illuminate\\Routing\\Events\\PreparingResponse",
+ "trace_id": 0,
+ "span_id": 7,
+ "parent_id": 2,
+ "type": "web",
+ "meta": {
+ "_dd.base_service": "example.com",
+ "component": "laravel",
+ "env": "local-test",
+ "version": "1.0"
+ }
+ },
+ {
+ "name": "laravel.event.handle",
+ "service": "swoole_test_app",
+ "resource": "Illuminate\\Routing\\Events\\ResponsePrepared",
+ "trace_id": 0,
+ "span_id": 8,
+ "parent_id": 2,
+ "type": "web",
+ "meta": {
+ "_dd.base_service": "example.com",
+ "component": "laravel",
+ "env": "local-test",
+ "version": "1.0"
+ }
+ },
+ {
+ "name": "laravel.event.handle",
+ "service": "swoole_test_app",
+ "resource": "Illuminate\\Routing\\Events\\PreparingResponse",
+ "trace_id": 0,
+ "span_id": 9,
+ "parent_id": 2,
+ "type": "web",
+ "meta": {
+ "_dd.base_service": "example.com",
+ "component": "laravel",
+ "env": "local-test",
+ "version": "1.0"
+ }
+ },
+ {
+ "name": "laravel.event.handle",
+ "service": "swoole_test_app",
+ "resource": "Illuminate\\Routing\\Events\\ResponsePrepared",
+ "trace_id": 0,
+ "span_id": 10,
+ "parent_id": 2,
+ "type": "web",
+ "meta": {
+ "_dd.base_service": "example.com",
+ "component": "laravel",
+ "env": "local-test",
+ "version": "1.0"
+ }
+ },
+ {
+ "name": "laravel.event.handle",
+ "service": "swoole_test_app",
+ "resource": "Illuminate\\Foundation\\Http\\Events\\RequestHandled",
+ "trace_id": 0,
+ "span_id": 11,
+ "parent_id": 2,
+ "type": "web",
+ "meta": {
+ "_dd.base_service": "example.com",
+ "component": "laravel",
+ "env": "local-test",
+ "version": "1.0"
+ }
+ },
+ {
+ "name": "laravel.event.handle",
+ "service": "swoole_test_app",
+ "resource": "Laravel\\Octane\\Events\\RequestHandled",
+ "trace_id": 0,
+ "span_id": 12,
+ "parent_id": 2,
+ "type": "web",
+ "meta": {
+ "_dd.base_service": "example.com",
+ "component": "laravel",
+ "env": "local-test",
+ "version": "1.0"
+ }
+ },
+ {
+ "name": "laravel.event.handle",
+ "service": "swoole_test_app",
+ "resource": "Illuminate\\Foundation\\Events\\Terminating",
+ "trace_id": 0,
+ "span_id": 13,
+ "parent_id": 2,
+ "type": "web",
+ "meta": {
+ "_dd.base_service": "example.com",
+ "component": "laravel",
+ "env": "local-test",
+ "version": "1.0"
+ }
+ },
+ {
+ "name": "laravel.event.handle",
+ "service": "swoole_test_app",
+ "resource": "Laravel\\Octane\\Events\\RequestTerminated",
+ "trace_id": 0,
+ "span_id": 14,
+ "parent_id": 2,
+ "type": "web",
+ "meta": {
+ "_dd.base_service": "example.com",
+ "component": "laravel",
+ "env": "local-test",
+ "version": "1.0"
+ }
+ }]]
diff --git a/tests/snapshots/tests.integrations.laravel.octane.apigw_test.test_inferred_proxy_exception.json b/tests/snapshots/tests.integrations.laravel.octane.apigw_test.test_inferred_proxy_exception.json
new file mode 100644
index 0000000000..f422be272c
--- /dev/null
+++ b/tests/snapshots/tests.integrations.laravel.octane.apigw_test.test_inferred_proxy_exception.json
@@ -0,0 +1,234 @@
+[[
+ {
+ "name": "aws.apigateway",
+ "service": "example.com",
+ "resource": "GET /test",
+ "trace_id": 0,
+ "span_id": 1,
+ "parent_id": 13636397762784364900,
+ "type": "cli",
+ "error": 1,
+ "meta": {
+ "_dd.inferred_span": "1",
+ "_dd.p.dm": "0",
+ "_dd.p.tid": "67b5c8bc00000000",
+ "component": "aws-apigateway",
+ "env": "local-test",
+ "error.message": "Uncaught Exception: Controller error in /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/app/Http/Controllers/CommonSpecsController.php:19",
+ "error.stack": "#0 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Routing/ControllerDispatcher.php(47): App\\Http\\Controllers\\CommonSpecsController->error()\n#1 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Routing/Route.php(266): Illuminate\\Routing\\ControllerDispatcher->dispatch()\n#2 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Routing/Route.php(212): Illuminate\\Routing\\Route->runController()\n#3 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Routing/Router.php(808): Illuminate\\Routing\\Route->run()\n#4 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(170): Illuminate\\Routing\\Router->Illuminate\\Routing\\{closure}()\n#5 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Routing/Middleware/SubstituteBindings.php(51): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()\n#6 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(209): Illuminate\\Routing\\Middleware\\SubstituteBindings->handle()\n#7 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/VerifyCsrfToken.php(88): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()\n#8 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(209): Illuminate\\Foundation\\Http\\Middleware\\VerifyCsrfToken->handle()\n#9 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/View/Middleware/ShareErrorsFromSession.php(49): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()\n#10 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(209): Illuminate\\View\\Middleware\\ShareErrorsFromSession->handle()\n#11 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Session/Middleware/StartSession.php(121): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()\n#12 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Session/Middleware/StartSession.php(64): Illuminate\\Session\\Middleware\\StartSession->handleStatefulRequest()\n#13 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(209): Illuminate\\Session\\Middleware\\StartSession->handle()\n#14 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Cookie/Middleware/AddQueuedCookiesToResponse.php(37): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()\n#15 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(209): Illuminate\\Cookie\\Middleware\\AddQueuedCookiesToResponse->handle()\n#16 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Cookie/Middleware/EncryptCookies.php(75): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()\n#17 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(209): Illuminate\\Cookie\\Middleware\\EncryptCookies->handle()\n#18 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(127): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()\n#19 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Routing/Router.php(807): Illuminate\\Pipeline\\Pipeline->then()\n#20 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Routing/Router.php(786): Illuminate\\Routing\\Router->runRouteWithinStack()\n#21 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Routing/Router.php(750): Illuminate\\Routing\\Router->runRoute()\n#22 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Routing/Router.php(739): Illuminate\\Routing\\Router->dispatchToRoute()\n#23 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(201): Illuminate\\Routing\\Router->dispatch()\n#24 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(170): Illuminate\\Foundation\\Http\\Kernel->Illuminate\\Foundation\\Http\\{closure}()\n#25 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TransformsRequest.php(21): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()\n#26 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/ConvertEmptyStringsToNull.php(31): Illuminate\\Foundation\\Http\\Middleware\\TransformsRequest->handle()\n#27 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(209): Illuminate\\Foundation\\Http\\Middleware\\ConvertEmptyStringsToNull->handle()\n#28 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TransformsRequest.php(21): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()\n#29 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TrimStrings.php(51): Illuminate\\Foundation\\Http\\Middleware\\TransformsRequest->handle()\n#30 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(209): Illuminate\\Foundation\\Http\\Middleware\\TrimStrings->handle()\n#31 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Http/Middleware/ValidatePostSize.php(27): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()\n#32 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(209): Illuminate\\Http\\Middleware\\ValidatePostSize->handle()\n#33 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/PreventRequestsDuringMaintenance.php(110): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()\n#34 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(209): Illuminate\\Foundation\\Http\\Middleware\\PreventRequestsDuringMaintenance->handle()\n#35 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Http/Middleware/HandleCors.php(49): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()\n#36 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(209): Illuminate\\Http\\Middleware\\HandleCors->handle()\n#37 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Http/Middleware/TrustProxies.php(58): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()\n#38 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(209): Illuminate\\Http\\Middleware\\TrustProxies->handle()\n#39 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/InvokeDeferredCallbacks.php(22): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()\n#40 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(209): Illuminate\\Foundation\\Http\\Middleware\\InvokeDeferredCallbacks->handle()\n#41 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(127): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()\n#42 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(176): Illuminate\\Pipeline\\Pipeline->then()\n#43 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(145): Illuminate\\Foundation\\Http\\Kernel->sendRequestThroughRouter()\n#44 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/octane/src/ApplicationGateway.php(36): Illuminate\\Foundation\\Http\\Kernel->handle()\n#45 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/octane/src/Worker.php(84): Laravel\\Octane\\ApplicationGateway->handle()\n#46 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/octane/bin/swoole-server(122): Laravel\\Octane\\Worker->handle()\n#47 [internal function]: {closure}()\n#48 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/octane/bin/swoole-server(172): Swoole\\Server->start()\n#49 {main}",
+ "error.type": "Exception",
+ "http.method": "GET",
+ "http.url": "example.com/test",
+ "runtime-id": "f17d43eb-d9ba-4756-b37a-8dab181a4319",
+ "stage": "aws-prod",
+ "version": "1.0"
+ },
+ "metrics": {
+ "_sampling_priority_v1": 1
+ }
+ },
+ {
+ "name": "laravel.request",
+ "service": "swoole_test_app",
+ "resource": "App\\Http\\Controllers\\CommonSpecsController@error unnamed_route",
+ "trace_id": 0,
+ "span_id": 2,
+ "parent_id": 1,
+ "type": "web",
+ "error": 1,
+ "meta": {
+ "_dd.base_service": "example.com",
+ "_dd.p.tid": "67b5c8bc00000000",
+ "component": "laravel",
+ "env": "local-test",
+ "error.message": "Uncaught Exception: Controller error in /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/app/Http/Controllers/CommonSpecsController.php:19",
+ "error.stack": "#0 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Routing/ControllerDispatcher.php(47): App\\Http\\Controllers\\CommonSpecsController->error()\n#1 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Routing/Route.php(266): Illuminate\\Routing\\ControllerDispatcher->dispatch()\n#2 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Routing/Route.php(212): Illuminate\\Routing\\Route->runController()\n#3 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Routing/Router.php(808): Illuminate\\Routing\\Route->run()\n#4 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(170): Illuminate\\Routing\\Router->Illuminate\\Routing\\{closure}()\n#5 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Routing/Middleware/SubstituteBindings.php(51): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()\n#6 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(209): Illuminate\\Routing\\Middleware\\SubstituteBindings->handle()\n#7 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/VerifyCsrfToken.php(88): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()\n#8 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(209): Illuminate\\Foundation\\Http\\Middleware\\VerifyCsrfToken->handle()\n#9 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/View/Middleware/ShareErrorsFromSession.php(49): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()\n#10 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(209): Illuminate\\View\\Middleware\\ShareErrorsFromSession->handle()\n#11 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Session/Middleware/StartSession.php(121): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()\n#12 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Session/Middleware/StartSession.php(64): Illuminate\\Session\\Middleware\\StartSession->handleStatefulRequest()\n#13 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(209): Illuminate\\Session\\Middleware\\StartSession->handle()\n#14 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Cookie/Middleware/AddQueuedCookiesToResponse.php(37): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()\n#15 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(209): Illuminate\\Cookie\\Middleware\\AddQueuedCookiesToResponse->handle()\n#16 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Cookie/Middleware/EncryptCookies.php(75): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()\n#17 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(209): Illuminate\\Cookie\\Middleware\\EncryptCookies->handle()\n#18 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(127): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()\n#19 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Routing/Router.php(807): Illuminate\\Pipeline\\Pipeline->then()\n#20 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Routing/Router.php(786): Illuminate\\Routing\\Router->runRouteWithinStack()\n#21 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Routing/Router.php(750): Illuminate\\Routing\\Router->runRoute()\n#22 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Routing/Router.php(739): Illuminate\\Routing\\Router->dispatchToRoute()\n#23 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(201): Illuminate\\Routing\\Router->dispatch()\n#24 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(170): Illuminate\\Foundation\\Http\\Kernel->Illuminate\\Foundation\\Http\\{closure}()\n#25 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TransformsRequest.php(21): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()\n#26 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/ConvertEmptyStringsToNull.php(31): Illuminate\\Foundation\\Http\\Middleware\\TransformsRequest->handle()\n#27 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(209): Illuminate\\Foundation\\Http\\Middleware\\ConvertEmptyStringsToNull->handle()\n#28 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TransformsRequest.php(21): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()\n#29 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TrimStrings.php(51): Illuminate\\Foundation\\Http\\Middleware\\TransformsRequest->handle()\n#30 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(209): Illuminate\\Foundation\\Http\\Middleware\\TrimStrings->handle()\n#31 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Http/Middleware/ValidatePostSize.php(27): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()\n#32 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(209): Illuminate\\Http\\Middleware\\ValidatePostSize->handle()\n#33 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/PreventRequestsDuringMaintenance.php(110): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()\n#34 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(209): Illuminate\\Foundation\\Http\\Middleware\\PreventRequestsDuringMaintenance->handle()\n#35 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Http/Middleware/HandleCors.php(49): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()\n#36 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(209): Illuminate\\Http\\Middleware\\HandleCors->handle()\n#37 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Http/Middleware/TrustProxies.php(58): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()\n#38 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(209): Illuminate\\Http\\Middleware\\TrustProxies->handle()\n#39 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/InvokeDeferredCallbacks.php(22): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()\n#40 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(209): Illuminate\\Foundation\\Http\\Middleware\\InvokeDeferredCallbacks->handle()\n#41 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(127): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()\n#42 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(176): Illuminate\\Pipeline\\Pipeline->then()\n#43 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(145): Illuminate\\Foundation\\Http\\Kernel->sendRequestThroughRouter()\n#44 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/octane/src/ApplicationGateway.php(36): Illuminate\\Foundation\\Http\\Kernel->handle()\n#45 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/octane/src/Worker.php(84): Laravel\\Octane\\ApplicationGateway->handle()\n#46 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/octane/bin/swoole-server(122): Laravel\\Octane\\Worker->handle()\n#47 [internal function]: {closure}()\n#48 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/octane/bin/swoole-server(172): Swoole\\Server->start()\n#49 {main}",
+ "error.type": "Exception",
+ "http.method": "GET",
+ "http.request.headers.x-dd-proxy": "aws-apigateway",
+ "http.request.headers.x-dd-proxy-domain-name": "example.com",
+ "http.request.headers.x-dd-proxy-httpmethod": "GET",
+ "http.request.headers.x-dd-proxy-path": "/test",
+ "http.request.headers.x-dd-proxy-request-time-ms": "1739261376000",
+ "http.request.headers.x-dd-proxy-stage": "aws-prod",
+ "http.route": "error",
+ "http.status_code": "500",
+ "http.url": "http://localhost/error?key=value&",
+ "laravel.route.action": "App\\Http\\Controllers\\CommonSpecsController@error",
+ "laravel.route.name": "unnamed_route",
+ "span.kind": "server",
+ "version": "1.0"
+ },
+ "metrics": {
+ "_sampling_priority_v1": 1
+ }
+ },
+ {
+ "name": "laravel.event.handle",
+ "service": "swoole_test_app",
+ "resource": "Laravel\\Octane\\Events\\RequestReceived",
+ "trace_id": 0,
+ "span_id": 3,
+ "parent_id": 2,
+ "type": "web",
+ "meta": {
+ "_dd.base_service": "example.com",
+ "component": "laravel",
+ "env": "local-test",
+ "version": "1.0"
+ }
+ },
+ {
+ "name": "laravel.event.handle",
+ "service": "swoole_test_app",
+ "resource": "Illuminate\\Routing\\Events\\Routing",
+ "trace_id": 0,
+ "span_id": 4,
+ "parent_id": 2,
+ "type": "web",
+ "meta": {
+ "_dd.base_service": "example.com",
+ "component": "laravel",
+ "env": "local-test",
+ "version": "1.0"
+ }
+ },
+ {
+ "name": "laravel.event.handle",
+ "service": "swoole_test_app",
+ "resource": "Illuminate\\Routing\\Events\\RouteMatched",
+ "trace_id": 0,
+ "span_id": 5,
+ "parent_id": 2,
+ "type": "web",
+ "meta": {
+ "_dd.base_service": "example.com",
+ "component": "laravel",
+ "env": "local-test",
+ "version": "1.0"
+ }
+ },
+ {
+ "name": "laravel.action",
+ "service": "swoole_test_app",
+ "resource": "error",
+ "trace_id": 0,
+ "span_id": 6,
+ "parent_id": 2,
+ "type": "web",
+ "error": 1,
+ "meta": {
+ "_dd.base_service": "example.com",
+ "component": "laravel",
+ "env": "local-test",
+ "error.message": "Thrown Exception: Controller error in /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/app/Http/Controllers/CommonSpecsController.php:19",
+ "error.stack": "#0 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Routing/ControllerDispatcher.php(47): App\\Http\\Controllers\\CommonSpecsController->error()\n#1 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Routing/Route.php(266): Illuminate\\Routing\\ControllerDispatcher->dispatch()\n#2 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Routing/Route.php(212): Illuminate\\Routing\\Route->runController()\n#3 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Routing/Router.php(808): Illuminate\\Routing\\Route->run()\n#4 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(170): Illuminate\\Routing\\Router->Illuminate\\Routing\\{closure}()\n#5 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Routing/Middleware/SubstituteBindings.php(51): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()\n#6 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(209): Illuminate\\Routing\\Middleware\\SubstituteBindings->handle()\n#7 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/VerifyCsrfToken.php(88): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()\n#8 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(209): Illuminate\\Foundation\\Http\\Middleware\\VerifyCsrfToken->handle()\n#9 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/View/Middleware/ShareErrorsFromSession.php(49): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()\n#10 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(209): Illuminate\\View\\Middleware\\ShareErrorsFromSession->handle()\n#11 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Session/Middleware/StartSession.php(121): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()\n#12 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Session/Middleware/StartSession.php(64): Illuminate\\Session\\Middleware\\StartSession->handleStatefulRequest()\n#13 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(209): Illuminate\\Session\\Middleware\\StartSession->handle()\n#14 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Cookie/Middleware/AddQueuedCookiesToResponse.php(37): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()\n#15 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(209): Illuminate\\Cookie\\Middleware\\AddQueuedCookiesToResponse->handle()\n#16 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Cookie/Middleware/EncryptCookies.php(75): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()\n#17 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(209): Illuminate\\Cookie\\Middleware\\EncryptCookies->handle()\n#18 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(127): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()\n#19 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Routing/Router.php(807): Illuminate\\Pipeline\\Pipeline->then()\n#20 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Routing/Router.php(786): Illuminate\\Routing\\Router->runRouteWithinStack()\n#21 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Routing/Router.php(750): Illuminate\\Routing\\Router->runRoute()\n#22 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Routing/Router.php(739): Illuminate\\Routing\\Router->dispatchToRoute()\n#23 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(201): Illuminate\\Routing\\Router->dispatch()\n#24 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(170): Illuminate\\Foundation\\Http\\Kernel->Illuminate\\Foundation\\Http\\{closure}()\n#25 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TransformsRequest.php(21): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()\n#26 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/ConvertEmptyStringsToNull.php(31): Illuminate\\Foundation\\Http\\Middleware\\TransformsRequest->handle()\n#27 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(209): Illuminate\\Foundation\\Http\\Middleware\\ConvertEmptyStringsToNull->handle()\n#28 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TransformsRequest.php(21): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()\n#29 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TrimStrings.php(51): Illuminate\\Foundation\\Http\\Middleware\\TransformsRequest->handle()\n#30 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(209): Illuminate\\Foundation\\Http\\Middleware\\TrimStrings->handle()\n#31 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Http/Middleware/ValidatePostSize.php(27): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()\n#32 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(209): Illuminate\\Http\\Middleware\\ValidatePostSize->handle()\n#33 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/PreventRequestsDuringMaintenance.php(110): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()\n#34 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(209): Illuminate\\Foundation\\Http\\Middleware\\PreventRequestsDuringMaintenance->handle()\n#35 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Http/Middleware/HandleCors.php(49): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()\n#36 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(209): Illuminate\\Http\\Middleware\\HandleCors->handle()\n#37 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Http/Middleware/TrustProxies.php(58): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()\n#38 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(209): Illuminate\\Http\\Middleware\\TrustProxies->handle()\n#39 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/InvokeDeferredCallbacks.php(22): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()\n#40 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(209): Illuminate\\Foundation\\Http\\Middleware\\InvokeDeferredCallbacks->handle()\n#41 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(127): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()\n#42 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(176): Illuminate\\Pipeline\\Pipeline->then()\n#43 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(145): Illuminate\\Foundation\\Http\\Kernel->sendRequestThroughRouter()\n#44 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/octane/src/ApplicationGateway.php(36): Illuminate\\Foundation\\Http\\Kernel->handle()\n#45 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/octane/src/Worker.php(84): Laravel\\Octane\\ApplicationGateway->handle()\n#46 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/octane/bin/swoole-server(122): Laravel\\Octane\\Worker->handle()\n#47 [internal function]: {closure}()\n#48 /home/circleci/app/tests/Frameworks/Laravel/Octane/Latest/vendor/laravel/octane/bin/swoole-server(172): Swoole\\Server->start()\n#49 {main}",
+ "error.type": "Exception",
+ "version": "1.0"
+ }
+ },
+ {
+ "name": "laravel.event.handle",
+ "service": "swoole_test_app",
+ "resource": "Illuminate\\Log\\Events\\MessageLogged",
+ "trace_id": 0,
+ "span_id": 7,
+ "parent_id": 2,
+ "type": "web",
+ "meta": {
+ "_dd.base_service": "example.com",
+ "component": "laravel",
+ "env": "local-test",
+ "version": "1.0"
+ }
+ },
+ {
+ "name": "laravel.event.handle",
+ "service": "swoole_test_app",
+ "resource": "Illuminate\\Routing\\Events\\PreparingResponse",
+ "trace_id": 0,
+ "span_id": 8,
+ "parent_id": 2,
+ "type": "web",
+ "meta": {
+ "_dd.base_service": "example.com",
+ "component": "laravel",
+ "env": "local-test",
+ "version": "1.0"
+ }
+ },
+ {
+ "name": "laravel.event.handle",
+ "service": "swoole_test_app",
+ "resource": "Illuminate\\Routing\\Events\\ResponsePrepared",
+ "trace_id": 0,
+ "span_id": 9,
+ "parent_id": 2,
+ "type": "web",
+ "meta": {
+ "_dd.base_service": "example.com",
+ "component": "laravel",
+ "env": "local-test",
+ "version": "1.0"
+ }
+ },
+ {
+ "name": "laravel.event.handle",
+ "service": "swoole_test_app",
+ "resource": "Illuminate\\Foundation\\Http\\Events\\RequestHandled",
+ "trace_id": 0,
+ "span_id": 10,
+ "parent_id": 2,
+ "type": "web",
+ "meta": {
+ "_dd.base_service": "example.com",
+ "component": "laravel",
+ "env": "local-test",
+ "version": "1.0"
+ }
+ },
+ {
+ "name": "laravel.event.handle",
+ "service": "swoole_test_app",
+ "resource": "Laravel\\Octane\\Events\\RequestHandled",
+ "trace_id": 0,
+ "span_id": 11,
+ "parent_id": 2,
+ "type": "web",
+ "meta": {
+ "_dd.base_service": "example.com",
+ "component": "laravel",
+ "env": "local-test",
+ "version": "1.0"
+ }
+ },
+ {
+ "name": "laravel.event.handle",
+ "service": "swoole_test_app",
+ "resource": "Illuminate\\Foundation\\Events\\Terminating",
+ "trace_id": 0,
+ "span_id": 12,
+ "parent_id": 2,
+ "type": "web",
+ "meta": {
+ "_dd.base_service": "example.com",
+ "component": "laravel",
+ "env": "local-test",
+ "version": "1.0"
+ }
+ },
+ {
+ "name": "laravel.event.handle",
+ "service": "swoole_test_app",
+ "resource": "Laravel\\Octane\\Events\\RequestTerminated",
+ "trace_id": 0,
+ "span_id": 13,
+ "parent_id": 2,
+ "type": "web",
+ "meta": {
+ "_dd.base_service": "example.com",
+ "component": "laravel",
+ "env": "local-test",
+ "version": "1.0"
+ }
+ }]]
diff --git a/tests/snapshots/tests.integrations.roadrunner.apigw_test.test_inferred_proxy.json b/tests/snapshots/tests.integrations.roadrunner.apigw_test.test_inferred_proxy.json
new file mode 100644
index 0000000000..22d6ae651f
--- /dev/null
+++ b/tests/snapshots/tests.integrations.roadrunner.apigw_test.test_inferred_proxy.json
@@ -0,0 +1,52 @@
+[[
+ {
+ "name": "aws.apigateway",
+ "service": "example.com",
+ "resource": "GET /simple",
+ "trace_id": 0,
+ "span_id": 1,
+ "parent_id": 496562999704294221,
+ "type": "cli",
+ "meta": {
+ "_dd.inferred_span": "1",
+ "_dd.p.dm": "0",
+ "_dd.p.tid": "67b5c9a300000000",
+ "component": "aws-apigateway",
+ "env": "local-test",
+ "http.method": "GET",
+ "http.request.headers.x-dd-proxy": "aws-apigateway",
+ "http.request.headers.x-dd-proxy-domain-name": "example.com",
+ "http.request.headers.x-dd-proxy-httpmethod": "GET",
+ "http.request.headers.x-dd-proxy-path": "/test",
+ "http.request.headers.x-dd-proxy-request-time-ms": "1739261376000",
+ "http.request.headers.x-dd-proxy-stage": "aws-prod",
+ "http.status_code": "200",
+ "http.url": "http://localhost/simple?key=value&",
+ "runtime-id": "6423c0c2-fbc3-4ee4-ad68-25dd48ee99f3",
+ "stage": "aws-prod",
+ "version": "1.0"
+ },
+ "metrics": {
+ "_sampling_priority_v1": 1
+ }
+ },
+ {
+ "name": "web.request",
+ "service": "roadrunner_test_app",
+ "resource": "web.request",
+ "trace_id": 0,
+ "span_id": 2,
+ "parent_id": 1,
+ "type": "web",
+ "meta": {
+ "_dd.base_service": "example.com",
+ "_dd.p.tid": "67b5c9a300000000",
+ "component": "roadrunner",
+ "env": "local-test",
+ "span.kind": "server",
+ "version": "1.0"
+ },
+ "metrics": {
+ "_sampling_priority_v1": 1
+ }
+ }]]
diff --git a/tests/snapshots/tests.integrations.roadrunner.apigw_test.test_inferred_proxy_exception.json b/tests/snapshots/tests.integrations.roadrunner.apigw_test.test_inferred_proxy_exception.json
new file mode 100644
index 0000000000..368f960024
--- /dev/null
+++ b/tests/snapshots/tests.integrations.roadrunner.apigw_test.test_inferred_proxy_exception.json
@@ -0,0 +1,60 @@
+[[
+ {
+ "name": "aws.apigateway",
+ "service": "example.com",
+ "resource": "GET /error",
+ "trace_id": 0,
+ "span_id": 1,
+ "parent_id": 6078099901530556271,
+ "type": "cli",
+ "error": 1,
+ "meta": {
+ "_dd.inferred_span": "1",
+ "_dd.p.dm": "0",
+ "_dd.p.tid": "67b5c9a800000000",
+ "component": "aws-apigateway",
+ "env": "local-test",
+ "error.message": "Uncaught Exception: Error page in /home/circleci/app/tests/Frameworks/Roadrunner/Version_2/worker.php:26",
+ "error.stack": "#0 {main}",
+ "error.type": "Exception",
+ "http.method": "GET",
+ "http.request.headers.x-dd-proxy": "aws-apigateway",
+ "http.request.headers.x-dd-proxy-domain-name": "example.com",
+ "http.request.headers.x-dd-proxy-httpmethod": "GET",
+ "http.request.headers.x-dd-proxy-path": "/test",
+ "http.request.headers.x-dd-proxy-request-time-ms": "1739261376000",
+ "http.request.headers.x-dd-proxy-stage": "aws-prod",
+ "http.status_code": "500",
+ "http.url": "http://localhost/error?key=value&",
+ "runtime-id": "6423c0c2-fbc3-4ee4-ad68-25dd48ee99f3",
+ "stage": "aws-prod",
+ "version": "1.0"
+ },
+ "metrics": {
+ "_sampling_priority_v1": 1
+ }
+ },
+ {
+ "name": "web.request",
+ "service": "roadrunner_test_app",
+ "resource": "web.request",
+ "trace_id": 0,
+ "span_id": 2,
+ "parent_id": 1,
+ "type": "web",
+ "error": 1,
+ "meta": {
+ "_dd.base_service": "example.com",
+ "_dd.p.tid": "67b5c9a800000000",
+ "component": "roadrunner",
+ "env": "local-test",
+ "error.message": "Uncaught Exception: Error page in /home/circleci/app/tests/Frameworks/Roadrunner/Version_2/worker.php:26",
+ "error.stack": "#0 {main}",
+ "error.type": "Exception",
+ "span.kind": "server",
+ "version": "1.0"
+ },
+ "metrics": {
+ "_sampling_priority_v1": 1
+ }
+ }]]