Skip to content

Commit

Permalink
Merge pull request #815 from newrelic/dev
Browse files Browse the repository at this point in the history
Release 10.16
  • Loading branch information
mfulb authored Jan 19, 2024
2 parents 6c27106 + de48e8f commit 320ea57
Show file tree
Hide file tree
Showing 51 changed files with 1,386 additions and 165 deletions.
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ Before submitting an Issue, please search for similar ones in the

1. Please open the pull request against the `dev` branch. This is the development branch where all changes are tested before merging to main.
2. Ensure any install or build dependencies are removed before the end of the layer when doing a build.
3. Increase the version numbers in any examples files and the README.md to the new version that this Pull Request would represent. The versioning scheme we use is [SemVer](http://semver.org/).
3. Increase the version numbers in any examples files and the README.md to the new version that this Pull Request would represent. The versioning scheme we use is [SemVer](https://semver.org/).
4. You may merge the Pull Request in once you have the sign-off of two other developers, or if you do not have permission to do that, you may request the second reviewer to merge it for you.

## Contributor License Agreement
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,4 +63,4 @@ If you would like to [contribute](https://github.com/newrelic/newrelic-php-agent
To all [contributors](https://github.com/newrelic/newrelic-php-agent/graphs/contributors), we thank you! Without your contribution, this project would not be what it is today. We also host a community project page dedicated to the [New Relic PHP agent](https://opensource.newrelic.com/projects/newrelic/newrelic-php-agent).

## License
The PHP agent is licensed under the [Apache 2.0](http://apache.org/licenses/LICENSE-2.0.txt) License and also uses source code from third-party libraries. You can find full details on which libraries are used and the terms under which they are licensed in the third-party notices document.
The PHP agent is licensed under the [Apache 2.0](https://apache.org/licenses/LICENSE-2.0.txt) License and also uses source code from third-party libraries. You can find full details on which libraries are used and the terms under which they are licensed in the third-party notices document.
2 changes: 1 addition & 1 deletion STYLEGUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ _"This does not contain everything, but what it contains is true"._
```
0. Format code with
[clang-format 3.8](http://releases.llvm.org/3.8.0/tools/clang/docs/ClangFormat.html)
[clang-format 3.8](https://releases.llvm.org/3.8.0/tools/clang/docs/ClangFormat.html)
or later using our [style configuration file](.clang-format).
0. Disregard directives from this list when other approaches are more
Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
10.15.0
10.16.0
2 changes: 1 addition & 1 deletion agent/README.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@ and API descriptions please see the online FAQ at:

For license and copyright, see LICENSE.

For support, contact us at http://support.newrelic.com for assistance.
For support, contact us at https://support.newrelic.com for assistance.
128 changes: 120 additions & 8 deletions agent/fw_wordpress.c
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,21 @@ static void free_wordpress_metadata(void* metadata) {
nr_free(metadata);
}

static inline void nr_wordpress_hooks_create_metric(nr_segment_t* segment,
const char* hook_name) {
if (NULL == segment) {
return;
}
// need to capture 'now' because segment has not finished yet and therefore
// can't use segment->stop_time
nrtime_t now = nr_txn_now_rel(segment->txn);
nrtime_t duration = nr_time_duration(segment->start_time, now);
if (duration >= NRINI(wordpress_hooks_threshold)) {
// only create metrics for hooks above threshold
nr_wordpress_create_metric(segment, NR_WORDPRESS_HOOK_PREFIX, hook_name);
}
}

static char* nr_wordpress_plugin_from_function(zend_function* func TSRMLS_DC) {
const char* filename = NULL;
size_t filename_len;
Expand Down Expand Up @@ -296,7 +311,9 @@ static char* nr_wordpress_plugin_from_function(zend_function* func TSRMLS_DC) {
}

NR_PHP_WRAPPER(nr_wordpress_wrap_hook) {
#if ZEND_MODULE_API_NO < ZEND_7_4_X_API_NO
zend_function* func = NULL;
#endif
char* plugin = NULL;

NR_UNUSED_SPECIALFN;
Expand All @@ -312,20 +329,27 @@ NR_PHP_WRAPPER(nr_wordpress_wrap_hook) {
if ((0 == NRINI(wordpress_hooks)) || (NULL == NRPRG(wordpress_tag))) {
NR_PHP_WRAPPER_LEAVE;
}
#if ZEND_MODULE_API_NO < ZEND_7_4_X_API_NO
func = nr_php_execute_function(NR_EXECUTE_ORIG_ARGS TSRMLS_CC);
plugin = nr_wordpress_plugin_from_function(func TSRMLS_CC);
#else
plugin = wraprec->wordpress_plugin_theme;
#endif

NR_PHP_WRAPPER_CALL;

nr_wordpress_create_metric(auto_segment, NR_WORDPRESS_HOOK_PREFIX,
NRPRG(wordpress_tag));
nr_wordpress_create_metric(auto_segment, NR_WORDPRESS_PLUGIN_PREFIX, plugin);
if (NULL != plugin || NRPRG(wordpress_core)) {
nr_wordpress_create_metric(auto_segment, NR_WORDPRESS_HOOK_PREFIX,
NRPRG(wordpress_tag));
nr_wordpress_create_metric(auto_segment, NR_WORDPRESS_PLUGIN_PREFIX,
plugin);
}
}
NR_PHP_WRAPPER_END

/*
* A call_user_func_array() callback to ensure that we wrap each hook function.
* PHP 7.3 and below uses old-style wraprec, and will use old style cufa calls.
*/
#if ZEND_MODULE_API_NO < ZEND_7_4_X_API_NO
static void nr_wordpress_call_user_func_array(zend_function* func,
const zend_function* caller
NRUNUSED TSRMLS_DC) {
Expand Down Expand Up @@ -357,6 +381,7 @@ static void nr_wordpress_call_user_func_array(zend_function* func,
*/
nr_php_wrap_callable(func, nr_wordpress_wrap_hook TSRMLS_CC);
}
#endif /* PHP < 7.4 */

static void free_tag(void* tag) {
nr_free(tag);
Expand Down Expand Up @@ -444,6 +469,9 @@ NR_PHP_WRAPPER(nr_wordpress_exec_handle_tag) {

NRPRG(wordpress_tag) = nr_wordpress_clean_tag(tag);
NR_PHP_WRAPPER_CALL;
if (0 == NRPRG(wordpress_plugins)) {
nr_wordpress_hooks_create_metric(auto_segment, NRPRG(wordpress_tag));
}
NRPRG(wordpress_tag) = old_tag;
if (NULL == NRPRG(wordpress_tag)) {
NRPRG(check_cufa) = false;
Expand Down Expand Up @@ -533,6 +561,9 @@ NR_PHP_WRAPPER(nr_wordpress_apply_filters) {
NRPRG(wordpress_tag) = nr_wordpress_clean_tag(tag);

NR_PHP_WRAPPER_CALL;
if (0 == NRPRG(wordpress_plugins)) {
nr_wordpress_hooks_create_metric(auto_segment, NRPRG(wordpress_tag));
}
NRPRG(wordpress_tag) = old_tag;
if (NULL == NRPRG(wordpress_tag)) {
NRPRG(check_cufa) = false;
Expand All @@ -551,6 +582,81 @@ NR_PHP_WRAPPER(nr_wordpress_apply_filters) {
}
NR_PHP_WRAPPER_END

#if ZEND_MODULE_API_NO >= ZEND_7_4_X_API_NO
/*
* Wrap the wordpress function add_filter
*
* function add_filter( $hook_name, $callback, $priority = 10, $accepted_args = 1 )
*
* @param string $hook_name The name of the filter to add the callback to.
* @param callable $callback The callback to be run when the filter is applied.
* @param int $priority Optional. Used to specify the order in which the functions
* associated with a particular filter are executed.
* Lower numbers correspond with earlier execution,
* and functions with the same priority are executed
* in the order in which they were added to the filter. Default 10.
* @param int $accepted_args Optional. The number of arguments the function accepts. Default 1.
* @return true Always returns true.
*/

NR_PHP_WRAPPER(nr_wordpress_add_filter) {
/* Wordpress's add_action() is just a wrapper around add_filter(),
* so we only need to instrument this function */
NR_UNUSED_SPECIALFN;
(void)wraprec;
const char* filename = NULL;
bool wrap_hook = true;

NR_PHP_WRAPPER_REQUIRE_FRAMEWORK(NR_FW_WORDPRESS);

/*
* We only want to hook the function being called if this is a WordPress
* function, we're instrumenting hooks, and WordPress is currently executing
* hooks (denoted by the wordpress_tag being set).
*/
if ((NR_FW_WORDPRESS != NRPRG(current_framework))
|| (0 == NRINI(wordpress_hooks))) {
wrap_hook = false;
}

if (NRINI(wordpress_hooks_skip_filename)
&& 0 != nr_strlen(NRINI(wordpress_hooks_skip_filename))) {
filename = nr_php_op_array_file_name(NR_OP_ARRAY);

if (nr_strstr(filename, NRINI(wordpress_hooks_skip_filename))) {
nrl_verbosedebug(NRL_FRAMEWORK, "skipping hooks for function from %s",
filename);
wrap_hook = false;
}
}

if (true == wrap_hook) {
nruserfn_t* callback_wraprec;
zval* callback = nr_php_arg_get(2, NR_EXECUTE_ORIG_ARGS);
zend_function* zf = nr_php_zval_to_function(callback);
if (NULL != zf) {
char* wordpress_plugin_theme = nr_wordpress_plugin_from_function(zf);
if (NULL != wordpress_plugin_theme || NRPRG(wordpress_core)) {
callback_wraprec = nr_php_wrap_callable(zf, nr_wordpress_wrap_hook);
// We can cheat here: wraprecs on callables are always transient, so if
// there's a wordpress_plugin_theme set we know it's from this
// transaction, and we don't have any issues around a possible
// multi-tenant setup.
if (NULL != callback_wraprec
&& NULL == callback_wraprec->wordpress_plugin_theme) {
// Unlike Drupal, we don't free the wordpress_plugin_theme, since we
// know it's transient anyway, and we only set the field if it was
// previously NULL.
callback_wraprec->wordpress_plugin_theme = wordpress_plugin_theme;
}
}
}
nr_php_arg_release(&callback);
}
}
NR_PHP_WRAPPER_END
#endif /* PHP 7.4+ */

void nr_wordpress_enable(TSRMLS_D) {
nr_php_wrap_user_function(NR_PSTR("apply_filters"),
nr_wordpress_apply_filters TSRMLS_CC);
Expand All @@ -564,9 +670,15 @@ void nr_wordpress_enable(TSRMLS_D) {

nr_php_wrap_user_function(NR_PSTR("do_action_ref_array"),
nr_wordpress_exec_handle_tag TSRMLS_CC);

nr_php_add_call_user_func_array_pre_callback(
nr_wordpress_call_user_func_array TSRMLS_CC);
if (0 != NRPRG(wordpress_plugins)) {
#if ZEND_MODULE_API_NO < ZEND_7_4_X_API_NO
nr_php_add_call_user_func_array_pre_callback(
nr_wordpress_call_user_func_array TSRMLS_CC);
#else
nr_php_wrap_user_function(NR_PSTR("add_filter"),
nr_wordpress_add_filter);
#endif
}
}
}

Expand Down
16 changes: 8 additions & 8 deletions agent/newrelic-install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -355,7 +355,7 @@ The New Relic installation directory is incomplete. The files or
directories listed above could not be found. This usually means that
you have a corrupt installation archive. Please re-download your New
Relic software and try again. If the problem persists, please contact
${bold}http://support.newrelic.com${rmso} and report the issue. Be sure
${bold}https://support.newrelic.com${rmso} and report the issue. Be sure
to include all the above output in your bug report. We apologize for the
inconvenience.
Expand Down Expand Up @@ -494,7 +494,7 @@ fatal() {
echo "FATAL: $@" >&2
cat >&2 <<EOF
FATAL: New Relic agent installation failed.
Please contact ${bold}http://support.newrelic.com${rmso}
Please contact ${bold}https://support.newrelic.com${rmso}
and report the above error. We have also created a tar file with
log files and other system info that can help solve the problem.
If the file $logtar exists please attach it to your bug report.
Expand Down Expand Up @@ -742,7 +742,7 @@ accompany each PHP install. Sometimes, these require that you install
the "dev" package for PHP or the "cli" version. We need one or the
other.
Please visit ${bold}http://newrelic.com/docs/php${rmso} and review the
Please visit ${bold}https://newrelic.com/docs/php${rmso} and review the
installation documentation for ways in which you can customize this
script to look for PHP in non-standard locations or to do a manual
install.
Expand Down Expand Up @@ -1832,8 +1832,8 @@ EOF
The New Relic Proxy Daemon is installed, but the agent
is not. Please point your favorite web browser at
${bold}http://newrelic.com/docs/php${rmso} for how to install the agent
by hand.
${bold}https://docs.newrelic.com/docs/apm/agents/php-agent/installation/php-agent-installation-overview/${rmso}
for how to install the agent by hand.
EOF
fi
Expand All @@ -1860,7 +1860,7 @@ EOF
2. Restart your web server. This will fix most reporting issues and
load the agent's new features and bug fixes.
If you have questions or comments, go to http://support.newrelic.com.
If you have questions or comments, go to https://support.newrelic.com.
EOF
fi
Expand Down Expand Up @@ -1991,7 +1991,7 @@ distribution. All existing configuration files that were modified
have been left in place. If you wish to permanently remove ${bold}New
Relic${rmso}, you may wish to invoke this script with the 'purge'
option to completely remove ${bold}New Relic${rmso}. If so, please take
a moment to mail ${bold}http://support.newrelic.com${rmso} telling us
a moment to mail ${bold}https://support.newrelic.com${rmso} telling us
why you are leaving us and what we can do to help you or improve your
experience. Thank you in advance.
Expand Down Expand Up @@ -2021,7 +2021,7 @@ do_purge() {
We are sorry to see you go! If there is anything we can do
to improve your experience with the product, please mail
${bold}http://support.newrelic.com${rmso} and we will do our very best
${bold}https://support.newrelic.com${rmso} and we will do our very best
to help you or to improve the product to meet your expectations. Thank
you in advance. -- The ${bold}New Relic${rmso} ${agent} Team
Expand Down
10 changes: 5 additions & 5 deletions agent/php_execute.c
Original file line number Diff line number Diff line change
Expand Up @@ -124,11 +124,11 @@ typedef void (*nr_library_enable_fn_t)(TSRMLS_D);
avail = avail - 3; \
}

static int nr_format_zval_for_debug(zval* arg,
char* pbuf,
size_t pos,
size_t avail,
size_t depth TSRMLS_DC) {
int nr_format_zval_for_debug(zval* arg,
char* pbuf,
size_t pos,
size_t avail,
size_t depth TSRMLS_DC) {
nr_string_len_t len;
nr_string_len_t i;
char* str;
Expand Down
8 changes: 8 additions & 0 deletions agent/php_newrelic.h
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,14 @@ nrinistr_t browser_monitoring_loader; /* newrelic.browser_monitoring.loader */

nrinibool_t drupal_modules; /* newrelic.framework.drupal.modules */
nrinibool_t wordpress_hooks; /* newrelic.framework.wordpress.hooks */
nrinistr_t
wordpress_hooks_options; /* newrelic.framework.wordpress.hooks.options */
nrinitime_t wordpress_hooks_threshold; /* newrelic.framework.wordpress.hooks.threshold
*/
bool wordpress_plugins; /* set based on
newrelic.framework.wordpress.hooks.options */
bool wordpress_core; /* set based on
newrelic.framework.wordpress.hooks.options */
nrinistr_t
wordpress_hooks_skip_filename; /* newrelic.framework.wordpress.hooks_skip_filename
*/
Expand Down
50 changes: 50 additions & 0 deletions agent/php_nrini.c
Original file line number Diff line number Diff line change
Expand Up @@ -1891,6 +1891,40 @@ static PHP_INI_MH(nr_custom_events_max_samples_stored_mh) {
return SUCCESS;
}

#define DEFAULT_WORDPRESS_HOOKS_OPTIONS "all_callbacks"
static PHP_INI_MH(nr_wordpress_hooks_options_mh) {
nrinistr_t* p;

char* base = (char*)mh_arg2;

p = (nrinistr_t*)(base + (size_t)mh_arg1);

(void)mh_arg3;
NR_UNUSED_TSRMLS;

if (0 == nr_strcmp(NEW_VALUE, "all_callbacks")) {
NRPRG(wordpress_plugins) = true;
NRPRG(wordpress_core) = true;
} else if (0 == nr_strcmp(NEW_VALUE, "plugin_callbacks")) {
NRPRG(wordpress_plugins) = true;
NRPRG(wordpress_core) = false;
} else if (0 == nr_strcmp(NEW_VALUE, "threshold")) {
NRPRG(wordpress_plugins) = false;
NRPRG(wordpress_core) = false;
} 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->value = NEW_VALUE;
p->where = stage;

return SUCCESS;
}

/*
* Now for the actual INI entry table. Please note there are two types of INI
* entry specification used.
Expand Down Expand Up @@ -2206,6 +2240,22 @@ STD_PHP_INI_ENTRY_EX("newrelic.framework.wordpress.hooks",
zend_newrelic_globals,
newrelic_globals,
nr_on_off_dh)
STD_PHP_INI_ENTRY_EX("newrelic.framework.wordpress.hooks.options",
DEFAULT_WORDPRESS_HOOKS_OPTIONS,
NR_PHP_REQUEST,
nr_wordpress_hooks_options_mh,
wordpress_hooks_options,
zend_newrelic_globals,
newrelic_globals,
0)
STD_PHP_INI_ENTRY_EX("newrelic.framework.wordpress.hooks.threshold",
"1ms",
NR_PHP_REQUEST,
nr_time_mh,
wordpress_hooks_threshold,
zend_newrelic_globals,
newrelic_globals,
0)
STD_PHP_INI_ENTRY_EX("newrelic.framework.wordpress.hooks_skip_filename",
"",
NR_PHP_REQUEST,
Expand Down
Loading

0 comments on commit 320ea57

Please sign in to comment.