@@ -1835,3 +1835,129 @@ func (n *nativeExemplars) addExemplar(e *dto.Exemplar) {
18351835 n .exemplars = append (n .exemplars [:nIdx ], append ([]* dto.Exemplar {e }, append (n .exemplars [nIdx :rIdx ], n .exemplars [rIdx + 1 :]... )... )... )
18361836 }
18371837}
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