forked from open-telemetry/opentelemetry-collector
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[exporter/debug] format metric data points as one-liners in
normal
…
…verbosity (open-telemetry#10462) #### Description This pull request is part of open-telemetry#7806; it implements the change for metrics. The changes for [logs](open-telemetry#10225) and [traces](open-telemetry#10280) have been proposed in separate pull requests. This change applies to the Debug exporter only. The behavior of the Logging exporter remains unchanged. To use this behavior, switch from the deprecated Logging exporter to Debug exporter. #### Link to tracking issue - open-telemetry#7806 #### Testing Added unit tests for the formatter. #### Documentation Described the formatting in the Debug exporter's README.
- Loading branch information
1 parent
3364ba1
commit 1d1ff4a
Showing
6 changed files
with
280 additions
and
36 deletions.
There are no files selected for viewing
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,149 @@ | ||
// Copyright The OpenTelemetry Authors | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
package normal // import "go.opentelemetry.io/collector/exporter/debugexporter/internal/normal" | ||
|
||
import ( | ||
"bytes" | ||
"fmt" | ||
"strings" | ||
|
||
"go.opentelemetry.io/collector/pdata/pmetric" | ||
) | ||
|
||
type normalMetricsMarshaler struct{} | ||
|
||
// Ensure normalMetricsMarshaller implements interface pmetric.Marshaler | ||
var _ pmetric.Marshaler = normalMetricsMarshaler{} | ||
|
||
// NewNormalMetricsMarshaler returns a pmetric.Marshaler for normal verbosity. It writes one line of text per log record | ||
func NewNormalMetricsMarshaler() pmetric.Marshaler { | ||
return normalMetricsMarshaler{} | ||
} | ||
|
||
func (normalMetricsMarshaler) MarshalMetrics(md pmetric.Metrics) ([]byte, error) { | ||
var buffer bytes.Buffer | ||
for i := 0; i < md.ResourceMetrics().Len(); i++ { | ||
resourceMetrics := md.ResourceMetrics().At(i) | ||
for j := 0; j < resourceMetrics.ScopeMetrics().Len(); j++ { | ||
scopeMetrics := resourceMetrics.ScopeMetrics().At(j) | ||
for k := 0; k < scopeMetrics.Metrics().Len(); k++ { | ||
metric := scopeMetrics.Metrics().At(k) | ||
|
||
var dataPointLines []string | ||
switch metric.Type() { | ||
case pmetric.MetricTypeGauge: | ||
dataPointLines = writeNumberDataPoints(metric, metric.Gauge().DataPoints()) | ||
case pmetric.MetricTypeSum: | ||
dataPointLines = writeNumberDataPoints(metric, metric.Sum().DataPoints()) | ||
case pmetric.MetricTypeHistogram: | ||
dataPointLines = writeHistogramDataPoints(metric) | ||
case pmetric.MetricTypeExponentialHistogram: | ||
dataPointLines = writeExponentialHistogramDataPoints(metric) | ||
case pmetric.MetricTypeSummary: | ||
dataPointLines = writeSummaryDataPoints(metric) | ||
} | ||
for _, line := range dataPointLines { | ||
buffer.WriteString(line) | ||
} | ||
} | ||
} | ||
} | ||
return buffer.Bytes(), nil | ||
} | ||
|
||
func writeNumberDataPoints(metric pmetric.Metric, dataPoints pmetric.NumberDataPointSlice) (lines []string) { | ||
for i := 0; i < dataPoints.Len(); i++ { | ||
dataPoint := dataPoints.At(i) | ||
dataPointAttributes := writeAttributes(dataPoint.Attributes()) | ||
|
||
var value string | ||
switch dataPoint.ValueType() { | ||
case pmetric.NumberDataPointValueTypeInt: | ||
value = fmt.Sprintf("%v", dataPoint.IntValue()) | ||
case pmetric.NumberDataPointValueTypeDouble: | ||
value = fmt.Sprintf("%v", dataPoint.DoubleValue()) | ||
} | ||
|
||
dataPointLine := fmt.Sprintf("%s{%s} %s\n", metric.Name(), strings.Join(dataPointAttributes, ","), value) | ||
lines = append(lines, dataPointLine) | ||
} | ||
return lines | ||
} | ||
|
||
func writeHistogramDataPoints(metric pmetric.Metric) (lines []string) { | ||
for i := 0; i < metric.Histogram().DataPoints().Len(); i++ { | ||
dataPoint := metric.Histogram().DataPoints().At(i) | ||
dataPointAttributes := writeAttributes(dataPoint.Attributes()) | ||
|
||
var value string | ||
value = fmt.Sprintf("count=%d", dataPoint.Count()) | ||
if dataPoint.HasSum() { | ||
value += fmt.Sprintf(" sum=%v", dataPoint.Sum()) | ||
} | ||
if dataPoint.HasMin() { | ||
value += fmt.Sprintf(" min=%v", dataPoint.Min()) | ||
} | ||
if dataPoint.HasMax() { | ||
value += fmt.Sprintf(" max=%v", dataPoint.Max()) | ||
} | ||
|
||
for bucketIndex := 0; bucketIndex < dataPoint.BucketCounts().Len(); bucketIndex++ { | ||
bucketBound := "" | ||
if bucketIndex < dataPoint.ExplicitBounds().Len() { | ||
bucketBound = fmt.Sprintf("le%v=", dataPoint.ExplicitBounds().At(bucketIndex)) | ||
} | ||
bucketCount := dataPoint.BucketCounts().At(bucketIndex) | ||
value += fmt.Sprintf(" %s%d", bucketBound, bucketCount) | ||
} | ||
|
||
dataPointLine := fmt.Sprintf("%s{%s} %s\n", metric.Name(), strings.Join(dataPointAttributes, ","), value) | ||
lines = append(lines, dataPointLine) | ||
} | ||
return lines | ||
} | ||
|
||
func writeExponentialHistogramDataPoints(metric pmetric.Metric) (lines []string) { | ||
for i := 0; i < metric.ExponentialHistogram().DataPoints().Len(); i++ { | ||
dataPoint := metric.ExponentialHistogram().DataPoints().At(i) | ||
dataPointAttributes := writeAttributes(dataPoint.Attributes()) | ||
|
||
var value string | ||
value = fmt.Sprintf("count=%d", dataPoint.Count()) | ||
if dataPoint.HasSum() { | ||
value += fmt.Sprintf(" sum=%v", dataPoint.Sum()) | ||
} | ||
if dataPoint.HasMin() { | ||
value += fmt.Sprintf(" min=%v", dataPoint.Min()) | ||
} | ||
if dataPoint.HasMax() { | ||
value += fmt.Sprintf(" max=%v", dataPoint.Max()) | ||
} | ||
|
||
// TODO display buckets | ||
|
||
dataPointLine := fmt.Sprintf("%s{%s} %s\n", metric.Name(), strings.Join(dataPointAttributes, ","), value) | ||
lines = append(lines, dataPointLine) | ||
} | ||
return lines | ||
} | ||
|
||
func writeSummaryDataPoints(metric pmetric.Metric) (lines []string) { | ||
for i := 0; i < metric.Summary().DataPoints().Len(); i++ { | ||
dataPoint := metric.Summary().DataPoints().At(i) | ||
dataPointAttributes := writeAttributes(dataPoint.Attributes()) | ||
|
||
var value string | ||
value = fmt.Sprintf("count=%d", dataPoint.Count()) | ||
value += fmt.Sprintf(" sum=%f", dataPoint.Sum()) | ||
|
||
for quantileIndex := 0; quantileIndex < dataPoint.QuantileValues().Len(); quantileIndex++ { | ||
quantile := dataPoint.QuantileValues().At(quantileIndex) | ||
value += fmt.Sprintf(" q%v=%v", quantile.Quantile(), quantile.Value()) | ||
} | ||
|
||
dataPointLine := fmt.Sprintf("%s{%s} %s\n", metric.Name(), strings.Join(dataPointAttributes, ","), value) | ||
lines = append(lines, dataPointLine) | ||
} | ||
return lines | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
// Copyright The OpenTelemetry Authors | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
package normal | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/stretchr/testify/assert" | ||
|
||
"go.opentelemetry.io/collector/pdata/pmetric" | ||
) | ||
|
||
func TestMarshalMetrics(t *testing.T) { | ||
tests := []struct { | ||
name string | ||
input pmetric.Metrics | ||
expected string | ||
}{ | ||
{ | ||
name: "empty metrics", | ||
input: pmetric.NewMetrics(), | ||
expected: "", | ||
}, | ||
{ | ||
name: "sum data point", | ||
input: func() pmetric.Metrics { | ||
metrics := pmetric.NewMetrics() | ||
metric := metrics.ResourceMetrics().AppendEmpty().ScopeMetrics().AppendEmpty().Metrics().AppendEmpty() | ||
metric.SetName("system.cpu.time") | ||
dataPoint := metric.SetEmptySum().DataPoints().AppendEmpty() | ||
dataPoint.SetDoubleValue(123.456) | ||
dataPoint.Attributes().PutStr("state", "user") | ||
dataPoint.Attributes().PutStr("cpu", "0") | ||
return metrics | ||
}(), | ||
expected: `system.cpu.time{state=user,cpu=0} 123.456 | ||
`, | ||
}, | ||
{ | ||
name: "gauge data point", | ||
input: func() pmetric.Metrics { | ||
metrics := pmetric.NewMetrics() | ||
metric := metrics.ResourceMetrics().AppendEmpty().ScopeMetrics().AppendEmpty().Metrics().AppendEmpty() | ||
metric.SetName("system.cpu.utilization") | ||
dataPoint := metric.SetEmptyGauge().DataPoints().AppendEmpty() | ||
dataPoint.SetDoubleValue(78.901234567) | ||
dataPoint.Attributes().PutStr("state", "free") | ||
dataPoint.Attributes().PutStr("cpu", "8") | ||
return metrics | ||
}(), | ||
expected: `system.cpu.utilization{state=free,cpu=8} 78.901234567 | ||
`, | ||
}, | ||
{ | ||
name: "histogram", | ||
input: func() pmetric.Metrics { | ||
metrics := pmetric.NewMetrics() | ||
metric := metrics.ResourceMetrics().AppendEmpty().ScopeMetrics().AppendEmpty().Metrics().AppendEmpty() | ||
metric.SetName("http.server.request.duration") | ||
dataPoint := metric.SetEmptyHistogram().DataPoints().AppendEmpty() | ||
dataPoint.Attributes().PutInt("http.response.status_code", 200) | ||
dataPoint.Attributes().PutStr("http.request.method", "GET") | ||
dataPoint.ExplicitBounds().FromRaw([]float64{0.125, 0.5, 1, 3}) | ||
dataPoint.BucketCounts().FromRaw([]uint64{1324, 13, 0, 2, 1}) | ||
dataPoint.SetCount(1340) | ||
dataPoint.SetSum(99.573) | ||
dataPoint.SetMin(0.017) | ||
dataPoint.SetMax(8.13) | ||
return metrics | ||
}(), | ||
expected: `http.server.request.duration{http.response.status_code=200,http.request.method=GET} count=1340 sum=99.573 min=0.017 max=8.13 le0.125=1324 le0.5=13 le1=0 le3=2 1 | ||
`, | ||
}, | ||
{ | ||
name: "exponential histogram", | ||
input: func() pmetric.Metrics { | ||
metrics := pmetric.NewMetrics() | ||
metric := metrics.ResourceMetrics().AppendEmpty().ScopeMetrics().AppendEmpty().Metrics().AppendEmpty() | ||
metric.SetName("http.server.request.duration") | ||
dataPoint := metric.SetEmptyExponentialHistogram().DataPoints().AppendEmpty() | ||
dataPoint.Attributes().PutInt("http.response.status_code", 200) | ||
dataPoint.Attributes().PutStr("http.request.method", "GET") | ||
dataPoint.SetCount(1340) | ||
dataPoint.SetSum(99.573) | ||
dataPoint.SetMin(0.017) | ||
dataPoint.SetMax(8.13) | ||
return metrics | ||
}(), | ||
expected: `http.server.request.duration{http.response.status_code=200,http.request.method=GET} count=1340 sum=99.573 min=0.017 max=8.13 | ||
`, | ||
}, | ||
{ | ||
name: "summary", | ||
input: func() pmetric.Metrics { | ||
metrics := pmetric.NewMetrics() | ||
metric := metrics.ResourceMetrics().AppendEmpty().ScopeMetrics().AppendEmpty().Metrics().AppendEmpty() | ||
metric.SetName("summary") | ||
dataPoint := metric.SetEmptySummary().DataPoints().AppendEmpty() | ||
dataPoint.Attributes().PutInt("http.response.status_code", 200) | ||
dataPoint.Attributes().PutStr("http.request.method", "GET") | ||
dataPoint.SetCount(1340) | ||
dataPoint.SetSum(99.573) | ||
quantile := dataPoint.QuantileValues().AppendEmpty() | ||
quantile.SetQuantile(0.01) | ||
quantile.SetValue(15) | ||
return metrics | ||
}(), | ||
expected: `summary{http.response.status_code=200,http.request.method=GET} count=1340 sum=99.573000 q0.01=15 | ||
`, | ||
}, | ||
} | ||
for _, tt := range tests { | ||
t.Run(tt.name, func(t *testing.T) { | ||
output, err := NewNormalMetricsMarshaler().MarshalMetrics(tt.input) | ||
assert.NoError(t, err) | ||
assert.Equal(t, tt.expected, string(output)) | ||
}) | ||
} | ||
} |