prom_wrapper.coffee 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. prom = require('prom-client')
  2. registry = require('prom-client').register
  3. metrics = new Map()
  4. optsKey = (opts) ->
  5. keys = Object.keys(opts)
  6. return '' if keys.length == 0
  7. keys = keys.sort()
  8. hash = '';
  9. for key in keys
  10. hash += "," if hash.length
  11. hash += "#{key}:#{opts[key]}"
  12. return hash
  13. extendOpts = (opts, labelNames) ->
  14. for label in labelNames
  15. opts[label] ||= ''
  16. return opts
  17. optsAsArgs = (opts, labelNames) ->
  18. args = []
  19. for label in labelNames
  20. args.push(opts[label] || '')
  21. return args
  22. PromWrapper =
  23. ttlInMinutes: 0
  24. registry: registry
  25. metric: (type, name) ->
  26. metrics.get(name) || new MetricWrapper(type, name)
  27. collectDefaultMetrics: prom.collectDefaultMetrics
  28. class MetricWrapper
  29. constructor: (type, name) ->
  30. metrics.set(name, this)
  31. @name = name
  32. @instances = new Map()
  33. @lastAccess = new Date()
  34. @metric = switch type
  35. when "counter"
  36. new prom.Counter({
  37. name: name,
  38. help: name,
  39. labelNames: ['app','host','status','method', 'path']
  40. })
  41. when "summary"
  42. new prom.Summary({
  43. name: name,
  44. help: name,
  45. maxAgeSeconds: 600,
  46. ageBuckets: 10,
  47. labelNames: ['app', 'host', 'path', 'status_code', 'method', 'collection', 'query']
  48. })
  49. when "gauge"
  50. prom.Gauge({
  51. name: name,
  52. help: name,
  53. labelNames: ['app','host', 'status']
  54. })
  55. inc: (opts, value) ->
  56. @_execMethod 'inc', opts, value
  57. observe: (opts, value) ->
  58. @_execMethod 'observe', opts, value
  59. set: (opts, value) ->
  60. @_execMethod 'set', opts, value
  61. sweep: () ->
  62. thresh = new Date(Date.now() - 1000 * 60 * PromWrapper.ttlInMinutes)
  63. @instances.forEach (instance, key) =>
  64. if thresh > instance.time
  65. if process.env['DEBUG_METRICS']
  66. console.log("Sweeping stale metric instance", @name, opts: instance.opts, key)
  67. @metric.remove(optsAsArgs(instance.opts, @metric.labelNames)...)
  68. if thresh > @lastAccess
  69. if process.env['DEBUG_METRICS']
  70. console.log("Sweeping stale metric", @name, thresh, @lastAccess)
  71. metrics.delete(@name)
  72. registry.removeSingleMetric(@name)
  73. _execMethod: (method, opts, value) ->
  74. opts = extendOpts(opts, @metric.labelNames)
  75. key = optsKey(opts)
  76. @instances.set(key, { time: new Date(), opts }) unless key == ''
  77. @lastAccess = new Date()
  78. @metric[method](opts, value)
  79. unless PromWrapper.sweepRegistered
  80. if process.env['DEBUG_METRICS']
  81. console.log("Registering sweep method")
  82. PromWrapper.sweepRegistered = true
  83. setInterval(
  84. () ->
  85. if PromWrapper.ttlInMinutes
  86. if process.env['DEBUG_METRICS']
  87. console.log("Sweeping metrics")
  88. metrics.forEach (metric, key) =>
  89. metric.sweep()
  90. 60000)
  91. module.exports = PromWrapper