@@ -536,6 +536,119 @@ static nrobj_t* nr_php_txn_get_labels() {
536
536
return nr_labels_parse (NR_PHP_PROCESS_GLOBALS (env_labels ));
537
537
}
538
538
539
+ static nr_status_t nr_php_txn_collect_label_keys_iter (const char * key ,
540
+ const nrobj_t * value ,
541
+ void * ptr ) {
542
+ nrobj_t * user_data = (nrobj_t * )ptr ;
543
+
544
+ (void )value ;
545
+
546
+ if (NULL == key || NULL == user_data ) {
547
+ return NR_FAILURE ;
548
+ }
549
+
550
+ nro_set_array_string (user_data , 0 , key );
551
+
552
+ return NR_SUCCESS ;
553
+ }
554
+
555
+ /*
556
+ * Purpose : Filter the labels hash to exclude any labels that are in the
557
+ * newrelic.application_logging.forwarding.labels.exclude list.
558
+ *
559
+ * Params : 1. The labels hash to filter.
560
+ *
561
+ * Returns : A new hash containing the filtered labels.
562
+ * If no labels exist or all labels are excluded, then return NULL.
563
+ *
564
+ */
565
+
566
+ nrobj_t * nr_php_txn_get_log_forwarding_labels (nrobj_t * labels ) {
567
+ nrobj_t * label_keys = NULL ;
568
+ nrobj_t * exclude_labels_list = NULL ;
569
+ nrobj_t * exclude_labels_hash = NULL ;
570
+ nrobj_t * log_labels = NULL ;
571
+
572
+ if (NULL == labels || 0 == nro_getsize (labels )) {
573
+ nrl_verbosedebug (NRL_TXN , "%s: No labels defined" , __FUNCTION__ );
574
+ return NULL ;
575
+ }
576
+
577
+ /* if logging labels are disabled then nothing to do */
578
+ if (0 == NRINI (log_forwarding_labels_enabled )) {
579
+ nrl_verbosedebug (NRL_TXN , "%s: Log forwarding labels disabled" ,
580
+ __FUNCTION__ );
581
+ return NULL ;
582
+ }
583
+
584
+ /* split exclude string on commas - nr_strsplit() will trim leading
585
+ * and trailing whitespace from each string extracted, as well as
586
+ * ignoring empty strings after whitespace trimming
587
+ */
588
+ exclude_labels_list
589
+ = nr_strsplit (NRINI (log_forwarding_labels_exclude ), "," , 0 );
590
+
591
+ /* convert to lowercase to support case insensitive search below
592
+ * will store lowercase version in a hash for more convenient lookup
593
+ */
594
+ exclude_labels_hash = nro_new (NR_OBJECT_HASH );
595
+ for (int i = 0 ; i < nro_getsize (exclude_labels_list ); i ++ ) {
596
+ char * label = nr_string_to_lowercase (
597
+ nro_get_array_string (exclude_labels_list , i + 1 , NULL ));
598
+
599
+ if (!nr_strempty (label )) {
600
+ nro_set_hash_boolean (exclude_labels_hash , label , 1 );
601
+ }
602
+ nr_free (label );
603
+ }
604
+
605
+ /* original parsed exclude list is no longer needed */
606
+ nro_delete (exclude_labels_list );
607
+
608
+ /* collect label keys from existing labels */
609
+ label_keys = nro_new (NR_OBJECT_ARRAY );
610
+ nro_iteratehash (labels , nr_php_txn_collect_label_keys_iter ,
611
+ (void * )label_keys );
612
+
613
+ /* filter by going over the list of label keys, seeing if it exists in the
614
+ * exclude hash, and if it does skip it otherwise copy key/value for label
615
+ * to the log labels
616
+ */
617
+ log_labels = nro_new (NR_OBJECT_HASH );
618
+ for (int i = 0 ; i < nro_getsize (label_keys ); i ++ ) {
619
+ const char * key = NULL ;
620
+ char * lower_key = NULL ;
621
+ int exclude = false;
622
+
623
+ key = nro_get_array_string (label_keys , i + 1 , NULL );
624
+ if (NULL == key ) {
625
+ continue ;
626
+ }
627
+
628
+ lower_key = nr_string_to_lowercase (key );
629
+
630
+ if (1 != nro_get_hash_boolean (exclude_labels_hash , lower_key , NULL )) {
631
+ nro_set_hash_string (log_labels , key ,
632
+ nro_get_hash_string (labels , key , NULL ));
633
+ } else {
634
+ nrl_verbosedebug (NRL_TXN , "%s: Excluding label %s" , __FUNCTION__ ,
635
+ NRSAFESTR (key ));
636
+ }
637
+ nr_free (lower_key );
638
+ }
639
+
640
+ nro_delete (exclude_labels_hash );
641
+ nro_delete (label_keys );
642
+
643
+ /* return NULL if all labels were excluded */
644
+ if (0 == nro_getsize (log_labels )) {
645
+ nro_delete (log_labels );
646
+ log_labels = NULL ;
647
+ }
648
+
649
+ return log_labels ;
650
+ }
651
+
539
652
static void nr_php_txn_prepared_statement_destroy (void * sql ) {
540
653
nr_free (sql );
541
654
}
@@ -666,6 +779,11 @@ static void nr_php_txn_send_metrics_once(nrtxn_t* txn TSRMLS_DC) {
666
779
nrm_force_add (NRTXN (unscoped_metrics ), metname , 0 );
667
780
nr_free (metname );
668
781
782
+ metname = nr_formatf ("Supportability/Logging/Labels/PHP/%s" ,
783
+ FMT_BOOL (nr_txn_log_forwarding_labels_enabled (txn )));
784
+ nrm_force_add (NRTXN (unscoped_metrics ), metname , 0 );
785
+ nr_free (metname );
786
+
669
787
txn -> created_logging_onetime_metrics = true;
670
788
671
789
#undef FMT_BOOL
@@ -762,6 +880,7 @@ nr_status_t nr_php_txn_begin(const char* appnames,
762
880
nrtxnopt_t opts ;
763
881
const char * lic_to_use ;
764
882
int pfd ;
883
+ nrobj_t * log_forwarding_labels = NULL ;
765
884
nr_attribute_config_t * attribute_config ;
766
885
nr_app_info_t info ;
767
886
bool is_cli = (0 != NR_PHP_PROCESS_GLOBALS (cli ));
@@ -854,6 +973,7 @@ nr_status_t nr_php_txn_begin(const char* appnames,
854
973
opts .log_forwarding_log_level = NRINI (log_forwarding_log_level );
855
974
opts .log_events_max_samples_stored = NRINI (log_events_max_samples_stored );
856
975
opts .log_metrics_enabled = NRINI (log_metrics_enabled );
976
+ opts .log_forwarding_labels_enabled = NRINI (log_forwarding_labels_enabled );
857
977
opts .message_tracer_segment_parameters_enabled
858
978
= NRINI (message_tracer_segment_parameters_enabled );
859
979
@@ -917,17 +1037,21 @@ nr_status_t nr_php_txn_begin(const char* appnames,
917
1037
& nr_php_app_settings , NR_PHP_PROCESS_GLOBALS (daemon_app_connect_timeout ));
918
1038
nr_app_info_destroy_fields (& info );
919
1039
920
- if (0 == NRPRG (app )) {
1040
+ if (NULL == NRPRG (app )) {
921
1041
nrl_debug (NRL_INIT , "unable to begin transaction: app '%.128s' is unknown" ,
922
1042
appnames ? appnames : "" );
923
1043
return NR_FAILURE ;
924
1044
}
925
1045
926
1046
attribute_config = nr_php_create_attribute_config (TSRMLS_C );
927
- NRPRG (txn ) = nr_txn_begin (NRPRG (app ), & opts , attribute_config );
1047
+ log_forwarding_labels
1048
+ = nr_php_txn_get_log_forwarding_labels (NRPRG (app )-> info .labels );
1049
+ NRPRG (txn ) = nr_txn_begin (NRPRG (app ), & opts , attribute_config ,
1050
+ log_forwarding_labels );
928
1051
nrt_mutex_unlock (& (NRPRG (app )-> app_lock ));
929
1052
930
1053
nr_attribute_config_destroy (& attribute_config );
1054
+ nro_delete (log_forwarding_labels );
931
1055
932
1056
if (0 == NRPRG (txn )) {
933
1057
nrl_debug (NRL_INIT , "no Axiom transaction this time around" );
0 commit comments