starttimemetricadjuster.go 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. // Copyright The OpenTelemetry Authors
  2. // SPDX-License-Identifier: Apache-2.0
  3. package internal // import "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/prometheusreceiver/internal"
  4. import (
  5. "errors"
  6. "regexp"
  7. "go.opentelemetry.io/collector/pdata/pmetric"
  8. "go.uber.org/zap"
  9. )
  10. var (
  11. errNoStartTimeMetrics = errors.New("start_time metric is missing")
  12. errNoDataPointsStartTimeMetric = errors.New("start time metric with no data points")
  13. errUnsupportedTypeStartTimeMetric = errors.New("unsupported data type for start time metric")
  14. )
  15. type startTimeMetricAdjuster struct {
  16. startTimeMetricRegex *regexp.Regexp
  17. logger *zap.Logger
  18. }
  19. // NewStartTimeMetricAdjuster returns a new MetricsAdjuster that adjust metrics' start times based on a start time metric.
  20. func NewStartTimeMetricAdjuster(logger *zap.Logger, startTimeMetricRegex *regexp.Regexp) MetricsAdjuster {
  21. return &startTimeMetricAdjuster{
  22. startTimeMetricRegex: startTimeMetricRegex,
  23. logger: logger,
  24. }
  25. }
  26. func (stma *startTimeMetricAdjuster) AdjustMetrics(metrics pmetric.Metrics) error {
  27. startTime, err := stma.getStartTime(metrics)
  28. if err != nil {
  29. return err
  30. }
  31. startTimeTs := timestampFromFloat64(startTime)
  32. for i := 0; i < metrics.ResourceMetrics().Len(); i++ {
  33. rm := metrics.ResourceMetrics().At(i)
  34. for j := 0; j < rm.ScopeMetrics().Len(); j++ {
  35. ilm := rm.ScopeMetrics().At(j)
  36. for k := 0; k < ilm.Metrics().Len(); k++ {
  37. metric := ilm.Metrics().At(k)
  38. switch metric.Type() {
  39. case pmetric.MetricTypeGauge:
  40. continue
  41. case pmetric.MetricTypeSum:
  42. dataPoints := metric.Sum().DataPoints()
  43. for l := 0; l < dataPoints.Len(); l++ {
  44. dp := dataPoints.At(l)
  45. dp.SetStartTimestamp(startTimeTs)
  46. }
  47. case pmetric.MetricTypeSummary:
  48. dataPoints := metric.Summary().DataPoints()
  49. for l := 0; l < dataPoints.Len(); l++ {
  50. dp := dataPoints.At(l)
  51. dp.SetStartTimestamp(startTimeTs)
  52. }
  53. case pmetric.MetricTypeHistogram:
  54. dataPoints := metric.Histogram().DataPoints()
  55. for l := 0; l < dataPoints.Len(); l++ {
  56. dp := dataPoints.At(l)
  57. dp.SetStartTimestamp(startTimeTs)
  58. }
  59. case pmetric.MetricTypeEmpty, pmetric.MetricTypeExponentialHistogram:
  60. fallthrough
  61. default:
  62. stma.logger.Warn("Unknown metric type", zap.String("type", metric.Type().String()))
  63. }
  64. }
  65. }
  66. }
  67. return nil
  68. }
  69. func (stma *startTimeMetricAdjuster) getStartTime(metrics pmetric.Metrics) (float64, error) {
  70. for i := 0; i < metrics.ResourceMetrics().Len(); i++ {
  71. rm := metrics.ResourceMetrics().At(i)
  72. for j := 0; j < rm.ScopeMetrics().Len(); j++ {
  73. ilm := rm.ScopeMetrics().At(j)
  74. for k := 0; k < ilm.Metrics().Len(); k++ {
  75. metric := ilm.Metrics().At(k)
  76. if stma.matchStartTimeMetric(metric.Name()) {
  77. switch metric.Type() {
  78. case pmetric.MetricTypeGauge:
  79. if metric.Gauge().DataPoints().Len() == 0 {
  80. return 0.0, errNoDataPointsStartTimeMetric
  81. }
  82. return metric.Gauge().DataPoints().At(0).DoubleValue(), nil
  83. case pmetric.MetricTypeSum:
  84. if metric.Sum().DataPoints().Len() == 0 {
  85. return 0.0, errNoDataPointsStartTimeMetric
  86. }
  87. return metric.Sum().DataPoints().At(0).DoubleValue(), nil
  88. case pmetric.MetricTypeEmpty, pmetric.MetricTypeHistogram, pmetric.MetricTypeExponentialHistogram, pmetric.MetricTypeSummary:
  89. fallthrough
  90. default:
  91. return 0, errUnsupportedTypeStartTimeMetric
  92. }
  93. }
  94. }
  95. }
  96. }
  97. return 0.0, errNoStartTimeMetrics
  98. }
  99. func (stma *startTimeMetricAdjuster) matchStartTimeMetric(metricName string) bool {
  100. if stma.startTimeMetricRegex != nil {
  101. return stma.startTimeMetricRegex.MatchString(metricName)
  102. }
  103. return metricName == startTimeMetricName
  104. }