Skip to content

Commit d48b9fa

Browse files
[exporter/debug] output buckets for exponential histograms (#14656)
<!--Ex. Fixing a bug - Describe the bug and how this fixes the issue. Ex. Adding a feature - Explain what this achieves.--> #### Description the `writeexponentialhistogramdatapoints` function in the debug exporter’s normal verbosity mode previously had todo placeholder and did not print any bucket data. this change implements the missing bucket display. each bucket is now printed as `leX=Y`, where `X` is the computed upper bound and `Y` is the bucket count. for positive buckets, the upper bound is calculated as `exp((index+1) * factor)`, and for negative buckets as `-exp(index * factor)`, where `factor = math.Ldexp(math.Ln2, -scale)`. negative buckets are listed from most-negative to least-negative, and the zero bucket is printed as `zero=N` when its count is non-zero. <!-- Issue number if applicable --> #### Link to tracking issue Fixes #10463 <!--Describe what testing was performed and which tests were added.--> #### Testing <!--Describe the documentation added.--> #### Documentation No documentation changes required. <!--Please delete paragraphs that you did not use before submitting.--> --------- Signed-off-by: arpit529srivastava <arpitsrivastava529@gmail.com>
1 parent 843bbc3 commit d48b9fa

3 files changed

Lines changed: 105 additions & 8 deletions

File tree

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# Use this changelog template to create an entry for release notes.
2+
3+
# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix'
4+
change_type: enhancement
5+
6+
# The name of the component, or a single word describing the area of concern, (e.g. receiver/otlp)
7+
component: exporter/debug
8+
9+
# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`).
10+
note: Output bucket counts for exponential histogram data points in normal verbosity.
11+
12+
# One or more tracking issues or pull requests related to the change
13+
issues: [10463]
14+
15+
# (Optional) One or more lines of additional information to render under the primary note.
16+
# These lines will be padded with 2 spaces and then inserted directly into the document.
17+
# Use pipe (|) for multiline entries.
18+
subtext:
19+
20+
# Optional: The change log or logs in which this entry should be included.
21+
# e.g. '[user]' or '[user, api]'
22+
# Include 'user' if the change is relevant to end users.
23+
# Include 'api' if there is a change to a library API.
24+
# Default: '[user]'
25+
change_logs: [user]

exporter/debugexporter/internal/normal/metrics.go

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ package normal // import "go.opentelemetry.io/collector/exporter/debugexporter/i
66
import (
77
"bytes"
88
"fmt"
9+
"math"
910
"strconv"
1011
"strings"
1112

@@ -115,21 +116,39 @@ func writeExponentialHistogramDataPoints(metric pmetric.Metric) (lines []string)
115116
dataPoint := metric.ExponentialHistogram().DataPoints().At(i)
116117
dataPointAttributes := writeAttributes(dataPoint.Attributes())
117118

118-
var value string
119-
value = fmt.Sprintf("count=%d", dataPoint.Count())
119+
var value strings.Builder
120+
fmt.Fprintf(&value, "count=%d", dataPoint.Count())
120121
if dataPoint.HasSum() {
121-
value += fmt.Sprintf(" sum=%v", dataPoint.Sum())
122+
fmt.Fprintf(&value, " sum=%v", dataPoint.Sum())
122123
}
123124
if dataPoint.HasMin() {
124-
value += fmt.Sprintf(" min=%v", dataPoint.Min())
125+
fmt.Fprintf(&value, " min=%v", dataPoint.Min())
125126
}
126127
if dataPoint.HasMax() {
127-
value += fmt.Sprintf(" max=%v", dataPoint.Max())
128+
fmt.Fprintf(&value, " max=%v", dataPoint.Max())
128129
}
129130

130-
// TODO display buckets
131+
factor := math.Ldexp(math.Ln2, -int(dataPoint.Scale()))
131132

132-
dataPointLine := fmt.Sprintf("%s{%s} %s\n", metric.Name(), strings.Join(dataPointAttributes, ","), value)
133+
negB := dataPoint.Negative()
134+
for j := negB.BucketCounts().Len() - 1; j >= 0; j-- {
135+
index := float64(negB.Offset()) + float64(j)
136+
upperBound := -math.Exp(index * factor)
137+
fmt.Fprintf(&value, " le%v=%d", upperBound, negB.BucketCounts().At(j))
138+
}
139+
140+
if dataPoint.ZeroCount() != 0 {
141+
fmt.Fprintf(&value, " zero=%d", dataPoint.ZeroCount())
142+
}
143+
144+
posB := dataPoint.Positive()
145+
for j := 0; j < posB.BucketCounts().Len(); j++ {
146+
index := float64(posB.Offset()) + float64(j)
147+
upperBound := math.Exp((index + 1) * factor)
148+
fmt.Fprintf(&value, " le%v=%d", upperBound, posB.BucketCounts().At(j))
149+
}
150+
151+
dataPointLine := fmt.Sprintf("%s{%s} %s\n", metric.Name(), strings.Join(dataPointAttributes, ","), value.String())
133152
lines = append(lines, dataPointLine)
134153
}
135154
return lines

exporter/debugexporter/internal/normal/metrics_test.go

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
package normal
55

66
import (
7+
"fmt"
8+
"math"
79
"testing"
810

911
"github.com/stretchr/testify/assert"
@@ -107,7 +109,7 @@ http.server.request.duration{http.response.status_code=200,http.request.method=G
107109
`,
108110
},
109111
{
110-
name: "exponential histogram",
112+
name: "exponential histogram without buckets",
111113
input: func() pmetric.Metrics {
112114
metrics := pmetric.NewMetrics()
113115
metric := metrics.ResourceMetrics().AppendEmpty().ScopeMetrics().AppendEmpty().Metrics().AppendEmpty()
@@ -126,6 +128,57 @@ ScopeMetrics #0
126128
http.server.request.duration{http.response.status_code=200,http.request.method=GET} count=1340 sum=99.573 min=0.017 max=8.13
127129
`,
128130
},
131+
{
132+
name: "exponential histogram with buckets",
133+
input: func() pmetric.Metrics {
134+
metrics := pmetric.NewMetrics()
135+
metric := metrics.ResourceMetrics().AppendEmpty().ScopeMetrics().AppendEmpty().Metrics().AppendEmpty()
136+
metric.SetName("http.server.request.duration")
137+
dataPoint := metric.SetEmptyExponentialHistogram().DataPoints().AppendEmpty()
138+
dataPoint.Attributes().PutInt("http.response.status_code", 200)
139+
dataPoint.Attributes().PutStr("http.request.method", "GET")
140+
dataPoint.SetCount(1340)
141+
dataPoint.SetSum(99.573)
142+
dataPoint.SetMin(0.017)
143+
dataPoint.SetMax(8.13)
144+
dataPoint.SetScale(3)
145+
dataPoint.SetZeroCount(3)
146+
dataPoint.Negative().SetOffset(-2)
147+
dataPoint.Negative().BucketCounts().FromRaw([]uint64{10, 20})
148+
dataPoint.Positive().SetOffset(1)
149+
dataPoint.Positive().BucketCounts().FromRaw([]uint64{40, 50, 60})
150+
return metrics
151+
}(),
152+
expected: func() string {
153+
f := math.Ldexp(math.Ln2, -3)
154+
return fmt.Sprintf("ResourceMetrics #0\nScopeMetrics #0\n"+
155+
"http.server.request.duration{http.response.status_code=200,http.request.method=GET}"+
156+
" count=1340 sum=99.573 min=0.017 max=8.13"+
157+
" le%v=20 le%v=10 zero=3 le%v=40 le%v=50 le%v=60\n",
158+
-math.Exp(-1*f), -math.Exp(-2*f),
159+
math.Exp(2*f), math.Exp(3*f), math.Exp(4*f))
160+
}(),
161+
},
162+
{
163+
name: "exponential histogram with positive buckets only",
164+
input: func() pmetric.Metrics {
165+
metrics := pmetric.NewMetrics()
166+
metric := metrics.ResourceMetrics().AppendEmpty().ScopeMetrics().AppendEmpty().Metrics().AppendEmpty()
167+
metric.SetName("latency")
168+
dataPoint := metric.SetEmptyExponentialHistogram().DataPoints().AppendEmpty()
169+
dataPoint.SetCount(2)
170+
dataPoint.SetScale(1)
171+
dataPoint.Positive().SetOffset(1)
172+
dataPoint.Positive().BucketCounts().FromRaw([]uint64{1, 1})
173+
return metrics
174+
}(),
175+
expected: func() string {
176+
f := math.Ldexp(math.Ln2, -1)
177+
return fmt.Sprintf("ResourceMetrics #0\nScopeMetrics #0\n"+
178+
"latency{} count=2 le%v=1 le%v=1\n",
179+
math.Exp(2*f), math.Exp(3*f))
180+
}(),
181+
},
129182
{
130183
name: "summary",
131184
input: func() pmetric.Metrics {

0 commit comments

Comments
 (0)