github.com/thanos-io/thanos@v0.32.5/test/e2e/targets_api_test.go (about) 1 // Copyright (c) The Thanos Authors. 2 // Licensed under the Apache License 2.0. 3 4 package e2e_test 5 6 import ( 7 "context" 8 "fmt" 9 "os" 10 "reflect" 11 "sort" 12 "testing" 13 "time" 14 15 "github.com/efficientgo/e2e" 16 e2emon "github.com/efficientgo/e2e/monitoring" 17 "github.com/go-kit/log" 18 "github.com/pkg/errors" 19 20 "github.com/efficientgo/core/testutil" 21 "github.com/thanos-io/thanos/pkg/promclient" 22 "github.com/thanos-io/thanos/pkg/runutil" 23 "github.com/thanos-io/thanos/pkg/store/labelpb" 24 "github.com/thanos-io/thanos/pkg/targets/targetspb" 25 "github.com/thanos-io/thanos/test/e2e/e2ethanos" 26 ) 27 28 func TestTargetsAPI_Fanout(t *testing.T) { 29 t.Parallel() 30 31 e, err := e2e.NewDockerEnvironment("targets-fanout") 32 testutil.Ok(t, err) 33 t.Cleanup(e2ethanos.CleanScenario(t, e)) 34 35 // 2x Prometheus. 36 prom1, sidecar1 := e2ethanos.NewPrometheusWithSidecar( 37 e, 38 "prom1", 39 e2ethanos.DefaultPromConfig("ha", 0, "", "", e2ethanos.LocalPrometheusTarget, "localhost:80"), 40 "", 41 e2ethanos.DefaultPrometheusImage(), "", 42 ) 43 prom2, sidecar2 := e2ethanos.NewPrometheusWithSidecar( 44 e, 45 "prom2", 46 e2ethanos.DefaultPromConfig("ha", 1, "", "", e2ethanos.LocalPrometheusTarget, "localhost:80"), 47 "", 48 e2ethanos.DefaultPrometheusImage(), "", 49 ) 50 testutil.Ok(t, e2e.StartAndWaitReady(prom1, sidecar1, prom2, sidecar2)) 51 52 stores := []string{sidecar1.InternalEndpoint("grpc"), sidecar2.InternalEndpoint("grpc")} 53 q := e2ethanos.NewQuerierBuilder(e, "query", stores...). 54 WithTargetAddresses(stores...). 55 Init() 56 testutil.Ok(t, err) 57 testutil.Ok(t, e2e.StartAndWaitReady(q)) 58 59 ctx, cancel := context.WithTimeout(context.Background(), 1*time.Minute) 60 t.Cleanup(cancel) 61 62 testutil.Ok(t, q.WaitSumMetricsWithOptions(e2emon.Equals(2), []string{"thanos_store_nodes_grpc_connections"}, e2emon.WaitMissingMetrics())) 63 64 targetAndAssert(t, ctx, q.Endpoint("http"), "", &targetspb.TargetDiscovery{ 65 ActiveTargets: []*targetspb.ActiveTarget{ 66 { 67 DiscoveredLabels: labelpb.ZLabelSet{Labels: []labelpb.ZLabel{ 68 {Name: "__address__", Value: "localhost:9090"}, 69 {Name: "__metrics_path__", Value: "/metrics"}, 70 {Name: "__scheme__", Value: "http"}, 71 {Name: "__scrape_interval__", Value: "1s"}, 72 {Name: "__scrape_timeout__", Value: "1s"}, 73 {Name: "job", Value: "myself"}, 74 {Name: "prometheus", Value: "ha"}, 75 }}, 76 Labels: labelpb.ZLabelSet{Labels: []labelpb.ZLabel{ 77 {Name: "instance", Value: "localhost:9090"}, 78 {Name: "job", Value: "myself"}, 79 {Name: "prometheus", Value: "ha"}, 80 }}, 81 ScrapePool: "myself", 82 ScrapeUrl: "http://localhost:9090/metrics", 83 Health: targetspb.TargetHealth_UP, 84 }, 85 }, 86 DroppedTargets: []*targetspb.DroppedTarget{ 87 { 88 DiscoveredLabels: labelpb.ZLabelSet{Labels: []labelpb.ZLabel{ 89 {Name: "__address__", Value: "localhost:80"}, 90 {Name: "__metrics_path__", Value: "/metrics"}, 91 {Name: "__scheme__", Value: "http"}, 92 {Name: "__scrape_interval__", Value: "1s"}, 93 {Name: "__scrape_timeout__", Value: "1s"}, 94 {Name: "job", Value: "myself"}, 95 {Name: "prometheus", Value: "ha"}, 96 }}, 97 }, 98 }, 99 }) 100 } 101 102 func targetAndAssert(t *testing.T, ctx context.Context, addr, state string, want *targetspb.TargetDiscovery) { 103 t.Helper() 104 105 fmt.Println("targetAndAssert: Waiting for results for targets state", state) 106 107 logger := log.NewLogfmtLogger(os.Stdout) 108 testutil.Ok(t, runutil.RetryWithLog(logger, time.Second, ctx.Done(), func() error { 109 res, err := promclient.NewDefaultClient().TargetsInGRPC(ctx, urlParse(t, "http://"+addr), state) 110 if err != nil { 111 return err 112 } 113 114 if len(res.ActiveTargets) != len(want.ActiveTargets) { 115 return errors.Errorf("unexpected result.ActiveTargets size, want %d; got: %d result: %v", len(want.ActiveTargets), len(res.ActiveTargets), res) 116 } 117 118 if len(res.DroppedTargets) != len(want.DroppedTargets) { 119 return errors.Errorf("unexpected result.DroppedTargets size, want %d; got: %d result: %v", len(want.DroppedTargets), len(res.DroppedTargets), res) 120 } 121 122 for it := range res.ActiveTargets { 123 res.ActiveTargets[it].LastScrape = time.Time{} 124 res.ActiveTargets[it].LastScrapeDuration = 0 125 res.ActiveTargets[it].GlobalUrl = "" 126 } 127 128 sort.Slice(res.ActiveTargets, func(i, j int) bool { return res.ActiveTargets[i].Compare(res.ActiveTargets[j]) < 0 }) 129 sort.Slice(res.DroppedTargets, func(i, j int) bool { return res.DroppedTargets[i].Compare(res.DroppedTargets[j]) < 0 }) 130 131 if !reflect.DeepEqual(want, res) { 132 return errors.Errorf("unexpected result\nwant %v\ngot: %v", want, res) 133 } 134 135 return nil 136 })) 137 }