vitals 0.0.2 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
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