| 213 | } |
| 214 | |
| 215 | func (m *MetricsCompare) result(multiplier float64) SeriesSet { |
| 216 | if m.seriesAgg != nil { |
| 217 | // In job-level mode the series come from the series aggregator. |
| 218 | return m.seriesAgg.Results() |
| 219 | } |
| 220 | |
| 221 | var ( |
| 222 | top = topN[StaticMapKey]{} |
| 223 | ss = make(SeriesSet) |
| 224 | erred = make(map[Attribute]struct{}) |
| 225 | ) |
| 226 | |
| 227 | add := func(ls Labels, counts []float64) { |
| 228 | ss[ls.MapKey()] = TimeSeries{ |
| 229 | Labels: ls, |
| 230 | Values: counts, |
| 231 | } |
| 232 | } |
| 233 | |
| 234 | addValues := func(prefix Label, data map[Attribute]map[StaticMapKey]*staticWithCounts) { |
| 235 | for a, values := range data { |
| 236 | name := a.String() |
| 237 | |
| 238 | // Compute topN values for this attribute |
| 239 | top.reset() |
| 240 | for mk, sc := range values { |
| 241 | top.add(mk, sc.counts) |
| 242 | } |
| 243 | |
| 244 | top.get(m.topN, func(mk StaticMapKey) { |
| 245 | sc := values[mk] |
| 246 | add(Labels{ |
| 247 | prefix, |
| 248 | {Name: name, Value: sc.val}, |
| 249 | }, sc.counts) |
| 250 | }) |
| 251 | |
| 252 | if len(values) > m.topN { |
| 253 | erred[a] = struct{}{} |
| 254 | } |
| 255 | } |
| 256 | } |
| 257 | |
| 258 | addValues(internalLabelTypeBaseline, m.baselines) |
| 259 | addValues(internalLabelTypeSelection, m.selections) |
| 260 | |
| 261 | // Add errors for attributes that hit the limit in either area |
| 262 | for a := range erred { |
| 263 | add(Labels{ |
| 264 | internalLabelErrorTooManyValues, |
| 265 | {Name: a.String()}, |
| 266 | }, nil) |
| 267 | } |
| 268 | |
| 269 | addTotals := func(prefix Label, data map[Attribute][]float64) { |
| 270 | for a, counts := range data { |
| 271 | add(Labels{ |
| 272 | prefix, |