collective-metrics 0.1.10 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 379c0c2d2acab801d80078737558b671ca1dae95
4
- data.tar.gz: 30738a23f12a71cdd9ae100364158a30843ab82e
3
+ metadata.gz: 8a1b7942a5478c2d4172906cb5b37a2f6646ab76
4
+ data.tar.gz: ed459633992d33f6d2d1378f689c057515ec9c60
5
5
  SHA512:
6
- metadata.gz: 346d61c9ceab426f7da3ecf1240e45b13202ad1884288a792fe0e34f5cff84adde525f063cf4a3986b12f5772e805fbdbe3415c2769e1f1b16d98d72e1f09aff
7
- data.tar.gz: 721dde8e9e5769c6de1dc8aefce6d64f72cdce8c403daf02ab614ec71e060ff860e706becb4fa91de05539b02319d9c65ffb20d83eab6beb93a220f2be506c5d
6
+ metadata.gz: 6ada75194ab9a260c3d74a5d62a95ddbb5755d9a10d5714fb80012664809d52544f6ceb17cd4596e413e0638ccb9bf8f85e33738ce5876d04ff04184d39680df
7
+ data.tar.gz: d7e65e934cb676c39da634e7a0ce3ae9ed1c7db19b8375f8c1598faebceb120486bb10594127abaf3d14cd5b85eb6148677ccb17c037f57732df632c9218bdd6
data/.gitignore CHANGED
@@ -15,3 +15,4 @@ spec/reports
15
15
  test/tmp
16
16
  test/version_tmp
17
17
  tmp
18
+ .idea
data/Collectfile CHANGED
@@ -1,3 +1,7 @@
1
1
  use Collective::Collectors::Sidekiq
2
2
  use Collective::Collectors::Redis
3
3
  use Collective::Collectors::Memcached
4
+ unless ENV['NEWRELIC_API_KEY'].nil? || ENV['NEWRELIC_API_KEY'].empty?
5
+ use Collective::Collectors::Newrelic, api_key: ENV['NEWRELIC_API_KEY'], filter: ENV['NEWRELIC_APPLICATION_FILTER']
6
+ end
7
+
data/Gemfile CHANGED
@@ -7,4 +7,5 @@ group :development do
7
7
  gem 'dalli'
8
8
  gem 'sidekiq'
9
9
  gem 'mongoid', '~> 3.0'
10
+ gem 'pg'
10
11
  end
data/lib/collective.rb CHANGED
@@ -8,11 +8,14 @@ module Collective
8
8
  autoload :Builder, 'collective/builder'
9
9
 
10
10
  module Collectors
11
- autoload :Sidekiq, 'collective/collectors/sidekiq'
12
- autoload :Redis, 'collective/collectors/redis'
13
- autoload :Memcached, 'collective/collectors/memcached'
14
- autoload :RabbitMQ, 'collective/collectors/rabbitmq'
15
- autoload :Mongodb, 'collective/collectors/mongodb'
11
+ autoload :Sidekiq, 'collective/collectors/sidekiq'
12
+ autoload :Redis, 'collective/collectors/redis'
13
+ autoload :Memcached, 'collective/collectors/memcached'
14
+ autoload :RabbitMQ, 'collective/collectors/rabbitmq'
15
+ autoload :Mongodb, 'collective/collectors/mongodb'
16
+ autoload :Honeybadger, 'collective/collectors/honeybadger'
17
+ autoload :Newrelic, 'collective/collectors/newrelic'
18
+ autoload :PGBouncer, 'collective/collectors/pgbouncer'
16
19
  end
17
20
 
18
21
  class << self
@@ -0,0 +1,62 @@
1
+ module Collective::Collectors
2
+ class Honeybadger < Collective::Collector
3
+ requires :faraday
4
+ requires :faraday_middleware
5
+ requires :json
6
+
7
+ resolution '60s'
8
+
9
+ collect do
10
+ instrument_exceptions
11
+ end
12
+
13
+ private
14
+
15
+ def instrument_exceptions
16
+ each_result('/v1/projects') do |project|
17
+ id = project['id']
18
+ totals_by_env = Hash.new { |hash, key| hash[key] = 0 }
19
+
20
+ each_result("/v1/projects/#{id}/faults", resolved: 'f') do |fault|
21
+ totals_by_env[fault['environment']] += fault['notices_count']
22
+ end
23
+
24
+ totals_by_env.each do |env, total|
25
+ instrument 'honeybadger.faults.notices', total, source: "%s.%s" % [project['name'], env], type: 'count'
26
+ end
27
+ end
28
+ end
29
+
30
+ def each_result(path, params={})
31
+ page = 1
32
+ resp = get_page(path, params, page)
33
+
34
+ while resp.body['num_pages'] > page do
35
+ resp.body['results'].each do |obj|
36
+ yield obj
37
+ end
38
+ page += 1
39
+ resp = get_page(path, params, page)
40
+ end
41
+ end
42
+
43
+ def get_page(path, params, page)
44
+ client.get(path, params.merge(auth_token: auth_token, page: page))
45
+ end
46
+
47
+ def client
48
+ @client ||= Faraday.new(url) do |builder|
49
+ builder.response :json, content_type: /\bjson$/
50
+ builder.adapter Faraday.default_adapter
51
+ end
52
+ end
53
+
54
+ def url
55
+ "https://api.honeybadger.io"
56
+ end
57
+
58
+ def auth_token
59
+ options[:auth_token]
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,96 @@
1
+ module Collective::Collectors
2
+ class Newrelic < Collective::Collector
3
+ requires :faraday
4
+ requires :faraday_middleware
5
+ requires :json
6
+
7
+ resolution '60s'
8
+
9
+ collect do
10
+ instrument_applications 'newrelic'
11
+ instrument_key_transactions 'newrelic'
12
+ end
13
+
14
+ private
15
+
16
+ def instrument_applications(prefix)
17
+ paged('/v2/applications.json', 'applications').each do |app|
18
+ next unless app['name'].include? filter
19
+ next unless app['reporting']
20
+
21
+ group "#{prefix}.#{app['name']}" do |group|
22
+ instrument_apdex group, app
23
+ end
24
+ end
25
+ end
26
+
27
+ def instrument_key_transactions(prefix)
28
+ # max_pages is a workaround for a new relic bug, it's currently returning the first page
29
+ # if you ask for a non-existent page instead of returning an empty list (as it
30
+ # does for /v2/applications.json)
31
+ paged('/v2/key_transactions.json', 'key_transactions', max_pages=1).each do |key_transaction|
32
+ # Not sure if the names are quoted, replace
33
+ sanitized_name = key_transaction['name'].gsub(/ /, '_')
34
+ group "#{prefix}.key.#{sanitized_name}" do |group|
35
+ instrument_apdex group, key_transaction
36
+ end
37
+ end
38
+ end
39
+
40
+ # Given an `info` hash that contains appdex summaries, instruments the
41
+ # application and browser appdex scores
42
+ def instrument_apdex(group, info)
43
+ if info.include? 'application_summary'
44
+ group.instrument 'response_time', info['application_summary']['response_time'], units: 'ms'
45
+ group.instrument 'apdex_score', info['application_summary']['apdex_score']
46
+ end
47
+ if info.include? 'end_user_summary'
48
+ group.group 'browser' do |group|
49
+ group.instrument 'response_time', info['end_user_summary']['response_time'], units: 's'
50
+ group.instrument 'apdex_score', info['end_user_summary']['apdex_score']
51
+ end
52
+ end
53
+ end
54
+
55
+ # Pages through items specified by `json_key` and yields them one at a time
56
+ def paged(path, json_key, max_pages=3)
57
+ Enumerator.new do |yielder|
58
+ page = 1
59
+ resp = get path, page: page
60
+ while resp.body[json_key].length > 0 && page <= max_pages do
61
+ resp.body[json_key].each { |obj| yielder.yield obj }
62
+ page += 1
63
+ resp = get path, page: page
64
+ end
65
+ end
66
+ end
67
+
68
+ # Make an authenticated get request to the new relic api
69
+ def get(path, options={})
70
+ client.get(path, options) do |req|
71
+ req.headers['X-Api-Key'] = api_key
72
+ end
73
+ end
74
+
75
+ def client
76
+ @client ||= Faraday.new(api_url) do |builder|
77
+ builder.response :json, content_type: /\bjson$/
78
+ builder.response :raise_error
79
+ builder.adapter Faraday.default_adapter
80
+ end
81
+ end
82
+
83
+ def api_key
84
+ options[:api_key]
85
+ end
86
+
87
+ def api_url
88
+ options[:api_url] || 'https://api.newrelic.com/'
89
+ end
90
+
91
+ # Specify to filter only applications whose name contains this string
92
+ def filter
93
+ options[:filter] || ''
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,41 @@
1
+ module Collective::Collectors
2
+ class PGBouncer < Collective::Collector
3
+ requires :pg
4
+
5
+ collect do
6
+ group 'pgbouncer' do |group|
7
+ instrument group, 'stats'
8
+ instrument group, 'pools'
9
+ end
10
+ end
11
+
12
+ private
13
+
14
+ def instrument(group, thing)
15
+ group.group thing do |group|
16
+ instrument_tuples group, show(thing)
17
+ end
18
+ end
19
+
20
+ def show(thing)
21
+ conn.exec "show #{thing};"
22
+ end
23
+
24
+ def instrument_tuples(group, tuples)
25
+ tuples.each do |tuple|
26
+ source = tuple.key?('database') ? tuple['database'] : ''
27
+ tuple.each do |k,v|
28
+ group.instrument(k, v, source: source) if instrumentable?(v)
29
+ end
30
+ end
31
+ end
32
+
33
+ def conn
34
+ @conn ||= PG.connect(connection_options)
35
+ end
36
+
37
+ def connection_options
38
+ (options[:connection] || {}).merge(dbname: 'pgbouncer')
39
+ end
40
+ end
41
+ end
@@ -1,3 +1,3 @@
1
1
  module Collective
2
- VERSION = '0.1.10'
2
+ VERSION = '0.2.1'
3
3
  end
metadata CHANGED
@@ -1,131 +1,131 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: collective-metrics
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.10
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Eric J. Holmes
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-04-11 00:00:00.000000000 Z
11
+ date: 2015-08-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rufus-scheduler
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ~>
17
+ - - "~>"
18
18
  - !ruby/object:Gem::Version
19
19
  version: '2.0'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - ~>
24
+ - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: '2.0'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: thor
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - ~>
31
+ - - "~>"
32
32
  - !ruby/object:Gem::Version
33
33
  version: '0.18'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - ~>
38
+ - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0.18'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: formatted-metrics
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - '>='
45
+ - - ">="
46
46
  - !ruby/object:Gem::Version
47
47
  version: 0.2.1
48
- - - <
48
+ - - "<"
49
49
  - !ruby/object:Gem::Version
50
50
  version: '2.0'
51
51
  type: :runtime
52
52
  prerelease: false
53
53
  version_requirements: !ruby/object:Gem::Requirement
54
54
  requirements:
55
- - - '>='
55
+ - - ">="
56
56
  - !ruby/object:Gem::Version
57
57
  version: 0.2.1
58
- - - <
58
+ - - "<"
59
59
  - !ruby/object:Gem::Version
60
60
  version: '2.0'
61
61
  - !ruby/object:Gem::Dependency
62
62
  name: faraday
63
63
  requirement: !ruby/object:Gem::Requirement
64
64
  requirements:
65
- - - '>='
65
+ - - ">="
66
66
  - !ruby/object:Gem::Version
67
67
  version: '0'
68
68
  type: :runtime
69
69
  prerelease: false
70
70
  version_requirements: !ruby/object:Gem::Requirement
71
71
  requirements:
72
- - - '>='
72
+ - - ">="
73
73
  - !ruby/object:Gem::Version
74
74
  version: '0'
75
75
  - !ruby/object:Gem::Dependency
76
76
  name: faraday_middleware
77
77
  requirement: !ruby/object:Gem::Requirement
78
78
  requirements:
79
- - - '>='
79
+ - - ">="
80
80
  - !ruby/object:Gem::Version
81
81
  version: '0'
82
82
  type: :runtime
83
83
  prerelease: false
84
84
  version_requirements: !ruby/object:Gem::Requirement
85
85
  requirements:
86
- - - '>='
86
+ - - ">="
87
87
  - !ruby/object:Gem::Version
88
88
  version: '0'
89
89
  - !ruby/object:Gem::Dependency
90
90
  name: bundler
91
91
  requirement: !ruby/object:Gem::Requirement
92
92
  requirements:
93
- - - ~>
93
+ - - "~>"
94
94
  - !ruby/object:Gem::Version
95
95
  version: '1.3'
96
96
  type: :development
97
97
  prerelease: false
98
98
  version_requirements: !ruby/object:Gem::Requirement
99
99
  requirements:
100
- - - ~>
100
+ - - "~>"
101
101
  - !ruby/object:Gem::Version
102
102
  version: '1.3'
103
103
  - !ruby/object:Gem::Dependency
104
104
  name: rake
105
105
  requirement: !ruby/object:Gem::Requirement
106
106
  requirements:
107
- - - '>='
107
+ - - ">="
108
108
  - !ruby/object:Gem::Version
109
109
  version: '0'
110
110
  type: :development
111
111
  prerelease: false
112
112
  version_requirements: !ruby/object:Gem::Requirement
113
113
  requirements:
114
- - - '>='
114
+ - - ">="
115
115
  - !ruby/object:Gem::Version
116
116
  version: '0'
117
117
  - !ruby/object:Gem::Dependency
118
118
  name: rspec
119
119
  requirement: !ruby/object:Gem::Requirement
120
120
  requirements:
121
- - - '>='
121
+ - - ">="
122
122
  - !ruby/object:Gem::Version
123
123
  version: '0'
124
124
  type: :development
125
125
  prerelease: false
126
126
  version_requirements: !ruby/object:Gem::Requirement
127
127
  requirements:
128
- - - '>='
128
+ - - ">="
129
129
  - !ruby/object:Gem::Version
130
130
  version: '0'
131
131
  description: Collect and output metrics
@@ -136,7 +136,7 @@ executables:
136
136
  extensions: []
137
137
  extra_rdoc_files: []
138
138
  files:
139
- - .gitignore
139
+ - ".gitignore"
140
140
  - Collectfile
141
141
  - Gemfile
142
142
  - LICENSE.txt
@@ -150,8 +150,11 @@ files:
150
150
  - lib/collective/cli.rb
151
151
  - lib/collective/collector.rb
152
152
  - lib/collective/collector/dsl.rb
153
+ - lib/collective/collectors/honeybadger.rb
153
154
  - lib/collective/collectors/memcached.rb
154
155
  - lib/collective/collectors/mongodb.rb
156
+ - lib/collective/collectors/newrelic.rb
157
+ - lib/collective/collectors/pgbouncer.rb
155
158
  - lib/collective/collectors/rabbitmq.rb
156
159
  - lib/collective/collectors/redis.rb
157
160
  - lib/collective/collectors/sidekiq.rb
@@ -166,17 +169,17 @@ require_paths:
166
169
  - lib
167
170
  required_ruby_version: !ruby/object:Gem::Requirement
168
171
  requirements:
169
- - - '>='
172
+ - - ">="
170
173
  - !ruby/object:Gem::Version
171
174
  version: '0'
172
175
  required_rubygems_version: !ruby/object:Gem::Requirement
173
176
  requirements:
174
- - - '>='
177
+ - - ">="
175
178
  - !ruby/object:Gem::Version
176
179
  version: '0'
177
180
  requirements: []
178
181
  rubyforge_project:
179
- rubygems_version: 2.0.14
182
+ rubygems_version: 2.4.5
180
183
  signing_key:
181
184
  specification_version: 4
182
185
  summary: Collect and output metrics