@@ -65,52 +65,52 @@ func TestNewAggregator_Valid(t *testing.T) {
6565 {
6666 name : "Default SplitAB" ,
6767 outputField : api.OutputField {Name : "MyAgg" , Operation : "sum" },
68- expected : & aSum {aggregateBase {"MyAgg" , "MyAgg" , false , float64 (0 ), nil }},
68+ expected : & aSum {aggregateBase {"MyAgg" , "MyAgg" , false , float64 (0 ), nil , false }},
6969 },
7070 {
7171 name : "Default input" ,
7272 outputField : api.OutputField {Name : "MyAgg" , Operation : "sum" , SplitAB : true },
73- expected : & aSum {aggregateBase {"MyAgg" , "MyAgg" , true , float64 (0 ), nil }},
73+ expected : & aSum {aggregateBase {"MyAgg" , "MyAgg" , true , float64 (0 ), nil , false }},
7474 },
7575 {
7676 name : "Custom input" ,
7777 outputField : api.OutputField {Name : "MyAgg" , Operation : "sum" , Input : "MyInput" },
78- expected : & aSum {aggregateBase {"MyInput" , "MyAgg" , false , float64 (0 ), nil }},
78+ expected : & aSum {aggregateBase {"MyInput" , "MyAgg" , false , float64 (0 ), nil , false }},
7979 },
8080 {
81- name : "OperationType sum" ,
82- outputField : api.OutputField {Name : "MyAgg" , Operation : "sum" },
83- expected : & aSum {aggregateBase {"MyAgg" , "MyAgg" , false , float64 (0 ), nil }},
81+ name : "OperationType sum with errors " ,
82+ outputField : api.OutputField {Name : "MyAgg" , Operation : "sum" , ReportMissing : true },
83+ expected : & aSum {aggregateBase {"MyAgg" , "MyAgg" , false , float64 (0 ), nil , true }},
8484 },
8585 {
86- name : "OperationType count" ,
87- outputField : api.OutputField {Name : "MyAgg" , Operation : "count" },
88- expected : & aCount {aggregateBase {"MyAgg" , "MyAgg" , false , float64 (0 ), nil }},
86+ name : "OperationType count with errors " ,
87+ outputField : api.OutputField {Name : "MyAgg" , Operation : "count" , ReportMissing : true },
88+ expected : & aCount {aggregateBase {"MyAgg" , "MyAgg" , false , float64 (0 ), nil , true }},
8989 },
9090 {
9191 name : "OperationType max" ,
9292 outputField : api.OutputField {Name : "MyAgg" , Operation : "max" },
93- expected : & aMax {aggregateBase {"MyAgg" , "MyAgg" , false , - math .MaxFloat64 , nil }},
93+ expected : & aMax {aggregateBase {"MyAgg" , "MyAgg" , false , - math .MaxFloat64 , nil , false }},
9494 },
9595 {
9696 name : "OperationType min" ,
9797 outputField : api.OutputField {Name : "MyAgg" , Operation : "min" },
98- expected : & aMin {aggregateBase {"MyAgg" , "MyAgg" , false , math .MaxFloat64 , nil }},
98+ expected : & aMin {aggregateBase {"MyAgg" , "MyAgg" , false , math .MaxFloat64 , nil , false }},
9999 },
100100 {
101101 name : "Default first" ,
102102 outputField : api.OutputField {Name : "MyCp" , Operation : "first" },
103- expected : & aFirst {aggregateBase {"MyCp" , "MyCp" , false , nil , nil }},
103+ expected : & aFirst {aggregateBase {"MyCp" , "MyCp" , false , nil , nil , false }},
104104 },
105105 {
106106 name : "Custom input first" ,
107107 outputField : api.OutputField {Name : "MyCp" , Operation : "first" , Input : "MyInput" },
108- expected : & aFirst {aggregateBase {"MyInput" , "MyCp" , false , nil , nil }},
108+ expected : & aFirst {aggregateBase {"MyInput" , "MyCp" , false , nil , nil , false }},
109109 },
110110 {
111111 name : "Default last" ,
112112 outputField : api.OutputField {Name : "MyCp" , Operation : "last" },
113- expected : & aLast {aggregateBase {"MyCp" , "MyCp" , false , nil , nil }},
113+ expected : & aLast {aggregateBase {"MyCp" , "MyCp" , false , nil , nil , false }},
114114 },
115115 }
116116
@@ -132,6 +132,7 @@ func TestAddField_and_Update(t *testing.T) {
132132 {Name : "maxFlowLogBytes" , Operation : "max" , Input : "Bytes" },
133133 {Name : "FirstFlowDirection" , Operation : "first" , Input : "FlowDirection" },
134134 {Name : "LastFlowDirection" , Operation : "last" , Input : "FlowDirection" },
135+ {Name : "PktDropLatestDropCause" , Operation : "last" , Input : "PktDropLatestDropCause" },
135136 }
136137 var aggs []aggregator
137138 for _ , of := range ofs {
@@ -158,21 +159,67 @@ func TestAddField_and_Update(t *testing.T) {
158159 name : "flowLog 1" ,
159160 flowLog : newMockFlowLog (ipA , portA , ipB , portB , protocolA , flowDirA , 100 , 10 , false ),
160161 direction : dirAB ,
161- expected : map [string ]interface {}{"Bytes_AB" : float64 (100 ), "Bytes_BA" : float64 (0 ), "Packets" : float64 (10 ), "maxFlowLogBytes" : float64 (100 ), "minFlowLogBytes" : float64 (100 ), "numFlowLogs" : float64 (1 ), "FirstFlowDirection" : 0 , "LastFlowDirection" : 0 },
162+ expected : map [string ]interface {}{
163+ "Bytes_AB" : float64 (100 ),
164+ "Bytes_BA" : float64 (0 ),
165+ "Packets" : float64 (10 ),
166+ "maxFlowLogBytes" : float64 (100 ),
167+ "minFlowLogBytes" : float64 (100 ),
168+ "numFlowLogs" : float64 (1 ),
169+ "FirstFlowDirection" : 0 ,
170+ "LastFlowDirection" : 0 ,
171+ "PktDropLatestDropCause" : nil ,
172+ },
162173 },
163174 {
164175 name : "flowLog 2" ,
165- flowLog : newMockFlowLog (ipA , portA , ipB , portB , protocolA , flowDirB , 200 , 20 , false ),
176+ flowLog : config.GenericMap {"SrcAddr" : ipA , "DstAddr" : ipB , "Bytes" : 100 , "FlowDirection" : flowDirA , "PktDropLatestDropCause" : "SKB_DROP_REASON_NO_SOCKET" },
177+ direction : dirAB ,
178+ expected : map [string ]interface {}{
179+ "Bytes_AB" : float64 (200 ), // updated bytes count
180+ "Bytes_BA" : float64 (0 ),
181+ "Packets" : float64 (10 ),
182+ "maxFlowLogBytes" : float64 (100 ),
183+ "minFlowLogBytes" : float64 (100 ),
184+ "numFlowLogs" : float64 (2 ), // updated flow count
185+ "FirstFlowDirection" : 0 ,
186+ "LastFlowDirection" : 0 ,
187+ "PktDropLatestDropCause" : "SKB_DROP_REASON_NO_SOCKET" , // added drop cause
188+ },
189+ },
190+ {
191+ name : "flowLog 3" ,
192+ flowLog : newMockFlowLog (ipA , portA , ipB , portB , protocolA , flowDirB , 300 , 20 , false ),
166193 direction : dirBA ,
167- expected : map [string ]interface {}{"Bytes_AB" : float64 (100 ), "Bytes_BA" : float64 (200 ), "Packets" : float64 (30 ), "maxFlowLogBytes" : float64 (200 ), "minFlowLogBytes" : float64 (100 ), "numFlowLogs" : float64 (2 ), "FirstFlowDirection" : 0 , "LastFlowDirection" : 1 },
194+ expected : map [string ]interface {}{
195+ "Bytes_AB" : float64 (200 ),
196+ "Bytes_BA" : float64 (300 ), // updated reverse direction byte count
197+ "Packets" : float64 (30 ),
198+ "maxFlowLogBytes" : float64 (300 ), // updated max bytes from any direction
199+ "minFlowLogBytes" : float64 (100 ),
200+ "numFlowLogs" : float64 (3 ), // updated count
201+ "FirstFlowDirection" : 0 ,
202+ "LastFlowDirection" : 1 ,
203+ "PktDropLatestDropCause" : "SKB_DROP_REASON_NO_SOCKET" , // missing field is kept to its last available value
204+ },
168205 },
169206 }
170207
171208 conn := NewConnBuilder (nil ).Build ()
172209 for _ , agg := range aggs {
173210 agg .addField (conn )
174211 }
175- expectedInits := map [string ]interface {}{"Bytes_AB" : float64 (0 ), "Bytes_BA" : float64 (0 ), "Packets" : float64 (0 ), "maxFlowLogBytes" : float64 (- math .MaxFloat64 ), "minFlowLogBytes" : float64 (math .MaxFloat64 ), "numFlowLogs" : float64 (0 ), "FirstFlowDirection" : nil , "LastFlowDirection" : nil }
212+ expectedInits := map [string ]interface {}{
213+ "Bytes_AB" : float64 (0 ),
214+ "Bytes_BA" : float64 (0 ),
215+ "Packets" : float64 (0 ),
216+ "maxFlowLogBytes" : float64 (- math .MaxFloat64 ),
217+ "minFlowLogBytes" : float64 (math .MaxFloat64 ),
218+ "numFlowLogs" : float64 (0 ),
219+ "FirstFlowDirection" : nil ,
220+ "LastFlowDirection" : nil ,
221+ "PktDropLatestDropCause" : nil ,
222+ }
176223 require .Equal (t , expectedInits , conn .(* connType ).aggFields )
177224
178225 for i , test := range table {
@@ -188,7 +235,7 @@ func TestAddField_and_Update(t *testing.T) {
188235func TestMissingFieldError (t * testing.T ) {
189236 test .ResetPromRegistry ()
190237 metrics := newMetrics (opMetrics )
191- agg , err := newAggregator (api.OutputField {Name : "Bytes" , Operation : "sum" , SplitAB : true }, metrics )
238+ agg , err := newAggregator (api.OutputField {Name : "Bytes" , Operation : "sum" , SplitAB : true , ReportMissing : true }, metrics )
192239 require .NoError (t , err )
193240
194241 conn := NewConnBuilder (metrics ).Build ()
@@ -201,6 +248,22 @@ func TestMissingFieldError(t *testing.T) {
201248 require .Contains (t , exposed , `conntrack_aggregator_errors{error="MissingFieldError",field="Bytes"} 1` )
202249}
203250
251+ func TestSkipMissingFieldError (t * testing.T ) {
252+ test .ResetPromRegistry ()
253+ metrics := newMetrics (opMetrics )
254+ agg , err := newAggregator (api.OutputField {Name : "Bytes" , Operation : "sum" , SplitAB : true }, metrics )
255+ require .NoError (t , err )
256+
257+ conn := NewConnBuilder (metrics ).Build ()
258+ agg .addField (conn )
259+
260+ flowLog := config.GenericMap {}
261+ agg .update (conn , flowLog , dirAB , true )
262+
263+ exposed := test .ReadExposedMetrics (t )
264+ require .NotContains (t , exposed , `conntrack_aggregator_errors{error="MissingFieldError",field="Bytes"}` )
265+ }
266+
204267func TestFloat64ConversionError (t * testing.T ) {
205268 test .ResetPromRegistry ()
206269 metrics := newMetrics (opMetrics )
0 commit comments