| 1928 | } |
| 1929 | |
| 1930 | func (h *HistogramAggregator) Results() SeriesSet { |
| 1931 | results := make(SeriesSet, len(h.ss)*len(h.qs)) |
| 1932 | |
| 1933 | // Aggregate buckets across all series and time intervals for better quantile calculation |
| 1934 | aggregatedBuckets := make(map[float64]int) // bucketMax -> totalCount |
| 1935 | |
| 1936 | for _, in := range h.ss { |
| 1937 | // Aggregate bucket counts across all time intervals |
| 1938 | for _, hist := range in.hist { |
| 1939 | for _, bucket := range hist.Buckets { |
| 1940 | aggregatedBuckets[bucket.Max] += bucket.Count |
| 1941 | } |
| 1942 | } |
| 1943 | } |
| 1944 | |
| 1945 | // Calculate quantile values from aggregated distribution |
| 1946 | // Convert map to sorted slice |
| 1947 | buckets := make([]HistogramBucket, 0, len(aggregatedBuckets)) |
| 1948 | for bucketMax, count := range aggregatedBuckets { |
| 1949 | buckets = append(buckets, HistogramBucket{ |
| 1950 | Max: bucketMax, |
| 1951 | Count: count, |
| 1952 | }) |
| 1953 | } |
| 1954 | |
| 1955 | sort.Slice(buckets, func(i, j int) bool { |
| 1956 | return buckets[i].Max < buckets[j].Max |
| 1957 | }) |
| 1958 | |
| 1959 | quantileValues := make([]float64, len(h.qs)) |
| 1960 | for i, q := range h.qs { |
| 1961 | quantileValues[i] = Log2Quantile(q, buckets) |
| 1962 | } |
| 1963 | |
| 1964 | // Build results using the calculated quantile values |
| 1965 | for _, in := range h.ss { |
| 1966 | for i := range in.hist { |
| 1967 | if len(in.hist[i].Buckets) > 0 { |
| 1968 | // Sort interval buckets in place for performance |
| 1969 | sort.Slice(in.hist[i].Buckets, func(a, b int) bool { |
| 1970 | return in.hist[i].Buckets[a].Max < in.hist[i].Buckets[b].Max |
| 1971 | }) |
| 1972 | } |
| 1973 | } |
| 1974 | |
| 1975 | // For each input series, we create a new series for each quantile. |
| 1976 | for qIdx, q := range h.qs { |
| 1977 | // Append label for the quantile |
| 1978 | labels := append((Labels)(nil), in.labels...) |
| 1979 | labels = append(labels, Label{"p", NewStaticFloat(q)}) |
| 1980 | |
| 1981 | ts := TimeSeries{ |
| 1982 | Labels: labels, |
| 1983 | Values: make([]float64, len(in.hist)), |
| 1984 | } |
| 1985 | |
| 1986 | for i := range in.hist { |
| 1987 | if len(in.hist[i].Buckets) == 0 { |