Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions agent/Makefile.frag
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ TEST_BINARIES = \
tests/test_curl_md \
tests/test_datastore \
tests/test_environment \
tests/test_fibers \
tests/test_fw_codeigniter \
tests/test_fw_drupal \
tests/test_fw_laravel_queue \
Expand Down
2 changes: 1 addition & 1 deletion agent/config.m4
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ if test "$PHP_NEWRELIC" = "yes"; then
php_api_distributed_trace.c php_api_internal.c php_autorum.c \
php_call.c php_curl.c php_curl_md.c php_datastore.c php_environment.c \
php_error.c php_execute.c php_explain.c php_explain_mysqli.c \
php_explain_pdo_mysql.c php_extension.c php_file_get_contents.c \
php_explain_pdo_mysql.c php_extension.c php_fibers.c php_file_get_contents.c \
php_globals.c php_hash.c php_header.c php_httprequest_send.c \
php_internal_instrument.c php_memcached.c php_minit.c php_mshutdown.c php_mysql.c \
php_mysqli.c php_newrelic.c php_nrini.c php_observer.c php_output.c php_pdo.c \
Expand Down
4 changes: 2 additions & 2 deletions agent/fw_drupal.c
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,7 @@ NR_PHP_WRAPPER(nr_drupal_http_request_before) {
* after function properly
*/
NRPRG_CTX(drupal_http_request_segment)
= nr_segment_start(NRPRG(txn), NULL, NULL);
= NR_SEGMENT_START_WITH_PARENT_CONTEXT(NRPRG(txn), auto_segment);
/*
* The new segment needs to have the wraprec data attached, so that
* fcall_end is able to properly dispatch to the after wrapper, as
Expand Down Expand Up @@ -412,7 +412,7 @@ NR_PHP_WRAPPER(nr_drupal_http_request_exec) {
external_params.procedure
= nr_drupal_http_request_get_method(NR_EXECUTE_ORIG_ARGS TSRMLS_CC);

segment = nr_segment_start(NRPRG(txn), NULL, NULL);
segment = NR_SEGMENT_START_WITH_PARENT_CONTEXT(NRPRG(txn), auto_segment);

/*
* Our wrapper for drupal_http_request (which we installed in
Expand Down
12 changes: 8 additions & 4 deletions agent/lib_aws_sdk_php.c
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,8 @@ void nr_lib_aws_sdk_php_kinesis_handle(nr_segment_t* auto_segment,
* only create the segment now, grab the parent segment start time, add our
* special segment attributes/metrics then close the newly created segment.
*/
message_segment = nr_segment_start(NRPRG(txn), NULL, NULL);
message_segment
= NR_SEGMENT_START_WITH_PARENT_CONTEXT(NRPRG(txn), auto_segment);
if (NULL == message_segment) {
return;
}
Expand Down Expand Up @@ -395,7 +396,8 @@ void nr_lib_aws_sdk_php_sqs_handle(nr_segment_t* auto_segment,
* only create the segment now, grab the parent segment start time, add our
* special segment attributes/metrics then close the newly created segment.
*/
message_segment = nr_segment_start(NRPRG(txn), NULL, NULL);
message_segment
= NR_SEGMENT_START_WITH_PARENT_CONTEXT(NRPRG(txn), auto_segment);
if (NULL == message_segment) {
return;
}
Expand Down Expand Up @@ -601,7 +603,8 @@ void nr_lib_aws_sdk_php_lambda_handle(nr_segment_t* auto_segment,
* only create the segment now, grab the parent segment start time, add our
* special segment attributes/metrics then close the newly created segment.
*/
external_segment = nr_segment_start(NRPRG(txn), NULL, NULL);
external_segment
= NR_SEGMENT_START_WITH_PARENT_CONTEXT(NRPRG(txn), auto_segment);
if (NULL == external_segment) {
nr_free(cloud_attrs.cloud_resource_id);
return;
Expand Down Expand Up @@ -925,7 +928,8 @@ void nr_lib_aws_sdk_php_dynamodb_handle(nr_segment_t* auto_segment,
* start time, add the special segment attributes/metrics then close the newly
* created segment.
*/
datastore_segment = nr_segment_start(NRPRG(txn), NULL, NULL);
datastore_segment
= NR_SEGMENT_START_WITH_PARENT_CONTEXT(NRPRG(txn), auto_segment);
if (NULL != datastore_segment) {
/* re-use start time from auto_segment started in func_begin */
datastore_segment->start_time = auto_segment->start_time;
Expand Down
25 changes: 19 additions & 6 deletions agent/lib_guzzle6.c
Original file line number Diff line number Diff line change
Expand Up @@ -112,12 +112,22 @@ static void nr_guzzle6_requesthandler_handle_response(zval* handler,
zval* request;
zval* method;
zval* status = NULL;
int old_context = 0;

if (NR_FAILURE
== nr_guzzle_obj_find_and_remove(handler, &segment TSRMLS_CC)) {
return;
}

/*
* This is a special case because guzzle stores all the external segments in
* the NRTXN(guzzle_objs) hashmap. When the extracted segment is ended, we
* don't want the context of this segment's parent to be set on the txn
* because for guzzle that is a special newrelic guzzle middleware segment.
* Save it now so we can restore it later.
*/
old_context = NRTXN(current_async_context);

request = nr_guzzle6_requesthandler_get_request(handler TSRMLS_CC);
if (NULL == request) {
return;
Expand All @@ -137,16 +147,17 @@ static void nr_guzzle6_requesthandler_handle_response(zval* handler,

if (NULL != response && nr_php_psr7_is_response(response TSRMLS_CC)) {
/*
* Get the X-NewRelic-App-Data response header. If there isn't one, NULL is
* returned, and everything still works just fine.
*/
external_params.encoded_response_header
= nr_php_psr7_message_get_header(response, X_NEWRELIC_APP_DATA TSRMLS_CC);
* Get the X-NewRelic-App-Data response header. If there isn't one, NULL is
* returned, and everything still works just fine.
*/
external_params.encoded_response_header = nr_php_psr7_message_get_header(
response, X_NEWRELIC_APP_DATA TSRMLS_CC);

if (NRPRG(txn) && NRTXN(special_flags.debug_cat)) {
nrl_verbosedebug(
NRL_CAT, "CAT: outbound response: transport='Guzzle 6' %s=" NRP_FMT,
X_NEWRELIC_APP_DATA, NRP_CAT(external_params.encoded_response_header));
X_NEWRELIC_APP_DATA,
NRP_CAT(external_params.encoded_response_header));
}

status = nr_php_call(response, "getStatusCode");
Expand All @@ -158,6 +169,8 @@ static void nr_guzzle6_requesthandler_handle_response(zval* handler,

nr_segment_external_end(&segment, &external_params);

NRTXN(current_async_context) = old_context;

nr_free(external_params.encoded_response_header);
nr_free(external_params.uri);
nr_free(external_params.procedure);
Expand Down
25 changes: 24 additions & 1 deletion agent/lib_guzzle_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -83,16 +83,38 @@ nr_segment_t* nr_guzzle_obj_add(const zval* obj,
const char* async_context_prefix TSRMLS_DC) {
nr_segment_t* segment = NULL;
char* async_context = NULL;
int old_context = 0;

/*
* Create the async context, in case there was parallelism.
*/
async_context
= nr_guzzle_create_async_context_name(async_context_prefix, obj);
/*
* This is a special case where we don't want the context of the newly
* created segment to be set on the txn because this segment is tracked
* separately based off of the unique created guzzle async context. We need to
* save the actual context so we can restore it later.
*/
old_context = NRTXN(current_async_context);

/*
* Must explicitly be parented to the current segment of the txn context;
* otherwise, it will be parented to the main NULL context. In non-fiber
* cases, this will be a segment on the default (NULL) context; otherwise, it
* will be the current segment on the actively executing fiber.
*
* Similar to curl_multi_exec curl handle segments, because async guzzle
* segments are stored separately in a hashmap, we don't want to this segment
* creation to affect the txn context.
*/

segment = nr_segment_start(NRPRG(txn), NULL, async_context);
segment = nr_segment_start(NRPRG(txn),
nr_txn_get_current_segment_txn_context(NRPRG(txn)),
async_context);

nr_free(async_context);
NRTXN(current_async_context) = old_context;

/*
* Create the guzzle_objs hash table if we haven't already done so.
Expand All @@ -108,6 +130,7 @@ nr_segment_t* nr_guzzle_obj_add(const zval* obj,
* architecture, and saves us having to transform the object handle into a
* string to use string keys.
*/

nr_hashmap_index_update(NRTXNGLOBAL(guzzle_objs),
(uint64_t)Z_OBJ_HANDLE_P(obj), segment);

Expand Down
6 changes: 3 additions & 3 deletions agent/lib_laminas_http.c
Original file line number Diff line number Diff line change
Expand Up @@ -337,7 +337,7 @@ NR_PHP_WRAPPER_START(nr_zend_http_client_request) {
goto leave;
}

segment = nr_segment_start(NRPRG(txn), NULL, NULL);
segment = NR_SEGMENT_START_WITH_PARENT_CONTEXT(NRPRG(txn), auto_segment);

/*
* We have to manually force this segment as the current segment on
Expand Down Expand Up @@ -422,6 +422,6 @@ NR_PHP_WRAPPER_START(nr_zend_http_client_request) {
NR_PHP_WRAPPER_END

void nr_laminas_http_enable(TSRMLS_D) {
nr_php_wrap_user_function(NR_PSTR(HTTP_CLIENT_REQUEST_L),
nr_zend_http_client_request TSRMLS_CC);
nr_php_wrap_user_function(NR_PSTR(HTTP_CLIENT_REQUEST_L),
nr_zend_http_client_request TSRMLS_CC);
}
2 changes: 1 addition & 1 deletion agent/lib_mongodb.c
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ NR_PHP_WRAPPER_END
NR_PHP_WRAPPER(nr_mongodb_operation_before) {
(void)wraprec;
nr_segment_t* segment = NULL;
segment = nr_segment_start(NRPRG(txn), NULL, NULL);
segment = NR_SEGMENT_START_WITH_PARENT_CONTEXT(NRPRG(txn), auto_segment);
if (NULL != segment) {
segment->wraprec = auto_segment->wraprec;
}
Expand Down
6 changes: 4 additions & 2 deletions agent/lib_php_amqplib.c
Original file line number Diff line number Diff line change
Expand Up @@ -621,7 +621,8 @@ NR_PHP_WRAPPER(nr_rabbitmq_basic_publish) {
goto end;
}

message_segment = nr_segment_start(NRPRG(txn), NULL, NULL);
message_segment
= NR_SEGMENT_START_WITH_PARENT_CONTEXT(NRPRG(txn), auto_segment);
if (NULL != message_segment) {
/* re-use start time from auto_segment started in func_begin */
message_segment->start_time = auto_segment->start_time;
Expand Down Expand Up @@ -749,7 +750,8 @@ NR_PHP_WRAPPER(nr_rabbitmq_basic_get) {
* time, add our message segment attributes/metrics then close the newly
* created message segment.
*/
message_segment = nr_segment_start(NRPRG(txn), NULL, NULL);
message_segment
= NR_SEGMENT_START_WITH_PARENT_CONTEXT(NRPRG(txn), auto_segment);

if (NULL == message_segment) {
goto end;
Expand Down
30 changes: 17 additions & 13 deletions agent/lib_predis.c
Original file line number Diff line number Diff line change
Expand Up @@ -81,16 +81,7 @@ const zend_long nr_predis_default_port = 6379;
static NR_PHP_WRAPPER_PROTOTYPE(nr_predis_connection_readResponse);
static NR_PHP_WRAPPER_PROTOTYPE(nr_predis_connection_writeRequest);

static void nr_predis_command_destroy(nrtime_t* time) {
nr_free(time);
}

static inline nr_hashmap_t* nr_predis_get_commands(TSRMLS_D) {
if (NULL == NRPRG_CTX(predis_commands)) {
NRPRG_CTX(predis_commands)
= nr_hashmap_create((nr_hashmap_dtor_func_t)nr_predis_command_destroy);
}

return NRPRG_CTX(predis_commands);
}

Expand Down Expand Up @@ -561,7 +552,13 @@ NR_PHP_WRAPPER(nr_predis_connection_readResponse) {
async_context = nr_formatf("%s." NR_UINT64_FMT, ctx, index);
}

segment = nr_segment_start(NRPRG(txn), NULL, async_context);
/*
* Must explicitly be parented to the parent segment; otherwise, it will
* parent to the main NULL context. In non-fiber cases, this will be a segment
* on the default (NULL) context; otherwise, it will be the current segment on
* the actively executing fiber.
*/
segment = nr_segment_start(NRPRG(txn), auto_segment, async_context);
nr_segment_set_timing(segment, *start, duration);
nr_segment_datastore_end(&segment, &params);

Expand Down Expand Up @@ -765,7 +762,12 @@ NR_PHP_WRAPPER(nr_predis_webdisconnection_executeCommand_before) {
(void)wraprec;

nr_segment_t* segment = NULL;
segment = nr_segment_start(NRPRG(txn), NULL, NULL);
/*
* Must be started in the context of its parent.
* In non-fiber cases, the context will be NULL(default context); otherwise,
* it will be the the context of the parent in an actively executing fiber.
*/
segment = NR_SEGMENT_START_WITH_PARENT_CONTEXT(NRPRG(txn), auto_segment);
if (NULL != segment) {
segment->wraprec = auto_segment->wraprec;
}
Expand Down Expand Up @@ -799,7 +801,7 @@ NR_PHP_WRAPPER(nr_predis_webdisconnection_executeCommand_after) {
}
NR_PHP_WRAPPER_END

#else
#else /* NON-OAPI, non-Fiber cases*/

NR_PHP_WRAPPER(nr_predis_webdisconnection_executeCommand) {
char* operation = NULL;
Expand All @@ -819,7 +821,9 @@ NR_PHP_WRAPPER(nr_predis_webdisconnection_executeCommand) {

operation = nr_predis_get_operation_name_from_object(command_obj TSRMLS_CC);
params.operation = operation;

/*
* This segment start can remain untouched since it is a non-fiber scenario.
*/
segment = nr_segment_start(NRPRG(txn), NULL, NULL);

NR_PHP_WRAPPER_CALL;
Expand Down
31 changes: 20 additions & 11 deletions agent/php_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -1242,9 +1242,12 @@ static nr_status_t nr_php_api_add_custom_span_attribute(const char* keystr,
TSRMLS_DC) {
bool rv;
char* key = NULL;
nr_segment_t* current;
nr_segment_t* current = NULL;
nrtxn_t* txn = NULL;

current = nr_txn_get_current_segment(NRPRG(txn), NULL);
txn = NRPRG(txn);

current = nr_txn_get_current_segment_txn_context(txn);
if (!current) {
return NR_FAILURE;
}
Expand Down Expand Up @@ -1483,6 +1486,8 @@ PHP_FUNCTION(newrelic_get_linking_metadata) {
NR_UNUSED_RETURN_VALUE_USED;
NR_UNUSED_THIS_PTR;

nrtxn_t* txn = NULL;

nr_php_api_add_supportability_metric("get_linking_metadata" TSRMLS_CC);

array_init(return_value);
Expand All @@ -1495,6 +1500,8 @@ PHP_FUNCTION(newrelic_get_linking_metadata) {
return;
}

txn = NRPRG(txn);

if (nrlikely(NRPRG_SHARED(app))) {
nr_php_add_assoc_string_const(return_value, "entity.name",
nr_app_get_entity_name(NRPRG_SHARED(app)));
Expand All @@ -1506,10 +1513,9 @@ PHP_FUNCTION(newrelic_get_linking_metadata) {
nr_app_get_host_name(NRPRG_SHARED(app)));
}

if (nrlikely(NRPRG(txn))) {
trace_id = nr_txn_get_current_trace_id(NRPRG(txn));
span_id = nr_txn_get_current_span_id(NRPRG(txn));

if (nrlikely(txn)) {
trace_id = nr_txn_get_current_trace_id(txn);
span_id = nr_txn_get_current_span_id(txn, nr_txn_get_current_context(txn));
if (trace_id) {
nr_php_add_assoc_string(return_value, "trace.id", trace_id);
}
Expand All @@ -1536,6 +1542,8 @@ PHP_FUNCTION(newrelic_get_trace_metadata) {
NR_UNUSED_RETURN_VALUE_USED;
NR_UNUSED_THIS_PTR;

nrtxn_t* txn = NULL;

nr_php_api_add_supportability_metric("get_trace_metadata" TSRMLS_CC);

array_init(return_value);
Expand All @@ -1548,14 +1556,15 @@ PHP_FUNCTION(newrelic_get_trace_metadata) {
return;
}

if (nrlikely(NRPRG(txn))) {
trace_id = nr_txn_get_current_trace_id(NRPRG(txn));
txn = NRPRG(txn);

if (nrlikely(txn)) {
trace_id = nr_txn_get_current_trace_id(txn);
if (trace_id) {
nr_php_add_assoc_string(return_value, "trace_id", trace_id);
}
nr_free(trace_id);

span_id = nr_txn_get_current_span_id(NRPRG(txn));
span_id = nr_txn_get_current_span_id(txn, nr_txn_get_current_context(txn));
if (span_id) {
nr_php_add_assoc_string(return_value, "span_id", span_id);
}
Expand All @@ -1565,7 +1574,7 @@ PHP_FUNCTION(newrelic_get_trace_metadata) {

/*
* Purpose Allows a caller to add a user id string to agent attributes in
transaction event, transaction trace, error and span.
* transaction event, transaction trace, error and span.
*
*/
#ifdef TAGS
Expand Down
4 changes: 2 additions & 2 deletions agent/php_api_datastore.c
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ zval* nr_php_api_datastore_validate(const HashTable* params) {
nr_php_zval_free(&validated_params);
return NULL;
} else if (datastore_validators[i].default_value) {
nr_php_add_assoc_string(validated_params, key,
nr_php_add_assoc_string(validated_params, key,
(char*)datastore_validators[i].default_value);
}
} else {
Expand Down Expand Up @@ -142,7 +142,7 @@ PHP_FUNCTION(newrelic_record_datastore_segment) {
}

if (instrument) {
segment = nr_segment_start(NRPRG(txn), NULL, NULL);
segment = NR_SEGMENT_START_WITH_TXN_CONTEXT(NRPRG(txn));
#if ZEND_MODULE_API_NO < ZEND_8_0_X_API_NO \
|| defined OVERWRITE_ZEND_EXECUTE_DATA /* not OAPI */
/*
Expand Down
Loading
Loading