vitals 0.0.2 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (240) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +7 -0
  3. data/.travis.yml +15 -0
  4. data/Gemfile +4 -0
  5. data/Gemfile.lock +157 -0
  6. data/Guardfile +11 -0
  7. data/LICENSE.txt +21 -0
  8. data/README.md +135 -9
  9. data/Rakefile +17 -31
  10. data/bin/console +14 -0
  11. data/bin/setup +8 -0
  12. data/integration/multiverse/grape-on-rack/.gitignore +7 -0
  13. data/integration/multiverse/grape-on-rack/.rspec +2 -0
  14. data/integration/multiverse/grape-on-rack/.rubocop.yml +2 -0
  15. data/integration/multiverse/grape-on-rack/.rubocop_todo.yml +50 -0
  16. data/integration/multiverse/grape-on-rack/.travis.yml +12 -0
  17. data/integration/multiverse/grape-on-rack/Gemfile +28 -0
  18. data/integration/multiverse/grape-on-rack/Gemfile.lock +187 -0
  19. data/integration/multiverse/grape-on-rack/Guardfile +8 -0
  20. data/integration/multiverse/grape-on-rack/LICENSE +21 -0
  21. data/integration/multiverse/grape-on-rack/README.md +88 -0
  22. data/integration/multiverse/grape-on-rack/Rakefile +27 -0
  23. data/integration/multiverse/grape-on-rack/api/content_type.rb +18 -0
  24. data/integration/multiverse/grape-on-rack/api/entities.rb +28 -0
  25. data/integration/multiverse/grape-on-rack/api/get_json.rb +24 -0
  26. data/integration/multiverse/grape-on-rack/api/header_versioning.rb +9 -0
  27. data/integration/multiverse/grape-on-rack/api/path_versioning.rb +9 -0
  28. data/integration/multiverse/grape-on-rack/api/ping.rb +8 -0
  29. data/integration/multiverse/grape-on-rack/api/post_json.rb +11 -0
  30. data/integration/multiverse/grape-on-rack/api/post_put.rb +24 -0
  31. data/integration/multiverse/grape-on-rack/api/rescue_from.rb +11 -0
  32. data/integration/multiverse/grape-on-rack/api/upload_file.rb +22 -0
  33. data/integration/multiverse/grape-on-rack/api/wrap_response.rb +14 -0
  34. data/integration/multiverse/grape-on-rack/api/wrap_response_decorator.rb +15 -0
  35. data/integration/multiverse/grape-on-rack/app/acme_app.rb +49 -0
  36. data/integration/multiverse/grape-on-rack/app/api.rb +18 -0
  37. data/integration/multiverse/grape-on-rack/config/application.rb +23 -0
  38. data/integration/multiverse/grape-on-rack/config/boot.rb +2 -0
  39. data/integration/multiverse/grape-on-rack/config/environment.rb +3 -0
  40. data/integration/multiverse/grape-on-rack/config/newrelic.yml +255 -0
  41. data/integration/multiverse/grape-on-rack/config.ru +11 -0
  42. data/integration/multiverse/grape-on-rack/public/errors/404.html +15 -0
  43. data/integration/multiverse/grape-on-rack/public/errors/500.html +15 -0
  44. data/integration/multiverse/grape-on-rack/public/images/index.html +1 -0
  45. data/integration/multiverse/grape-on-rack/public/images/rack-logo.png +0 -0
  46. data/integration/multiverse/grape-on-rack/public/index.html +23 -0
  47. data/integration/multiverse/grape-on-rack/public/scripts/jquery-1.7.1.min.js +4 -0
  48. data/integration/multiverse/grape-on-rack/public/scripts/ring.js +17 -0
  49. data/integration/multiverse/grape-on-rack/spec/api/post_put_spec.rb +21 -0
  50. data/integration/multiverse/grape-on-rack/spec/fixtures/grape_logo.png +0 -0
  51. data/integration/multiverse/grape-on-rack/spec/spec_helper.rb +24 -0
  52. data/integration/multiverse/grape-on-rails/.gitignore +16 -0
  53. data/integration/multiverse/grape-on-rails/.rspec +2 -0
  54. data/integration/multiverse/grape-on-rails/.rubocop.yml +6 -0
  55. data/integration/multiverse/grape-on-rails/.rubocop_todo.yml +33 -0
  56. data/integration/multiverse/grape-on-rails/.travis.yml +17 -0
  57. data/integration/multiverse/grape-on-rails/Gemfile +22 -0
  58. data/integration/multiverse/grape-on-rails/Gemfile.lock +238 -0
  59. data/integration/multiverse/grape-on-rails/README.md +29 -0
  60. data/integration/multiverse/grape-on-rails/Rakefile +16 -0
  61. data/integration/multiverse/grape-on-rails/app/api/acme/ping.rb +8 -0
  62. data/integration/multiverse/grape-on-rails/app/api/acme/post.rb +10 -0
  63. data/integration/multiverse/grape-on-rails/app/api/acme/protected.rb +13 -0
  64. data/integration/multiverse/grape-on-rails/app/api/acme/raise.rb +8 -0
  65. data/integration/multiverse/grape-on-rails/app/api/api.rb +8 -0
  66. data/integration/multiverse/grape-on-rails/app/assets/images/rails.png +0 -0
  67. data/integration/multiverse/grape-on-rails/app/assets/javascripts/application.js +15 -0
  68. data/integration/multiverse/grape-on-rails/app/assets/javascripts/welcome.js.coffee +3 -0
  69. data/integration/multiverse/grape-on-rails/app/assets/stylesheets/application.css +13 -0
  70. data/integration/multiverse/grape-on-rails/app/assets/stylesheets/welcome.css.scss +3 -0
  71. data/{test/dummy → integration/multiverse/grape-on-rails}/app/controllers/application_controller.rb +0 -0
  72. data/integration/multiverse/grape-on-rails/app/controllers/welcome_controller.rb +4 -0
  73. data/{test/dummy → integration/multiverse/grape-on-rails}/app/helpers/application_helper.rb +0 -0
  74. data/integration/multiverse/grape-on-rails/app/helpers/welcome_helper.rb +2 -0
  75. data/{test/dummy/db/development.sqlite3 → integration/multiverse/grape-on-rails/app/mailers/.gitkeep} +0 -0
  76. data/{test/dummy/db/test.sqlite3 → integration/multiverse/grape-on-rails/app/models/.gitkeep} +0 -0
  77. data/{test/dummy → integration/multiverse/grape-on-rails}/app/views/layouts/application.html.erb +2 -2
  78. data/integration/multiverse/grape-on-rails/app/views/welcome/index.html.erb +6 -0
  79. data/integration/multiverse/grape-on-rails/bin/bundle +3 -0
  80. data/integration/multiverse/grape-on-rails/bin/rails +4 -0
  81. data/integration/multiverse/grape-on-rails/bin/rake +4 -0
  82. data/{test/dummy → integration/multiverse/grape-on-rails}/config/application.rb +26 -6
  83. data/integration/multiverse/grape-on-rails/config/boot.rb +6 -0
  84. data/integration/multiverse/grape-on-rails/config/database.travis.yml +4 -0
  85. data/integration/multiverse/grape-on-rails/config/database.yml +16 -0
  86. data/{test/dummy → integration/multiverse/grape-on-rails}/config/environment.rb +1 -1
  87. data/{test/dummy → integration/multiverse/grape-on-rails}/config/environments/development.rb +4 -5
  88. data/{test/dummy → integration/multiverse/grape-on-rails}/config/environments/production.rb +9 -4
  89. data/{test/dummy → integration/multiverse/grape-on-rails}/config/environments/test.rb +9 -18
  90. data/{test/dummy → integration/multiverse/grape-on-rails}/config/initializers/backtrace_silencers.rb +0 -0
  91. data/{test/dummy → integration/multiverse/grape-on-rails}/config/initializers/inflections.rb +5 -0
  92. data/{test/dummy → integration/multiverse/grape-on-rails}/config/initializers/mime_types.rb +0 -0
  93. data/integration/multiverse/grape-on-rails/config/initializers/reload_api.rb +13 -0
  94. data/integration/multiverse/grape-on-rails/config/initializers/secret_token.rb +1 -0
  95. data/{test/dummy → integration/multiverse/grape-on-rails}/config/initializers/session_store.rb +2 -2
  96. data/integration/multiverse/grape-on-rails/config/initializers/vitals.rb +8 -0
  97. data/{test/dummy → integration/multiverse/grape-on-rails}/config/initializers/wrap_parameters.rb +0 -0
  98. data/{test/dummy → integration/multiverse/grape-on-rails}/config/locales/en.yml +0 -0
  99. data/integration/multiverse/grape-on-rails/config/routes.rb +5 -0
  100. data/integration/multiverse/grape-on-rails/config.ru +4 -0
  101. data/integration/multiverse/grape-on-rails/db/schema.rb +16 -0
  102. data/integration/multiverse/grape-on-rails/db/seeds.rb +7 -0
  103. data/integration/multiverse/grape-on-rails/doc/README_FOR_APP +2 -0
  104. data/{test/dummy/log/test.log → integration/multiverse/grape-on-rails/lib/assets/.gitkeep} +0 -0
  105. data/{test/dummy/public/favicon.ico → integration/multiverse/grape-on-rails/lib/tasks/.gitkeep} +0 -0
  106. data/integration/multiverse/grape-on-rails/log/.gitkeep +0 -0
  107. data/{test/dummy → integration/multiverse/grape-on-rails}/public/404.html +0 -0
  108. data/{test/dummy → integration/multiverse/grape-on-rails}/public/422.html +0 -0
  109. data/{test/dummy → integration/multiverse/grape-on-rails}/public/500.html +0 -1
  110. data/integration/multiverse/grape-on-rails/public/favicon.ico +0 -0
  111. data/integration/multiverse/grape-on-rails/public/robots.txt +5 -0
  112. data/{test/dummy → integration/multiverse/grape-on-rails}/script/rails +2 -2
  113. data/integration/multiverse/grape-on-rails/spec/api/ping_spec.rb +15 -0
  114. data/integration/multiverse/grape-on-rails/spec/spec_helper.rb +15 -0
  115. data/integration/multiverse/rails42_app/.gitignore +18 -0
  116. data/integration/multiverse/rails42_app/Gemfile +49 -0
  117. data/integration/multiverse/rails42_app/Gemfile.lock +167 -0
  118. data/integration/multiverse/rails42_app/README.rdoc +28 -0
  119. data/{test/dummy → integration/multiverse/rails42_app}/Rakefile +1 -2
  120. data/integration/multiverse/rails42_app/app/assets/images/.keep +0 -0
  121. data/integration/multiverse/rails42_app/app/assets/javascripts/application.js +16 -0
  122. data/integration/multiverse/rails42_app/app/assets/javascripts/posts.coffee +3 -0
  123. data/integration/multiverse/rails42_app/app/assets/stylesheets/application.css +15 -0
  124. data/integration/multiverse/rails42_app/app/assets/stylesheets/posts.scss +3 -0
  125. data/integration/multiverse/rails42_app/app/assets/stylesheets/scaffolds.scss +73 -0
  126. data/integration/multiverse/rails42_app/app/controllers/application_controller.rb +5 -0
  127. data/integration/multiverse/rails42_app/app/controllers/concerns/.keep +0 -0
  128. data/integration/multiverse/rails42_app/app/controllers/posts_controller.rb +75 -0
  129. data/integration/multiverse/rails42_app/app/helpers/application_helper.rb +2 -0
  130. data/integration/multiverse/rails42_app/app/helpers/posts_helper.rb +2 -0
  131. data/integration/multiverse/rails42_app/app/jobs/foobar_cleanup_job.rb +7 -0
  132. data/integration/multiverse/rails42_app/app/mailers/.keep +0 -0
  133. data/integration/multiverse/rails42_app/app/models/.keep +0 -0
  134. data/integration/multiverse/rails42_app/app/models/concerns/.keep +0 -0
  135. data/integration/multiverse/rails42_app/app/models/post.rb +2 -0
  136. data/integration/multiverse/rails42_app/app/views/layouts/application.html.erb +14 -0
  137. data/integration/multiverse/rails42_app/app/views/posts/_form.html.erb +21 -0
  138. data/integration/multiverse/rails42_app/app/views/posts/edit.html.erb +6 -0
  139. data/integration/multiverse/rails42_app/app/views/posts/index.html.erb +27 -0
  140. data/integration/multiverse/rails42_app/app/views/posts/index.json.jbuilder +4 -0
  141. data/integration/multiverse/rails42_app/app/views/posts/new.html.erb +5 -0
  142. data/integration/multiverse/rails42_app/app/views/posts/show.html.erb +9 -0
  143. data/integration/multiverse/rails42_app/app/views/posts/show.json.jbuilder +1 -0
  144. data/integration/multiverse/rails42_app/bin/bundle +3 -0
  145. data/integration/multiverse/rails42_app/bin/rails +9 -0
  146. data/integration/multiverse/rails42_app/bin/rake +9 -0
  147. data/integration/multiverse/rails42_app/bin/setup +29 -0
  148. data/integration/multiverse/rails42_app/bin/spring +15 -0
  149. data/integration/multiverse/rails42_app/config/application.rb +26 -0
  150. data/integration/multiverse/rails42_app/config/boot.rb +3 -0
  151. data/{test/dummy → integration/multiverse/rails42_app}/config/database.yml +8 -8
  152. data/integration/multiverse/rails42_app/config/environment.rb +5 -0
  153. data/integration/multiverse/rails42_app/config/environments/development.rb +41 -0
  154. data/integration/multiverse/rails42_app/config/environments/production.rb +79 -0
  155. data/integration/multiverse/rails42_app/config/environments/test.rb +42 -0
  156. data/integration/multiverse/rails42_app/config/initializers/assets.rb +11 -0
  157. data/integration/multiverse/rails42_app/config/initializers/backtrace_silencers.rb +7 -0
  158. data/integration/multiverse/rails42_app/config/initializers/cookies_serializer.rb +3 -0
  159. data/integration/multiverse/rails42_app/config/initializers/filter_parameter_logging.rb +4 -0
  160. data/integration/multiverse/rails42_app/config/initializers/inflections.rb +16 -0
  161. data/integration/multiverse/rails42_app/config/initializers/mime_types.rb +4 -0
  162. data/integration/multiverse/rails42_app/config/initializers/session_store.rb +3 -0
  163. data/integration/multiverse/rails42_app/config/initializers/vitals.rb +12 -0
  164. data/integration/multiverse/rails42_app/config/initializers/wrap_parameters.rb +14 -0
  165. data/integration/multiverse/rails42_app/config/locales/en.yml +23 -0
  166. data/integration/multiverse/rails42_app/config/routes.rb +57 -0
  167. data/integration/multiverse/rails42_app/config/secrets.yml +22 -0
  168. data/integration/multiverse/rails42_app/config.ru +4 -0
  169. data/integration/multiverse/rails42_app/db/migrate/20160321140358_create_posts.rb +9 -0
  170. data/integration/multiverse/rails42_app/db/schema.rb +22 -0
  171. data/integration/multiverse/rails42_app/db/seeds.rb +7 -0
  172. data/integration/multiverse/rails42_app/lib/assets/.keep +0 -0
  173. data/integration/multiverse/rails42_app/lib/tasks/.keep +0 -0
  174. data/integration/multiverse/rails42_app/log/.keep +0 -0
  175. data/integration/multiverse/rails42_app/public/404.html +67 -0
  176. data/integration/multiverse/rails42_app/public/422.html +67 -0
  177. data/integration/multiverse/rails42_app/public/500.html +66 -0
  178. data/integration/multiverse/rails42_app/public/favicon.ico +0 -0
  179. data/integration/multiverse/rails42_app/public/robots.txt +5 -0
  180. data/integration/multiverse/rails42_app/test/controllers/.keep +0 -0
  181. data/integration/multiverse/rails42_app/test/controllers/posts_controller_test.rb +49 -0
  182. data/integration/multiverse/rails42_app/test/fixtures/.keep +0 -0
  183. data/integration/multiverse/rails42_app/test/fixtures/posts.yml +7 -0
  184. data/integration/multiverse/rails42_app/test/helpers/.keep +0 -0
  185. data/integration/multiverse/rails42_app/test/integration/.keep +0 -0
  186. data/integration/multiverse/rails42_app/test/integration/vitals_flow_test.rb +78 -0
  187. data/integration/multiverse/rails42_app/test/jobs/foobar_cleanup_job_test.rb +7 -0
  188. data/integration/multiverse/rails42_app/test/mailers/.keep +0 -0
  189. data/integration/multiverse/rails42_app/test/models/.keep +0 -0
  190. data/{test/dummy/test/unit/task_test.rb → integration/multiverse/rails42_app/test/models/post_test.rb} +1 -1
  191. data/integration/multiverse/rails42_app/test/test_helper.rb +11 -0
  192. data/integration/multiverse_helper.rb +16 -0
  193. data/integration/multiverse_spec.rb +40 -0
  194. data/lib/vitals/configuration.rb +35 -0
  195. data/lib/vitals/formats/host_last_format.rb +26 -0
  196. data/lib/vitals/formats/production_format.rb +21 -0
  197. data/lib/vitals/integrations/notifications/action_controller.rb +26 -0
  198. data/lib/vitals/integrations/notifications/active_job.rb +18 -0
  199. data/lib/vitals/integrations/notifications/base.rb +20 -0
  200. data/lib/vitals/integrations/notifications/grape.rb +30 -0
  201. data/lib/vitals/integrations/rack/requests.rb +23 -0
  202. data/lib/vitals/reporters/base_reporter.rb +9 -0
  203. data/lib/vitals/reporters/console_reporter.rb +23 -0
  204. data/lib/vitals/reporters/inmem_reporter.rb +31 -0
  205. data/lib/vitals/reporters/multi_reporter.rb +24 -0
  206. data/lib/vitals/reporters/statsd_reporter.rb +27 -0
  207. data/lib/vitals/utils.rb +15 -0
  208. data/lib/vitals/version.rb +1 -1
  209. data/lib/vitals.rb +46 -23
  210. data/vitals.gemspec +48 -0
  211. metadata +404 -147
  212. data/MIT-LICENSE +0 -20
  213. data/lib/generators/vitals/templates/vitals_initializer.rb +0 -7
  214. data/lib/generators/vitals/vitals_generator.rb +0 -12
  215. data/lib/tasks/vitals_tasks.rake +0 -4
  216. data/lib/vitals/reporter.rb +0 -23
  217. data/test/dummy/app/assets/javascripts/application.js +0 -9
  218. data/test/dummy/app/assets/javascripts/tasks.js +0 -2
  219. data/test/dummy/app/assets/stylesheets/application.css +0 -7
  220. data/test/dummy/app/assets/stylesheets/scaffold.css +0 -56
  221. data/test/dummy/app/assets/stylesheets/tasks.css +0 -4
  222. data/test/dummy/app/controllers/tasks_controller.rb +0 -83
  223. data/test/dummy/app/helpers/tasks_helper.rb +0 -2
  224. data/test/dummy/app/models/task.rb +0 -2
  225. data/test/dummy/app/views/tasks/_form.html.erb +0 -21
  226. data/test/dummy/app/views/tasks/edit.html.erb +0 -6
  227. data/test/dummy/app/views/tasks/index.html.erb +0 -23
  228. data/test/dummy/app/views/tasks/new.html.erb +0 -5
  229. data/test/dummy/app/views/tasks/show.html.erb +0 -10
  230. data/test/dummy/config/boot.rb +0 -10
  231. data/test/dummy/config/initializers/secret_token.rb +0 -7
  232. data/test/dummy/config/routes.rb +0 -60
  233. data/test/dummy/config.ru +0 -4
  234. data/test/dummy/db/migrate/20110917182114_create_tasks.rb +0 -9
  235. data/test/dummy/log/development.log +0 -55
  236. data/test/dummy/test/fixtures/tasks.yml +0 -7
  237. data/test/dummy/test/functional/tasks_controller_test.rb +0 -49
  238. data/test/dummy/test/unit/helpers/tasks_helper_test.rb +0 -4
  239. data/test/test_helper.rb +0 -10
  240. data/test/vitals_test.rb +0 -7
@@ -0,0 +1,26 @@
1
+ module Vitals::Formats
2
+ class HostLastFormat
3
+ attr_accessor :environment
4
+ attr_accessor :host
5
+ attr_accessor :facility
6
+
7
+ def initialize(environment:'development', facility:'default', host:'localhost')
8
+ @environment = environment
9
+ @facility = facility
10
+ @host = host
11
+ @host = Vitals::Utils.normalize_metric(host).freeze if @host
12
+ @prefix = [environment, facility].compact.map{|m| Vitals::Utils.normalize_metric(m) }
13
+ .join(Vitals::Utils::SEPARATOR).freeze
14
+ @prefix_with_host = [environment, facility, @host].compact.map{|m| Vitals::Utils.normalize_metric(m) }
15
+ .join(Vitals::Utils::SEPARATOR).freeze
16
+ end
17
+
18
+ def format(m)
19
+ return @prefix_with_host if (m.nil? || m.empty?)
20
+ # TODO optimize by building a renderer function (inlining this) in the initializer.
21
+ # see https://github.com/evanphx/benchmark-ips/blob/master/lib/benchmark/ips/job/entry.rb#L63
22
+ [@prefix, Vitals::Utils.normalize_metric(m), @host].reject{|s| s.nil? || s.empty? }.join(Vitals::Utils::SEPARATOR)
23
+ end
24
+ end
25
+ end
26
+
@@ -0,0 +1,21 @@
1
+ module Vitals::Formats
2
+ class ProductionFormat
3
+ attr_accessor :environment
4
+ attr_accessor :host
5
+ attr_accessor :facility
6
+
7
+ def initialize(environment:'development', facility:'default', host:'localhost')
8
+ @environment = environment
9
+ @facility = facility
10
+ @host = host
11
+ @prefix = [environment, host, facility].compact.map{|m| Vitals::Utils.normalize_metric(m) }
12
+ .join(".").freeze
13
+ # TODO prematerialize working prefix with metric name sanitation
14
+ end
15
+
16
+ def format(m)
17
+ return @prefix if (m.nil? || m.empty?)
18
+ "#{@prefix}.#{Vitals::Utils.normalize_metric(m)}"
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,26 @@
1
+ require 'vitals/integrations/notifications/base'
2
+
3
+ module Vitals::Integrations::Notifications
4
+ class ActionController < Base
5
+ def self.event_name
6
+ 'process_action.action_controller'
7
+ end
8
+
9
+ private
10
+
11
+ def self.handle(name, started, finished, unique_id, payload)
12
+ method = payload[:method].downcase
13
+ status = payload[:status]
14
+ action = payload[:action]
15
+ ctrl = payload[:controller].sub(/Controller$/, '').downcase
16
+ # format = payload[:format]
17
+
18
+ m = "controllers.#{ctrl}_#{action}_#{method}.#{status}"
19
+ Vitals.timing("#{m}.all", duration(started, finished))
20
+ Vitals.timing("#{m}.db", payload[:db_runtime]) if payload[:db_runtime]
21
+ Vitals.timing("#{m}.view", payload[:view_runtime]) if payload[:view_runtime]
22
+ end
23
+
24
+ end
25
+ end
26
+
@@ -0,0 +1,18 @@
1
+ require 'vitals/integrations/notifications/base'
2
+
3
+ module Vitals::Integrations::Notifications
4
+ # see https://github.com/rails/rails/blob/master/activejob/lib/active_job/logging.rb#L23
5
+ class ActiveJob < Base
6
+ def self.event_name
7
+ 'perform.active_job'
8
+ end
9
+
10
+ private
11
+ def self.handle(name, started, finished, unique_id, payload)
12
+ job = payload[:job]
13
+ name = job.class.name.sub(/Job$/, '').sub(/Worker$/,'').downcase
14
+
15
+ Vitals.timing("jobs.#{job.queue_name}.#{name}", duration(started, finished))
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,20 @@
1
+ require 'active_support'
2
+
3
+ module Vitals::Integrations::Notifications
4
+ class Base
5
+ def self.subscribe!
6
+ subscriber = ActiveSupport::Notifications.subscribe(event_name, &method(:handle))
7
+
8
+ subscriber
9
+ end
10
+
11
+ def self.handle
12
+ raise "#handle not implemented"
13
+ end
14
+
15
+ def self.duration(started, finished)
16
+ Vitals::Utils.sec_to_ms(finished - started)
17
+ end
18
+ end
19
+ end
20
+
@@ -0,0 +1,30 @@
1
+ require 'vitals/integrations/notifications/base'
2
+
3
+ module Vitals::Integrations::Notifications
4
+ class Grape < Base
5
+ def self.event_name
6
+ 'endpoint_run.grape'
7
+ end
8
+
9
+ private
10
+
11
+ def self.handle(name, started, finished, unique_id, payload)
12
+ endpoint = payload[:endpoint]
13
+ route = endpoint.route
14
+ version = route.route_version
15
+ method = route.route_method.downcase
16
+
17
+ path = route.route_path.dup
18
+ path.sub!(/\(\..*\)$/, '')
19
+ path.sub!(":version", version) if version
20
+ path.gsub!(/\//, ".")
21
+
22
+ # TODO move 'grape' to configuration opts in subscribe!(opts)
23
+ m = "grape#{path}_#{method}.#{endpoint.status}.all"
24
+ Vitals.timing(m, duration(started, finished))
25
+ end
26
+
27
+ end
28
+ end
29
+
30
+
@@ -0,0 +1,23 @@
1
+
2
+ module Vitals::Integrations::Rack
3
+ class Requests
4
+ REQUEST_METHOD = 'REQUEST_METHOD'.freeze
5
+ PATH_INFO = 'PATH_INFO'.freeze
6
+
7
+ def initialize(app, options = {})
8
+ @app = app
9
+ end
10
+
11
+ def call(env)
12
+ start = Time.now
13
+ status, header, body = @app.call(env)
14
+
15
+ # TODO add option to customize 'requests' through options
16
+ m = "requests.#{env[PATH_INFO]}.#{env[REQUEST_METHOD].downcase}.#{status}"
17
+ Vitals.timing(m, Vitals::Utils.sec_to_ms(Time.now - start))
18
+
19
+ [status, header, body]
20
+ end
21
+ end
22
+ end
23
+
@@ -0,0 +1,9 @@
1
+ module Vitals::Reporters
2
+ class BaseReporter
3
+ def time(m)
4
+ start = Time.now
5
+ yield
6
+ timing(m, Vitals::Utils::sec_to_ms(Time.now - start))
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,23 @@
1
+ module Vitals::Reporters
2
+ class ConsoleReporter < BaseReporter
3
+ attr_accessor :format
4
+
5
+ def initialize(category:'main', format:nil)
6
+ @format = format
7
+ @category = category
8
+ end
9
+
10
+ def inc(m)
11
+ puts "#{@category} INC #{self.format.format(m)}"
12
+ end
13
+
14
+ def gauge(m, v)
15
+ puts "#{@category} GAUGE #{self.format.format(m)} #{v}"
16
+ end
17
+
18
+ def timing(m, v)
19
+ puts "#{@category} TIME #{self.format.format(m)} #{v}"
20
+ end
21
+ end
22
+ end
23
+
@@ -0,0 +1,31 @@
1
+ module Vitals::Reporters
2
+ class InmemReporter < BaseReporter
3
+ attr_accessor :reports
4
+ attr_accessor :format
5
+
6
+ def initialize
7
+ flush
8
+ end
9
+
10
+ def flush
11
+ @reports = []
12
+ end
13
+
14
+ def inc(m)
15
+ @reports << { :inc => n( m ) }
16
+ end
17
+
18
+ def gauge(m, v)
19
+ @reports << { :gauge => n( m ), :val => v }
20
+ end
21
+
22
+ def timing(m, v)
23
+ @reports << { :timing => n( m ), :val => v }
24
+ end
25
+
26
+ private
27
+ def n(m)
28
+ Vitals::Utils.normalize_metric(m)
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,24 @@
1
+ module Vitals::Reporters
2
+ class MultiReporter < BaseReporter
3
+ attr_accessor :format
4
+
5
+ def initialize(format:nil, reporters:[])
6
+ @format = format
7
+ @reporters = reporters
8
+ end
9
+
10
+ def inc(m)
11
+ @reporters.each{|r| r.inc(m) }
12
+ end
13
+
14
+ def gauge(m, v)
15
+ @reporters.each{|r| r.gauge(m, v) }
16
+ end
17
+
18
+ def timing(m, v)
19
+ @reporters.each{|r| r.timing(m, v) }
20
+ end
21
+ end
22
+ end
23
+
24
+
@@ -0,0 +1,27 @@
1
+ require 'statsd-ruby'
2
+
3
+ module Vitals::Reporters
4
+ class StatsdReporter < BaseReporter
5
+ attr_accessor :format
6
+ attr_accessor :statsd
7
+
8
+ def initialize(host:'localhost', port:8125, format:nil)
9
+ @statsd = Statsd.new(host, port)
10
+ @format = format
11
+ end
12
+
13
+ def inc(m)
14
+ @statsd.increment(format.format(m))
15
+ end
16
+
17
+ def gauge(m, v)
18
+ @statsd.gauge(format.format(m), v)
19
+ end
20
+
21
+ def timing(m, v)
22
+ @statsd.timing(format.format(m), v)
23
+ end
24
+ end
25
+ end
26
+
27
+
@@ -0,0 +1,15 @@
1
+ module Vitals
2
+ module Utils
3
+ BAD_METRICS_CHARS = Regexp.compile('[\/\-:\s]').freeze
4
+ SEPARATOR = '.'.freeze
5
+ def self.normalize_metric(m)
6
+ m.gsub(BAD_METRICS_CHARS, '_')
7
+ end
8
+ def self.hostname
9
+ `hostname -s`.chomp
10
+ end
11
+ def self.sec_to_ms(sec)
12
+ (1000.0 * sec).round
13
+ end
14
+ end
15
+ end
@@ -1,3 +1,3 @@
1
1
  module Vitals
2
- VERSION = "0.0.2"
2
+ VERSION = "0.3.0"
3
3
  end
data/lib/vitals.rb CHANGED
@@ -1,33 +1,56 @@
1
- require 'active_support/notifications'
2
- require 'vitals/reporter'
1
+ require "vitals/version"
2
+ module Vitals
3
+ module Formats;end
4
+ module Reporters;end
5
+ module Integrations
6
+ module Notifications;end
7
+ end
8
+ end
9
+
10
+ require 'vitals/configuration'
11
+ require 'vitals/utils'
12
+
13
+ require 'vitals/reporters/base_reporter'
14
+ require 'vitals/reporters/inmem_reporter'
15
+ require 'vitals/reporters/console_reporter'
16
+ require 'vitals/reporters/multi_reporter'
17
+ require 'vitals/reporters/statsd_reporter'
18
+
19
+ require 'vitals/formats/production_format'
20
+ require 'vitals/formats/host_last_format'
21
+
3
22
 
4
23
  module Vitals
5
- class Engine < Rails::Engine
6
- config.vitals = ActiveSupport::OrderedOptions.new
7
-
8
- config.vitals.enabled = true
9
- config.vitals.host = 'localhost'
10
- config.vitals.port = 8125
11
-
12
- initializer "vitals.configure" do |app|
13
- Vitals.configure(app.config.vitals.host, app.config.vitals.port) if app.config.vitals.enabled
14
- end
15
-
16
- initializer "vitals.subscribe" do |app|
17
- ActiveSupport::Notifications.subscribe /[^!]$/ do |*args|
18
- Vitals.report! args
19
- end
20
- end
24
+ def self.configure!
25
+ @config = Configuration.new
26
+ yield(@config) if block_given?
27
+ @reporter = @config.reporter
28
+ @reporter.format = @config.build_format
21
29
  end
22
30
 
31
+ def self.reporter=(r)
32
+ @reporter = r
33
+ end
23
34
 
24
- @reporter = NullReporter.new
35
+ def self.reporter
36
+ @reporter
37
+ end
38
+
39
+ #
40
+ # reporter delegators
41
+ #
42
+ # hardwired for performance
43
+ #
44
+ # TODO timing
45
+ def self.inc(m)
46
+ reporter.inc(m)
47
+ end
25
48
 
26
- def self.report!(args)
27
- @reporter.report!(args)
49
+ def self.timing(m, val)
50
+ reporter.timing(m, val)
28
51
  end
29
52
 
30
- def self.configure(host, port)
31
- @reporter = Reporter.new(host, port)
53
+ def self.gauge(m, val)
54
+ reporter.gauge(m, val)
32
55
  end
33
56
  end
data/vitals.gemspec ADDED
@@ -0,0 +1,48 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'vitals/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "vitals"
8
+ spec.version = Vitals::VERSION
9
+ spec.authors = ["Dotan Nahum"]
10
+ spec.email = ["jondotan@gmail.com"]
11
+
12
+ spec.summary = %q{Flexible StatsD instrumentation for Rails, Rack, Grape and more}
13
+ spec.description = %q{Flexible StatsD instrumentation for Rails, Rack, Grape and more}
14
+ spec.homepage = "https://github.com/jondot/vitals"
15
+ spec.license = "MIT"
16
+
17
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features|multiverse)/}) }
18
+ spec.bindir = "exe"
19
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
20
+ spec.require_paths = ["lib"]
21
+
22
+ spec.add_runtime_dependency "statsd-ruby", "~> 1.3.0"
23
+
24
+ spec.add_development_dependency "guard-rubocop", "~> 1.2.0"
25
+ spec.add_development_dependency "guard-minitest", "~> 2.4.4"
26
+ spec.add_development_dependency "bundler", "~> 1.11"
27
+ spec.add_development_dependency "rake", "~> 10.0"
28
+ spec.add_development_dependency "minitest", "~> 5.0"
29
+ spec.add_development_dependency "rack-test", "~> 0.6.3"
30
+ spec.add_development_dependency "rr", "~> 1.1.2"
31
+ spec.add_development_dependency "benchmark-ips", "~> 2.5.0"
32
+ spec.add_development_dependency "memory_profiler", "~> 0.9.6"
33
+
34
+ spec.add_development_dependency "coveralls", "~> 0.8.13"
35
+ # integrations
36
+ # TODO we should test these under isolated environment while removing
37
+ # these from here and running without bundler, inside docker, or by
38
+ # doing what newrelic does - which is hooking into bundler and Gemfile so that
39
+ # we simulate different bundler environment, so,
40
+ # we should test many versions of rails, grape, and so on with the same
41
+ # set of integration tests
42
+ # for now, we keep latest versions
43
+ spec.add_development_dependency "grape", "~> 0.15.0"
44
+ spec.add_development_dependency "activesupport", "~> 4.2.6"
45
+ spec.add_development_dependency "sinatra", "~> 1.4.7"
46
+
47
+
48
+ end