Skip to content

Commit aae7611

Browse files
fix(agent): fix Drupal error and exception handling (#995)
Co-authored-by: Michal Nowacki <[email protected]>
1 parent c9c5992 commit aae7611

File tree

1 file changed

+77
-0
lines changed

1 file changed

+77
-0
lines changed

agent/fw_drupal8.c

Lines changed: 77 additions & 0 deletions
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.

0 commit comments

Comments
 (0)