@@ -1835,3 +1835,129 @@ func (n *nativeExemplars) addExemplar(e *dto.Exemplar) {
1835
1835
n .exemplars = append (n .exemplars [:nIdx ], append ([]* dto.Exemplar {e }, append (n .exemplars [nIdx :rIdx ], n .exemplars [rIdx + 1 :]... )... )... )
1836
1836
}
1837
1837
}
1838
+
1839
+ type constNativeHistogram struct {
1840
+ desc * Desc
1841
+ count uint64
1842
+ sum float64
1843
+ labelPairs []* dto.LabelPair
1844
+ nativeHistogramSchema int32
1845
+ nativeHistogramZeroThreshold float64
1846
+ nativeHistogramMaxZeroThreshold float64
1847
+ nativeHistogramMaxBuckets uint32
1848
+ nativeHistogramMinResetDuration time.Duration
1849
+ timeStamp time.Time
1850
+ nativeExemplars []* dto.Exemplar
1851
+
1852
+ positiveBuckets map [int ]int64
1853
+ negativeBuckets map [int ]int64
1854
+ zeroBucket uint64
1855
+ }
1856
+
1857
+ func NewconstNativeHistogram (desc * Desc , count uint64 , sum float64 , postiveBuckets , negativeBuckets map [int ]int64 , zeroBucket uint64 ,
1858
+ labelPairs []* dto.LabelPair , nativeHistogramSchema int32 , nativeHistogramZeroThreshold float64 ,
1859
+ nativeHistogramMaxZeroThreshold float64 , nativeHistogramMaxBuckets uint32 ,
1860
+ nativeHistogramMinResetDuration time.Duration ,
1861
+ timeStamp time.Time ,
1862
+ nativeExemplars []* dto.Exemplar ,
1863
+ ) constNativeHistogram {
1864
+ return constNativeHistogram {
1865
+ desc : desc ,
1866
+ count : count ,
1867
+ sum : sum ,
1868
+ positiveBuckets : postiveBuckets ,
1869
+ negativeBuckets : negativeBuckets ,
1870
+ zeroBucket : zeroBucket ,
1871
+ labelPairs : labelPairs ,
1872
+ nativeHistogramSchema : nativeHistogramSchema ,
1873
+ nativeHistogramZeroThreshold : nativeHistogramZeroThreshold ,
1874
+ nativeHistogramMaxZeroThreshold : nativeHistogramMaxZeroThreshold ,
1875
+ nativeHistogramMaxBuckets : nativeHistogramMaxBuckets ,
1876
+ nativeHistogramMinResetDuration : nativeHistogramMinResetDuration ,
1877
+ timeStamp : timeStamp ,
1878
+ nativeExemplars : nativeExemplars ,
1879
+ }
1880
+ }
1881
+
1882
+ func (h * constNativeHistogram ) Desc () * Desc {
1883
+ return h .desc
1884
+ }
1885
+
1886
+ func (h * constNativeHistogram ) Write (out * dto.Metric ) error {
1887
+ his := & dto.Histogram {
1888
+ CreatedTimestamp : timestamppb .New (h .timeStamp ),
1889
+ Schema : & h .nativeHistogramSchema ,
1890
+ ZeroThreshold : & h .nativeHistogramZeroThreshold ,
1891
+ Exemplars : h .nativeExemplars ,
1892
+ SampleCount : & h .count ,
1893
+ SampleSum : & h .sum ,
1894
+ }
1895
+ his .ZeroThreshold = proto .Float64 (h .nativeHistogramZeroThreshold )
1896
+ his .ZeroCount = proto .Uint64 (h .zeroBucket )
1897
+ his .NegativeSpan , his .NegativeDelta = makeBucketsAny (h .negativeBuckets )
1898
+ his .PositiveSpan , his .PositiveDelta = makeBucketsAny (h .positiveBuckets )
1899
+ if * his .ZeroThreshold == 0 && * his .ZeroCount == 0 && len (his .PositiveSpan ) == 0 && len (his .NegativeSpan ) == 0 {
1900
+ his .PositiveSpan = []* dto.BucketSpan {{
1901
+ Offset : proto .Int32 (0 ),
1902
+ Length : proto .Uint32 (0 ),
1903
+ }}
1904
+ }
1905
+ his .Exemplars = append (his .Exemplars , h .nativeExemplars ... )
1906
+ out .Histogram = his
1907
+ out .Label = h .labelPairs
1908
+ return nil
1909
+ }
1910
+
1911
+ func makeBucketsAny (buckets map [int ]int64 ) ([]* dto.BucketSpan , []int64 ) {
1912
+ var ii []int
1913
+
1914
+ for k := range buckets {
1915
+ ii = append (ii , k )
1916
+ }
1917
+ sort .Ints (ii )
1918
+
1919
+ if len (ii ) == 0 {
1920
+ return nil , nil
1921
+ }
1922
+
1923
+ var (
1924
+ spans []* dto.BucketSpan
1925
+ deltas []int64
1926
+ prevCount int64
1927
+ nextI int
1928
+ )
1929
+
1930
+ appendDelta := func (count int64 ) {
1931
+ * spans [len (spans )- 1 ].Length ++
1932
+ deltas = append (deltas , count - prevCount )
1933
+ prevCount = count
1934
+ }
1935
+
1936
+ for n , i := range ii {
1937
+ count := buckets [i ]
1938
+ // Multiple spans with only small gaps in between are probably
1939
+ // encoded more efficiently as one larger span with a few empty
1940
+ // buckets. Needs some research to find the sweet spot. For now,
1941
+ // we assume that gaps of one or two buckets should not create
1942
+ // a new span.
1943
+ iDelta := int32 (i - nextI )
1944
+ if n == 0 || iDelta > 2 {
1945
+ // We have to create a new span, either because we are
1946
+ // at the very beginning, or because we have found a gap
1947
+ // of more than two buckets.
1948
+ spans = append (spans , & dto.BucketSpan {
1949
+ Offset : proto .Int32 (iDelta ),
1950
+ Length : proto .Uint32 (0 ),
1951
+ })
1952
+ } else {
1953
+ // We have found a small gap (or no gap at all).
1954
+ // Insert empty buckets as needed.
1955
+ for j := int32 (0 ); j < iDelta ; j ++ {
1956
+ appendDelta (0 )
1957
+ }
1958
+ }
1959
+ appendDelta (count )
1960
+ nextI = i + 1
1961
+ }
1962
+ return spans , deltas
1963
+ }
0 commit comments