collective-metrics 0.2.3 → 0.3.0

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: 38cbe392ebdab08135fb07eda42511cb2af92383
4
- data.tar.gz: 7c95091a0665ae20eb66df3090402a21b021cd90
3
+ metadata.gz: 867d160cc98d20a4135bd89a7e20818ca0a59523
4
+ data.tar.gz: 14a2dee02b5a23b46e485d3734fbdf8f09b5bf9d
5
5
  SHA512:
6
- metadata.gz: 74345281798d952090dfa93fef3cbe40dd92f9c20390eed768f3b879e555b74e0d0b8bbcaf937833c737845fd5be535244785d8376dccbecad8ad3c2359b3d07
7
- data.tar.gz: 9985f3810e6f1c75708c527cee766b1019c52db720deaa89a42a2b9ece81dddffad93d76fdfcd6c826562acc0006fd979e7509172dd810bdb998c01b5428507e
6
+ metadata.gz: d95c2229f1ee18d673702c209ff9a508e0e4f32f20f0c4060c7f69f7b0625b02650a9f2617aaccce8097bf7bad46cf2d893dafaf74c010592bc9ef39c78c24a1
7
+ data.tar.gz: 505be1fbd644e0a3580bbec41c9218bb7a53ce8f817d8c3fd2fd837ac5403c2cf96385e23f3ed9147439d39e7260ba3a0124ff7d0ab2b10d4d9e75f43a6f5f54
data/Collectfile CHANGED
@@ -4,4 +4,6 @@ use Collective::Collectors::Memcached
4
4
  unless ENV['NEWRELIC_API_KEY'].nil? || ENV['NEWRELIC_API_KEY'].empty?
5
5
  use Collective::Collectors::Newrelic, api_key: ENV['NEWRELIC_API_KEY'], filter: ENV['NEWRELIC_APPLICATION_FILTER']
6
6
  end
7
-
7
+ unless ENV['TRACKJS_API_KEY'].nil? || ENV['TRACKJS_API_KEY'].empty?
8
+ use Collective::Collectors::TrackJS, api_key: ENV['TRACKJS_API_KEY'], customer_id: ENV['TRACKJS_CUSTOMER_ID']
9
+ end
data/Gemfile CHANGED
@@ -6,6 +6,17 @@ gemspec
6
6
  group :development do
7
7
  gem 'dalli'
8
8
  gem 'sidekiq'
9
- gem 'mongoid', '~> 3.0'
9
+ gem 'mongoid', '~> 3.0'
10
10
  gem 'pg'
11
11
  end
12
+
13
+ group :development, :test do
14
+ gem 'rspec', '~> 3.4.0'
15
+ gem 'dotenv', '~> 2.1.1'
16
+ gem 'faker'
17
+ gem 'activesupport'
18
+ end
19
+
20
+ group :test do
21
+ gem 'webmock'
22
+ end
@@ -0,0 +1,112 @@
1
+ module Collective::Collectors
2
+ class TrackJS < Collective::Collector
3
+ requires :faraday
4
+ requires :faraday_middleware
5
+ requires :json
6
+ @@frequency = 60 # seconds
7
+
8
+ resolution @@frequency.to_s + 's'
9
+
10
+ def initialize(options = {})
11
+ @last_seen_id = options[:last_seen_id] || {}
12
+ super(options)
13
+ end
14
+
15
+ collect do
16
+ options[:applications].each do |application|
17
+ instrument_errors application
18
+ end
19
+ end
20
+
21
+ private
22
+
23
+ def instrument_errors(application)
24
+ count = 0
25
+ paged("/#{customer_id}/v1/errors", {application: application}).each do |error|
26
+ count += 1
27
+ end
28
+ instrument 'trackjs.url.errors', count, source: application, type: 'count'
29
+ end
30
+
31
+ # This function goes through a paged list of errors and yields each
32
+ # individual error.
33
+ #
34
+ # The most basic endpoint in the TrackJS API returns all the errors that
35
+ # have been detected from the beginning of time to the current date. This
36
+ # endpoint can return the number of errors seen in the last day, but since
37
+ # we're just trying to determine the number of errors that occurred in the
38
+ # last 60s, we use the default endpoint options.
39
+ #
40
+ # To avoid fetching all the errors, only the ones we haven't seen since
41
+ # the last time we checked, so we keep track of the id of the last error
42
+ # we saw and page through the error list until either:
43
+ #
44
+ # 1. We see an error we've already returned
45
+ # 2. We hit an errors that's more than 60s old (to avoid scanning the entire list of
46
+ # errors the first time the collector is run)
47
+ # 3. We hit the very end of the error list
48
+ #
49
+ def paged(path, params={})
50
+ Enumerator.new do |yielder|
51
+ current_error_time = Time.now.utc
52
+ oldest_error = current_error_time - @@frequency
53
+ page = 1
54
+ page_size = 250
55
+ current_initial_id = nil
56
+ get_another_page = true # set to true until an error id that has already been seen is hit
57
+ application = params[:application]
58
+
59
+ resp = get_page(path, params, page, page_size)
60
+ data = resp.body['data']
61
+
62
+ if data.length > 0
63
+ current_initial_id = data[0]['id']
64
+
65
+ while current_error_time > oldest_error do
66
+ resp.body['data'].each do |error|
67
+ current_error_time = Time.parse(error['timestamp'])
68
+ if (error['id'] == @last_seen_id[application]) || (current_error_time <= oldest_error)
69
+ get_another_page = false
70
+ break
71
+ else
72
+ yielder.yield error
73
+ end
74
+ end
75
+
76
+ break if !get_another_page or !resp.body['metadata']['hasMore']
77
+
78
+ page += 1
79
+ resp = get_page(path, params, page, page_size)
80
+ end
81
+
82
+ @last_seen_id[application] = current_initial_id
83
+ end
84
+ end
85
+ end
86
+
87
+ def get_page(path, params, page, page_size = 500)
88
+ client.get(path, params.merge(page: page, size: page_size)) do |req|
89
+ req.headers['Authorization'] = api_key
90
+ end
91
+ end
92
+
93
+ def client
94
+ @client ||= Faraday.new(api_url) do |builder|
95
+ builder.response :json, content_type: /\bjson$/
96
+ builder.adapter Faraday.default_adapter
97
+ end
98
+ end
99
+
100
+ def api_url
101
+ "https://api.trackjs.com"
102
+ end
103
+
104
+ def customer_id
105
+ options[:customer_id]
106
+ end
107
+
108
+ def api_key
109
+ options[:api_key]
110
+ end
111
+ end
112
+ end
@@ -1,3 +1,3 @@
1
1
  module Collective
2
- VERSION = '0.2.3'
2
+ VERSION = '0.3.0'
3
3
  end
data/lib/collective.rb CHANGED
@@ -17,6 +17,7 @@ module Collective
17
17
  autoload :Newrelic, 'collective/collectors/newrelic'
18
18
  autoload :PGBouncer, 'collective/collectors/pgbouncer'
19
19
  autoload :Postgres, 'collective/collectors/postgres'
20
+ autoload :TrackJS, 'collective/collectors/trackjs'
20
21
  end
21
22
 
22
23
  class << self
@@ -0,0 +1,342 @@
1
+ require 'spec_helper'
2
+ require 'collective'
3
+ require 'active_support/core_ext/numeric/time'
4
+
5
+ describe Collective::Collectors::TrackJS do
6
+ let(:env_api_key) { ENV["TRACKJS_API_KEY"] }
7
+ let(:env_customer_id) { ENV["TRACKJS_CUSTOMER_ID"] }
8
+ let(:page_size) { 250 }
9
+ let(:page) { 1 }
10
+ let(:no_errors) { 0 }
11
+ let(:empty_response) { trackjs_response errors: no_errors, total_errors: no_errors, page: page, page_size: page_size }
12
+
13
+ before do
14
+ @collector = Collective::Collectors::TrackJS.new(
15
+ :api_key => env_api_key,
16
+ :customer_id => env_customer_id
17
+ )
18
+ end
19
+
20
+ context 'when no errors are returned' do
21
+ let(:errors) { 0 }
22
+ let(:response) { trackjs_response errors: errors, total_errors: errors, page: page, page_size: page_size }
23
+
24
+ it 'logs an error count of 0' do
25
+ stub_request(:get, "https://api.trackjs.com/#{env_customer_id}/v1/errors")
26
+ .with(:query => {"page" => page, "size" => page_size, "application" => "r101-frontend"})
27
+ .to_return(
28
+ :body => response.to_json,
29
+ :status => 200,
30
+ :headers => {'Content-Type' => 'application/json'}
31
+ )
32
+ stub_request(:get, "https://api.trackjs.com/#{env_customer_id}/v1/errors")
33
+ .with(:query => {"page" => page, "size" => page_size, "application" => "r101-marketing"})
34
+ .to_return(
35
+ :body => response.to_json,
36
+ :status => 200,
37
+ :headers => {'Content-Type' => 'application/json'}
38
+ )
39
+
40
+ expect(Metrics).to receive(:instrument).with('trackjs.url.errors', 0, hash_including(:source => "r101-frontend"))
41
+ expect(Metrics).to receive(:instrument).with('trackjs.url.errors', 0, hash_including(:source => "r101-marketing"))
42
+ @collector.collect
43
+ expect(
44
+ a_request(:get, "https://api.trackjs.com/#{env_customer_id}/v1/errors").with(:query => {"page" => page, "size" => page_size, "application" => "r101-frontend"})
45
+ ).to have_been_made
46
+ expect(
47
+ a_request(:get, "https://api.trackjs.com/#{env_customer_id}/v1/errors").with(:query => {"page" => page, "size" => page_size, "application" => "r101-marketing"})
48
+ ).to have_been_made
49
+ end
50
+ end
51
+
52
+ context 'when less than a page of errors are returned' do
53
+ let(:error_count) { 45 }
54
+ let(:metadata) { trackjs_metadata total_count: error_count, page: page, page_size: page_size, has_more: false }
55
+ let(:response) { trackjs_response errors: error_count, total_errors: error_count, page: page, page_size: page_size }
56
+
57
+ context 'when none of the errors have been logged before' do
58
+ context 'all the errors are within the last @frequency seconds' do
59
+ it 'logs all the errors returned' do
60
+ stub_request(:get, "https://api.trackjs.com/#{env_customer_id}/v1/errors")
61
+ .with(:query => {"page" => page, "size" => page_size, "application" => "r101-frontend"})
62
+ .to_return(
63
+ :body => response.to_json,
64
+ :status => 200,
65
+ :headers => {'Content-Type' => 'application/json'}
66
+ )
67
+ stub_request(:get, "https://api.trackjs.com/#{env_customer_id}/v1/errors")
68
+ .with(:query => {"page" => page, "size" => page_size, "application" => "r101-marketing"})
69
+ .to_return(
70
+ :body => empty_response.to_json,
71
+ :status => 200,
72
+ :headers => {'Content-Type' => 'application/json'}
73
+ )
74
+
75
+ expect(Metrics).to receive(:instrument).with('trackjs.url.errors', error_count, hash_including(:source => "r101-frontend"))
76
+ expect(Metrics).to receive(:instrument).with('trackjs.url.errors', 0, hash_including(:source => "r101-marketing"))
77
+ @collector.collect
78
+ expect(
79
+ a_request(:get, "https://api.trackjs.com/#{env_customer_id}/v1/errors").with(:query => {"page" => page, "size" => page_size, "application" => "r101-frontend"})
80
+ ).to have_been_made
81
+ expect(
82
+ a_request(:get, "https://api.trackjs.com/#{env_customer_id}/v1/errors").with(:query => {"page" => page, "size" => page_size, "application" => "r101-marketing"})
83
+ ).to have_been_made
84
+ end
85
+ end
86
+
87
+ context 'not all the errors are within the last @frequency seconds' do
88
+ let(:old_error_count) { 7 }
89
+ let(:old_timestamps) { old_error_count.times.map { 3.hours.ago.utc.strftime("%FT%T%:z") } }
90
+ let(:old_errors) { old_error_count.times.map { |i| trackjs_error({timestamp: old_timestamps[i]}) } }
91
+ let(:errors) { (error_count - old_error_count).times.map { trackjs_error} + old_errors }
92
+ let(:response) { { "data" => errors, "metadata" => metadata } }
93
+
94
+ it 'logs only the errors in the last @frequency s' do
95
+ stub_request(:get, "https://api.trackjs.com/#{env_customer_id}/v1/errors")
96
+ .with(:query => {"page" => page, "size" => page_size, "application" => "r101-frontend"})
97
+ .to_return(
98
+ :body => response.to_json,
99
+ :status => 200,
100
+ :headers => {'Content-Type' => 'application/json'}
101
+ )
102
+ stub_request(:get, "https://api.trackjs.com/#{env_customer_id}/v1/errors")
103
+ .with(:query => {"page" => page, "size" => page_size, "application" => "r101-marketing"})
104
+ .to_return(
105
+ :body => empty_response.to_json,
106
+ :status => 200,
107
+ :headers => {'Content-Type' => 'application/json'}
108
+ )
109
+
110
+ expect(Metrics).to receive(:instrument).with('trackjs.url.errors', error_count - old_error_count, hash_including(:source => "r101-frontend"))
111
+ expect(Metrics).to receive(:instrument).with('trackjs.url.errors', 0, hash_including(:source => "r101-marketing"))
112
+ @collector.collect
113
+ expect(
114
+ a_request(:get, "https://api.trackjs.com/#{env_customer_id}/v1/errors").with(:query => {"page" => page, "size" => page_size, "application" => "r101-frontend"})
115
+ ).to have_been_made
116
+ expect(
117
+ a_request(:get, "https://api.trackjs.com/#{env_customer_id}/v1/errors").with(:query => {"page" => page, "size" => page_size, "application" => "r101-marketing"})
118
+ ).to have_been_made
119
+ end
120
+ end
121
+
122
+ context 'none of the errors are within the last @frequency seconds' do
123
+ let(:old_timestamps) { error_count.times.map { 3.hours.ago.utc.strftime("%FT%T%:z") } }
124
+ let(:errors) { error_count.times.map { |i| trackjs_error({timestamp: old_timestamps[i]}) } }
125
+ let(:response) { { "data" => errors, "metadata" => metadata } }
126
+
127
+ it 'logs 0 errors' do
128
+ stub_request(:get, "https://api.trackjs.com/#{env_customer_id}/v1/errors")
129
+ .with(:query => {"page" => page, "size" => page_size, "application" => "r101-frontend"})
130
+ .to_return(
131
+ :body => response.to_json,
132
+ :status => 200,
133
+ :headers => {'Content-Type' => 'application/json'}
134
+ )
135
+ stub_request(:get, "https://api.trackjs.com/#{env_customer_id}/v1/errors")
136
+ .with(:query => {"page" => page, "size" => page_size, "application" => "r101-marketing"})
137
+ .to_return(
138
+ :body => empty_response.to_json,
139
+ :status => 200,
140
+ :headers => {'Content-Type' => 'application/json'}
141
+ )
142
+
143
+ expect(Metrics).to receive(:instrument).with('trackjs.url.errors', 0, hash_including(:source => "r101-frontend"))
144
+ expect(Metrics).to receive(:instrument).with('trackjs.url.errors', 0, hash_including(:source => "r101-marketing"))
145
+ @collector.collect
146
+ expect(
147
+ a_request(:get, "https://api.trackjs.com/#{env_customer_id}/v1/errors").with(:query => {"page" => page, "size" => page_size, "application" => "r101-frontend"})
148
+ ).to have_been_made
149
+ expect(
150
+ a_request(:get, "https://api.trackjs.com/#{env_customer_id}/v1/errors").with(:query => {"page" => page, "size" => page_size, "application" => "r101-marketing"})
151
+ ).to have_been_made
152
+ end
153
+ end
154
+ end
155
+
156
+ context 'some of the errors have been logged before' do
157
+ let(:old_error_count) { 5 }
158
+ let(:new_error_count) { 3 }
159
+ let(:old_errors) { old_error_count.times.map { trackjs_error } }
160
+ let(:new_errors) { new_error_count.times.map { trackjs_error } }
161
+ let(:all_errors) { new_errors + old_errors }
162
+ let(:old_metadata) { trackjs_metadata total_count: old_error_count, page: page, page_size: page_size, has_more: false }
163
+ let(:new_metadata) { trackjs_metadata total_count: (old_error_count + new_error_count), page: page, page_size: page_size, has_more: false }
164
+ let(:old_response) { {"data" => old_errors, "metadata" => old_metadata} }
165
+ let(:new_response) { {"data" => all_errors, "metadata" => new_metadata} }
166
+
167
+ before do
168
+ stub_request(:get, "https://api.trackjs.com/#{env_customer_id}/v1/errors")
169
+ .with(:query => {"page" => page, "size" => page_size, "application" => "r101-frontend"})
170
+ .to_return(
171
+ :body => empty_response.to_json,
172
+ :status => 200,
173
+ :headers => {'Content-Type' => 'application/json'}
174
+ )
175
+ stub_request(:get, "https://api.trackjs.com/#{env_customer_id}/v1/errors")
176
+ .with(:query => {"page" => page, "size" => page_size, "application" => "r101-marketing"})
177
+ .to_return(
178
+ :body => old_response.to_json,
179
+ :status => 200,
180
+ :headers => {'Content-Type' => 'application/json'}
181
+ )
182
+
183
+ @collector.collect
184
+ end
185
+
186
+ it 'logs only the errors that have occurred since the last time logging happened' do
187
+ stub_request(:get, "https://api.trackjs.com/#{env_customer_id}/v1/errors")
188
+ .with(:query => {"page" => page, "size" => page_size, "application" => "r101-frontend"})
189
+ .to_return(
190
+ :body => empty_response.to_json,
191
+ :status => 200,
192
+ :headers => {'Content-Type' => 'application/json'}
193
+ )
194
+ stub_request(:get, "https://api.trackjs.com/#{env_customer_id}/v1/errors")
195
+ .with(:query => {"page" => page, "size" => page_size, "application" => "r101-marketing"})
196
+ .to_return(
197
+ :body => new_response.to_json,
198
+ :status => 200,
199
+ :headers => {'Content-Type' => 'application/json'}
200
+ )
201
+
202
+ expect(Metrics).to receive(:instrument).with('trackjs.url.errors', 0, hash_including(:source => "r101-frontend"))
203
+ expect(Metrics).to receive(:instrument).with('trackjs.url.errors', new_errors.length, hash_including(:source => "r101-marketing"))
204
+ @collector.collect
205
+ expect(
206
+ a_request(:get, "https://api.trackjs.com/#{env_customer_id}/v1/errors").with(:query => {"page" => page, "size" => page_size, "application" => "r101-frontend"})
207
+ ).to have_been_made.times(2)
208
+ expect(
209
+ a_request(:get, "https://api.trackjs.com/#{env_customer_id}/v1/errors").with(:query => {"page" => page, "size" => page_size, "application" => "r101-marketing"})
210
+ ).to have_been_made.times(2)
211
+ end
212
+ end
213
+ end
214
+
215
+ context 'when multiple pages of errors are returned' do
216
+ let(:old_error_count) { 250 }
217
+ let(:new_error_count) { 50 }
218
+ let(:total_errors) { 800 }
219
+ let(:page2) { 2 }
220
+
221
+ context 'none of the errors have been logged before' do
222
+ let(:recent_timestamps) { old_error_count.times.map { Time.now.utc.strftime("%FT%T%:z") } }
223
+ let(:old_timestamps) { new_error_count.times.map { 3.hours.ago.utc.strftime("%FT%T%:z") } }
224
+ let(:combined_timestamps) { recent_timestamps.slice(0, old_error_count - new_error_count) + old_timestamps }
225
+ let(:response) { trackjs_response errors: old_error_count, timestamps: recent_timestamps, total_errors: total_errors, page: page, page_size: page_size }
226
+ let(:response2) { trackjs_response errors: old_error_count, timestamps: combined_timestamps, total_errors: total_errors, page: page2, page_size: page_size }
227
+
228
+ it 'logs only the errors that occurred in the last @frequency seconds' do
229
+ stub_request(:get, "https://api.trackjs.com/#{env_customer_id}/v1/errors")
230
+ .with(:query => {"page" => page, "size" => page_size, "application" => "r101-frontend"})
231
+ .to_return(
232
+ :body => response.to_json,
233
+ :status => 200,
234
+ :headers => {'Content-Type' => 'application/json'}
235
+ )
236
+ stub_request(:get, "https://api.trackjs.com/#{env_customer_id}/v1/errors")
237
+ .with(:query => {"page" => page, "size" => page_size, "application" => "r101-marketing"})
238
+ .to_return(
239
+ :body => empty_response.to_json,
240
+ :status => 200,
241
+ :headers => {'Content-Type' => 'application/json'}
242
+ )
243
+ stub_request(:get, "https://api.trackjs.com/#{env_customer_id}/v1/errors")
244
+ .with(:query => {"page" => page2, "size" => page_size, "application" => "r101-frontend"})
245
+ .to_return(
246
+ :body => response2.to_json,
247
+ :status => 200,
248
+ :headers => {'Content-Type' => 'application/json'}
249
+ )
250
+ stub_request(:get, "https://api.trackjs.com/#{env_customer_id}/v1/errors")
251
+ .with(:query => {"page" => page2, "size" => page_size, "application" => "r101-marketing"})
252
+ .to_return(
253
+ :body => empty_response.to_json,
254
+ :status => 200,
255
+ :headers => {'Content-Type' => 'application/json'}
256
+ )
257
+
258
+ expect(Metrics).to receive(:instrument).with('trackjs.url.errors', 2 * page_size - old_timestamps.length, hash_including(:source => "r101-frontend"))
259
+ expect(Metrics).to receive(:instrument).with('trackjs.url.errors', 0, hash_including(:source => "r101-marketing"))
260
+ @collector.collect
261
+ expect(
262
+ a_request(:get, "https://api.trackjs.com/#{env_customer_id}/v1/errors").with(:query => {"page" => page, "size" => page_size, "application" => "r101-frontend"})
263
+ ).to have_been_made.times(1)
264
+ expect(
265
+ a_request(:get, "https://api.trackjs.com/#{env_customer_id}/v1/errors").with(:query => {"page" => page, "size" => page_size, "application" => "r101-marketing"})
266
+ ).to have_been_made.times(1)
267
+ end
268
+ end
269
+
270
+ context 'some of the errors have been logged before' do
271
+ let(:page1_errors) { old_error_count.times.map { trackjs_error } }
272
+ let(:old_timestamps) { new_error_count.times.map { 3.hours.ago.utc.strftime("%FT%T%:z") } }
273
+ let(:out_of_date_errors) { new_error_count.times.map { |i| trackjs_error({timestamp: old_timestamps[i]}) } }
274
+ let(:page2_errors) { ((old_error_count - new_error_count).times.map { trackjs_error }) + out_of_date_errors }
275
+ let(:new_errors) { new_error_count.times.map { trackjs_error } }
276
+ let(:combined_errors) { (new_errors + page1_errors).first page_size }
277
+ let(:old_metadata) { trackjs_metadata total_count: old_error_count, page: page, page_size: page_size, has_more: true }
278
+ let(:combined_metadata) { trackjs_metadata total_count: (old_error_count + new_error_count), page: page2, page_size: page_size, has_more: true }
279
+ let(:old_page1_response) { { "data" => page1_errors, "metadata" => old_metadata } }
280
+ let(:old_page2_response) { { "data" => page2_errors, "metadata" => old_metadata } }
281
+ let(:combined_response) { { "data" => combined_errors, "metadata" => combined_metadata } }
282
+
283
+ before do
284
+ stub_request(:get, "https://api.trackjs.com/#{env_customer_id}/v1/errors")
285
+ .with(:query => {"page" => page, "size" => page_size, "application" => "r101-frontend"})
286
+ .to_return(
287
+ :body => old_page1_response.to_json,
288
+ :status => 200,
289
+ :headers => {'Content-Type' => 'application/json'}
290
+ )
291
+ stub_request(:get, "https://api.trackjs.com/#{env_customer_id}/v1/errors")
292
+ .with(:query => {"page" => page, "size" => page_size, "application" => "r101-marketing"})
293
+ .to_return(
294
+ :body => empty_response.to_json,
295
+ :status => 200,
296
+ :headers => {'Content-Type' => 'application/json'}
297
+ )
298
+ stub_request(:get, "https://api.trackjs.com/#{env_customer_id}/v1/errors")
299
+ .with(:query => {"page" => page2, "size" => page_size, "application" => "r101-frontend"})
300
+ .to_return(
301
+ :body => old_page2_response.to_json,
302
+ :status => 200,
303
+ :headers => {'Content-Type' => 'application/json'}
304
+ )
305
+ stub_request(:get, "https://api.trackjs.com/#{env_customer_id}/v1/errors")
306
+ .with(:query => {"page" => page2, "size" => page_size, "application" => "r101-marketing"})
307
+ .to_return(
308
+ :body => empty_response.to_json,
309
+ :status => 200,
310
+ :headers => {'Content-Type' => 'application/json'}
311
+ )
312
+ @collector.collect
313
+ end
314
+
315
+ it 'logs only the errors that have occurred since the last time logging happened' do
316
+ stub_request(:get, "https://api.trackjs.com/#{env_customer_id}/v1/errors")
317
+ .with(:query => {"page" => page, "size" => page_size, "application" => "r101-frontend"})
318
+ .to_return(
319
+ :body => combined_response.to_json,
320
+ :status => 200,
321
+ :headers => {'Content-Type' => 'application/json'}
322
+ )
323
+ stub_request(:get, "https://api.trackjs.com/#{env_customer_id}/v1/errors")
324
+ .with(:query => {"page" => page, "size" => page_size, "application" => "r101-marketing"})
325
+ .to_return(
326
+ :body => empty_response.to_json,
327
+ :status => 200,
328
+ :headers => {'Content-Type' => 'application/json'}
329
+ )
330
+ expect(Metrics).to receive(:instrument).with('trackjs.url.errors', new_errors.length, hash_including(:source => "r101-frontend"))
331
+ expect(Metrics).to receive(:instrument).with('trackjs.url.errors', 0, hash_including(:source => "r101-marketing"))
332
+ @collector.collect
333
+ expect(
334
+ a_request(:get, "https://api.trackjs.com/#{env_customer_id}/v1/errors").with(:query => {"page" => page, "size" => page_size, "application" => "r101-frontend"})
335
+ ).to have_been_made.times(2)
336
+ expect(
337
+ a_request(:get, "https://api.trackjs.com/#{env_customer_id}/v1/errors").with(:query => {"page" => page, "size" => page_size, "application" => "r101-marketing"})
338
+ ).to have_been_made.times(2)
339
+ end
340
+ end
341
+ end
342
+ end
@@ -0,0 +1,25 @@
1
+ require 'webmock/rspec'
2
+
3
+ require 'dotenv'
4
+ Dotenv.load('.env.test')
5
+
6
+
7
+ # Requires supporting ruby files with custom matchers and macros, etc,
8
+ # in spec/support/ and its subdirectories.
9
+ Dir[File.join(File.dirname(__FILE__), 'support/**/*.rb')].each {|f| require f}
10
+
11
+ RSpec.configure do |config|
12
+ config.mock_with :rspec
13
+
14
+ config.raise_errors_for_deprecations!
15
+
16
+ # Allow RSpec to run focused specs
17
+ config.filter_run_including focus: true
18
+ config.filter_run_excluding broken: true
19
+ config.filter_run_excluding :bollocksed
20
+ config.run_all_when_everything_filtered = true
21
+ config.fail_fast = false
22
+ config.before focus: true do
23
+ fail "Hey dummy, don't commit focused specs." if ENV['CI']
24
+ end
25
+ end
@@ -0,0 +1,65 @@
1
+ require 'securerandom'
2
+ require 'faker'
3
+
4
+ module TrackJSHelpers
5
+ def trackjs_error(
6
+ message: nil,
7
+ timestamp: Time.now.utc.strftime("%FT%T%:z"),
8
+ url: "https://www.remind.com",
9
+ application: "r101-frontend",
10
+ id: SecureRandom.uuid
11
+ )
12
+ trackjs_url = "https://my.trackjs.com/details/#{id}"
13
+ message = message || Faker::Lorem.sentence
14
+
15
+ return {
16
+ "message" => message,
17
+ "timestamp" => timestamp,
18
+ "url" => url,
19
+ "id" => id,
20
+ "browserName" => "Chrome",
21
+ "browserVersion" => "49.0.2623",
22
+ "entry" => "window",
23
+ "application" => application,
24
+ "line" => 11,
25
+ "column" => 13161,
26
+ "file" => "https://www.remind.com/classes/sci02",
27
+ "userId" => "11111111",
28
+ "sessionId" => "",
29
+ "trackJsUrl" => trackjs_url,
30
+ "isStarred" => false
31
+ }
32
+ end
33
+
34
+ def trackjs_metadata(total_count: 0, page: 1, page_size: 250, has_more: true)
35
+ return {
36
+ "totalCount" => total_count,
37
+ "page" => page,
38
+ "size" => page_size,
39
+ "hasMore" => has_more,
40
+ "trackJsUrl" => "https://my.trackjs.com/recent?"
41
+ }
42
+ end
43
+
44
+ def trackjs_response(errors: 0, timestamps: nil, total_errors: 0, page: 1, page_size: 250)
45
+ timestamps = timestamps || errors.times.map { Time.now.utc.strftime("%FT%T%:z") }
46
+ data = errors.times.map do |i|
47
+ trackjs_error(timestamp: timestamps[i])
48
+ end
49
+ has_more = (page * page_size) < total_errors
50
+
51
+ return {
52
+ "data" => data,
53
+ "metadata" => trackjs_metadata(
54
+ total_count: total_errors,
55
+ page: page,
56
+ page_size: page_size,
57
+ has_more: has_more
58
+ )
59
+ }
60
+ end
61
+ end
62
+
63
+ RSpec.configure do |config|
64
+ config.include TrackJSHelpers
65
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: collective-metrics
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.3
4
+ version: 0.3.0
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: 2016-03-28 00:00:00.000000000 Z
11
+ date: 2016-05-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rufus-scheduler
@@ -159,7 +159,11 @@ files:
159
159
  - lib/collective/collectors/rabbitmq.rb
160
160
  - lib/collective/collectors/redis.rb
161
161
  - lib/collective/collectors/sidekiq.rb
162
+ - lib/collective/collectors/trackjs.rb
162
163
  - lib/collective/version.rb
164
+ - spec/lib/collective/collectors/trackjs_spec.rb
165
+ - spec/spec_helper.rb
166
+ - spec/support/trackjs_helpers.rb
163
167
  homepage: https://github.com/remind101/collective-metrics
164
168
  licenses:
165
169
  - MIT
@@ -180,8 +184,11 @@ required_rubygems_version: !ruby/object:Gem::Requirement
180
184
  version: '0'
181
185
  requirements: []
182
186
  rubyforge_project:
183
- rubygems_version: 2.4.5
187
+ rubygems_version: 2.4.8
184
188
  signing_key:
185
189
  specification_version: 4
186
190
  summary: Collect and output metrics
187
- test_files: []
191
+ test_files:
192
+ - spec/lib/collective/collectors/trackjs_spec.rb
193
+ - spec/spec_helper.rb
194
+ - spec/support/trackjs_helpers.rb