collective-metrics 0.2.3 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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