Skip to content

Commit 5b320e8

Browse files
authored
Merge pull request #1007 from newrelic/dev
Release 11.5
2 parents eab6b4b + 8a73dde commit 5b320e8

File tree

183 files changed

+8839
-366
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

183 files changed

+8839
-366
lines changed

.github/workflows/code-coverage-baseline.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ jobs:
6969
matrix:
7070
platform: [gnu, musl]
7171
arch: [amd64]
72-
php: ['7.2', '7.3', '7.4', '8.0', '8.1', '8.2', '8.3']
72+
php: ['7.2', '7.3', '7.4', '8.0', '8.1', '8.2', '8.3', '8.4']
7373
include:
7474
- codecov: 0
7575
- platform: gnu
@@ -147,7 +147,7 @@ jobs:
147147
matrix:
148148
platform: [gnu, musl]
149149
arch: [amd64]
150-
php: ['7.2', '7.3', '7.4', '8.0', '8.1', '8.2', '8.3']
150+
php: ['7.2', '7.3', '7.4', '8.0', '8.1', '8.2', '8.3', '8.4']
151151
include:
152152
- codecov: 0
153153
- platform: gnu

.github/workflows/codeql.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ jobs:
1616
# - https://gh.io/supported-runners-and-hardware-resources
1717
# - https://gh.io/using-larger-runners
1818
# Consider using larger runners for possible analysis time improvements.
19-
runs-on: 'ubuntu-latest'
19+
runs-on: 'ubuntu-22.04'
2020
timeout-minutes: 360
2121
permissions:
2222
# required for all workflows

.github/workflows/make-agent.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ jobs:
3232
strategy:
3333
matrix:
3434
platform: [gnu, musl]
35-
php: ['8.0', '8.1', '8.2', '8.3']
35+
php: ['8.0', '8.1', '8.2', '8.3', '8.4']
3636
steps:
3737
- name: Checkout Repo
3838
uses: actions/checkout@v4

.github/workflows/make-integration-tests.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ jobs:
3434
fail-fast: true
3535
matrix:
3636
platform: [gnu, musl]
37-
php: ['8.0', '8.1', '8.2', '8.3']
37+
php: ['8.0', '8.1', '8.2', '8.3', '8.4']
3838
steps:
3939
- name: Checkout integration tests
4040
uses: actions/checkout@v4

.github/workflows/security-scan.yml

+1
Original file line numberDiff line numberDiff line change
@@ -45,4 +45,5 @@ jobs:
4545
if: ${{ github.event_name == 'schedule' }}
4646
uses: github/codeql-action/upload-sarif@v3
4747
with:
48+
checkout_path: ./php-agent
4849
sarif_file: trivy-results.sarif

.github/workflows/test-agent.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ jobs:
9797
matrix:
9898
platform: [gnu, musl]
9999
arch: [amd64, arm64]
100-
php: ['7.2', '7.3', '7.4', '8.0', '8.1', '8.2', '8.3']
100+
php: ['7.2', '7.3', '7.4', '8.0', '8.1', '8.2', '8.3', '8.4']
101101
exclude:
102102
- arch: arm64
103103
php: '7.2'
@@ -203,7 +203,7 @@ jobs:
203203
matrix:
204204
platform: [gnu, musl]
205205
arch: [amd64, arm64]
206-
php: ['7.2', '7.3', '7.4', '8.0', '8.1', '8.2', '8.3']
206+
php: ['7.2', '7.3', '7.4', '8.0', '8.1', '8.2', '8.3', '8.4']
207207
exclude:
208208
- arch: arm64
209209
php: '7.2'

VERSION

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
11.4.0
1+
11.5.0

agent/config.m4

+4-1
Original file line numberDiff line numberDiff line change
@@ -232,13 +232,16 @@ if test "$PHP_NEWRELIC" = "yes"; then
232232
lib_guzzle4.c lib_guzzle6.c lib_guzzle_common.c \
233233
lib_mongodb.c lib_phpunit.c lib_predis.c lib_zend_http.c \
234234
lib_composer.c"
235-
PHP_NEW_EXTENSION(newrelic, $FRAMEWORKS $LIBRARIES $NEWRELIC_AGENT, $ext_shared,, \\$(NEWRELIC_CFLAGS))
235+
PHP_NEW_EXTENSION(newrelic, $FRAMEWORKS $LIBRARIES $NEWRELIC_AGENT, $ext_shared,, $(NEWRELIC_CFLAGS))
236236

237237
PHP_SUBST(NEWRELIC_CFLAGS)
238238

239239
dnl Define $(PHP_CONFIG) so we can call it when building tests.
240240
PHP_SUBST(PHP_CONFIG)
241241

242+
dnl Make sure we include the source directory in the include search path.
243+
PHP_ADD_INCLUDE([$abs_srcdir], [1])
244+
242245
dnl Include the Makefile.frag, which we use to handle build time
243246
dnl dependencies.
244247
PHP_ADD_MAKEFILE_FRAGMENT

agent/fw_drupal8.c

+77
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include "php_user_instrument.h"
1010
#include "php_execute.h"
1111
#include "php_wrapper.h"
12+
#include "php_error.h"
1213
#include "fw_drupal_common.h"
1314
#include "fw_hooks.h"
1415
#include "fw_support.h"
@@ -20,6 +21,62 @@
2021

2122
#define PHP_PACKAGE_NAME "drupal/core"
2223

24+
NR_PHP_WRAPPER(nr_drupal_exception) {
25+
int priority = nr_php_error_get_priority(E_ERROR);
26+
zval* event = NULL;
27+
zval* exception = NULL;
28+
29+
/* Warning avoidance */
30+
(void)wraprec;
31+
32+
NR_PHP_WRAPPER_REQUIRE_FRAMEWORK(NR_FW_DRUPAL8);
33+
34+
if (NR_SUCCESS != nr_txn_record_error_worthy(NRPRG(txn), priority)) {
35+
NR_PHP_WRAPPER_CALL;
36+
goto end;
37+
}
38+
39+
/* Get the event that was given. */
40+
event = nr_php_arg_get(1, NR_EXECUTE_ORIG_ARGS);
41+
42+
/* Call the original function. */
43+
NR_PHP_WRAPPER_CALL;
44+
45+
if (0 == nr_php_is_zval_valid_object(event)) {
46+
nrl_verbosedebug(NRL_TXN,
47+
"Drupal: ExceptionSubscriber::onException() does not "
48+
"have an `event` parameter");
49+
goto end;
50+
}
51+
52+
/*
53+
* Get the exception from the event.
54+
*/
55+
exception = nr_php_call(event, "getThrowable");
56+
if (!nr_php_is_zval_valid_object(exception)) {
57+
// be abundantly cautious: free exception before attempting to re-assign
58+
nr_php_zval_free(&exception);
59+
exception = nr_php_call(event, "getException");
60+
}
61+
62+
if (!nr_php_is_zval_valid_object(exception)) {
63+
nrl_verbosedebug(NRL_TXN, "Drupal: getException() returned a non-object");
64+
goto end;
65+
}
66+
67+
if (NR_SUCCESS
68+
!= nr_php_error_record_exception(NRPRG(txn), exception, priority, true,
69+
NULL,
70+
&NRPRG(exception_filters))) {
71+
nrl_verbosedebug(NRL_TXN, "Drupal: unable to record exception");
72+
}
73+
74+
end:
75+
nr_php_arg_release(&event);
76+
nr_php_zval_free(&exception);
77+
}
78+
NR_PHP_WRAPPER_END
79+
2380
/*
2481
* Purpose : Convenience function to handle adding a callback to a method,
2582
* given a class entry and a method name. This will check the
@@ -730,6 +787,26 @@ void nr_drupal8_enable(TSRMLS_D) {
730787
"er::getControllerFromDefinition"),
731788
nr_drupal8_name_the_wt TSRMLS_CC);
732789

790+
/*
791+
* ExceptionSubscribers handle Drupal errors and exceptions before
792+
* the agent has the opportunity to capture them. Instrument several
793+
* of these ExceptionSubscriber function `onException` methods in order
794+
* to capture Exceptions and Errors in Drupal 9.x+
795+
*/
796+
// clang-format off
797+
/*
798+
* Log exceptions without further handling.
799+
*/
800+
nr_php_wrap_user_function(NR_PSTR("Drupal\\Core\\EventSubscriber\\ExceptionLoggingSubscriber::onException"),
801+
nr_drupal_exception);
802+
803+
/*
804+
* Last-chance handler for exceptions: the final exception subscriber.
805+
*/
806+
nr_php_wrap_user_function(NR_PSTR("Drupal\\Core\\EventSubscriber\\FinalExceptionSubscriber::onException"),
807+
nr_drupal_exception);
808+
// clang-format on
809+
733810
/*
734811
* The drupal_modules config setting controls instrumentation of modules,
735812
* hooks, and views.

agent/lib_aws_sdk_php.c

+43-57
Original file line numberDiff line numberDiff line change
@@ -22,49 +22,40 @@
2222
* In a normal course of events, the following line will always work
2323
* zend_eval_string("Aws\\Sdk::VERSION;", &retval, "Get AWS Version")
2424
* By the time we have detected the existence of the aws-sdk-php and with
25-
* default composer profject settings, it callable even from
25+
* default composer project settings, it is callable even from
2626
* nr_aws_sdk_php_enable which will automatically load the class if it isn't
27-
* loaded yet and then evaluate the string. However, in the rare case that files
27+
* loaded yet and then evaluate the string. In the rare case that files
2828
* are not loaded via autoloader and/or have non-default composer classload
29-
* settings, if the class is not found, PHP 8.2+ will generate a fatal
30-
* unrecoverable uncatchable error error whenever it cannot find a class. While
31-
* calling this from nr_aws_sdk_php_enable would have been great and would allow
32-
* the sdk version value to be set only once, to avoid the very unlikely but not
33-
* impossible fatal error, this will be called from the
34-
* "Aws\\ClientResolver::_apply_user_agent" wrapper which GUARANTEES that
35-
* aws/sdk exists and is already loaded.
36-
*
37-
*
38-
* Additionally given that aws-sdk-php is currently detected from the
39-
* AwsClient.php file, this method will always be called when a client is
40-
* created unlike Sdk::construct which doesn't show with PHP 8.2+.
41-
*
42-
* Using Aws/Sdk::__construct for version is currently nonviable as it is
43-
* unreliable as a version determiner.
44-
* Having separate functionality to extract from Aws/Sdk::__construct
45-
* is both not required and is redundant and causes additional overhead and
46-
* so only one function is needed to extract version.
47-
*
48-
* Aws\\ClientResolver::_apply_user_agent a reliable function as it is
49-
* always called on client initialization since it is key to populating
50-
* the request headers, and it loads Sdk by default.
51-
*
52-
* Concerns about future/past proofing to the checking prioritized the following
53-
* implementation vs using the eval method.
29+
* settings, if the class is not found, PHP 8.2+ will generate an
30+
* error whenever it cannot find a class which must be caught. Calling this
31+
* from nr_aws_sdk_php_enable would allow the sdk version value to be set only
32+
* once. To avoid the VERY unlikely but not impossible fatal error, we need to
33+
* wrap the call in a try/catch block and make it a lambda so that we avoid
34+
* fatal errors.
5435
*/
5536
void nr_lib_aws_sdk_php_handle_version() {
56-
zval* zval_version = NULL;
57-
zend_class_entry* class_entry = NULL;
5837
char* version = NULL;
59-
60-
class_entry = nr_php_find_class("aws\\sdk");
61-
if (NULL != class_entry) {
62-
zval_version = nr_php_get_class_constant(class_entry, "VERSION");
63-
64-
if (nr_php_is_zval_non_empty_string(zval_version)) {
65-
version = Z_STRVAL_P(zval_version);
38+
zval retval;
39+
int result = FAILURE;
40+
41+
result = zend_eval_string(
42+
"(function() {"
43+
" $nr_aws_sdk_version = '';"
44+
" try {"
45+
" $nr_aws_sdk_version = Aws\\Sdk::VERSION;"
46+
" } catch (Throwable $e) {"
47+
" }"
48+
" return $nr_aws_sdk_version;"
49+
"})();",
50+
&retval, "Get nr_aws_sdk_version");
51+
52+
/* See if we got a non-empty/non-null string for version. */
53+
if (SUCCESS == result) {
54+
if (nr_php_is_zval_non_empty_string(&retval)) {
55+
version = Z_STRVAL(retval);
6656
}
6757
}
58+
6859
if (NRINI(vulnerability_management_package_detection_enabled)) {
6960
/* Add php package to transaction */
7061
nr_txn_add_php_package(NRPRG(txn), PHP_PACKAGE_NAME, version);
@@ -73,7 +64,7 @@ void nr_lib_aws_sdk_php_handle_version() {
7364
nr_txn_suggest_package_supportability_metric(NRPRG(txn), PHP_PACKAGE_NAME,
7465
version);
7566

76-
nr_php_zval_free(&zval_version);
67+
zval_dtor(&retval);
7768
}
7869

7970
void nr_lib_aws_sdk_php_add_supportability_service_metric(
@@ -96,13 +87,6 @@ void nr_lib_aws_sdk_php_add_supportability_service_metric(
9687
nrm_force_add(NRPRG(txn) ? NRTXN(unscoped_metrics) : 0, buf, 0);
9788
}
9889

99-
NR_PHP_WRAPPER(nr_create_aws_sdk_version_metrics) {
100-
(void)wraprec;
101-
NR_PHP_WRAPPER_CALL;
102-
nr_lib_aws_sdk_php_handle_version();
103-
}
104-
NR_PHP_WRAPPER_END
105-
10690
/*
10791
* AwsClient::parseClass
10892
* This is called from the base AwsClient class for every client associated
@@ -144,7 +128,7 @@ NR_PHP_WRAPPER_END
144128
* optimizable library. Small overhead incurred when encountering an autoload
145129
* file, but detects aws-sdk-php immediately before any sdk code executes
146130
* (changes needed for this are detailed in the original PR)
147-
* 2. use a file that gets called later and only when AwsClient.php file file is
131+
* 2. use a file that gets called later and only when AwsClient.php file is
148132
* called. It's called later and we'll miss some instrumentation, but if we're
149133
* only ever going to be interested in Client calls anyway, maybe that's ok?
150134
* Doesn't detect Sdk.php (optimized out) so when customers only use that or
@@ -158,22 +142,24 @@ NR_PHP_WRAPPER_END
158142
* to wrap, this will add overhead to every hash map lookup. Currently
159143
* implemented option is 2, use the AwsClient.php as this is our main focus.
160144
* This means until a call to an Aws/AwsClient function,
161-
* all calls including aws\sdk calls are ignored. Version detection will be
162-
* tied to Aws/ClientResolver::_apply_user_agent which is ALWAYS called when
163-
* dealing with aws clients. It will not be computed from
164-
* Aws/Sdk::__constructor which would at best be duplicate info and worst would
165-
* never be ignored until a client is called.
145+
* all calls including aws\sdk calls are ignored.
146+
*
147+
* Version detection will be called directly from Aws\Sdk.php
166148
*/
167149
void nr_aws_sdk_php_enable() {
168-
/* This will be used to extract the version. */
169-
nr_php_wrap_user_function(NR_PSTR("Aws\\ClientResolver::_apply_user_agent"),
170-
nr_create_aws_sdk_version_metrics);
171-
/* Called when initializing all other Clients */
172-
nr_php_wrap_user_function(NR_PSTR("Aws\\AwsClient::parseClass"),
173-
nr_create_aws_service_metric);
174-
150+
/*
151+
* Set the UNKNOWN package first, so it doesn't overwrite what we find with
152+
* nr_lib_aws_sdk_php_handle_version.
153+
*/
175154
if (NRINI(vulnerability_management_package_detection_enabled)) {
176155
nr_txn_add_php_package(NRPRG(txn), PHP_PACKAGE_NAME,
177156
PHP_PACKAGE_VERSION_UNKNOWN);
178157
}
158+
159+
/* Extract the version for aws-sdk 3+ */
160+
nr_lib_aws_sdk_php_handle_version();
161+
162+
/* Called when initializing all Clients */
163+
nr_php_wrap_user_function(NR_PSTR("Aws\\AwsClient::parseClass"),
164+
nr_create_aws_service_metric);
179165
}

agent/newrelic-install.sh

+12-3
Original file line numberDiff line numberDiff line change
@@ -335,10 +335,10 @@ for pmv in "20170718" "20180731" "20190902"; do
335335
done
336336
fi
337337
# Currently supported versions:
338-
# (8.0, 8.1, 8.2, 8.3)
338+
# (8.0, 8.1, 8.2, 8.3, 8.4)
339339
# for x64 and aarch64
340340
if [ ${arch} = x64 ] || [ ${arch} = aarch64 ]; then
341-
for pmv in "20200930" "20210902" "20220829" "20230831"; do
341+
for pmv in "20200930" "20210902" "20220829" "20230831" "20240924"; do
342342
check_file "${ilibdir}/agent/${arch}/newrelic-${pmv}.so"
343343
done
344344
fi
@@ -542,6 +542,7 @@ add_to_path /usr/local/php-8.0/bin
542542
add_to_path /usr/local/php-8.1/bin
543543
add_to_path /usr/local/php-8.2/bin
544544
add_to_path /usr/local/php-8.3/bin
545+
add_to_path /usr/local/php-8.4/bin
545546

546547
add_to_path /opt/local/bin
547548
add_to_path /usr/php/bin
@@ -553,6 +554,7 @@ add_to_path /usr/php-8.0/bin
553554
add_to_path /usr/php-8.1/bin
554555
add_to_path /usr/php-8.2/bin
555556
add_to_path /usr/php-8.3/bin
557+
add_to_path /usr/php-8.4/bin
556558

557559
add_to_path /usr/php/7.2/bin
558560
add_to_path /usr/php/7.3/bin
@@ -561,6 +563,7 @@ add_to_path /usr/php/8.0/bin
561563
add_to_path /usr/php/8.1/bin
562564
add_to_path /usr/php/8.2/bin
563565
add_to_path /usr/php/8.3/bin
566+
add_to_path /usr/php/8.4/bin
564567

565568
add_to_path /opt/php/bin
566569
add_to_path /opt/zend/bin
@@ -572,6 +575,7 @@ add_to_path /opt/php-8.0/bin
572575
add_to_path /opt/php-8.1/bin
573576
add_to_path /opt/php-8.2/bin
574577
add_to_path /opt/php-8.3/bin
578+
add_to_path /opt/php-8.4/bin
575579

576580
if [ -n "${NR_INSTALL_PATH}" ]; then
577581
oIFS="${IFS}"
@@ -1052,7 +1056,11 @@ for this copy of PHP. We apologize for the inconvenience.
10521056

10531057
8.3.*)
10541058
pi_php8="yes"
1055-
;;
1059+
;;
1060+
1061+
8.4.*)
1062+
pi_php8="yes"
1063+
;;
10561064

10571065
*)
10581066
error "unsupported version '${pi_ver}' of PHP found at:
@@ -1232,6 +1240,7 @@ does not exist. This particular instance of PHP will be skipped.
12321240
8.1.*) pi_modver="20210902" ;;
12331241
8.2.*) pi_modver="20220829" ;;
12341242
8.3.*) pi_modver="20230831" ;;
1243+
8.4.*) pi_modver="20240924" ;;
12351244
esac
12361245
log "${pdir}: pi_modver=${pi_modver}"
12371246

0 commit comments

Comments
 (0)