66#include <fluent-bit/flb_config.h>
77#include <fluent-bit/flb_router.h>
88#include <fluent-bit/flb_sds.h>
9+ #include <fluent-bit/flb_log_event_encoder.h>
910#include <fluent-bit/flb_event.h>
11+ #include <fluent-bit/flb_mem.h>
1012#include <fluent-bit/config_format/flb_cf.h>
1113
1214#include <cfl/cfl.h>
2729
2830static struct cfl_variant * clone_variant (struct cfl_variant * var );
2931
32+ static int build_log_chunk (const char * level ,
33+ struct flb_log_event_encoder * encoder ,
34+ struct flb_event_chunk * chunk )
35+ {
36+ int ret ;
37+
38+ if (!level || !encoder || !chunk ) {
39+ return -1 ;
40+ }
41+
42+ ret = flb_log_event_encoder_init (encoder , FLB_LOG_EVENT_FORMAT_DEFAULT );
43+ TEST_CHECK (ret == FLB_EVENT_ENCODER_SUCCESS );
44+ if (ret != FLB_EVENT_ENCODER_SUCCESS ) {
45+ return -1 ;
46+ }
47+
48+ ret = flb_log_event_encoder_begin_record (encoder );
49+ TEST_CHECK (ret == FLB_EVENT_ENCODER_SUCCESS );
50+ if (ret != FLB_EVENT_ENCODER_SUCCESS ) {
51+ flb_log_event_encoder_destroy (encoder );
52+ return -1 ;
53+ }
54+
55+ ret = flb_log_event_encoder_set_current_timestamp (encoder );
56+ TEST_CHECK (ret == FLB_EVENT_ENCODER_SUCCESS );
57+ if (ret != FLB_EVENT_ENCODER_SUCCESS ) {
58+ flb_log_event_encoder_destroy (encoder );
59+ return -1 ;
60+ }
61+
62+ ret = flb_log_event_encoder_append_body_values (
63+ encoder ,
64+ FLB_LOG_EVENT_STRING_VALUE ("level" , 5 ),
65+ FLB_LOG_EVENT_CSTRING_VALUE (level ));
66+ TEST_CHECK (ret == FLB_EVENT_ENCODER_SUCCESS );
67+ if (ret != FLB_EVENT_ENCODER_SUCCESS ) {
68+ flb_log_event_encoder_destroy (encoder );
69+ return -1 ;
70+ }
71+
72+ ret = flb_log_event_encoder_commit_record (encoder );
73+ TEST_CHECK (ret == FLB_EVENT_ENCODER_SUCCESS );
74+ if (ret != FLB_EVENT_ENCODER_SUCCESS ) {
75+ flb_log_event_encoder_destroy (encoder );
76+ return -1 ;
77+ }
78+
79+ memset (chunk , 0 , sizeof (* chunk ));
80+ chunk -> type = FLB_EVENT_TYPE_LOGS ;
81+ chunk -> data = encoder -> output_buffer ;
82+ chunk -> size = encoder -> output_length ;
83+ chunk -> total_events = 1 ;
84+
85+ return 0 ;
86+ }
87+
88+ static void free_route_condition (struct flb_route_condition * condition )
89+ {
90+ struct cfl_list * tmp ;
91+ struct cfl_list * head ;
92+ struct flb_route_condition_rule * rule ;
93+ size_t idx ;
94+
95+ if (!condition ) {
96+ return ;
97+ }
98+
99+ if (condition -> compiled ) {
100+ flb_condition_destroy (condition -> compiled );
101+ }
102+
103+ cfl_list_foreach_safe (head , tmp , & condition -> rules ) {
104+ rule = cfl_list_entry (head , struct flb_route_condition_rule , _head );
105+ cfl_list_del (& rule -> _head );
106+
107+ if (rule -> field ) {
108+ flb_sds_destroy (rule -> field );
109+ }
110+ if (rule -> op ) {
111+ flb_sds_destroy (rule -> op );
112+ }
113+ if (rule -> value ) {
114+ flb_sds_destroy (rule -> value );
115+ }
116+ if (rule -> values ) {
117+ for (idx = 0 ; idx < rule -> values_count ; idx ++ ) {
118+ if (rule -> values [idx ]) {
119+ flb_sds_destroy (rule -> values [idx ]);
120+ }
121+ }
122+ flb_free (rule -> values );
123+ }
124+
125+ flb_free (rule );
126+ }
127+
128+ flb_free (condition );
129+ }
130+
30131static struct cfl_array * clone_array (struct cfl_array * array )
31132{
32133 struct cfl_array * copy ;
@@ -850,6 +951,257 @@ void test_router_route_default_precedence()
850951 flb_cf_destroy (cf );
851952}
852953
954+ static void test_router_condition_eval_logs_match ()
955+ {
956+ struct flb_route route ;
957+ struct flb_route_condition * condition ;
958+ struct flb_route_condition_rule * rule ;
959+ struct flb_log_event_encoder encoder ;
960+ struct flb_event_chunk chunk ;
961+ int ret ;
962+
963+ memset (& route , 0 , sizeof (route ));
964+ cfl_list_init (& route .outputs );
965+ cfl_list_init (& route .processors );
966+
967+ condition = flb_calloc (1 , sizeof (struct flb_route_condition ));
968+ TEST_CHECK (condition != NULL );
969+ if (!condition ) {
970+ return ;
971+ }
972+
973+ cfl_list_init (& condition -> rules );
974+ condition -> op = FLB_COND_OP_AND ;
975+ condition -> compiled_status = 0 ;
976+ condition -> compiled = NULL ;
977+ condition -> is_default = FLB_FALSE ;
978+
979+ rule = flb_calloc (1 , sizeof (struct flb_route_condition_rule ));
980+ TEST_CHECK (rule != NULL );
981+ if (!rule ) {
982+ free_route_condition (condition );
983+ return ;
984+ }
985+
986+ cfl_list_init (& rule -> _head );
987+ rule -> field = flb_sds_create ("$level" );
988+ rule -> op = flb_sds_create ("eq" );
989+ rule -> value = flb_sds_create ("error" );
990+ TEST_CHECK (rule -> field != NULL && rule -> op != NULL && rule -> value != NULL );
991+ if (!rule -> field || !rule -> op || !rule -> value ) {
992+ if (rule -> field ) {
993+ flb_sds_destroy (rule -> field );
994+ }
995+ if (rule -> op ) {
996+ flb_sds_destroy (rule -> op );
997+ }
998+ if (rule -> value ) {
999+ flb_sds_destroy (rule -> value );
1000+ }
1001+ flb_free (rule );
1002+ free_route_condition (condition );
1003+ return ;
1004+ }
1005+
1006+ cfl_list_add (& rule -> _head , & condition -> rules );
1007+
1008+ route .condition = condition ;
1009+ route .signals = FLB_ROUTER_SIGNAL_LOGS ;
1010+
1011+ ret = build_log_chunk ("error" , & encoder , & chunk );
1012+ TEST_CHECK (ret == 0 );
1013+ if (ret == 0 ) {
1014+ TEST_CHECK (flb_condition_eval_logs (& chunk , & route ) == FLB_TRUE );
1015+ }
1016+ flb_log_event_encoder_destroy (& encoder );
1017+
1018+ ret = build_log_chunk ("info" , & encoder , & chunk );
1019+ TEST_CHECK (ret == 0 );
1020+ if (ret == 0 ) {
1021+ TEST_CHECK (flb_condition_eval_logs (& chunk , & route ) == FLB_FALSE );
1022+ }
1023+ flb_log_event_encoder_destroy (& encoder );
1024+
1025+ free_route_condition (condition );
1026+ }
1027+
1028+ static void test_router_condition_eval_logs_in_operator ()
1029+ {
1030+ struct flb_route route ;
1031+ struct flb_route_condition * condition ;
1032+ struct flb_route_condition_rule * rule ;
1033+ struct flb_log_event_encoder encoder ;
1034+ struct flb_event_chunk chunk ;
1035+ int ret ;
1036+
1037+ memset (& route , 0 , sizeof (route ));
1038+ cfl_list_init (& route .outputs );
1039+ cfl_list_init (& route .processors );
1040+
1041+ condition = flb_calloc (1 , sizeof (struct flb_route_condition ));
1042+ TEST_CHECK (condition != NULL );
1043+ if (!condition ) {
1044+ return ;
1045+ }
1046+
1047+ cfl_list_init (& condition -> rules );
1048+ condition -> op = FLB_COND_OP_AND ;
1049+ condition -> compiled_status = 0 ;
1050+ condition -> compiled = NULL ;
1051+ condition -> is_default = FLB_FALSE ;
1052+
1053+ rule = flb_calloc (1 , sizeof (struct flb_route_condition_rule ));
1054+ TEST_CHECK (rule != NULL );
1055+ if (!rule ) {
1056+ free_route_condition (condition );
1057+ return ;
1058+ }
1059+
1060+ cfl_list_init (& rule -> _head );
1061+ rule -> field = flb_sds_create ("$level" );
1062+ rule -> op = flb_sds_create ("in" );
1063+ TEST_CHECK (rule -> field != NULL && rule -> op != NULL );
1064+ if (!rule -> field || !rule -> op ) {
1065+ if (rule -> field ) {
1066+ flb_sds_destroy (rule -> field );
1067+ }
1068+ if (rule -> op ) {
1069+ flb_sds_destroy (rule -> op );
1070+ }
1071+ flb_free (rule );
1072+ free_route_condition (condition );
1073+ return ;
1074+ }
1075+
1076+ rule -> values_count = 2 ;
1077+ rule -> values = flb_calloc (rule -> values_count , sizeof (flb_sds_t ));
1078+ TEST_CHECK (rule -> values != NULL );
1079+ if (!rule -> values ) {
1080+ free_route_condition (condition );
1081+ flb_sds_destroy (rule -> field );
1082+ flb_sds_destroy (rule -> op );
1083+ flb_free (rule );
1084+ return ;
1085+ }
1086+
1087+ rule -> values [0 ] = flb_sds_create ("error" );
1088+ rule -> values [1 ] = flb_sds_create ("fatal" );
1089+ TEST_CHECK (rule -> values [0 ] != NULL && rule -> values [1 ] != NULL );
1090+ if (!rule -> values [0 ] || !rule -> values [1 ]) {
1091+ if (rule -> values [0 ]) {
1092+ flb_sds_destroy (rule -> values [0 ]);
1093+ }
1094+ if (rule -> values [1 ]) {
1095+ flb_sds_destroy (rule -> values [1 ]);
1096+ }
1097+ flb_free (rule -> values );
1098+ flb_sds_destroy (rule -> field );
1099+ flb_sds_destroy (rule -> op );
1100+ flb_free (rule );
1101+ free_route_condition (condition );
1102+ return ;
1103+ }
1104+
1105+ cfl_list_add (& rule -> _head , & condition -> rules );
1106+
1107+ route .condition = condition ;
1108+ route .signals = FLB_ROUTER_SIGNAL_LOGS ;
1109+
1110+ ret = build_log_chunk ("fatal" , & encoder , & chunk );
1111+ TEST_CHECK (ret == 0 );
1112+ if (ret == 0 ) {
1113+ TEST_CHECK (flb_condition_eval_logs (& chunk , & route ) == FLB_TRUE );
1114+ }
1115+ flb_log_event_encoder_destroy (& encoder );
1116+
1117+ ret = build_log_chunk ("debug" , & encoder , & chunk );
1118+ TEST_CHECK (ret == 0 );
1119+ if (ret == 0 ) {
1120+ TEST_CHECK (flb_condition_eval_logs (& chunk , & route ) == FLB_FALSE );
1121+ }
1122+ flb_log_event_encoder_destroy (& encoder );
1123+
1124+ free_route_condition (condition );
1125+ }
1126+
1127+ static void test_router_path_should_route_condition ()
1128+ {
1129+ struct flb_router_path path ;
1130+ struct flb_route route ;
1131+ struct flb_route_condition * condition ;
1132+ struct flb_route_condition_rule * rule ;
1133+ struct flb_log_event_encoder encoder ;
1134+ struct flb_event_chunk chunk ;
1135+ int ret ;
1136+
1137+ memset (& route , 0 , sizeof (route ));
1138+ cfl_list_init (& route .outputs );
1139+ cfl_list_init (& route .processors );
1140+
1141+ condition = flb_calloc (1 , sizeof (struct flb_route_condition ));
1142+ TEST_CHECK (condition != NULL );
1143+ if (!condition ) {
1144+ return ;
1145+ }
1146+
1147+ cfl_list_init (& condition -> rules );
1148+ condition -> op = FLB_COND_OP_AND ;
1149+ condition -> compiled_status = 0 ;
1150+ condition -> compiled = NULL ;
1151+ condition -> is_default = FLB_FALSE ;
1152+
1153+ rule = flb_calloc (1 , sizeof (struct flb_route_condition_rule ));
1154+ TEST_CHECK (rule != NULL );
1155+ if (!rule ) {
1156+ free_route_condition (condition );
1157+ return ;
1158+ }
1159+
1160+ cfl_list_init (& rule -> _head );
1161+ rule -> field = flb_sds_create ("$level" );
1162+ rule -> op = flb_sds_create ("eq" );
1163+ rule -> value = flb_sds_create ("error" );
1164+ TEST_CHECK (rule -> field != NULL && rule -> op != NULL && rule -> value != NULL );
1165+ if (!rule -> field || !rule -> op || !rule -> value ) {
1166+ if (rule -> field ) {
1167+ flb_sds_destroy (rule -> field );
1168+ }
1169+ if (rule -> op ) {
1170+ flb_sds_destroy (rule -> op );
1171+ }
1172+ if (rule -> value ) {
1173+ flb_sds_destroy (rule -> value );
1174+ }
1175+ flb_free (rule );
1176+ free_route_condition (condition );
1177+ return ;
1178+ }
1179+
1180+ cfl_list_add (& rule -> _head , & condition -> rules );
1181+
1182+ route .condition = condition ;
1183+ route .signals = FLB_ROUTER_SIGNAL_LOGS ;
1184+
1185+ memset (& path , 0 , sizeof (path ));
1186+ path .route = & route ;
1187+
1188+ ret = build_log_chunk ("error" , & encoder , & chunk );
1189+ TEST_CHECK (ret == 0 );
1190+ if (ret == 0 ) {
1191+ TEST_CHECK (flb_router_path_should_route (& chunk , & path ) == FLB_TRUE );
1192+ }
1193+ flb_log_event_encoder_destroy (& encoder );
1194+
1195+ ret = build_log_chunk ("info" , & encoder , & chunk );
1196+ TEST_CHECK (ret == 0 );
1197+ if (ret == 0 ) {
1198+ TEST_CHECK (flb_router_path_should_route (& chunk , & path ) == FLB_FALSE );
1199+ }
1200+ flb_log_event_encoder_destroy (& encoder );
1201+
1202+ free_route_condition (condition );
1203+ }
1204+
8531205TEST_LIST = {
8541206 { "parse_basic" , test_router_config_parse_basic },
8551207 { "duplicate_route" , test_router_config_duplicate_route },
@@ -859,5 +1211,8 @@ TEST_LIST = {
8591211 { "apply_config_success" , test_router_apply_config_success },
8601212 { "apply_config_missing_output" , test_router_apply_config_missing_output },
8611213 { "route_default_precedence" , test_router_route_default_precedence },
1214+ { "condition_eval_logs_match" , test_router_condition_eval_logs_match },
1215+ { "condition_eval_logs_in_operator" , test_router_condition_eval_logs_in_operator },
1216+ { "path_should_route_condition" , test_router_path_should_route_condition },
8621217 { 0 }
8631218};
0 commit comments