@@ -204,6 +204,17 @@ def createSummarySection(self):
204204
205205 # Generate summary for categorical metrics
206206 if data_type == "categorical" :
207+ # Check if this is a labeled_counter with sum aggregate
208+ is_sum_aggregate = False
209+ for hist_key in self .data .get ("histograms" , {}):
210+ hist_name = hist_key .split ("." )[- 1 ]
211+ if hist_name == metric :
212+ is_sum_aggregate = (
213+ self .data ["histograms" ][hist_key ].get ("aggregate" )
214+ == "sum"
215+ )
216+ break
217+
207218 branches = []
208219 for branch in self .data ["branches" ]:
209220 branch_name = (
@@ -223,23 +234,66 @@ def createSummarySection(self):
223234 ][metric ]
224235 rows = []
225236 n_labels = len (metric_data ["labels" ])
226- for i in range (n_labels ):
237+
238+ # For labeled_counter with sum aggregate and many labels,
239+ # only show top 2-3 by absolute uplift
240+ if is_sum_aggregate and n_labels > 10 :
241+ # Create list of (index, label, uplift) tuples
242+ label_uplifts = [
243+ (
244+ i ,
245+ metric_data ["labels" ][i ],
246+ metric_data ["uplift" ][i ],
247+ )
248+ for i in range (n_labels )
249+ ]
250+ # Sort by absolute uplift descending
251+ label_uplifts .sort (
252+ key = lambda x : abs (x [2 ]), reverse = True
253+ )
254+ # Take top 3
255+ label_uplifts = label_uplifts [:3 ]
256+ indices_to_show = [x [0 ] for x in label_uplifts ]
257+ else :
258+ indices_to_show = range (n_labels )
259+
260+ for i in indices_to_show :
227261 label = metric_data ["labels" ][i ]
228262 uplift = metric_data ["uplift" ][i ]
229263
230264 # Skip small uplifts for enumerated histograms with many labels
231- if n_labels > 5 and abs (uplift ) < 0.05 :
265+ if (
266+ not is_sum_aggregate
267+ and n_labels > 5
268+ and abs (uplift ) < 0.05
269+ ):
232270 continue
233271
234272 weight = "font-weight:normal;"
273+ color = ""
235274 if abs (uplift ) >= 10 :
236275 effect = "Large"
237276 weight = "font-weight:bold;"
277+ color = (
278+ "color:red;"
279+ if uplift > 0
280+ else "color:green;"
281+ )
238282 elif abs (uplift ) >= 5 :
239283 effect = "Medium"
240284 weight = "font-weight:bold;"
285+ color = (
286+ "color:red;"
287+ if uplift > 0
288+ else "color:green;"
289+ )
241290 elif abs (uplift ) >= 2 :
242291 effect = "Small"
292+ color = (
293+ "color:red;"
294+ if uplift > 0
295+ else "color:green;"
296+ )
243297 else :
244298 effect = "None"
245299
@@ -255,6 +309,7 @@ def createSummarySection(self):
255309 "uplift" : uplift_desc ,
256310 "effect" : effect ,
257311 "weight" : weight ,
312+ "color" : color ,
258313 "style" : f"background:{ row_background } ;" ,
259314 }
260315 )
@@ -1154,36 +1209,51 @@ def createCategoricalComparison(self, segment, metric, metric_type):
11541209
11551210 n_elem = len (self .data [control ][segment ][metric_type ][metric ]["counts" ])
11561211
1157- # Get unit from metric config if available
1212+ # Get unit and aggregate type from metric config if available
11581213 unit = ""
1214+ aggregate = None
11591215 for hist_key in self .data .get ("histograms" , {}):
11601216 hist_name = hist_key .split ("." )[- 1 ]
11611217 if hist_name == metric :
11621218 unit = self .data ["histograms" ][hist_key ].get ("unit" , "" )
1219+ aggregate = self .data ["histograms" ][hist_key ].get ("aggregate" )
11631220 break
1164- if n_elem <= 10 :
1221+ if n_elem <= 20 :
1222+ # For metrics with <= 20 categories (like labeled counters), show all
11651223 indices = set (range (0 , n_elem ))
1224+ else :
1225+ # For metrics with many categories, only show significant changes
1226+ for branch in self .data ["branches" ]:
1227+ if branch == control :
1228+ continue
1229+ uplift = self .data [branch ][segment ][metric_type ][metric ]["uplift" ]
11661230
1167- for branch in self .data ["branches" ]:
1168- if branch == control :
1169- continue
1170- uplift = self .data [branch ][segment ][metric_type ][metric ]["uplift" ]
1171-
1172- for i in range (len (uplift )):
1173- # Show categories with > 1% change
1174- if abs (uplift [i ]) > 1 :
1175- indices .add (i )
1231+ for i in range (len (uplift )):
1232+ # Show categories with > 1% change
1233+ if abs (uplift [i ]) > 1 :
1234+ indices .add (i )
11761235
11771236 datasets = []
11781237 for branch in self .data ["branches" ]:
11791238 counts_branch = [
11801239 float (self .data [branch ][segment ][metric_type ][metric ]["counts" ][i ])
11811240 for i in indices
11821241 ]
1242+ sample_counts_branch = []
1243+ if "sample_counts" in self .data [branch ][segment ][metric_type ][metric ]:
1244+ sample_counts_list = self .data [branch ][segment ][metric_type ][metric ][
1245+ "sample_counts"
1246+ ]
1247+ if sample_counts_list :
1248+ sample_counts_branch = [
1249+ float (sample_counts_list [i ]) for i in indices
1250+ ]
1251+
11831252 datasets .append (
11841253 {
11851254 "branch" : branch ,
11861255 "counts" : counts_branch ,
1256+ "sample_counts" : sample_counts_branch ,
11871257 }
11881258 )
11891259
@@ -1217,6 +1287,19 @@ def createCategoricalComparison(self, segment, metric, metric_type):
12171287 else :
12181288 count_display = f"{ count_num :,} "
12191289
1290+ # Get sample count if available
1291+ sample_count = None
1292+ if "sample_counts" in dataset and dataset ["sample_counts" ]:
1293+ sample_count_num = int (dataset ["sample_counts" ][idx ])
1294+ if sample_count_num >= 1000000000 :
1295+ sample_count = f"{ sample_count_num / 1000000000 :.1f} B"
1296+ elif sample_count_num >= 1000000 :
1297+ sample_count = f"{ sample_count_num / 1000000 :.1f} M"
1298+ elif sample_count_num >= 1000 :
1299+ sample_count = f"{ sample_count_num / 1000 :.1f} K"
1300+ else :
1301+ sample_count = f"{ sample_count_num :,} "
1302+
12201303 # Uplift only for non-control branches
12211304 uplift = None
12221305 if j > 0 and len (datasets ) > 1 and "uplift" in datasets [1 ]:
@@ -1226,6 +1309,7 @@ def createCategoricalComparison(self, segment, metric, metric_type):
12261309 {
12271310 "branch_name" : dataset ["branch" ],
12281311 "count" : count_display ,
1312+ "sample_count" : sample_count ,
12291313 "uplift" : uplift ,
12301314 }
12311315 )
@@ -1246,6 +1330,7 @@ def createCategoricalComparison(self, segment, metric, metric_type):
12461330 "metric" : metric ,
12471331 "segment" : segment ,
12481332 "unit" : unit ,
1333+ "aggregate" : aggregate ,
12491334 }
12501335 self .doc (t .render (context ))
12511336
0 commit comments