Skip to content
Merged
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
10 changes: 10 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ GCOV ?= gcov
SHELL = /bin/bash
GCOVR ?= gcovr
GIT ?= git
# make sure go toolchain defined in daemon/go.mod is always used
GOTOOLCHAIN=auto

include make/config.mk
include make/vendor.mk
Expand Down Expand Up @@ -165,9 +167,17 @@ agent-valgrind: agent/Makefile
# Configure the target directory for go install
export GOBIN=$(CURDIR)/bin

.PHONY: daemon-golang-verify
daemon-golang-verify:
@golang_in_binary=$$(go version -m bin/daemon | awk '/^bin\/daemon/ {print $$2;}') \
&& golang_from_toolchain=$$(awk '/^toolchain/ {print $$2;}' daemon/go.mod) \
&& [ "$$golang_in_binary" = "$$golang_from_toolchain" ] && echo "daemon built using: $$golang_from_toolchain" \
|| { echo "ERROR: daemon built using go: $$golang_in_binary, required: $$golang_from_toolchain"; exit 1; }

.PHONY: daemon
daemon:
$(MAKE) -C daemon
$(MAKE) daemon-golang-verify

.PHONY: daemon_race
daemon_race:
Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
12.0.0
12.1.0
10 changes: 6 additions & 4 deletions agent/fw_cakephp.c
Original file line number Diff line number Diff line change
Expand Up @@ -173,10 +173,12 @@ void nr_cakephp_enable(TSRMLS_D) {
nr_php_wrap_user_function(
NR_PSTR("Cake\\Controller\\Controller::invokeAction"),
nr_cakephp_name_the_wt_4);
nr_php_wrap_user_function(
NR_PSTR(
"Cake\\Error\\Middleware\\ErrorHandlerMiddleware::handleException"),
nr_cakephp_error_handler_wrapper);
if (!NRINI(ignore_framework_error_exception_handler)) {
nr_php_wrap_user_function(
NR_PSTR(
"Cake\\Error\\Middleware\\ErrorHandlerMiddleware::handleException"),
nr_cakephp_error_handler_wrapper);
}
nr_txn_suggest_package_supportability_metric(NRPRG(txn), PHP_PACKAGE_NAME,
PHP_PACKAGE_VERSION_UNKNOWN);
}
16 changes: 9 additions & 7 deletions agent/fw_drupal8.c
Original file line number Diff line number Diff line change
Expand Up @@ -898,14 +898,16 @@ void nr_drupal8_enable(TSRMLS_D) {
/*
* Log exceptions without further handling.
*/
nr_php_wrap_user_function(NR_PSTR("Drupal\\Core\\EventSubscriber\\ExceptionLoggingSubscriber::onException"),
nr_drupal_exception);
if (!NRINI(ignore_framework_error_exception_handler)) {
nr_php_wrap_user_function(NR_PSTR("Drupal\\Core\\EventSubscriber\\ExceptionLoggingSubscriber::onException"),
nr_drupal_exception);

/*
* Last-chance handler for exceptions: the final exception subscriber.
*/
nr_php_wrap_user_function(NR_PSTR("Drupal\\Core\\EventSubscriber\\FinalExceptionSubscriber::onException"),
nr_drupal_exception);
/*
* Last-chance handler for exceptions: the final exception subscriber.
*/
nr_php_wrap_user_function(NR_PSTR("Drupal\\Core\\EventSubscriber\\FinalExceptionSubscriber::onException"),
nr_drupal_exception);
}
// clang-format on

/*
Expand Down
28 changes: 15 additions & 13 deletions agent/fw_laravel.c
Original file line number Diff line number Diff line change
Expand Up @@ -865,19 +865,21 @@ NR_PHP_WRAPPER(nr_laravel5_application_boot) {
* to sensibly name transactions when an exception is thrown during routing
* and also to record the error.
*/
exception_handler = nr_php_call_offsetGet(
this_var, "Illuminate\\Contracts\\Debug\\ExceptionHandler" TSRMLS_CC);
if (nr_php_is_zval_valid_object(exception_handler)) {
nr_laravel_add_callback_method(Z_OBJCE_P(exception_handler),
NR_PSTR("render"),
nr_laravel5_exception_render TSRMLS_CC);

nr_laravel_add_callback_method(Z_OBJCE_P(exception_handler),
NR_PSTR("report"),
nr_laravel5_exception_report TSRMLS_CC);
} else {
nrl_verbosedebug(NRL_FRAMEWORK, "%s: cannot get exception handler",
__func__);
if (!NRINI(ignore_framework_error_exception_handler)) {
exception_handler = nr_php_call_offsetGet(
this_var, "Illuminate\\Contracts\\Debug\\ExceptionHandler" TSRMLS_CC);
if (nr_php_is_zval_valid_object(exception_handler)) {
nr_laravel_add_callback_method(Z_OBJCE_P(exception_handler),
NR_PSTR("render"),
nr_laravel5_exception_render TSRMLS_CC);

nr_laravel_add_callback_method(Z_OBJCE_P(exception_handler),
NR_PSTR("report"),
nr_laravel5_exception_report TSRMLS_CC);
} else {
nrl_verbosedebug(NRL_FRAMEWORK, "%s: cannot get exception handler",
__func__);
}
}

end:
Expand Down
14 changes: 8 additions & 6 deletions agent/fw_lumen.c
Original file line number Diff line number Diff line change
Expand Up @@ -218,16 +218,18 @@ void nr_lumen_enable(TSRMLS_D) {
nr_php_wrap_user_function(
NR_PSTR("Laravel\\Lumen\\Application::handleFoundRoute"),
nr_lumen_handle_found_route TSRMLS_CC);
if (!NRINI(ignore_framework_error_exception_handler)) {
#if ZEND_MODULE_API_NO >= ZEND_8_0_X_API_NO \
&& !defined OVERWRITE_ZEND_EXECUTE_DATA
nr_php_wrap_user_function_before_after_clean(
NR_PSTR("Laravel\\Lumen\\Application::sendExceptionToHandler"),
nr_lumen_exception, NULL, NULL);
nr_php_wrap_user_function_before_after_clean(
NR_PSTR("Laravel\\Lumen\\Application::sendExceptionToHandler"),
nr_lumen_exception, NULL, NULL);
#else
nr_php_wrap_user_function(
NR_PSTR("Laravel\\Lumen\\Application::sendExceptionToHandler"),
nr_lumen_exception TSRMLS_CC);
nr_php_wrap_user_function(
NR_PSTR("Laravel\\Lumen\\Application::sendExceptionToHandler"),
nr_lumen_exception TSRMLS_CC);
#endif
}

if (NRINI(vulnerability_management_package_detection_enabled)) {
nr_txn_add_php_package(NRPRG(txn), PHP_PACKAGE_NAME,
Expand Down
26 changes: 14 additions & 12 deletions agent/fw_symfony4.c
Original file line number Diff line number Diff line change
Expand Up @@ -250,19 +250,21 @@ void nr_symfony4_enable(TSRMLS_D) {
* nr_txn_record_error and pass the exception message. Now we get errors in
* the error analytics page.
*/
nr_php_wrap_user_function(
NR_PSTR("Symfony\\Component\\HttpKernel\\"
"EventListener\\ExceptionListener::onKernelException"),
nr_symfony4_exception TSRMLS_CC);
if (!NRINI(ignore_framework_error_exception_handler)) {
nr_php_wrap_user_function(
NR_PSTR("Symfony\\Component\\HttpKernel\\"
"EventListener\\ExceptionListener::onKernelException"),
nr_symfony4_exception TSRMLS_CC);

/*
* In Symfony 5 listener that catch errors was changed to ErrorListener,
* we try to hook into it
*/
nr_php_wrap_user_function(
NR_PSTR("Symfony\\Component\\HttpKernel\\"
"EventListener\\ErrorListener::onKernelException"),
nr_symfony4_exception TSRMLS_CC);
/*
* In Symfony 5 listener that catch errors was changed to ErrorListener,
* we try to hook into it
*/
nr_php_wrap_user_function(
NR_PSTR("Symfony\\Component\\HttpKernel\\"
"EventListener\\ErrorListener::onKernelException"),
nr_symfony4_exception TSRMLS_CC);
}

/*
* Listen for Symfony commands so we can name those appropriately.
Expand Down
6 changes: 4 additions & 2 deletions agent/fw_yii.c
Original file line number Diff line number Diff line change
Expand Up @@ -219,8 +219,10 @@ void nr_yii2_enable(TSRMLS_D) {
* allowing default PHP error handler to be intercepted by the NewRelic agent
* implementation.
*/
nr_php_wrap_user_function(NR_PSTR("yii\\base\\ErrorHandler::logException"),
nr_yii2_error_handler_wrapper TSRMLS_CC);
if (!NRINI(ignore_framework_error_exception_handler)) {
nr_php_wrap_user_function(NR_PSTR("yii\\base\\ErrorHandler::logException"),
nr_yii2_error_handler_wrapper TSRMLS_CC);
}
#endif

if (NRINI(vulnerability_management_package_detection_enabled)) {
Expand Down
25 changes: 25 additions & 0 deletions agent/php_mysqli.c
Original file line number Diff line number Diff line change
Expand Up @@ -688,3 +688,28 @@ const char* nr_php_mysqli_strip_persistent_prefix(const char* host) {

return host;
}

void nr_php_mysqli_rshutdown() {
/*
* This frees mysqli metadata stored in the transaction.
*
* `mysqli_queries` contains duplicates of zvals. If
* `nr_php_txn_end` is called from the post-deactivate callback, request
* shutdown functions have already been called; and the Zend VM has already
* forcefully freed all dangling zvals that are not referenced by the global
* scope (regardless of their reference count), thus leaving the zvals stored
* in the mysqli_queries metadata in an "undefined" state. Consequently,
* freeing the zvals in `nr_php_txn_end` at this stage can result in undefined
* behavior.
*
* Calling this function during the RSHUTDOWN phase ensures that the zvals in
* `mysqli_queries` are cleaned up before Zend winds down the VM and
* forcefully frees zvals.
*
* If `nr_php_txn_end` is called outside the post-deactivate callback,
* it frees `mysqli_queries` by itself.
*/
if (nrlikely(NRPRG(txn))) {
nr_hashmap_destroy(&NRTXNGLOBAL(mysqli_queries));
}
}
6 changes: 6 additions & 0 deletions agent/php_mysqli.h
Original file line number Diff line number Diff line change
Expand Up @@ -163,4 +163,10 @@ extern nr_datastore_instance_t* nr_php_mysqli_retrieve_datastore_instance(
extern void nr_php_mysqli_remove_datastore_instance(
const zval* mysqli_obj TSRMLS_DC);

/*
* Purpose : Frees reference incremented, transaction global zvals
* that must be cleaned up prior to postdeactivate
*/
extern void nr_php_mysqli_rshutdown();

#endif /* PHP_MYSQLI_HDR */
13 changes: 13 additions & 0 deletions agent/php_newrelic.h
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,9 @@ nrinibool_t
nrinibool_t
ignore_user_exception_handler; /* newrelic.error_collector.ignore_user_exception_handler
*/
nrinibool_t
ignore_framework_error_exception_handler; /* newrelic.error_collector.ignore_framework_error_excpetion_handler
*/
nriniint_t ignore_errors; /* newrelic.error_collector.ignore_errors */
nrinistr_t ignore_exceptions; /* newrelic.error_collector.ignore_exceptions */
nrinibool_t
Expand Down Expand Up @@ -491,6 +494,16 @@ nrinibool_t span_events_enabled; /* newrelic.span_events_enabled */
nriniuint_t
span_events_max_samples_stored; /* newrelic.span_events.max_samples_stored
*/

nrinistr_t dt_remote_parent_sampled; /* newrelic.distributed_tracing.sampler.remote_parent_sampled */
nrinistr_t
dt_remote_parent_not_sampled; /* newrelic.distributed_tracing.sampler.remote_parent_not_sampled */
/* decoding of newrelic.distributed_tracing.sampler.remote_parent_sampled and
* newrelic.distributed_tracing.sampler.remote_parent_not_sampled.
*/
nr_upstream_parent_sampling_control_t dt_sampler_parent_sampled;
nr_upstream_parent_sampling_control_t dt_sampler_parent_not_sampled;

nrinistr_t
trace_observer_host; /* newrelic.infinite_tracing.trace_observer.host */
nriniuint_t
Expand Down
75 changes: 75 additions & 0 deletions agent/php_nrini.c
Original file line number Diff line number Diff line change
Expand Up @@ -1970,6 +1970,55 @@ static PHP_INI_MH(nr_wordpress_hooks_options_mh) {
return SUCCESS;
}

static PHP_INI_MH(nr_dt_sampler_remote_parent_mh) {
nrinistr_t* p;

char* base = (char*)mh_arg2;
p = (nrinistr_t*)(base + (size_t)mh_arg1);
bool parent_sampled = false;

(void)mh_arg3;
NR_UNUSED_TSRMLS;

p->where = 0;

if (0 == nr_strcmp(ZEND_STRING_VALUE(entry->name),
"newrelic.distributed_tracing.sampler.remote_parent_sampled")) {
parent_sampled = true;
}

if (0 == nr_strcmp(NEW_VALUE, "default")) {
if (parent_sampled) {
NRPRG(dt_sampler_parent_sampled) = DEFAULT;
} else {
NRPRG(dt_sampler_parent_not_sampled) = DEFAULT;
}
} else if (0 == nr_strcmp(NEW_VALUE, "always_on")) {
if (parent_sampled) {
NRPRG(dt_sampler_parent_sampled) = ALWAYS_KEEP;
} else {
NRPRG(dt_sampler_parent_not_sampled) = ALWAYS_KEEP;
}
} else if (0 == nr_strcmp(NEW_VALUE, "always_off")) {
if (parent_sampled) {
NRPRG(dt_sampler_parent_sampled) = ALWAYS_DROP;
} else {
NRPRG(dt_sampler_parent_not_sampled) = ALWAYS_DROP;
}
} else {
nrl_warning(NRL_INIT, "Invalid %s value \"%s\"; using \"%s\" instead.",
ZEND_STRING_VALUE(entry->name), NEW_VALUE,
DEFAULT_WORDPRESS_HOOKS_OPTIONS);
/* This will cause PHP to call the handler again with default value */
return FAILURE;
}

p->where = stage;
p->value = NEW_VALUE;

return SUCCESS;
}

/*
* Now for the actual INI entry table. Please note there are two types of INI
* entry specification used.
Expand Down Expand Up @@ -2587,6 +2636,14 @@ STD_PHP_INI_ENTRY_EX("newrelic.error_collector.ignore_user_exception_handler",
zend_newrelic_globals,
newrelic_globals,
nr_yes_no_dh)
STD_PHP_INI_ENTRY_EX("newrelic.error_collector.ignore_framework_error_exception_handler",
"0",
NR_PHP_REQUEST,
nr_boolean_mh,
ignore_framework_error_exception_handler,
zend_newrelic_globals,
newrelic_globals,
nr_yes_no_dh)
STD_PHP_INI_ENTRY_EX("newrelic.error_collector.ignore_errors",
"",
NR_PHP_REQUEST,
Expand Down Expand Up @@ -2930,6 +2987,24 @@ STD_PHP_INI_ENTRY_EX("newrelic.distributed_tracing_exclude_newrelic_header",
newrelic_globals,
0)


STD_PHP_INI_ENTRY_EX("newrelic.distributed_tracing.sampler.remote_parent_sampled",
"default",
NR_PHP_REQUEST,
nr_dt_sampler_remote_parent_mh,
dt_remote_parent_sampled,
zend_newrelic_globals,
newrelic_globals,
0)
STD_PHP_INI_ENTRY_EX("newrelic.distributed_tracing.sampler.remote_parent_not_sampled",
"default",
NR_PHP_REQUEST,
nr_dt_sampler_remote_parent_mh,
dt_remote_parent_not_sampled,
zend_newrelic_globals,
newrelic_globals,
0)

/*
* This setting is not documented and affects the length of the interally used
* trace id. This INI setting should not be modified unless requested by
Expand Down
4 changes: 4 additions & 0 deletions agent/php_observer.c
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,10 @@ static zend_observer_fcall_handlers nr_php_fcall_register_handlers(
return handlers;
}

if (0 == nr_php_recording()) {
return handlers;
}

if (nrunlikely(NR_PHP_PROCESS_GLOBALS(special_flags).show_executes)) {
nr_php_show_exec("observe", execute_data, NULL);
}
Expand Down
25 changes: 25 additions & 0 deletions agent/php_pdo.c
Original file line number Diff line number Diff line change
Expand Up @@ -638,3 +638,28 @@ zval* nr_php_pdo_disable_persistence(const zval* options TSRMLS_DC) {
nr_php_zval_free(&persistent);
return result;
}

void nr_php_pdo_rshutdown() {
/*
* This frees pdo metadata stored in the transaction.
*
* `pdo_link_options` contains duplicates of zvals. If
* `nr_php_txn_end` is called from the post-deactivate callback, request
* shutdown functions have already been called; and the Zend VM has already
* forcefully freed all dangling zvals that are not referenced by the global
* scope (regardless of their reference count), thus leaving the zvals stored
* in the pdo_link_options metadata in an "undefined" state. Consequently,
* freeing the zvals in `nr_php_txn_end` at this stage can result in undefined
* behavior.
*
* Calling this function during the RSHUTDOWN phase ensures that the zvals in
* `pdo_link_options` are cleaned up before Zend winds down the VM and
* forcefully frees zvals.
*
* If `nr_php_txn_end` is called outside the post-deactivate callback,
* it frees `pdo_link_options` by itself.
*/
if (nrlikely(NRPRG(txn))) {
nr_hashmap_destroy(&NRTXNGLOBAL(pdo_link_options));
}
}
5 changes: 5 additions & 0 deletions agent/php_pdo.h
Original file line number Diff line number Diff line change
Expand Up @@ -161,4 +161,9 @@ extern nr_status_t nr_php_pdo_parse_data_source(
extern void nr_php_pdo_free_data_sources(struct pdo_data_src_parser* parsed,
size_t nparams);

/*
* Purpose : Frees reference incremented, transaction global zvals
* that must be cleaned up prior to postdeactivate
*/
extern void nr_php_pdo_rshutdown();
#endif
Loading
Loading