Skip to content

Commit

Permalink
Log metric data points in logging exporter (open-telemetry#1258)
Browse files Browse the repository at this point in the history
* Log metric data point labels in logging exporter

* Add logging for data point values

* Add test case with empty data points
  • Loading branch information
nilebox authored and wyTrivail committed Jul 13, 2020
1 parent e37840a commit 812477f
Show file tree
Hide file tree
Showing 3 changed files with 230 additions and 2 deletions.
141 changes: 139 additions & 2 deletions exporter/loggingexporter/logging_exporter.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,17 @@ func (b *logDataBuffer) logAttributeMap(label string, am pdata.AttributeMap) {
})
}

func (b *logDataBuffer) logStringMap(description string, sm pdata.StringMap) {
if sm.Len() == 0 {
return
}

b.logEntry("%s:", description)
sm.ForEach(func(k string, v pdata.StringValue) {
b.logEntry(" -> %s: %s", k, v.Value())
})
}

func (b *logDataBuffer) logInstrumentationLibrary(il pdata.InstrumentationLibrary) {
b.logEntry(
"InstrumentationLibrary %s %s",
Expand All @@ -74,6 +85,132 @@ func (b *logDataBuffer) logMetricDescriptor(md pdata.MetricDescriptor) {
b.logEntry(" -> Type: %s", md.Type().String())
}

func (b *logDataBuffer) logMetricDataPoints(m pdata.Metric) {
md := m.MetricDescriptor()
if md.IsNil() {
return
}

switch md.Type() {
case pdata.MetricTypeInvalid:
return
case pdata.MetricTypeInt64:
b.logInt64DataPoints(m.Int64DataPoints())
case pdata.MetricTypeDouble:
b.logDoubleDataPoints(m.DoubleDataPoints())
case pdata.MetricTypeMonotonicInt64:
b.logInt64DataPoints(m.Int64DataPoints())
case pdata.MetricTypeMonotonicDouble:
b.logDoubleDataPoints(m.DoubleDataPoints())
case pdata.MetricTypeHistogram:
b.logHistogramDataPoints(m.HistogramDataPoints())
case pdata.MetricTypeSummary:
b.logSummaryDataPoints(m.SummaryDataPoints())
}
}

func (b *logDataBuffer) logInt64DataPoints(ps pdata.Int64DataPointSlice) {
for i := 0; i < ps.Len(); i++ {
p := ps.At(i)
if p.IsNil() {
continue
}

b.logEntry("Int64DataPoints #%d", i)
b.logDataPointLabels(p.LabelsMap())

b.logEntry("StartTime: %d", p.StartTime())
b.logEntry("Timestamp: %d", p.Timestamp())
b.logEntry("Value: %d", p.Value())
}
}

func (b *logDataBuffer) logDoubleDataPoints(ps pdata.DoubleDataPointSlice) {
for i := 0; i < ps.Len(); i++ {
p := ps.At(i)
if p.IsNil() {
continue
}

b.logEntry("DoubleDataPoints #%d", i)
b.logDataPointLabels(p.LabelsMap())

b.logEntry("StartTime: %d", p.StartTime())
b.logEntry("Timestamp: %d", p.Timestamp())
b.logEntry("Value: %f", p.Value())
}
}

func (b *logDataBuffer) logHistogramDataPoints(ps pdata.HistogramDataPointSlice) {
for i := 0; i < ps.Len(); i++ {
p := ps.At(i)
if p.IsNil() {
continue
}

b.logEntry("HistogramDataPoints #%d", i)
b.logDataPointLabels(p.LabelsMap())

b.logEntry("StartTime: %d", p.StartTime())
b.logEntry("Timestamp: %d", p.Timestamp())
b.logEntry("Count: %d", p.Count())
b.logEntry("Sum: %f", p.Sum())

buckets := p.Buckets()
if buckets.Len() != 0 {
for i := 0; i < buckets.Len(); i++ {
bucket := buckets.At(i)
if bucket.IsNil() {
continue
}

b.logEntry("Buckets #%d, Count: %d", i, bucket.Count())
}
}

bounds := p.ExplicitBounds()
if len(bounds) != 0 {
for i, bound := range bounds {
b.logEntry("ExplicitBounds #%d: %f", i, bound)
}
}
}
}

func (b *logDataBuffer) logSummaryDataPoints(ps pdata.SummaryDataPointSlice) {
for i := 0; i < ps.Len(); i++ {
p := ps.At(i)
if p.IsNil() {
continue
}

b.logEntry("SummaryDataPoints #%d", i)
b.logDataPointLabels(p.LabelsMap())

b.logEntry("StartTime: %d", p.StartTime())
b.logEntry("Timestamp: %d", p.Timestamp())
b.logEntry("Count: %d", p.Count())
b.logEntry("Sum: %f", p.Sum())

percentiles := p.ValueAtPercentiles()
if percentiles.Len() != 0 {
for i := 0; i < percentiles.Len(); i++ {
percentile := percentiles.At(i)
if percentile.IsNil() {
continue
}

b.logEntry("ValueAtPercentiles #%d, Value: %f, Percentile: %f",
i, percentile.Value(), percentile.Percentile())
}
}
}
}

func (b *logDataBuffer) logDataPointLabels(labels pdata.StringMap) {
b.logStringMap("Data point labels", labels)
}

func attributeValueToString(av pdata.AttributeValue) string {
switch av.Type() {
case pdata.AttributeValueSTRING:
Expand Down Expand Up @@ -205,11 +342,11 @@ func (s *loggingExporter) pushMetricsData(
}

buf.logMetricDescriptor(metric.MetricDescriptor())

// TODO: Add logging for the rest of the metric properties: points.
buf.logMetricDataPoints(metric)
}
}
}

s.logger.Debug(buf.str.String())

return 0, nil
Expand Down
4 changes: 4 additions & 0 deletions exporter/loggingexporter/logging_exporter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@ func TestLoggingMetricsExporterNoErrors(t *testing.T) {
assert.NoError(t, lme.ConsumeMetrics(context.Background(), pdatautil.MetricsFromInternalMetrics(testdata.GenerateMetricDataOneEmptyOneNilInstrumentationLibrary())))
assert.NoError(t, lme.ConsumeMetrics(context.Background(), pdatautil.MetricsFromInternalMetrics(testdata.GenerateMetricDataOneMetricOneNil())))
assert.NoError(t, lme.ConsumeMetrics(context.Background(), pdatautil.MetricsFromInternalMetrics(testdata.GenerateMetricDataWithCountersHistogramAndSummary())))
assert.NoError(t, lme.ConsumeMetrics(context.Background(), pdatautil.MetricsFromInternalMetrics(testdata.GenerateMetricDataAllTypesNilDataPoint())))
assert.NoError(t, lme.ConsumeMetrics(context.Background(), pdatautil.MetricsFromInternalMetrics(testdata.GenerateMetricDataAllTypesEmptyDataPoint())))
assert.NoError(t, lme.ConsumeMetrics(context.Background(), pdatautil.MetricsFromInternalMetrics(testdata.GenerateMetricDataNilMetricDescriptor())))
assert.NoError(t, lme.ConsumeMetrics(context.Background(), pdatautil.MetricsFromInternalMetrics(testdata.GenerateMetricDataMetricTypeInvalid())))

assert.NoError(t, lme.Shutdown(context.Background()))
}
87 changes: 87 additions & 0 deletions internal/data/testdata/metric.go
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,93 @@ func GenerateMetricDataAllTypesNoDataPoints() data.MetricData {
return md
}

func GenerateMetricDataAllTypesNilDataPoint() data.MetricData {
md := GenerateMetricDataOneEmptyInstrumentationLibrary()
ilm0 := md.ResourceMetrics().At(0).InstrumentationLibraryMetrics().At(0)
ms := ilm0.Metrics()
ms.Resize(6)

nilInt64 := pdata.NewInt64DataPoint()
nilDouble := pdata.NewDoubleDataPoint()
nilHistogram := pdata.NewHistogramDataPoint()
nilSummary := pdata.NewSummaryDataPoint()

initMetricDescriptor(
ms.At(0).MetricDescriptor(), TestGaugeDoubleMetricName, pdata.MetricTypeDouble)
ms.At(0).DoubleDataPoints().Append(&nilDouble)
initMetricDescriptor(
ms.At(1).MetricDescriptor(), TestGaugeIntMetricName, pdata.MetricTypeInt64)
ms.At(1).Int64DataPoints().Append(&nilInt64)
initMetricDescriptor(
ms.At(2).MetricDescriptor(), TestCounterDoubleMetricName, pdata.MetricTypeMonotonicDouble)
ms.At(2).DoubleDataPoints().Append(&nilDouble)
initMetricDescriptor(
ms.At(3).MetricDescriptor(), TestCounterIntMetricName, pdata.MetricTypeMonotonicInt64)
ms.At(3).Int64DataPoints().Append(&nilInt64)
initMetricDescriptor(
ms.At(4).MetricDescriptor(), TestCumulativeHistogramMetricName, pdata.MetricTypeHistogram)
ms.At(4).HistogramDataPoints().Append(&nilHistogram)
initMetricDescriptor(
ms.At(5).MetricDescriptor(), TestSummaryMetricName, pdata.MetricTypeSummary)
ms.At(5).SummaryDataPoints().Append(&nilSummary)
return md
}

func GenerateMetricDataAllTypesEmptyDataPoint() data.MetricData {
md := GenerateMetricDataOneEmptyInstrumentationLibrary()
ilm0 := md.ResourceMetrics().At(0).InstrumentationLibraryMetrics().At(0)
ms := ilm0.Metrics()
ms.Resize(6)

emptyInt64 := pdata.NewInt64DataPoint()
emptyInt64.InitEmpty()
emptyDouble := pdata.NewDoubleDataPoint()
emptyDouble.InitEmpty()
emptyHistogram := pdata.NewHistogramDataPoint()
emptyHistogram.InitEmpty()
emptySummary := pdata.NewSummaryDataPoint()
emptySummary.InitEmpty()

initMetricDescriptor(
ms.At(0).MetricDescriptor(), TestGaugeDoubleMetricName, pdata.MetricTypeDouble)
ms.At(0).DoubleDataPoints().Append(&emptyDouble)
initMetricDescriptor(
ms.At(1).MetricDescriptor(), TestGaugeIntMetricName, pdata.MetricTypeInt64)
ms.At(1).Int64DataPoints().Append(&emptyInt64)
initMetricDescriptor(
ms.At(2).MetricDescriptor(), TestCounterDoubleMetricName, pdata.MetricTypeMonotonicDouble)
ms.At(2).DoubleDataPoints().Append(&emptyDouble)
initMetricDescriptor(
ms.At(3).MetricDescriptor(), TestCounterIntMetricName, pdata.MetricTypeMonotonicInt64)
ms.At(3).Int64DataPoints().Append(&emptyInt64)
initMetricDescriptor(
ms.At(4).MetricDescriptor(), TestCumulativeHistogramMetricName, pdata.MetricTypeHistogram)
ms.At(4).HistogramDataPoints().Append(&emptyHistogram)
initMetricDescriptor(
ms.At(5).MetricDescriptor(), TestSummaryMetricName, pdata.MetricTypeSummary)
ms.At(5).SummaryDataPoints().Append(&emptySummary)
return md
}

func GenerateMetricDataNilMetricDescriptor() data.MetricData {
md := GenerateMetricDataOneEmptyInstrumentationLibrary()
ilm0 := md.ResourceMetrics().At(0).InstrumentationLibraryMetrics().At(0)
ms := ilm0.Metrics()
ms.Resize(1)
return md
}

func GenerateMetricDataMetricTypeInvalid() data.MetricData {
md := GenerateMetricDataOneEmptyInstrumentationLibrary()
ilm0 := md.ResourceMetrics().At(0).InstrumentationLibraryMetrics().At(0)
ms := ilm0.Metrics()
ms.Resize(1)

initMetricDescriptor(
ms.At(0).MetricDescriptor(), TestGaugeDoubleMetricName, pdata.MetricTypeInvalid)
return md
}

func generateMetricOtlpAllTypesNoDataPoints() []*otlpmetrics.ResourceMetrics {
return []*otlpmetrics.ResourceMetrics{
{
Expand Down

0 comments on commit 812477f

Please sign in to comment.