123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533 |
- // Copyright The OpenTelemetry Authors
- // SPDX-License-Identifier: Apache-2.0
- package prometheusreceiver
- import (
- "fmt"
- "sync"
- "testing"
- "time"
- promcfg "github.com/prometheus/prometheus/config"
- "github.com/stretchr/testify/assert"
- "go.opentelemetry.io/collector/pdata/pcommon"
- "go.opentelemetry.io/collector/pdata/pmetric"
- )
- var (
- timeNow = time.Now()
- ts1 = timeNow.Add(10 * time.Second).UnixMilli()
- ts2 = timeNow.Add(20 * time.Second).UnixMilli()
- ts3 = timeNow.Add(30 * time.Second).UnixMilli()
- ts4 = timeNow.Add(40 * time.Second).UnixMilli()
- ts5 = timeNow.Add(50 * time.Second).UnixMilli()
- ts6 = timeNow.Add(60 * time.Second).UnixMilli()
- ts7 = timeNow.Add(70 * time.Second).UnixMilli()
- ts8 = timeNow.Add(80 * time.Second).UnixMilli()
- ts9 = timeNow.Add(90 * time.Second).UnixMilli()
- ts10 = timeNow.Add(100 * time.Second).UnixMilli()
- ts11 = timeNow.Add(110 * time.Second).UnixMilli()
- ts12 = timeNow.Add(120 * time.Second).UnixMilli()
- ts13 = timeNow.Add(130 * time.Second).UnixMilli()
- ts14 = timeNow.Add(140 * time.Second).UnixMilli()
- ts15 = timeNow.Add(150 * time.Second).UnixMilli()
- )
- var onlyOnce sync.Once
- // honorTimestampsPage2 has lower values for metrics than honorTimestampsPage1.
- // So, the start_timestamp should get reset.
- var honorTimestampsPage1 = `
- # HELP go_threads Number of OS threads created
- # TYPE go_thread gauge
- go_threads 19 %v
- # HELP http_requests_total The total number of HTTP requests.
- # TYPE http_requests_total counter
- http_requests_total{method="post",code="200"} 100 %v
- http_requests_total{method="post",code="400"} 5 %v
- # HELP http_request_duration_seconds A histogram of the request duration.
- # TYPE http_request_duration_seconds histogram
- http_request_duration_seconds_bucket{le="0.05"} 1000 %v
- http_request_duration_seconds_bucket{le="0.5"} 1500 %v
- http_request_duration_seconds_bucket{le="1"} 2000 %v
- http_request_duration_seconds_bucket{le="+Inf"} 2500 %v
- http_request_duration_seconds_sum 5000 %v
- http_request_duration_seconds_count 2500 %v
- # HELP rpc_duration_seconds A summary of the RPC duration in seconds.
- # TYPE rpc_duration_seconds summary
- rpc_duration_seconds{quantile="0.01"} 1 %v
- rpc_duration_seconds{quantile="0.9"} 5 %v
- rpc_duration_seconds{quantile="0.99"} 8 %v
- rpc_duration_seconds_sum 5000 %v
- rpc_duration_seconds_count 1000 %v
- `
- var honorTimestampsPage2 = `
- # HELP go_threads Number of OS threads created
- # TYPE go_thread gauge
- go_threads 18 %v
- # HELP http_requests_total The total number of HTTP requests.
- # TYPE http_requests_total counter
- http_requests_total{method="post",code="200"} 99 %v
- http_requests_total{method="post",code="400"} 3 %v
- # HELP http_request_duration_seconds A histogram of the request duration.
- # TYPE http_request_duration_seconds histogram
- http_request_duration_seconds_bucket{le="0.05"} 900 %v
- http_request_duration_seconds_bucket{le="0.5"} 1400 %v
- http_request_duration_seconds_bucket{le="1"} 1900 %v
- http_request_duration_seconds_bucket{le="+Inf"} 2400 %v
- http_request_duration_seconds_sum 4950 %v
- http_request_duration_seconds_count 2400 %v
- # HELP rpc_duration_seconds A summary of the RPC duration in seconds.
- # TYPE rpc_duration_seconds summary
- rpc_duration_seconds{quantile="0.01"} 1 %v
- rpc_duration_seconds{quantile="0.9"} 6 %v
- rpc_duration_seconds{quantile="0.99"} 8 %v
- rpc_duration_seconds_sum 4980 %v
- rpc_duration_seconds_count 900 %v
- `
- // honorTimestampsPage3 has higher value than previous scrape.
- // So, start_timestamp should not be reset for honorTimestampsPage3
- var honorTimestampsPage3 = `
- # HELP go_threads Number of OS threads created
- # TYPE go_thread gauge
- go_threads 19 %v
- # HELP http_requests_total The total number of HTTP requests.
- # TYPE http_requests_total counter
- http_requests_total{method="post",code="200"} 100 %v
- http_requests_total{method="post",code="400"} 5 %v
- # HELP http_request_duration_seconds A histogram of the request duration.
- # TYPE http_request_duration_seconds histogram
- http_request_duration_seconds_bucket{le="0.05"} 1000 %v
- http_request_duration_seconds_bucket{le="0.5"} 1500 %v
- http_request_duration_seconds_bucket{le="1"} 2000 %v
- http_request_duration_seconds_bucket{le="+Inf"} 2500 %v
- http_request_duration_seconds_sum 5000 %v
- http_request_duration_seconds_count 2500 %v
- # HELP rpc_duration_seconds A summary of the RPC duration in seconds.
- # TYPE rpc_duration_seconds summary
- rpc_duration_seconds{quantile="0.01"} 1 %v
- rpc_duration_seconds{quantile="0.9"} 5 %v
- rpc_duration_seconds{quantile="0.99"} 8 %v
- rpc_duration_seconds_sum 5000 %v
- rpc_duration_seconds_count 1000 %v
- `
- // TestHonorTimeStampsWithTrue validates honor_timestamp configuration
- // where all metricFamilies (and each datapoint) in the testdata has explicit timestamps.
- // TestHonorTimeStampsWithTrue does not check for scenario where timestamp is not provided
- // to all metric families in a scrape- as those situations are rare though valid.
- // TestHonorTimeStampsWithTrue has testdata such that
- // For valid data- Start_timestamps should not be ahead of point_timestamps.
- // TestHonorTimeStampsWithTrue validates:
- // - For initial scrape, start_timestamp is same as point timestamp,
- // - Start_timestamp should be the explicit timestamp of first-time a particular metric is seen
- // - Start_timestamp should get reset if current scrape has lower value than previous scrape
- func TestHonorTimeStampsWithTrue(t *testing.T) {
- setMetricsTimestamp()
- targets := []*testData{
- {
- name: "target1",
- pages: []mockPrometheusResponse{
- {code: 200, data: honorTimestampsPage1},
- {code: 200, data: honorTimestampsPage2},
- {code: 200, data: honorTimestampsPage3},
- },
- validateFunc: verifyHonorTimeStampsTrue,
- },
- }
- testComponent(t, targets, nil)
- }
- // TestHonorTimeStampsWithFalse validates that with honor_timestamp config set to false,
- // valid testdata provided with explicit timestamps does not get honored.
- func TestHonorTimeStampsWithFalse(t *testing.T) {
- setMetricsTimestamp()
- targets := []*testData{
- {
- name: "target1",
- pages: []mockPrometheusResponse{
- {code: 200, data: honorTimestampsPage1},
- {code: 200, data: honorTimestampsPage2},
- },
- validateFunc: verifyHonorTimeStampsFalse,
- },
- }
- testComponent(t, targets, nil, func(cfg *promcfg.Config) {
- for _, scrapeConfig := range cfg.ScrapeConfigs {
- scrapeConfig.HonorTimestamps = false
- }
- })
- }
- func setMetricsTimestamp() {
- onlyOnce.Do(func() {
- honorTimestampsPage1 = fmt.Sprintf(honorTimestampsPage1,
- ts1, // timestamp for gauge
- ts2, ts3, // timestamp for counter
- ts4, ts4, ts4, ts4, ts4, ts4, // timestamp for histogram
- ts5, ts5, ts5, ts5, ts5, // timestamp for summary
- )
- honorTimestampsPage2 = fmt.Sprintf(honorTimestampsPage2,
- ts6, // timestamp for gauge
- ts7, ts8, // timestamp for counter
- ts9, ts9, ts9, ts9, ts9, ts9, // timestamp for histogram
- ts10, ts10, ts10, ts10, ts10, // timestamp for summary
- )
- honorTimestampsPage3 = fmt.Sprintf(honorTimestampsPage3,
- ts11, // timestamp for gauge
- ts12, ts13, // timestamp for counter
- ts14, ts14, ts14, ts14, ts14, ts14, // timestamp for histogram
- ts15, ts15, ts15, ts15, ts15, // timestamp for summary
- )
- })
- }
- func verifyHonorTimeStampsTrue(t *testing.T, td *testData, resourceMetrics []pmetric.ResourceMetrics) {
- verifyNumValidScrapeResults(t, td, resourceMetrics)
- m1 := resourceMetrics[0]
- // m1 has 4 metrics + 5 internal scraper metrics
- assert.Equal(t, 9, metricsCount(m1))
- wantAttributes := td.attributes
- e1 := []testExpectation{
- assertMetricPresent("go_threads",
- compareMetricType(pmetric.MetricTypeGauge),
- compareMetricUnit(""),
- []dataPointExpectation{
- {
- numberPointComparator: []numberPointComparator{
- compareTimestamp(pcommon.NewTimestampFromTime(time.UnixMilli(ts1))),
- compareDoubleValue(19),
- },
- },
- }),
- assertMetricPresent("http_requests_total",
- compareMetricType(pmetric.MetricTypeSum),
- compareMetricUnit(""),
- []dataPointExpectation{
- {
- numberPointComparator: []numberPointComparator{
- compareStartTimestamp(pcommon.NewTimestampFromTime(time.UnixMilli(ts2))),
- compareTimestamp(pcommon.NewTimestampFromTime(time.UnixMilli(ts2))),
- compareDoubleValue(100),
- compareAttributes(map[string]string{"method": "post", "code": "200"}),
- },
- },
- {
- numberPointComparator: []numberPointComparator{
- compareStartTimestamp(pcommon.NewTimestampFromTime(time.UnixMilli(ts3))),
- compareTimestamp(pcommon.NewTimestampFromTime(time.UnixMilli(ts3))),
- compareDoubleValue(5),
- compareAttributes(map[string]string{"method": "post", "code": "400"}),
- },
- },
- }),
- assertMetricPresent("http_request_duration_seconds",
- compareMetricType(pmetric.MetricTypeHistogram),
- compareMetricUnit(""),
- []dataPointExpectation{
- {
- histogramPointComparator: []histogramPointComparator{
- compareHistogramStartTimestamp(pcommon.NewTimestampFromTime(time.UnixMilli(ts4))),
- compareHistogramTimestamp(pcommon.NewTimestampFromTime(time.UnixMilli(ts4))),
- compareHistogram(2500, 5000, []float64{0.05, 0.5, 1}, []uint64{1000, 500, 500, 500}),
- },
- },
- }),
- assertMetricPresent("rpc_duration_seconds",
- compareMetricType(pmetric.MetricTypeSummary),
- compareMetricUnit(""),
- []dataPointExpectation{
- {
- summaryPointComparator: []summaryPointComparator{
- compareSummaryStartTimestamp(pcommon.NewTimestampFromTime(time.UnixMilli(ts5))),
- compareSummaryTimestamp(pcommon.NewTimestampFromTime(time.UnixMilli(ts5))),
- compareSummary(1000, 5000, [][]float64{{0.01, 1}, {0.9, 5}, {0.99, 8}}),
- },
- },
- }),
- }
- doCompare(t, "scrape-honorTimestamp-1", wantAttributes, m1, e1)
- m2 := resourceMetrics[1]
- // m1 has 4 metrics + 5 internal scraper metrics
- assert.Equal(t, 9, metricsCount(m2))
- e2 := []testExpectation{
- assertMetricPresent("go_threads",
- compareMetricType(pmetric.MetricTypeGauge),
- compareMetricUnit(""),
- []dataPointExpectation{
- {
- numberPointComparator: []numberPointComparator{
- compareTimestamp(pcommon.NewTimestampFromTime(time.UnixMilli(ts6))),
- compareDoubleValue(18),
- },
- },
- }),
- assertMetricPresent("http_requests_total",
- compareMetricType(pmetric.MetricTypeSum),
- compareMetricUnit(""),
- []dataPointExpectation{
- {
- numberPointComparator: []numberPointComparator{
- compareStartTimestamp(pcommon.NewTimestampFromTime(time.UnixMilli(ts7))),
- compareTimestamp(pcommon.NewTimestampFromTime(time.UnixMilli(ts7))),
- compareDoubleValue(99),
- compareAttributes(map[string]string{"method": "post", "code": "200"}),
- },
- },
- {
- numberPointComparator: []numberPointComparator{
- compareStartTimestamp(pcommon.NewTimestampFromTime(time.UnixMilli(ts8))),
- compareTimestamp(pcommon.NewTimestampFromTime(time.UnixMilli(ts8))),
- compareDoubleValue(3),
- compareAttributes(map[string]string{"method": "post", "code": "400"}),
- },
- },
- }),
- assertMetricPresent("http_request_duration_seconds",
- compareMetricType(pmetric.MetricTypeHistogram),
- compareMetricUnit(""),
- []dataPointExpectation{
- {
- histogramPointComparator: []histogramPointComparator{
- compareHistogramStartTimestamp(pcommon.NewTimestampFromTime(time.UnixMilli(ts9))),
- compareHistogramTimestamp(pcommon.NewTimestampFromTime(time.UnixMilli(ts9))),
- compareHistogram(2400, 4950, []float64{0.05, 0.5, 1}, []uint64{900, 500, 500, 500}),
- },
- },
- }),
- assertMetricPresent("rpc_duration_seconds",
- compareMetricType(pmetric.MetricTypeSummary),
- compareMetricUnit(""),
- []dataPointExpectation{
- {
- summaryPointComparator: []summaryPointComparator{
- compareSummaryStartTimestamp(pcommon.NewTimestampFromTime(time.UnixMilli(ts10))),
- compareSummaryTimestamp(pcommon.NewTimestampFromTime(time.UnixMilli(ts10))),
- compareSummary(900, 4980, [][]float64{{0.01, 1}, {0.9, 6}, {0.99, 8}}),
- },
- },
- }),
- }
- doCompare(t, "scrape-honorTimestamp-2", wantAttributes, m2, e2)
- m3 := resourceMetrics[2]
- // m1 has 4 metrics + 5 internal scraper metrics
- assert.Equal(t, 9, metricsCount(m3))
- e3 := []testExpectation{
- assertMetricPresent("go_threads",
- compareMetricType(pmetric.MetricTypeGauge),
- compareMetricUnit(""),
- []dataPointExpectation{
- {
- numberPointComparator: []numberPointComparator{
- compareTimestamp(pcommon.NewTimestampFromTime(time.UnixMilli(ts11))),
- compareDoubleValue(19),
- },
- },
- }),
- assertMetricPresent("http_requests_total",
- compareMetricType(pmetric.MetricTypeSum),
- compareMetricUnit(""),
- []dataPointExpectation{
- {
- numberPointComparator: []numberPointComparator{
- compareStartTimestamp(pcommon.NewTimestampFromTime(time.UnixMilli(ts7))),
- compareTimestamp(pcommon.NewTimestampFromTime(time.UnixMilli(ts12))),
- compareDoubleValue(100),
- compareAttributes(map[string]string{"method": "post", "code": "200"}),
- },
- },
- {
- numberPointComparator: []numberPointComparator{
- compareStartTimestamp(pcommon.NewTimestampFromTime(time.UnixMilli(ts8))),
- compareTimestamp(pcommon.NewTimestampFromTime(time.UnixMilli(ts13))),
- compareDoubleValue(5),
- compareAttributes(map[string]string{"method": "post", "code": "400"}),
- },
- },
- }),
- assertMetricPresent("http_request_duration_seconds",
- compareMetricType(pmetric.MetricTypeHistogram),
- compareMetricUnit(""),
- []dataPointExpectation{
- {
- histogramPointComparator: []histogramPointComparator{
- compareHistogramStartTimestamp(pcommon.NewTimestampFromTime(time.UnixMilli(ts9))),
- compareHistogramTimestamp(pcommon.NewTimestampFromTime(time.UnixMilli(ts14))),
- compareHistogram(2500, 5000, []float64{0.05, 0.5, 1}, []uint64{1000, 500, 500, 500}),
- },
- },
- }),
- assertMetricPresent("rpc_duration_seconds",
- compareMetricType(pmetric.MetricTypeSummary),
- compareMetricUnit(""),
- []dataPointExpectation{
- {
- summaryPointComparator: []summaryPointComparator{
- compareSummaryStartTimestamp(pcommon.NewTimestampFromTime(time.UnixMilli(ts10))),
- compareSummaryTimestamp(pcommon.NewTimestampFromTime(time.UnixMilli(ts15))),
- compareSummary(1000, 5000, [][]float64{{0.01, 1}, {0.9, 5}, {0.99, 8}}),
- },
- },
- }),
- }
- doCompare(t, "scrape-honorTimestamp-3", wantAttributes, m3, e3)
- }
- func verifyHonorTimeStampsFalse(t *testing.T, td *testData, resourceMetrics []pmetric.ResourceMetrics) {
- verifyNumValidScrapeResults(t, td, resourceMetrics)
- m1 := resourceMetrics[0]
- // m1 has 4 metrics + 5 internal scraper metrics
- assert.Equal(t, 9, metricsCount(m1))
- wantAttributes := td.attributes
- metrics1 := m1.ScopeMetrics().At(0).Metrics()
- ts1 := getTS(metrics1)
- e1 := []testExpectation{
- assertMetricPresent("go_threads",
- compareMetricType(pmetric.MetricTypeGauge),
- compareMetricUnit(""),
- []dataPointExpectation{
- {
- numberPointComparator: []numberPointComparator{
- compareTimestamp(ts1),
- compareDoubleValue(19),
- },
- },
- }),
- assertMetricPresent("http_requests_total",
- compareMetricType(pmetric.MetricTypeSum),
- compareMetricUnit(""),
- []dataPointExpectation{
- {
- numberPointComparator: []numberPointComparator{
- compareStartTimestamp(ts1),
- compareTimestamp(ts1),
- compareDoubleValue(100),
- compareAttributes(map[string]string{"method": "post", "code": "200"}),
- },
- },
- {
- numberPointComparator: []numberPointComparator{
- compareStartTimestamp(ts1),
- compareTimestamp(ts1),
- compareDoubleValue(5),
- compareAttributes(map[string]string{"method": "post", "code": "400"}),
- },
- },
- }),
- assertMetricPresent("http_request_duration_seconds",
- compareMetricType(pmetric.MetricTypeHistogram),
- compareMetricUnit(""),
- []dataPointExpectation{
- {
- histogramPointComparator: []histogramPointComparator{
- compareHistogramStartTimestamp(ts1),
- compareHistogramTimestamp(ts1),
- compareHistogram(2500, 5000, []float64{0.05, 0.5, 1}, []uint64{1000, 500, 500, 500}),
- },
- },
- }),
- assertMetricPresent("rpc_duration_seconds",
- compareMetricType(pmetric.MetricTypeSummary),
- compareMetricUnit(""),
- []dataPointExpectation{
- {
- summaryPointComparator: []summaryPointComparator{
- compareSummaryStartTimestamp(ts1),
- compareSummaryTimestamp(ts1),
- compareSummary(1000, 5000, [][]float64{{0.01, 1}, {0.9, 5}, {0.99, 8}}),
- },
- },
- }),
- }
- doCompare(t, "scrape-honorTimestamp-1", wantAttributes, m1, e1)
- m2 := resourceMetrics[1]
- // m2 has 4 metrics + 5 internal scraper metrics
- assert.Equal(t, 9, metricsCount(m2))
- metricsScrape2 := m2.ScopeMetrics().At(0).Metrics()
- ts2 := getTS(metricsScrape2)
- e2 := []testExpectation{
- assertMetricPresent("go_threads",
- compareMetricType(pmetric.MetricTypeGauge),
- compareMetricUnit(""),
- []dataPointExpectation{
- {
- numberPointComparator: []numberPointComparator{
- compareTimestamp(ts2),
- compareDoubleValue(18),
- },
- },
- }),
- assertMetricPresent("http_requests_total",
- compareMetricType(pmetric.MetricTypeSum),
- compareMetricUnit(""),
- []dataPointExpectation{
- {
- numberPointComparator: []numberPointComparator{
- compareStartTimestamp(ts2),
- compareTimestamp(ts2),
- compareDoubleValue(99),
- compareAttributes(map[string]string{"method": "post", "code": "200"}),
- },
- },
- {
- numberPointComparator: []numberPointComparator{
- compareStartTimestamp(ts2),
- compareTimestamp(ts2),
- compareDoubleValue(3),
- compareAttributes(map[string]string{"method": "post", "code": "400"}),
- },
- },
- }),
- assertMetricPresent("http_request_duration_seconds",
- compareMetricType(pmetric.MetricTypeHistogram),
- compareMetricUnit(""),
- []dataPointExpectation{
- {
- histogramPointComparator: []histogramPointComparator{
- compareHistogramStartTimestamp(ts2),
- compareHistogramTimestamp(ts2),
- compareHistogram(2400, 4950, []float64{0.05, 0.5, 1}, []uint64{900, 500, 500, 500}),
- },
- },
- }),
- assertMetricPresent("rpc_duration_seconds",
- compareMetricType(pmetric.MetricTypeSummary),
- compareMetricUnit(""),
- []dataPointExpectation{
- {
- summaryPointComparator: []summaryPointComparator{
- compareSummaryStartTimestamp(ts2),
- compareSummaryTimestamp(ts2),
- compareSummary(900, 4980, [][]float64{{0.01, 1}, {0.9, 6}, {0.99, 8}}),
- },
- },
- }),
- }
- doCompare(t, "scrape-honorTimestamp-2", wantAttributes, m2, e2)
- }
|