metrics_tests.js 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  1. const os = require('os')
  2. const http = require('http')
  3. const { expect } = require('chai')
  4. const Metrics = require('../..')
  5. const HOSTNAME = os.hostname()
  6. const APP_NAME = 'test-app'
  7. describe('Metrics module', function() {
  8. before(function() {
  9. Metrics.initialize(APP_NAME)
  10. })
  11. describe('at startup', function() {
  12. it('increments the process_startup counter', async function() {
  13. await expectMetricValue('process_startup', 1)
  14. })
  15. it('collects default metrics', async function() {
  16. const metric = await getMetric('process_cpu_user_seconds_total')
  17. expect(metric).to.exist
  18. })
  19. })
  20. describe('inc()', function() {
  21. it('increments counts by 1', async function() {
  22. Metrics.inc('duck_count')
  23. await expectMetricValue('duck_count', 1)
  24. Metrics.inc('duck_count')
  25. Metrics.inc('duck_count')
  26. await expectMetricValue('duck_count', 3)
  27. })
  28. it('escapes special characters in the key', async function() {
  29. Metrics.inc('show.me the $!!')
  30. await expectMetricValue('show_me_the____', 1)
  31. })
  32. })
  33. describe('count()', function() {
  34. it('increments counts by the given count', async function() {
  35. Metrics.count('rabbit_count', 5)
  36. await expectMetricValue('rabbit_count', 5)
  37. Metrics.count('rabbit_count', 6)
  38. Metrics.count('rabbit_count', 7)
  39. await expectMetricValue('rabbit_count', 18)
  40. })
  41. })
  42. describe('summary()', function() {
  43. it('collects observations', async function() {
  44. Metrics.summary('oven_temp', 200)
  45. Metrics.summary('oven_temp', 300)
  46. Metrics.summary('oven_temp', 450)
  47. const sum = await getSummarySum('oven_temp')
  48. expect(sum).to.equal(950)
  49. })
  50. })
  51. describe('timing()', function() {
  52. it('collects timings', async function() {
  53. Metrics.timing('sprint_100m', 10)
  54. Metrics.timing('sprint_100m', 20)
  55. Metrics.timing('sprint_100m', 30)
  56. const sum = await getSummarySum('timer_sprint_100m')
  57. expect(sum).to.equal(60)
  58. })
  59. })
  60. describe('gauge()', function() {
  61. it('records values', async function() {
  62. Metrics.gauge('water_level', 1.5)
  63. await expectMetricValue('water_level', 1.5)
  64. Metrics.gauge('water_level', 4.2)
  65. await expectMetricValue('water_level', 4.2)
  66. })
  67. })
  68. describe('globalGauge()', function() {
  69. it('records values without a host label', async function() {
  70. Metrics.globalGauge('tire_pressure', 99.99)
  71. const { value, labels } = await getMetricValue('tire_pressure')
  72. expect(value).to.equal(99.99)
  73. expect(labels.host).to.equal('global')
  74. expect(labels.app).to.equal(APP_NAME)
  75. })
  76. })
  77. describe('open_sockets', function() {
  78. const keyServer1 = 'open_connections_http_127_42_42_1'
  79. const keyServer2 = 'open_connections_http_127_42_42_2'
  80. let finish1, finish2, emitResponse1, emitResponse2
  81. function resetEmitResponse1() {
  82. emitResponse1 = new Promise(resolve => (finish1 = resolve))
  83. }
  84. resetEmitResponse1()
  85. function resetEmitResponse2() {
  86. emitResponse2 = new Promise(resolve => (finish2 = resolve))
  87. }
  88. resetEmitResponse2()
  89. let server1, server2
  90. before(function setupServer1(done) {
  91. server1 = http.createServer((req, res) => {
  92. res.write('...')
  93. emitResponse1.then(() => res.end())
  94. })
  95. server1.listen(0, '127.42.42.1', done)
  96. })
  97. before(function setupServer2(done) {
  98. server2 = http.createServer((req, res) => {
  99. res.write('...')
  100. emitResponse2.then(() => res.end())
  101. })
  102. server2.listen(0, '127.42.42.2', done)
  103. })
  104. after(function cleanupPendingRequests() {
  105. finish1()
  106. finish2()
  107. })
  108. after(function shutdownServer1(done) {
  109. if (server1) server1.close(done)
  110. })
  111. after(function shutdownServer2(done) {
  112. if (server2) server2.close(done)
  113. })
  114. let urlServer1, urlServer2
  115. before(function setUrls() {
  116. urlServer1 = `http://127.42.42.1:${server1.address().port}/`
  117. urlServer2 = `http://127.42.42.2:${server2.address().port}/`
  118. })
  119. describe('gaugeOpenSockets()', function() {
  120. beforeEach(function runGaugeOpenSockets() {
  121. Metrics.open_sockets.gaugeOpenSockets()
  122. })
  123. describe('without pending connections', function() {
  124. it('emits no open_connections', async function() {
  125. await expectNoMetricValue(keyServer1)
  126. await expectNoMetricValue(keyServer2)
  127. })
  128. })
  129. describe('with pending connections for server1', function() {
  130. before(function(done) {
  131. http.get(urlServer1)
  132. http.get(urlServer1)
  133. setTimeout(done, 10)
  134. })
  135. it('emits 2 open_connections for server1', async function() {
  136. await expectMetricValue(keyServer1, 2)
  137. })
  138. it('emits no open_connections for server2', async function() {
  139. await expectNoMetricValue(keyServer2)
  140. })
  141. })
  142. describe('with pending connections for server1 and server2', function() {
  143. before(function(done) {
  144. http.get(urlServer2)
  145. http.get(urlServer2)
  146. setTimeout(done, 10)
  147. })
  148. it('emits 2 open_connections for server1', async function() {
  149. await expectMetricValue(keyServer1, 2)
  150. })
  151. it('emits 2 open_connections for server2', async function() {
  152. await expectMetricValue(keyServer2, 2)
  153. })
  154. })
  155. describe('when requests finish for server1', function() {
  156. before(function(done) {
  157. finish1()
  158. resetEmitResponse1()
  159. http.get(urlServer1)
  160. setTimeout(done, 10)
  161. })
  162. it('emits 1 open_connections for server1', async function() {
  163. await expectMetricValue(keyServer1, 1)
  164. })
  165. it('emits 2 open_connections for server2', async function() {
  166. await expectMetricValue(keyServer2, 2)
  167. })
  168. })
  169. describe('when all requests complete', function() {
  170. before(function(done) {
  171. finish1()
  172. finish2()
  173. setTimeout(done, 10)
  174. })
  175. it('emits no open_connections', async function() {
  176. await expectNoMetricValue(keyServer1)
  177. await expectNoMetricValue(keyServer2)
  178. })
  179. })
  180. })
  181. })
  182. })
  183. function getMetric(key) {
  184. return Metrics.register.getSingleMetric(key)
  185. }
  186. async function getSummarySum(key) {
  187. const metric = getMetric(key)
  188. const item = await metric.get()
  189. for (const value of item.values) {
  190. if (value.metricName === `${key}_sum`) {
  191. return value.value
  192. }
  193. }
  194. return null
  195. }
  196. async function getMetricValue(key) {
  197. const metrics = await Metrics.register.getMetricsAsJSON()
  198. const metric = metrics.find(m => m.name === key)
  199. return metric.values[0]
  200. }
  201. async function expectMetricValue(key, expectedValue) {
  202. const value = await getMetricValue(key)
  203. expect(value.value).to.equal(expectedValue)
  204. expect(value.labels.host).to.equal(HOSTNAME)
  205. expect(value.labels.app).to.equal(APP_NAME)
  206. }
  207. async function expectNoMetricValue(key) {
  208. const metric = getMetric(key)
  209. if (!metric) return
  210. await expectMetricValue(key, 0)
  211. }