nsa 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 911dad2e98c8f5fbd1f15023ed5c547930c2e2ec
4
+ data.tar.gz: 6c2123585565c8eb5eb41f54a141f3be57431d11
5
+ SHA512:
6
+ metadata.gz: ad14487a0c6ed7a63c8ea14f734775faaa0729412e7dc150601620e967503c20300bb2829901784f275412634c88fd70aff471c62a47e9cf4585b412dbd61764
7
+ data.tar.gz: c6ae6b0d35649f93f735ea3d995f7b8a86bcbd40667f72334e803369ef1c6bc8ac809c4c861f4aa2bce798db5b5acba02587d97686628632a93f02bbd740350a
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
@@ -0,0 +1,4 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.2.2
4
+ before_install: gem install bundler -v 1.10.6
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in nsa.gemspec
4
+ gemspec
@@ -0,0 +1,155 @@
1
+ # NSA (National Statsd Agency)
2
+
3
+ Listen to your Rails ActiveSupport::Notifications and deliver to a Statsd backend.
4
+ Support for writing your own custom collectors.
5
+
6
+ ## Installation
7
+
8
+ Add this line to your application's Gemfile:
9
+
10
+ ```ruby
11
+ gem "nsa"
12
+ ```
13
+
14
+ And then execute:
15
+
16
+ $ bundle
17
+
18
+ Or install it yourself as:
19
+
20
+ $ gem install nsa
21
+
22
+ ## Usage
23
+
24
+ NSA comes packaged with collectors for ActionController, ActiveRecord, ActiveSupport Caching,
25
+ and Sidekiq.
26
+
27
+ To use this gem, simply get a reference to a statsd backend, then indicate which
28
+ collectors you'd like to run. Each `collect` method specifies a Collector to use
29
+ and the additional key namespace.
30
+
31
+ ```ruby
32
+ $statsd = ::Statsd.new(ENV["STATSD_HOST"], ENV["STATSD_PORT"])
33
+ application_name = ::Rails.application.class.parent_name.underscore
34
+ application_env = ENV["PLATFORM_ENV"] || ::Rails.env
35
+ $statsd.namespace = [ application_name, application_env ].join(".")
36
+
37
+ ::NSA.inform_statsd($statsd) do |informant|
38
+ # Load :action_controller collector with a key prefix of :web
39
+ informant.collect(:action_controller, :web)
40
+ informant.collect(:active_record, :db)
41
+ informant.collect(:cache, :cache)
42
+ informant.collect(:sidekiq, :sidekiq)
43
+ end
44
+ ```
45
+
46
+ ## Built-in Collectors
47
+
48
+ ### `:action_controller`
49
+
50
+ Listens to: `process_action.action_controller
51
+
52
+ Metrics recorded:
53
+
54
+ + Timing: `{ns}.{prefix}.{controller}.{action}.{format}.total_duration`
55
+ + Timing: `{ns}.{prefix}.{controller}.{action}.{format}.db_time`
56
+ + Timing: `{ns}.{prefix}.{controller}.{action}.{format}.view_time`
57
+ + Increment: `{ns}.{prefix}.{controller}.{action}.{format}.status.{status_code}`
58
+
59
+ ### `:active_record`
60
+
61
+ Listens to: `sql.active_record`
62
+
63
+ Metrics recorded:
64
+
65
+ + Timing: `{ns}.{prefix}.tables.{table_name}.queries.delete.duration`
66
+ + Timing: `{ns}.{prefix}.tables.{table_name}.queries.insert.duration`
67
+ + Timing: `{ns}.{prefix}.tables.{table_name}.queries.select.duration`
68
+ + Timing: `{ns}.{prefix}.tables.{table_name}.queries.update.duration`
69
+
70
+ ### `:active_support_cache`
71
+
72
+ Listens to: `cache_*.active_suppport`
73
+
74
+ Metrics recorded:
75
+
76
+ + Timing: `{ns}.{prefix}.delete.duration`
77
+ + Timing: `{ns}.{prefix}.exist?.duration`
78
+ + Timing: `{ns}.{prefix}.fetch_hit.duration`
79
+ + Timing: `{ns}.{prefix}.generate.duration`
80
+ + Timing: `{ns}.{prefix}.read_hit.duration`
81
+ + Timing: `{ns}.{prefix}.read_miss.duration`
82
+ + Timing: `{ns}.{prefix}.read_miss.duration`
83
+
84
+ ### `:sidekiq`
85
+
86
+ Listens to: Sidekiq middleware, run before each job that is processed
87
+
88
+ Metrics recorded:
89
+
90
+ + Time: `{ns}.{prefix}.{WorkerName}.processing_time`
91
+ + Increment: `{ns}.{prefix}.{WorkerName}.success`
92
+ + Increment: `{ns}.{prefix}.{WorkerName}.failure`
93
+ + Gauge: `{ns}.{prefix}.queues.{queue_name}.enqueued`
94
+ + Gauge: `{ns}.{prefix}.queues.{queue_name}.latency`
95
+ + Gauge: `{ns}.{prefix}.dead_size`
96
+ + Gauge: `{ns}.{prefix}.enqueued`
97
+ + Gauge: `{ns}.{prefix}.failed`
98
+ + Gauge: `{ns}.{prefix}.processed`
99
+ + Gauge: `{ns}.{prefix}.processes_size`
100
+ + Gauge: `{ns}.{prefix}.retry_size`
101
+ + Gauge: `{ns}.{prefix}.scheduled_size`
102
+ + Gauge: `{ns}.{prefix}.workers_size`
103
+
104
+ ## Writing your own collector
105
+
106
+ Writing your own collector is very simple. To take advantage of the keyspace handling you must:
107
+
108
+ 1. Create an object/module which responds to `collect`, taking the `key_prefix` as its only argument.
109
+ 2. Include or extend your class/module with `NSA::Statsd::Publisher`.
110
+
111
+ For example:
112
+
113
+ ```ruby
114
+ module UsersCollector
115
+ extend ::NSA::Statsd::Publisher
116
+
117
+ def self.collect(key_prefix)
118
+ loop do
119
+ statsd_gauge("count", ::User.count)
120
+ sleep 10 # don't do this, obvi
121
+ end
122
+ end
123
+ end
124
+ ```
125
+
126
+ Then let the informant know about it:
127
+
128
+ ```ruby
129
+ # $statsd =
130
+ NSA.inform_statsd($statsd) do |informant|
131
+ # ...
132
+ informant.collect(UserCollector, :users)
133
+ end
134
+ ```
135
+
136
+ The `NSA::Statsd::Publisher` module exposes the following methods:
137
+
138
+ + `statsd_count(key, value = 1, sample_rate = nil)`
139
+ + `statsd_decrement(key, sample_rate = nil)`
140
+ + `statsd_gauge(key, value = 1, sample_rate = nil)`
141
+ + `statsd_increment(key, sample_rate = nil)`
142
+ + `statsd_set(key, value = 1, sample_rate = nil)`
143
+ + `statsd_time(key, sample_rate = nil, &block)`
144
+ + `statsd_timing(key, value = 1, sample_rate = nil)`
145
+
146
+ ## Development
147
+
148
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
149
+
150
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
151
+
152
+ ## Contributing
153
+
154
+ Bug reports and pull requests are welcome on GitHub at https://github.com/localshred/nsa.
155
+
@@ -0,0 +1,10 @@
1
+ require "bundler/gem_tasks"
2
+ require "rake/testtask"
3
+
4
+ Rake::TestTask.new(:test) do |t|
5
+ t.libs << "test"
6
+ t.libs << "lib"
7
+ t.test_files = FileList['test/**/*_test.rb']
8
+ end
9
+
10
+ task :default => :test
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "nsa"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start
@@ -0,0 +1,7 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+
5
+ bundle install
6
+
7
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,11 @@
1
+ require "nsa/version"
2
+ require "nsa/statsd_informant"
3
+
4
+ module NSA
5
+
6
+ def self.inform_statsd(backend)
7
+ yield ::NSA::StatsdInformant
8
+ ::NSA::StatsdInformant.listen(backend)
9
+ end
10
+
11
+ end
@@ -0,0 +1,29 @@
1
+ require "active_support/notifications"
2
+ require "nsa/statsd/publisher"
3
+
4
+ module NSA
5
+ module Collectors
6
+ module ActionController
7
+ extend ::NSA::Statsd::Publisher
8
+
9
+ def self.collect(key_prefix)
10
+ ::ActiveSupport::Notifications.subscribe(/process_action.action_controller/) do |*args|
11
+ event = ::ActiveSupport::Notifications::Event.new(*args)
12
+ controller = event.payload[:controller]
13
+ action = event.payload[:action]
14
+ format = event.payload[:format] || "all"
15
+ format = "all" if format == "*/*"
16
+ status = event.payload[:status]
17
+ key = "#{key_prefix}.#{controller}.#{action}.#{format}"
18
+
19
+ statsd_timing("#{key}.total_duration", event.duration)
20
+ statsd_timing("#{key}.db_time", event.payload[:db_runtime])
21
+ statsd_timing("#{key}.view_time", event.payload[:view_runtime])
22
+ statsd_increment("#{key}.status.#{status}")
23
+ end
24
+ end
25
+
26
+ end
27
+ end
28
+ end
29
+
@@ -0,0 +1,34 @@
1
+ require "nsa/statsd/publisher"
2
+
3
+ module NSA
4
+ module Collectors
5
+ module ActiveRecord
6
+ extend ::NSA::Statsd::Publisher
7
+
8
+ DELETE_SQL_REGEX = /^DELETE.+FROM\s+"([^"]+)"/
9
+ INSERT_SQL_REGEX = /^INSERT INTO\s+"([^"]+)"/
10
+ SELECT_SQL_REGEX = /^SELECT.+FROM\s+"([^"]+)"/
11
+ UPDATE_SQL_REGEX = /^UPDATE\s+"([^"]+)"/
12
+
13
+ def self.collect(key_prefix)
14
+ ::ActiveSupport::Notifications.subscribe("sql.active_record") do |_, start, finish, _id, payload|
15
+ query_type, table_name = case payload[:sql]
16
+ when DELETE_SQL_REGEX then [ :delete, $1 ]
17
+ when INSERT_SQL_REGEX then [ :insert, $1 ]
18
+ when SELECT_SQL_REGEX then [ :select, $1 ]
19
+ when UPDATE_SQL_REGEX then [ :update, $1 ]
20
+ else nil
21
+ end
22
+
23
+ unless query_type.nil?
24
+ stat_name = "#{key_prefix}.tables.#{table_name}.queries.#{query_type}.duration"
25
+ duration_ms = (finish - start) * 1000
26
+ statsd_timing(stat_name, duration_ms)
27
+ end
28
+ end
29
+
30
+ end
31
+ end
32
+ end
33
+ end
34
+
@@ -0,0 +1,37 @@
1
+ require "active_support/notifications"
2
+ require "nsa/statsd/publisher"
3
+
4
+ module NSA
5
+ module Collectors
6
+ module ActiveSupportCache
7
+ extend ::NSA::Statsd::Publisher
8
+
9
+ CACHE_TYPES = {
10
+ "cache_delete.active_support" => :delete,
11
+ "cache_exist?.active_support" => :exist?,
12
+ "cache_fetch_hit.active_support" => :fetch_hit,
13
+ "cache_generate.active_support" => :generate,
14
+ "cache_read.active_support" => :read,
15
+ "cache_write.active_support" => :write,
16
+ }.freeze
17
+
18
+ def self.collect(key_prefix)
19
+ ::ActiveSupport::Notifications.subscribe(/cache_[^.]+.active_support/) do |*event_args|
20
+ event = ::ActiveSupport::Notifications::Event.new(*event_args)
21
+ cache_type = CACHE_TYPES.fetch(event.name) do
22
+ event.name.split(".").first.gsub(/^cache_/, "")
23
+ end
24
+
25
+ if cache_type == :read
26
+ cache_type = event.payload[:hit] ? :read_hit : :read_miss
27
+ end
28
+
29
+ stat_name = "#{key_prefix}.#{cache_type}.duration"
30
+ statsd_timing(stat_name, event.duration)
31
+ end
32
+ end
33
+
34
+ end
35
+ end
36
+ end
37
+
@@ -0,0 +1,11 @@
1
+ module NSA
2
+ module Collectors
3
+ module Null
4
+
5
+ def self.collect(*_)
6
+ end
7
+
8
+ end
9
+ end
10
+ end
11
+
@@ -0,0 +1,72 @@
1
+ require "nsa/statsd/publisher"
2
+
3
+ module NSA
4
+ module Collectors
5
+ class Sidekiq
6
+ include ::NSA::Statsd::Publisher
7
+
8
+ def self.collect(key_prefix)
9
+ require "sidekiq"
10
+
11
+ ::Sidekiq.configure_server do |config|
12
+ config.server_middleware do |chain|
13
+ chain.add(::NSA::Collectors::Sidekiq, key_prefix)
14
+ end
15
+ end
16
+ rescue ::LoadError => exception
17
+ $stderr.puts("[LoadError] Failed to load sidekiq!", exception.message, *(exception.backtrace))
18
+ end
19
+
20
+ attr_accessor :key_prefix
21
+ private :key_prefix=
22
+
23
+ def initialize(key_prefix)
24
+ self.key_prefix = key_prefix.to_s.split(".")
25
+ end
26
+
27
+ def call(worker, message, queue_name)
28
+ worker_name = worker.class.name.tr("::", ".")
29
+
30
+ statsd_time(make_key(worker_name, :processing_time)) do
31
+ yield
32
+ end
33
+
34
+ statsd_increment(make_key(worker_name, :success))
35
+ rescue => exception
36
+ statsd_increment(make_key(worker_name, :failure))
37
+ fail exception
38
+ ensure
39
+ publish_overall_stats
40
+ publish_queue_size_and_latency(queue_name)
41
+ end
42
+
43
+ private
44
+
45
+ def publish_overall_stats
46
+ stats = ::Sidekiq::Stats.new
47
+ statsd_gauge(make_key(:dead_size), stats.dead_size)
48
+ statsd_gauge(make_key(:enqueued), stats.enqueued)
49
+ statsd_gauge(make_key(:failed), stats.failed)
50
+ statsd_gauge(make_key(:processed), stats.processed)
51
+ statsd_gauge(make_key(:processes_size), stats.processes_size)
52
+ statsd_gauge(make_key(:retry_size), stats.retry_size)
53
+ statsd_gauge(make_key(:scheduled_size), stats.scheduled_size)
54
+ statsd_gauge(make_key(:workers_size), stats.workers_size)
55
+ end
56
+
57
+ def publish_queue_size_and_latency(queue_name)
58
+ queue = ::Sidekiq::Queue.new(queue_name)
59
+ statsd_gauge(make_key(:queues, queue_name, :enqueued), queue.size)
60
+
61
+ if queue.respond_to?(:latency)
62
+ statsd_gauge(make_key(:queues, queue_name, :latency), queue.latency)
63
+ end
64
+ end
65
+
66
+ def make_key(*args)
67
+ (key_prefix + args).compact.join(".")
68
+ end
69
+
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,44 @@
1
+ module NSA
2
+ module Statsd
3
+ module Publisher
4
+
5
+ def statsd_count(key, value = 1, sample_rate = nil)
6
+ __statsd_publish(:count, key, value, sample_rate)
7
+ end
8
+
9
+ def statsd_decrement(key, sample_rate = nil)
10
+ __statsd_publish(:decrement, key, 1, sample_rate)
11
+ end
12
+
13
+ def statsd_gauge(key, value = 1, sample_rate = nil)
14
+ __statsd_publish(:gauge, key, value, sample_rate)
15
+ end
16
+
17
+ def statsd_increment(key, sample_rate = nil)
18
+ __statsd_publish(:increment, key, 1, sample_rate)
19
+ end
20
+
21
+ def statsd_set(key, value = 1, sample_rate = nil)
22
+ __statsd_publish(:set, key, value, sample_rate)
23
+ end
24
+
25
+ def statsd_time(key, sample_rate = nil, &block)
26
+ __statsd_publish(:time, key, nil, sample_rate, &block)
27
+ end
28
+
29
+ def statsd_timing(key, value = 1, sample_rate = nil)
30
+ __statsd_publish(:timing, key, value, sample_rate)
31
+ end
32
+
33
+ def __statsd_publish(stat_type, key, value = nil, sample_rate = nil, &block)
34
+ payload = { :key => key }
35
+ payload.merge!({ :value => value }) if value
36
+ payload.merge!({ :sample_rate => sample_rate }) if sample_rate
37
+ payload.merge!({ :block => block }) if block_given?
38
+
39
+ ::ActiveSupport::Notifications.instrument("#{stat_type}.statsd", payload)
40
+ end
41
+
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,30 @@
1
+ module NSA
2
+ module Statsd
3
+ module Subscriber
4
+
5
+ def statsd_subscribe(backend)
6
+ ::ActiveSupport::Notifications.subscribe(/.statsd$/) do |name, start, finish, id, payload|
7
+ __send_event_to_statsd(backend, name, start, finish, id, payload)
8
+ end
9
+ end
10
+
11
+ def __send_event_to_statsd(backend, name, start, finish, id, payload)
12
+ action = name.to_s.split(".").first || :count
13
+
14
+ key_name = payload[:key]
15
+ sample_rate = payload.fetch(:sample_rate, 1)
16
+ block = payload[:block]
17
+
18
+ case action.to_sym
19
+ when :count, :timing, :set, :gauge then
20
+ value = payload.fetch(:value) { 1 }
21
+ backend.__send__(action, key_name, value, sample_rate, &block)
22
+ when :increment, :decrement, :time then
23
+ backend.__send__(action, key_name, sample_rate, &block)
24
+ end
25
+ end
26
+
27
+ end
28
+ end
29
+ end
30
+
@@ -0,0 +1,31 @@
1
+ require "nsa/statsd/subscriber"
2
+
3
+ require "nsa/collectors/action_controller"
4
+ require "nsa/collectors/active_record"
5
+ require "nsa/collectors/active_support_cache"
6
+ require "nsa/collectors/null"
7
+ require "nsa/collectors/sidekiq"
8
+
9
+ module NSA
10
+ module StatsdInformant
11
+ extend ::NSA::Statsd::Subscriber
12
+
13
+ COLLECTOR_TYPES = ::Hash.new(::NSA::Collectors::Null).merge({
14
+ :action_controller => ::NSA::Collectors::ActionController,
15
+ :active_record => ::NSA::Collectors::ActiveRecord,
16
+ :active_support_cache => ::NSA::Collectors::ActiveSupportCache,
17
+ :sidekiq => ::NSA::Collectors::Sidekiq
18
+ }).freeze
19
+
20
+ def self.collect(collector, key_prefix)
21
+ collector = COLLECTOR_TYPES[collector.to_sym] unless collector.respond_to?(:collect)
22
+ collector.collect(key_prefix)
23
+ end
24
+
25
+ def self.listen(backend)
26
+ statsd_subscribe(backend)
27
+ end
28
+
29
+ end
30
+ end
31
+
@@ -0,0 +1,3 @@
1
+ module NSA
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,29 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path("../lib", __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require "nsa/version"
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "nsa"
8
+ spec.version = ::NSA::VERSION
9
+ spec.authors = ["BJ Neilsen"]
10
+ spec.email = ["bj.neilsen@gmail.com"]
11
+
12
+ spec.summary = %q{Listen to your Rails ActiveSupport::Notifications and deliver to a Statsd backend.}
13
+ spec.description = spec.summary
14
+ spec.homepage = "https://www.github.com/localshred/nsa"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
17
+ spec.bindir = "exe"
18
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_dependency "activesupport", "~> 4.2.0"
22
+ spec.add_dependency "sidekiq", "~> 3.5.0"
23
+
24
+ spec.add_development_dependency "bundler", "~> 1.10"
25
+ spec.add_development_dependency "rake", "~> 10.0"
26
+ spec.add_development_dependency "minitest"
27
+ spec.add_development_dependency "mocha"
28
+ spec.add_development_dependency "byebug"
29
+ end
metadata ADDED
@@ -0,0 +1,161 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: nsa
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - BJ Neilsen
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2015-11-17 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activesupport
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 4.2.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 4.2.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: sidekiq
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 3.5.0
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 3.5.0
41
+ - !ruby/object:Gem::Dependency
42
+ name: bundler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.10'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.10'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '10.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '10.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: minitest
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: mocha
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: byebug
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ description: Listen to your Rails ActiveSupport::Notifications and deliver to a Statsd
112
+ backend.
113
+ email:
114
+ - bj.neilsen@gmail.com
115
+ executables: []
116
+ extensions: []
117
+ extra_rdoc_files: []
118
+ files:
119
+ - ".gitignore"
120
+ - ".travis.yml"
121
+ - Gemfile
122
+ - README.md
123
+ - Rakefile
124
+ - bin/console
125
+ - bin/setup
126
+ - lib/nsa.rb
127
+ - lib/nsa/collectors/action_controller.rb
128
+ - lib/nsa/collectors/active_record.rb
129
+ - lib/nsa/collectors/active_support_cache.rb
130
+ - lib/nsa/collectors/null.rb
131
+ - lib/nsa/collectors/sidekiq.rb
132
+ - lib/nsa/statsd/publisher.rb
133
+ - lib/nsa/statsd/subscriber.rb
134
+ - lib/nsa/statsd_informant.rb
135
+ - lib/nsa/version.rb
136
+ - nsa.gemspec
137
+ homepage: https://www.github.com/localshred/nsa
138
+ licenses: []
139
+ metadata: {}
140
+ post_install_message:
141
+ rdoc_options: []
142
+ require_paths:
143
+ - lib
144
+ required_ruby_version: !ruby/object:Gem::Requirement
145
+ requirements:
146
+ - - ">="
147
+ - !ruby/object:Gem::Version
148
+ version: '0'
149
+ required_rubygems_version: !ruby/object:Gem::Requirement
150
+ requirements:
151
+ - - ">="
152
+ - !ruby/object:Gem::Version
153
+ version: '0'
154
+ requirements: []
155
+ rubyforge_project:
156
+ rubygems_version: 2.4.5
157
+ signing_key:
158
+ specification_version: 4
159
+ summary: Listen to your Rails ActiveSupport::Notifications and deliver to a Statsd
160
+ backend.
161
+ test_files: []