github.com/pf-qiu/concourse/v6@v6.7.3-0.20201207032516-1f455d73275f/atc/metric/emitter/prometheus_test.go (about) 1 package emitter_test 2 3 import ( 4 "fmt" 5 "io/ioutil" 6 "net/http" 7 8 . "github.com/onsi/ginkgo" 9 . "github.com/onsi/gomega" 10 11 "code.cloudfoundry.org/lager/lagertest" 12 "github.com/prometheus/client_golang/prometheus" 13 14 "github.com/pf-qiu/concourse/v6/atc/metric" 15 "github.com/pf-qiu/concourse/v6/atc/metric/emitter" 16 "github.com/pf-qiu/concourse/v6/atc/metric/emitter/emitterfakes" 17 ) 18 19 var _ = Describe("PrometheusEmitter garbage collector", func() { 20 var ( 21 fake emitterfakes.FakePrometheusGarbageCollectable 22 23 labelsLong prometheus.Labels 24 labelsShort prometheus.Labels 25 26 workerContainers *prometheus.GaugeVec 27 workerVolumes *prometheus.GaugeVec 28 workerTasks *prometheus.GaugeVec 29 30 workerContainersLabels map[string]map[string]prometheus.Labels 31 workerVolumesLabels map[string]map[string]prometheus.Labels 32 workerTasksLabels map[string]map[string]prometheus.Labels 33 ) 34 35 BeforeEach(func() { 36 workerContainers = prometheus.NewGaugeVec( 37 prometheus.GaugeOpts{ 38 Namespace: "concourse", 39 Subsystem: "workers", 40 Name: "containers", 41 Help: "Number of containers per worker", 42 }, 43 []string{"worker", "platform", "team", "tags"}, 44 ) 45 prometheus.Register(workerContainers) 46 47 workerVolumes = prometheus.NewGaugeVec( 48 prometheus.GaugeOpts{ 49 Namespace: "concourse", 50 Subsystem: "workers", 51 Name: "volumes", 52 Help: "Number of volumes per worker", 53 }, 54 []string{"worker", "platform", "team", "tags"}, 55 ) 56 prometheus.Register(workerVolumes) 57 58 workerTasks = prometheus.NewGaugeVec( 59 prometheus.GaugeOpts{ 60 Namespace: "concourse", 61 Subsystem: "workers", 62 Name: "tasks", 63 Help: "Number of active tasks per worker", 64 }, 65 []string{"worker", "platform"}, 66 ) 67 prometheus.Register(workerTasks) 68 69 workerContainersLabels = map[string]map[string]prometheus.Labels{} 70 workerVolumesLabels = map[string]map[string]prometheus.Labels{} 71 workerTasksLabels = map[string]map[string]prometheus.Labels{} 72 73 labelsLong = prometheus.Labels{ 74 "worker": "foo", 75 "platform": "linux", 76 "team": "main", 77 "tags": "", 78 } 79 80 labelsShort = prometheus.Labels{ 81 "worker": "foo", 82 "platform": "linux", 83 } 84 }) 85 JustBeforeEach(func() { 86 fake = emitterfakes.FakePrometheusGarbageCollectable{ 87 WorkerContainersStub: func() *prometheus.GaugeVec { return workerContainers }, 88 WorkerVolumesStub: func() *prometheus.GaugeVec { return workerVolumes }, 89 WorkerTasksStub: func() *prometheus.GaugeVec { return workerTasks }, 90 91 WorkerContainersLabelsStub: func() map[string]map[string]prometheus.Labels { 92 return workerContainersLabels 93 }, 94 WorkerVolumesLabelsStub: func() map[string]map[string]prometheus.Labels { 95 return workerVolumesLabels 96 }, 97 WorkerTasksLabelsStub: func() map[string]map[string]prometheus.Labels { 98 return workerTasksLabels 99 }, 100 } 101 102 // Deep copy the labels so we can use them to verify the test results later 103 labels := make(prometheus.Labels) 104 for k, v := range labelsLong { 105 labels[k] = v 106 } 107 fake.WorkerContainers().With(labels).Set(42.0) 108 fake.WorkerContainersLabels()["foo"] = make(map[string]prometheus.Labels) 109 fake.WorkerContainersLabels()["foo"]["foo_linux_main__"] = labels 110 111 fake.WorkerVolumes().With(labels).Set(42.0) 112 fake.WorkerVolumesLabels()["foo"] = make(map[string]prometheus.Labels) 113 fake.WorkerVolumesLabels()["foo"]["foo_linux_main__"] = labels 114 115 labels = make(prometheus.Labels) 116 for k, v := range labelsShort { 117 labels[k] = v 118 } 119 fake.WorkerTasks().With(labels).Set(42.0) 120 fake.WorkerTasksLabels()["foo"] = make(map[string]prometheus.Labels) 121 fake.WorkerTasksLabels()["foo"]["foo_linux"] = labels 122 }) 123 124 It("should remove all metrics from the emitter", func() { 125 Expect(fake.WorkerContainersLabels()).To(HaveLen(1)) 126 Expect(fake.WorkerVolumesLabels()).To(HaveLen(1)) 127 Expect(fake.WorkerTasksLabels()).To(HaveLen(1)) 128 129 emitter.DoGarbageCollection(&fake, "foo") 130 131 Expect(fake.WorkerContainersLabels()).To(HaveLen(0)) 132 Expect(fake.WorkerVolumesLabels()).To(HaveLen(0)) 133 Expect(fake.WorkerTasksLabels()).To(HaveLen(0)) 134 135 // Delete should return false if the metrics no longer exist 136 Expect(fake.WorkerContainers().Delete(labelsLong)).To(Equal(false)) 137 Expect(fake.WorkerVolumes().Delete(labelsLong)).To(Equal(false)) 138 Expect(fake.WorkerTasks().Delete(labelsShort)).To(Equal(false)) 139 }) 140 141 // There is no easy way to detect whether metrics are REALLY garbage collected due to the 142 // limitations of the Prometheus client library, so here we verify that the metrics that were 143 // deleted in the previous spec were actually present from the beginning. 144 It("should not do anything if there are no metrics", func() { 145 // Delete should return true if the metrics are actually deleted 146 Expect(fake.WorkerContainers().Delete(labelsLong)).To(Equal(true)) 147 Expect(fake.WorkerVolumes().Delete(labelsLong)).To(Equal(true)) 148 Expect(fake.WorkerTasks().Delete(labelsShort)).To(Equal(true)) 149 150 emitter.DoGarbageCollection(&fake, "foo") 151 152 // Delete should return false if the metrics no longer exist 153 Expect(fake.WorkerContainers().Delete(labelsLong)).To(Equal(false)) 154 Expect(fake.WorkerVolumes().Delete(labelsLong)).To(Equal(false)) 155 Expect(fake.WorkerTasks().Delete(labelsShort)).To(Equal(false)) 156 157 }) 158 159 AfterEach(func() { 160 workerContainers.Reset() 161 workerVolumes.Reset() 162 workerTasks.Reset() 163 164 workerContainersLabels = map[string]map[string]prometheus.Labels{} 165 workerVolumesLabels = map[string]map[string]prometheus.Labels{} 166 workerTasksLabels = map[string]map[string]prometheus.Labels{} 167 168 prometheus.Unregister(workerContainers) 169 prometheus.Unregister(workerVolumes) 170 prometheus.Unregister(workerTasks) 171 }) 172 }) 173 174 var _ = Describe("PrometheusEmitter", func() { 175 var ( 176 prometheusConfig *emitter.PrometheusConfig 177 prometheusEmitter metric.Emitter 178 logger *lagertest.TestLogger 179 err error 180 ) 181 182 BeforeEach(func() { 183 logger = lagertest.NewTestLogger("test") 184 prometheusConfig = &emitter.PrometheusConfig{ 185 BindIP: "localhost", 186 BindPort: "9090", 187 } 188 }) 189 190 JustBeforeEach(func() { 191 prometheusEmitter, err = prometheusConfig.NewEmitter() 192 }) 193 194 It("emits task waiting metric", func() { 195 prometheusEmitter.Emit(logger, metric.Event{ 196 Name: "tasks waiting", 197 Value: 4, 198 Attributes: map[string]string{ 199 "teamId": "42", 200 "workerTags": "tester", 201 "platform": "darwin", 202 }, 203 }) 204 205 res, _ := http.Get(fmt.Sprintf("http://%s:%s/metrics", prometheusConfig.BindIP, prometheusConfig.BindPort)) 206 defer res.Body.Close() 207 body, _ := ioutil.ReadAll(res.Body) 208 209 Expect(res.StatusCode).To(Equal(http.StatusOK)) 210 Expect(string(body)).To(ContainSubstring("concourse_tasks_waiting{platform=\"darwin\",teamId=\"42\",workerTags=\"tester\"} 4")) 211 Expect(err).To(BeNil()) 212 }) 213 })