diff --git a/exporter/loggingexporter/logging_exporter.go b/exporter/loggingexporter/logging_exporter.go index 1c2a49a0f1b..20da7f566da 100644 --- a/exporter/loggingexporter/logging_exporter.go +++ b/exporter/loggingexporter/logging_exporter.go @@ -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", @@ -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: @@ -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 diff --git a/exporter/loggingexporter/logging_exporter_test.go b/exporter/loggingexporter/logging_exporter_test.go index 8850bbfe2b7..8d37ddd1b8d 100644 --- a/exporter/loggingexporter/logging_exporter_test.go +++ b/exporter/loggingexporter/logging_exporter_test.go @@ -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())) } diff --git a/internal/data/testdata/metric.go b/internal/data/testdata/metric.go index 96be10c52fd..c348a5f0d3d 100644 --- a/internal/data/testdata/metric.go +++ b/internal/data/testdata/metric.go @@ -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{ {