open_sockets.js 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. /*
  2. * decaffeinate suggestions:
  3. * DS102: Remove unnecessary code created because of implicit returns
  4. * DS205: Consider reworking code to avoid use of IIFEs
  5. * DS207: Consider shorter variations of null checks
  6. * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
  7. */
  8. let OpenSocketsMonitor
  9. const seconds = 1000
  10. // In Node 0.10 the default is 5, which means only 5 open connections at one.
  11. // Node 0.12 has a default of Infinity. Make sure we have no limit set,
  12. // regardless of Node version.
  13. require('node:http').globalAgent.maxSockets = Infinity
  14. require('node:https').globalAgent.maxSockets = Infinity
  15. const SOCKETS_HTTP = require('node:http').globalAgent.sockets
  16. const SOCKETS_HTTPS = require('node:https').globalAgent.sockets
  17. const FREE_SOCKETS_HTTP = require('node:http').globalAgent.freeSockets
  18. const FREE_SOCKETS_HTTPS = require('node:https').globalAgent.freeSockets
  19. // keep track of set gauges and reset them in the next collection cycle
  20. const SEEN_HOSTS_HTTP = new Set()
  21. const SEEN_HOSTS_HTTPS = new Set()
  22. const FREE_SEEN_HOSTS_HTTP = new Set()
  23. const FREE_SEEN_HOSTS_HTTPS = new Set()
  24. function collectConnectionsCount(
  25. sockets,
  26. seenHosts,
  27. status,
  28. https,
  29. emitLegacyMetric
  30. ) {
  31. const Metrics = require('./index')
  32. Object.keys(sockets).forEach(host => seenHosts.add(host))
  33. seenHosts.forEach(host => {
  34. // host: 'HOST:PORT:'
  35. const hostname = host.split(':')[0]
  36. const openConnections = (sockets[host] || []).length
  37. if (!openConnections) {
  38. seenHosts.delete(host)
  39. }
  40. Metrics.gauge('sockets', openConnections, 1, {
  41. path: hostname,
  42. method: https,
  43. status,
  44. })
  45. if (status === 'open' && emitLegacyMetric) {
  46. // Emit legacy metric to keep old time series intact.
  47. Metrics.gauge(
  48. `${status}_connections.${https}.${hostname}`,
  49. openConnections
  50. )
  51. }
  52. })
  53. }
  54. module.exports = OpenSocketsMonitor = {
  55. monitor(emitLegacyMetric) {
  56. const interval = setInterval(
  57. () => OpenSocketsMonitor.gaugeOpenSockets(emitLegacyMetric),
  58. 5 * seconds
  59. )
  60. const Metrics = require('./index')
  61. return Metrics.registerDestructor(() => clearInterval(interval))
  62. },
  63. gaugeOpenSockets(emitLegacyMetric) {
  64. collectConnectionsCount(
  65. SOCKETS_HTTP,
  66. SEEN_HOSTS_HTTP,
  67. 'open',
  68. 'http',
  69. emitLegacyMetric
  70. )
  71. collectConnectionsCount(
  72. SOCKETS_HTTPS,
  73. SEEN_HOSTS_HTTPS,
  74. 'open',
  75. 'https',
  76. emitLegacyMetric
  77. )
  78. collectConnectionsCount(
  79. FREE_SOCKETS_HTTP,
  80. FREE_SEEN_HOSTS_HTTP,
  81. 'free',
  82. 'http',
  83. false
  84. )
  85. collectConnectionsCount(
  86. FREE_SOCKETS_HTTPS,
  87. FREE_SEEN_HOSTS_HTTPS,
  88. 'free',
  89. 'https',
  90. false
  91. )
  92. },
  93. }