7
7
#include "php_globals.h"
8
8
#include "php_user_instrument.h"
9
9
#include "php_user_instrument_hashmap.h"
10
+ #include "php_user_instrument_wraprec_hashmap.h"
10
11
#include "php_wrapper.h"
11
12
#include "lib_guzzle_common.h"
12
13
#include "util_logging.h"
@@ -114,7 +115,32 @@ int nr_zend_call_orig_execute_special(nruserfn_t* wraprec,
114
115
return zcaught ;
115
116
}
116
117
117
- #if ZEND_MODULE_API_NO >= ZEND_7_4_X_API_NO
118
+ #if ZEND_MODULE_API_NO >= ZEND_8_0_X_API_NO
119
+ static inline void nr_php_wraprec_lookup_set (nruserfn_t * wr ,
120
+ zend_function * zf ) {
121
+ // for situation when wraprec is added after first execution of the function
122
+ // store the wraprec in the op_array extension for the duration of the request for later lookup
123
+ // The op_array extension slot for function may not be initialized yet because it is
124
+ // initialized only on the first call made to the function in that request. This would
125
+ // mean that run_time_cache is NULL and wraprec cannot be stored yet! It will be stored
126
+ // on the first call to the function when observer is registered for that function.
127
+ if (NULL != RUN_TIME_CACHE (& zf -> op_array )) {
128
+ ZEND_OP_ARRAY_EXTENSION (& zf -> op_array , NR_PHP_PROCESS_GLOBALS (op_array_extension_handle )) = wr ;
129
+ }
130
+ }
131
+
132
+ static inline nruserfn_t * nr_php_wraprec_lookup_get (zend_function * zf ) {
133
+ nruserfn_t * wraprec = NULL ;
134
+
135
+ if (NULL != RUN_TIME_CACHE (& zf -> op_array )) {
136
+ wraprec = ZEND_OP_ARRAY_EXTENSION (& zf -> op_array , NR_PHP_PROCESS_GLOBALS (op_array_extension_handle ));
137
+ }
138
+ if (NULL != wraprec && NRPRG (pid ) != wraprec -> pid ) {
139
+ wraprec = NULL ;
140
+ }
141
+ return wraprec ;
142
+ }
143
+ #elif ZEND_MODULE_API_NO == ZEND_7_4_X_API_NO
118
144
/* Hashmap with pointers to wraprecs. Some, that are re-usable between requests,
119
145
* are stored in linked list. These wraprecs are created once per interesting
120
146
* function detection, and destroyed at module shutdown. Some, that are
@@ -130,17 +156,6 @@ static nr_php_wraprec_hashmap_t* user_function_wrappers;
130
156
static inline void nr_php_wraprec_lookup_set (nruserfn_t * wr ,
131
157
zend_function * zf ) {
132
158
nr_php_wraprec_hashmap_update (user_function_wrappers , zf , wr );
133
- #if ZEND_MODULE_API_NO >= ZEND_8_0_X_API_NO /* PHP 8.0+ */
134
- // for situation when wraprec is added after first execution of the function
135
- // store the wraprec in the op_array extension for the duration of the request for later lookup
136
- // The op_array extension slot for function may not be initialized yet because it is
137
- // initialized only on the first call made to the function in that request. This would
138
- // mean that run_time_cache is NULL and wraprec cannot be stored yet! It will be stored
139
- // on the first call to the function when observer is registered for that function.
140
- if (NULL != RUN_TIME_CACHE (& zf -> op_array )) {
141
- ZEND_OP_ARRAY_EXTENSION (& zf -> op_array , NR_PHP_PROCESS_GLOBALS (op_array_extension_handle )) = wr ;
142
- }
143
- #endif
144
159
}
145
160
static inline nruserfn_t * nr_php_wraprec_lookup_get (zend_function * zf ) {
146
161
nruserfn_t * wraprec = NULL ;
@@ -306,6 +321,7 @@ nruserfn_t* nr_php_user_wraprec_create(void) {
306
321
return wr ;
307
322
}
308
323
324
+ #if ZEND_MODULE_API_NO < ZEND_8_0_X_API_NO
309
325
static nruserfn_t * nr_php_user_wraprec_create_named (const char * full_name ,
310
326
int full_name_len ) {
311
327
int i ;
@@ -355,6 +371,7 @@ static nruserfn_t* nr_php_user_wraprec_create_named(const char* full_name,
355
371
356
372
return wraprec ;
357
373
}
374
+ #endif
358
375
359
376
void nr_php_user_wraprec_destroy (nruserfn_t * * wraprec_ptr ) {
360
377
nruserfn_t * wraprec ;
@@ -377,6 +394,7 @@ void nr_php_user_wraprec_destroy(nruserfn_t** wraprec_ptr) {
377
394
nr_realfree ((void * * )wraprec_ptr );
378
395
}
379
396
397
+ #if ZEND_MODULE_API_NO < ZEND_8_0_X_API_NO
380
398
static int nr_php_user_wraprec_is_match (const nruserfn_t * w1 ,
381
399
const nruserfn_t * w2 ) {
382
400
if ((0 == w1 ) && (0 == w2 )) {
@@ -393,11 +411,42 @@ static int nr_php_user_wraprec_is_match(const nruserfn_t* w1,
393
411
}
394
412
return 1 ;
395
413
}
414
+ #endif
415
+
416
+ #if ZEND_MODULE_API_NO > ZEND_7_4_X_API_NO
417
+ static nruserfn_t * nr_transient_wraprecs = NULL ; /* a singly linked list */
418
+ #else
419
+ static nruserfn_t * nr_wrapped_user_functions = NULL ; /* a singly linked list */
420
+ #endif
396
421
397
422
static void nr_php_add_custom_tracer_common (nruserfn_t * wraprec ) {
398
423
/* Add the wraprecord to the list. */
424
+ #if ZEND_MODULE_API_NO > ZEND_7_4_X_API_NO
425
+ if (wraprec -> is_transient ) {
426
+ /* Transient (unnamed) wraprecs are not added to wraprec hashmap which only stores named
427
+ * wraprecs. Keep track of all transient wraprecs so that they can be destroyed at the
428
+ * end of the request. */
429
+ wraprec -> next = nr_transient_wraprecs ;
430
+ nr_transient_wraprecs = wraprec ;
431
+ return ;
432
+ }
433
+ #endif
434
+ #if ZEND_MODULE_API_NO == ZEND_7_4_X_API_NO
435
+ if (!wraprec -> is_transient ) {
436
+ /* Non-transient wraprecs are added to both the hashmap and linked list.
437
+ * At request shutdown, the hashmap will free transients, but leave
438
+ * non-transients to be freed when the linked list is disposed of which is at
439
+ * module shutdown */
440
+ wraprec -> next = nr_wrapped_user_functions ;
441
+ nr_wrapped_user_functions = wraprec ;
442
+ return ;
443
+ }
444
+ #endif
445
+ #if ZEND_MODULE_API_NO < ZEND_7_4_X_API_NO
399
446
wraprec -> next = nr_wrapped_user_functions ;
400
447
nr_wrapped_user_functions = wraprec ;
448
+ return ;
449
+ #endif
401
450
}
402
451
403
452
#define NR_PHP_UNKNOWN_FUNCTION_NAME "{unknown}"
@@ -440,16 +489,15 @@ nruserfn_t* nr_php_add_custom_tracer_callable(zend_function* func TSRMLS_DC) {
440
489
nr_free (name );
441
490
442
491
nr_php_wrap_zend_function (func , wraprec TSRMLS_CC );
443
- #if ZEND_MODULE_API_NO < ZEND_7_4_X_API_NO
444
492
nr_php_add_custom_tracer_common (wraprec );
445
- #endif
446
493
447
494
return wraprec ;
448
495
}
449
496
450
497
nruserfn_t * nr_php_add_custom_tracer_named (const char * namestr ,
451
498
size_t namestrlen ) {
452
499
nruserfn_t * wraprec ;
500
+ #if ZEND_MODULE_API_NO < ZEND_8_0_X_API_NO
453
501
nruserfn_t * p ;
454
502
455
503
wraprec = nr_php_user_wraprec_create_named (namestr , namestrlen );
@@ -474,17 +522,15 @@ nruserfn_t* nr_php_add_custom_tracer_named(const char* namestr,
474
522
}
475
523
p = p -> next ;
476
524
}
477
-
525
+ #else
526
+ wraprec = nr_php_user_instrument_wraprec_hashmap_add (namestr , namestrlen );
527
+ #endif
478
528
nrl_verbosedebug (
479
529
NRL_INSTRUMENT , "adding custom for '" NRP_FMT_UQ "%.5s" NRP_FMT_UQ "'" ,
480
530
NRP_PHP (wraprec -> classname ),
481
531
(0 == wraprec -> classname ) ? "" : "::" , NRP_PHP (wraprec -> funcname ));
482
532
483
533
nr_php_wrap_user_function_internal (wraprec TSRMLS_CC );
484
- /* non-transient wraprecs are added to both the hashmap and linked list.
485
- * At request shutdown, the hashmap will free transients, but leave
486
- * non-transients to be freed when the linked list is disposed of which is at
487
- * module shutdown */
488
534
nr_php_add_custom_tracer_common (wraprec );
489
535
490
536
return wraprec ; /* return the new wraprec */
@@ -501,7 +547,13 @@ nruserfn_t* nr_php_add_custom_tracer_named(const char* namestr,
501
547
*
502
548
*/
503
549
void nr_php_reset_user_instrumentation (void ) {
504
- #if ZEND_MODULE_API_NO >= ZEND_7_4_X_API_NO
550
+ #if ZEND_MODULE_API_NO >= ZEND_8_0_X_API_NO
551
+ /* No need to do anything at rshutdown:
552
+ * - Observer API takes care of resetting user instrumentation for each request
553
+ * - All named wraprecs ever created persist in wraprec hashmap until mshutdown
554
+ */
555
+ return ;
556
+ #elif ZEND_MODULE_API_NO >= ZEND_7_4_X_API_NO
505
557
// send a metric with the number of transient wrappers
506
558
if (NULL != user_function_wrappers ) {
507
559
nr_php_wraprec_hashmap_stats_t stats
@@ -554,14 +606,16 @@ void nr_php_remove_transient_user_instrumentation(void) {
554
606
* Wrap all the interesting user functions with instrumentation.
555
607
*/
556
608
void nr_php_add_user_instrumentation (TSRMLS_D ) {
557
- nruserfn_t * p = nr_wrapped_user_functions ;
609
+ #if ZEND_MODULE_API_NO < ZEND_8_0_X_API_NO
610
+ nruserfn_t * p = nr_named_wraprecs ;
558
611
559
612
while (0 != p ) {
560
613
if ((0 == p -> is_wrapped ) && (0 == p -> is_disabled )) {
561
614
nr_php_wrap_user_function_internal (p TSRMLS_CC );
562
615
}
563
616
p = p -> next ;
564
617
}
618
+ #endif
565
619
}
566
620
567
621
void nr_php_add_transaction_naming_function (const char * namestr ,
@@ -608,6 +662,7 @@ void nr_php_remove_exception_function(zend_function* func TSRMLS_DC) {
608
662
}
609
663
610
664
void nr_php_destroy_user_wrap_records (void ) {
665
+ #if ZEND_MODULE_API_NO < ZEND_8_0_X_API_NO
611
666
nruserfn_t * next_user_wraprec ;
612
667
613
668
next_user_wraprec = nr_wrapped_user_functions ;
@@ -618,15 +673,12 @@ void nr_php_destroy_user_wrap_records(void) {
618
673
nr_php_user_wraprec_destroy (& wraprec );
619
674
}
620
675
621
- nr_wrapped_user_functions = NULL ;
676
+ nr_named_wraprecs = NULL ;
677
+ #else
678
+ nr_php_user_instrument_wraprec_hashmap_destroy ();
679
+ #endif
622
680
}
623
681
624
- /*
625
- * This is a similar list, but for the dynamically added user-defined functions
626
- * rather than the statically defined internal/binary functions above.
627
- */
628
- nruserfn_t * nr_wrapped_user_functions = 0 ;
629
-
630
682
void nr_php_user_function_add_declared_callback (const char * namestr ,
631
683
int namestrlen ,
632
684
nruserfn_declared_t callback
0 commit comments