Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(agent): use Observer API to hook into Zend Engine for PHPs 8.0+ #542

Merged
merged 68 commits into from
Mar 1, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
68 commits
Select commit Hold shift + click to select a range
fa73a84
chore: Update branches that the GHA PR runner monitors. (#509)
zsistla Aug 24, 2022
a3c4cb5
feat(agent): Registered function begin/end and error handlers with Ob…
zsistla Sep 12, 2022
73d2816
feat(agent): Add/Update functions to utilize the OAPI zend_execute_da…
zsistla Oct 3, 2022
5365878
feat(agent): Propagate OAPI return values and update return value fun…
zsistla Oct 6, 2022
2871e2f
feat(agent): update nr_get_zend_execute_data to only use OAPI provide…
zsistla Oct 6, 2022
ecd977c
feat(agent): Add code level metrics functionality. (#506)
zsistla Oct 7, 2022
6d632da
feat(agent): user instrumentation via PHP's OAPI (#551)
zsistla Oct 13, 2022
e74dfc0
feat(agent): implement php_execute_show functionality for OAPI (#555)
bduranleau-nr Oct 20, 2022
8db0cab
fix(agent): detect framework in oapi's fcall_begin (#554)
lavarou Oct 25, 2022
4c732d9
tests(integration): update generator tests for oapi (#562)
bduranleau-nr Oct 25, 2022
363983d
fix(agent): fix check for max strlen when generating clm attributes (…
bduranleau-nr Oct 31, 2022
5896966
fix(agent): instrument `drupal_http_request` (#552)
lavarou Nov 1, 2022
4893277
feat(agent): OAPI exception handling (#580)
zsistla Jan 20, 2023
c7d4dfc
Merge remote-tracking branch 'origin/dev' into oapi
zsistla Jan 20, 2023
8764ea6
fix(agent): move globals that utilized the call stack into a global s…
ZNeumann Jan 26, 2023
0051e67
feat(agent): Remove php_vm.c overwriting opcodes when using OAPI (#559)
ZNeumann Jan 26, 2023
4ea50b6
fix(agent): Ensure txn exists before we try to reference it. (#600)
zsistla Jan 26, 2023
947f42a
fix(wordpress): fix unbound memory allocation when wordpress tags off…
ZNeumann Jan 27, 2023
7648b1a
fix(agent): Explicitly call some special function instrumentation in …
zsistla Feb 16, 2023
295ab5d
Merge remote-tracking branch 'origin/dev' into oapi
zsistla Feb 28, 2023
c974a2e
Merge remote-tracking branch 'origin/dev' into oapi
zsistla Mar 9, 2023
f3c38a3
test(agent): Fix tests to CLM on (#637)
mfulb Mar 10, 2023
4209f55
chore(install): Disable ZTS installs (#636)
mfulb Mar 10, 2023
cd99428
Revert "chore(install): Disable ZTS installs" (#662)
lavarou Apr 28, 2023
712396c
Merge remote-tracking branch 'origin/dev' into oapi
zsistla Jul 19, 2023
21a383b
tests: 'enhance' logging libraries mocks (#699)
lavarou Jul 26, 2023
447daab
tests: fix predis/test_pipeline expectation (#704)
lavarou Aug 1, 2023
fdb79fd
suppress `Invalid read` error in test_redis (#707)
lavarou Aug 8, 2023
33fed1d
fix(agent): set oapi callbacks the right way (#700)
ZNeumann Aug 8, 2023
6846ba4
feat(agent): instrument Drupal 9.4 hooks with oapi (#701)
ZNeumann Aug 9, 2023
dca53bd
fix: add guards to oapi cufa opcode check (#708)
ZNeumann Aug 9, 2023
1e7c861
fix(agent): wrap zend_try in a func to avoid clobbering (#703)
ZNeumann Aug 9, 2023
7d0a768
tests: 'enhance' laravel framework mock (#716)
lavarou Aug 21, 2023
8e683b1
Merge remote-tracking branch 'origin/dev' into oapi
zsistla Aug 22, 2023
f582376
tests: fix metrics expectation in drupal tests (#726)
lavarou Sep 6, 2023
7b142fc
refactor(agent): improve phpunit instrumentation (#725)
lavarou Sep 6, 2023
fae2aed
Merge branch 'dev' into oapi
zsistla Sep 8, 2023
f9fa14a
feat: optimize oapi cufa detection (#729)
ZNeumann Sep 21, 2023
54a23d4
feat: optional instrumentated function metric (#730)
ZNeumann Sep 21, 2023
b6c47aa
feat: redo wordpress hooks instrumentation for OAPI (#731)
ZNeumann Sep 21, 2023
4e791b7
Merge branch 'dev' (release 10.12) into oapi
lavarou Sep 22, 2023
3eb2abe
fix(agent): fix wrapping transient user functions (#735)
ZNeumann Sep 29, 2023
7b349f5
Merge branch 'dev' (release 10.13) into oapi
lavarou Sep 29, 2023
2b9e3b4
add new metric to oapi integration tests
lavarou Sep 29, 2023
8bcd5ca
tests(agent): Add tests that specifically exercise JIT. (#715)
zsistla Oct 22, 2023
a0783d4
tests: fix user exception and error handler implementation (#748)
lavarou Oct 23, 2023
58662eb
fix(agent): Correctly handle laravel queues (#746)
zsistla Nov 13, 2023
069310b
Merge branch 'dev' (release 10.14+tests) into oapi
lavarou Nov 21, 2023
55d781c
Merge branch 'dev' (release 10.15) into oapi
lavarou Dec 22, 2023
b4e3e5f
fixup! 24c1c656540a742d9d0466b79d33808ca2507ed7
lavarou Dec 22, 2023
bdb1174
fixup! 0150c096dc959dad60f820defb95d031d692aef9
lavarou Dec 21, 2023
99bd0ef
tests: remove broken exception handling unit tests (#817)
bduranleau-nr Jan 25, 2024
93e5a54
Merge branch 'dev' (release 10.16) into oapi
lavarou Jan 31, 2024
bfc5ac2
fixup! 43590ae2dfe0a86ca12d699e4406ad9d831d04bb
lavarou Jan 25, 2024
5035298
fixup! 43590ae2dfe0a86ca12d699e4406ad9d831d04bb
lavarou Jan 25, 2024
a20529b
fixup! 0fa3083c32c65abf8d48b28f76e96ee17679440a
lavarou Jan 29, 2024
e99f7cb
fixup! ac78511ede0e96d59610b798b6a41b53a202364b
lavarou Jan 29, 2024
53d10e0
fixup! 43590ae2dfe0a86ca12d699e4406ad9d831d04bb
lavarou Jan 29, 2024
4da1211
fix(agent): revert zend_try/catch php call logic (#811)
bduranleau-nr Jan 31, 2024
5640be3
feat(oapi): rework exception handling (#767)
ZNeumann Feb 2, 2024
49a6c1a
refactor: condense exception handling instrumentation (#825)
ZNeumann Feb 5, 2024
26648fe
feat(oapi): use segment pool instead of stacked segments (#776)
ZNeumann Feb 6, 2024
5d7ee9b
fix: correctly instrument WebdisConnection executeCommand in OAPI (#779)
ZNeumann Feb 6, 2024
958d859
feat: faster segment de-parenting via index tracking (#801)
ZNeumann Feb 8, 2024
55d3904
feat(tests): Enable opcache by default for the integration runner. (#…
zsistla Feb 22, 2024
b38f940
Merge branch 'dev' (release 10.17) into oapi
lavarou Feb 23, 2024
180bf59
fixup! e11b992cda2bad691bc651e28b0184ea720cdc04
lavarou Feb 23, 2024
4086b6b
fix(agent): fix Lumen detection (#838)
lavarou Feb 27, 2024
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
Prev Previous commit
Next Next commit
feat(oapi): rework exception handling (#767)
Removing the need to manual handling of dangling segments, because Zend
calls all of the hooks we need.

- adds a boolean argument to nr_php_error_record_exception to control
whether we add the error to the current segment. This is needed because
the OAPI context of when the above is called is no longer during a
segment with an uncaught exception and was incorrectly adding the error
to the root segment.
- removes all language of "dangling segments". These no longer exist.
Zend calls all of the necessary `fcall_end`'s, even when an exception is
thrown. When this happens,` func_return_value` is a C `NULL` pointer
which is distinct from a `NULL` (but valid) zval when there is no return
value from a function. We use this `NULL` value to determine the
presence of an uncaught exception.
- no longer overwrites the exception hook; no longer stores a copy of
exceptions locally
- replace storing metadata in the segment, which was used to pair
segments from func_begin with func_end, with logic that always creates
segment in func_begin

Mostly undoes the work of
#580

---------

Co-authored-by: Michal Nowacki <mnowacki@newrelic.com>
Co-authored-by: bduranleau-nr <106178551+bduranleau-nr@users.noreply.github.com>
Co-authored-by: Amber Sistla <asistla@newrelic.com>
  • Loading branch information
4 people authored Feb 2, 2024
commit 5640be38fdc8693efb0214029b3df0f418ea234b
1 change: 1 addition & 0 deletions agent/fw_laravel.c
Original file line number Diff line number Diff line change
Expand Up @@ -619,6 +619,7 @@ NR_PHP_WRAPPER(nr_laravel5_exception_report) {
nr_status_t st;

st = nr_php_error_record_exception(NRPRG(txn), exception, priority,
true /* add to segment */,
NULL /* use default prefix */,
&NRPRG(exception_filters) TSRMLS_CC);

Expand Down
2 changes: 1 addition & 1 deletion agent/fw_laravel_queue.c
Original file line number Diff line number Diff line change
Expand Up @@ -642,7 +642,7 @@ NR_PHP_WRAPPER(nr_laravel_queue_worker_process) {

nr_php_error_record_exception(
NRPRG(txn), exception_zval, NR_PHP_ERROR_PRIORITY_UNCAUGHT_EXCEPTION,
"Unhandled exception within Laravel Queue job: ",
true, "Unhandled exception within Laravel Queue job: ",
&NRPRG(exception_filters) TSRMLS_CC);
}

Expand Down
1 change: 1 addition & 0 deletions agent/fw_lumen.c
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,7 @@ NR_PHP_WRAPPER(nr_lumen_exception) {
int priority = nr_php_error_get_priority(E_ERROR);

st = nr_php_error_record_exception(NRPRG(txn), exception, priority,
true /* add to segment */,
NULL /* use default prefix */,
&NRPRG(exception_filters) TSRMLS_CC);

Expand Down
2 changes: 1 addition & 1 deletion agent/fw_symfony4.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ NR_PHP_WRAPPER(nr_symfony4_exception) {
}

if (NR_SUCCESS
!= nr_php_error_record_exception(NRPRG(txn), exception, priority, NULL,
!= nr_php_error_record_exception(NRPRG(txn), exception, priority, true, NULL,
&NRPRG(exception_filters) TSRMLS_CC)) {
nrl_verbosedebug(NRL_TXN, "Symfony 4: unable to record exception");
}
Expand Down
36 changes: 0 additions & 36 deletions agent/php_agent.h
Original file line number Diff line number Diff line change
Expand Up @@ -776,42 +776,6 @@ nr_php_ini_entry_name_length(const zend_ini_entry* entry) {
#define ZVAL_OR_ZEND_OBJECT(x) x
#endif /* PHP8+ */

/*
* Purpose : Ensure all dangling segments caused by an OAPI exception are closed
* before having an API act on the calling segment.
*
* Params :
*
* Returns :
*/
static inline void nr_php_api_ensure_current_segment() {
#if ZEND_MODULE_API_NO >= ZEND_8_0_X_API_NO \
&& !defined OVERWRITE_ZEND_EXECUTE_DATA
/*
* Before we call an API that depends on current segment, we need to ensure
* there isn't an outstanding uncaught exception that needs to be applied to
* dangling segments. If so, we need to apply the exception and close the
* stacked segments until we get to the segment that called the API. To do
* this, we detect the execute_data that called the API which is guaranteed to
* be what the current segment should be (otherwise, fcall_end would have
* closed normal segments and we would have taken care of any dangling
* segments already) and any segments stacked above it need to be closed due
* to an exception.
*/

/*
* Get the function that called the API. prev_execute_data
* should never be null, but doublecheck for it anyway.
*/
if (NULL != EG(current_execute_data)->prev_execute_data) {
zval* prev_this = &EG(current_execute_data)->prev_execute_data->This;

nr_php_observer_handle_uncaught_exception(prev_this);
}

#endif
}

/*
* Purpose : Wrap the native PHP json_decode function for those times when we
* need a more robust JSON decoder than nro_create_from_json.
Expand Down
13 changes: 2 additions & 11 deletions agent/php_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,6 @@ PHP_FUNCTION(newrelic_notice_error) {
priority = nr_php_error_get_priority(E_ERROR);
}

nr_php_api_ensure_current_segment();

if (NR_SUCCESS != nr_txn_record_error_worthy(NRPRG(txn), priority)) {
nrl_debug(NRL_API,
"newrelic_notice_error: a higher severity error has already been "
Expand Down Expand Up @@ -162,7 +160,7 @@ PHP_FUNCTION(newrelic_notice_error) {
if (exc) {
if (NR_SUCCESS
== nr_php_error_record_exception(
NRPRG(txn), exc, priority, "Noticed exception ", NULL TSRMLS_CC)) {
NRPRG(txn), exc, priority, true, "Noticed exception ", NULL TSRMLS_CC)) {
RETURN_TRUE;
} else {
nrl_debug(NRL_API, "newrelic_notice_error: invalid exception argument");
Expand All @@ -174,7 +172,7 @@ PHP_FUNCTION(newrelic_notice_error) {
char* buf = nr_strndup(errormsgstr, errormsglen);
char* stack_json = nr_php_backtrace_to_json(NULL TSRMLS_CC);

nr_txn_record_error(NRPRG(txn), priority, buf, errclass, stack_json);
nr_txn_record_error(NRPRG(txn), priority, true, buf, errclass, stack_json);

nr_free(buf);
nr_free(stack_json);
Expand Down Expand Up @@ -306,8 +304,6 @@ PHP_FUNCTION(newrelic_end_transaction) {
}
}

nr_php_api_ensure_current_segment();

ret = nr_php_txn_end((0 != ignore), 0 TSRMLS_CC);
if (NR_SUCCESS == ret) {
nrl_debug(NRL_API, "transaction completed by API");
Expand Down Expand Up @@ -744,7 +740,6 @@ PHP_FUNCTION(newrelic_add_custom_parameter) {
obj = nr_php_api_zval_to_attribute_obj(zzvalue TSRMLS_CC);

if (obj) {
nr_php_api_ensure_current_segment();
rv = nr_txn_add_user_custom_parameter(NRPRG(txn), key, obj);
}

Expand Down Expand Up @@ -1238,7 +1233,6 @@ PHP_FUNCTION(newrelic_set_user_attributes) {
RETURN_FALSE;
}

nr_php_api_ensure_current_segment();
rv = nr_php_api_add_custom_parameter_string(NRPRG(txn), "user", userstr,
userlen);
if (NR_FAILURE == rv) {
Expand Down Expand Up @@ -1266,7 +1260,6 @@ static nr_status_t nr_php_api_add_custom_span_attribute(const char* keystr,
char* key = NULL;
nr_segment_t* current;

nr_php_api_ensure_current_segment();
current = nr_txn_get_current_segment(NRPRG(txn), NULL);
if (!current) {
return NR_FAILURE;
Expand Down Expand Up @@ -1530,7 +1523,6 @@ PHP_FUNCTION(newrelic_get_linking_metadata) {
}

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

Expand Down Expand Up @@ -1573,7 +1565,6 @@ PHP_FUNCTION(newrelic_get_trace_metadata) {
}

if (nrlikely(NRPRG(txn))) {
nr_php_api_ensure_current_segment();
trace_id = nr_txn_get_current_trace_id(NRPRG(txn));
if (trace_id) {
nr_php_add_assoc_string(return_value, "trace_id", trace_id);
Expand Down
22 changes: 0 additions & 22 deletions agent/php_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,28 +7,6 @@
#ifndef PHP_API_HDR
#define PHP_API_HDR

/*
* Recommendations for API calls when using OAPI instrumentation and PHP 8+
*
* Dangling segments:
* With the use of Observer API we have the possibility of dangling segments
* that can occur due to an exception occurring. In the normal course of
* events, nr_php_observer_fcall_begin starts segments and
* nr_php_observer_fcall_end keeps/discards/ends segments. However, in the case
* of an uncaught exception, nr_php_observer_fcall_end is never called and
* therefore, the logic to keep/discard/end the segment doesn't automatically
* get initiated which can lead to dangling stacked segments.
*
* However, certain agent API calls need to be associated with particular
* segments.
*
* To handle this , dangling exception cleanup is initiated by the following
* call: nr_php_api_ensure_current_segment();
*
* ANY API call that depends on the current segment needs to use this function
* to ensure the API uses the correct segment.
*/

extern void nr_php_api_add_supportability_metric(const char* name TSRMLS_DC);

extern void nr_php_api_error(const char* format, ...) NRPRINTFMT(1);
Expand Down
1 change: 0 additions & 1 deletion agent/php_api_internal.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ PHP_FUNCTION(newrelic_get_request_metadata) {
}

array_init(return_value);
nr_php_api_ensure_current_segment();
outbound_headers = nr_header_outbound_request_create(
NRPRG(txn), nr_txn_get_current_segment(NRPRG(txn), NULL));

Expand Down
11 changes: 7 additions & 4 deletions agent/php_error.c
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,7 @@ PHP_FUNCTION(newrelic_exception_handler) {

nr_php_error_record_exception(
NRPRG(txn), exception, NR_PHP_ERROR_PRIORITY_UNCAUGHT_EXCEPTION,
"Uncaught exception ", &NRPRG(exception_filters) TSRMLS_CC);
true, "Uncaught exception ", &NRPRG(exception_filters) TSRMLS_CC);
/*
* Finally, we need to generate an E_ERROR to match what PHP would have done
* if this handler wasn't installed. Happily, PHP exposes an API function
Expand Down Expand Up @@ -603,8 +603,8 @@ void nr_php_error_cb(int type,
stack_json = nr_php_backtrace_to_json(0 TSRMLS_CC);
errclass = get_error_type_string(type);

nr_txn_record_error(NRPRG(txn), nr_php_error_get_priority(type), msg,
errclass, stack_json);
nr_txn_record_error(NRPRG(txn), nr_php_error_get_priority(type), true,
msg, errclass, stack_json);

/*
* Error Fingerprinting Callback
Expand Down Expand Up @@ -645,6 +645,7 @@ void nr_php_error_cb(int type,
nr_status_t nr_php_error_record_exception(nrtxn_t* txn,
zval* exception,
int priority,
bool add_to_current_segment,
const char* prefix,
zend_llist* filters TSRMLS_DC) {
zend_class_entry* ce;
Expand Down Expand Up @@ -715,7 +716,9 @@ nr_status_t nr_php_error_record_exception(nrtxn_t* txn,
stack_json);
}

nr_txn_record_error(NRPRG(txn), priority, error_message, klass, stack_json);
nr_txn_record_error(NRPRG(txn), priority,
add_to_current_segment,
error_message, klass, stack_json);

nr_free(error_message);
nr_free(file);
Expand Down
6 changes: 4 additions & 2 deletions agent/php_error.h
Original file line number Diff line number Diff line change
Expand Up @@ -124,9 +124,10 @@ extern void nr_php_error_install_exception_handler(TSRMLS_D);
* Params : 1. The transaction to record the error in.
* 2. The exception to record an error for.
* 3. The error priority to use.
* 4. A prefix to prepend to the error message before the class name.
* 4. Whether we want to add the error to the current segment.
* 5. A prefix to prepend to the error message before the class name.
* If NULL, then the default "Exception " will be used.
* 5. The exception filters to apply.
* 6. The exception filters to apply.
* Typically, &NRPRG (exception_filters) or NULL to disable
* exception filtering.
*
Expand All @@ -137,6 +138,7 @@ extern void nr_php_error_install_exception_handler(TSRMLS_D);
extern nr_status_t nr_php_error_record_exception(nrtxn_t* txn,
zval* exception,
int priority,
bool add_to_current_segment,
const char* prefix,
zend_llist* filters TSRMLS_DC);

Expand Down
Loading
Loading