| 243 | } |
| 244 | |
| 245 | func sortResponse(res *tempopb.QueryRangeResponse) { |
| 246 | // Sort all output, series alphabetically, samples by time |
| 247 | sort.SliceStable(res.Series, func(i, j int) bool { |
| 248 | li := len(res.Series[i].Labels) |
| 249 | lj := len(res.Series[j].Labels) |
| 250 | if li != lj { |
| 251 | return li < lj |
| 252 | } |
| 253 | for k := range res.Series[i].Labels { |
| 254 | ki := res.Series[i].Labels[k].Key |
| 255 | kj := res.Series[j].Labels[k].Key |
| 256 | if ki != kj { |
| 257 | return ki < kj |
| 258 | } |
| 259 | |
| 260 | si := res.Series[i].Labels[k].Value.String() |
| 261 | sj := res.Series[j].Labels[k].Value.String() |
| 262 | if si != sj { |
| 263 | return si < sj |
| 264 | } |
| 265 | } |
| 266 | return false |
| 267 | }) |
| 268 | for _, series := range res.Series { |
| 269 | sort.Slice(series.Samples, func(i, j int) bool { |
| 270 | return series.Samples[i].TimestampMs < series.Samples[j].TimestampMs |
| 271 | }) |
| 272 | sort.Slice(series.Exemplars, func(i, j int) bool { |
| 273 | return series.Exemplars[i].TimestampMs < series.Exemplars[j].TimestampMs |
| 274 | }) |
| 275 | } |
| 276 | } |
| 277 | |
| 278 | // attachExemplars to the final series outputs. Placeholder exemplars for things like rate() |
| 279 | // have NaNs, and we can't attach them until the very end. |