coverband-service-client 0.0.8 → 0.0.12.rc.1

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
  SHA256:
3
- metadata.gz: 9d70bb9e3268a13b06640e0437e517cf00ccc4030f2b7f2c20e7b314d26828e2
4
- data.tar.gz: 3400abcd93c90f5f8bb011757933dd08b0619ef907d3f2675a1326bb5eb7a102
3
+ metadata.gz: 9b93d9abe50ba1657318562b8fa04b645cfdd2fc22bca0f711cbde57b6d6b3c7
4
+ data.tar.gz: 1918f4689b50c6bda5b51d2f578b13b4bf439d38fb3510318165152b9093f1d2
5
5
  SHA512:
6
- metadata.gz: fd6972fc75a2e8320a6ce2f991e871df0fed4c6a1298e0d2a443c479d309aca58d56f6c9c0aa346731fec7e1a9e12836e2cdb18480bd687667804f7b3d2a802d
7
- data.tar.gz: e4bd36b15a82c5ab95fcc770909d04b3426d818a1468b90cf1f45667facd1f4fda9d37809c667c85b822b7b8651f3f8576d8323914c331bf207a6458bad81e99
6
+ metadata.gz: 33c461c2915ef4f9582fd8f87b5b2afa230076f1349e88ef7f66987cb1a8dda25d97c26983421ca52f900c3dd2d48d313e44dd69a8b15984a349dbe3fe4b3fd9
7
+ data.tar.gz: 0ea1b378ae8044400d50ad33944881d27552b42296cae06ceda360617b30d26a9bb3614e6a81c10b0bd530bcf59ca10ef9be3fba928e4c98b2f22929c21f4a66
@@ -1,17 +1,17 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- coverband-service-client (0.0.8)
4
+ coverband-service-client (0.0.12.rc.1)
5
5
  coverband (~> 4.2.4)
6
6
 
7
7
  GEM
8
8
  remote: https://rubygems.org/
9
9
  specs:
10
- coverband (4.2.4)
10
+ coverband (4.2.5)
11
11
  redis
12
12
  minitest (5.14.0)
13
13
  rake (13.0.1)
14
- redis (4.1.3)
14
+ redis (4.1.4)
15
15
 
16
16
  PLATFORMS
17
17
  ruby
@@ -1,24 +1,32 @@
1
1
  # frozen_string_literal: true
2
+ require 'socket'
2
3
 
4
+ COVERBAND_ORIGINAL_START = ENV['COVERBAND_DISABLE_AUTO_START']
5
+ ENV['COVERBAND_DISABLE_AUTO_START'] = 'true'
3
6
  require 'coverband'
4
7
  require 'coverband/service/client/version'
5
8
  require 'securerandom'
6
9
 
7
- COVERBAND_ENV = ENV['RACK_ENV'] || ENV['RAILS_ENV'] || (defined?(Rails) ? Rails.env : 'unknown')
8
- COVERBAND_SERVICE_URL = ENV['COVERBAND_URL'] || 'https://coverband.io'
9
- COVERBAND_TIMEOUT = (COVERBAND_ENV == 'development') ? 5 : 1
10
- COVERBAND_ENABLE_DEV_MODE = ENV['COVERBAND_ENABLE_DEV_MODE'] || false
11
- COVERBAND_ENABLE_TEST_MODE = ENV['COVERBAND_ENABLE_TEST_MODE'] || false
12
- COVERBAND_PROCESS_TYPE = ENV['PROCESS_TYPE'] || 'unknown'
13
- COVERBAND_REPORT_PERIOD = (ENV['COVERBAND_REPORT_PERIOD'] || 600).to_i
14
-
15
10
  module Coverband
11
+ COVERBAND_ENV = ENV['RACK_ENV'] || ENV['RAILS_ENV'] || (defined?(Rails) ? Rails.env : 'unknown')
12
+ COVERBAND_SERVICE_URL = ENV['COVERBAND_URL'] || 'https://coverband.io'
13
+ COVERBAND_TIMEOUT = (COVERBAND_ENV == 'development') ? 5 : 2
14
+ COVERBAND_ENABLE_DEV_MODE = ENV['COVERBAND_ENABLE_DEV_MODE'] || false
15
+ COVERBAND_ENABLE_TEST_MODE = ENV['COVERBAND_ENABLE_TEST_MODE'] || false
16
+ COVERBAND_PROCESS_TYPE = ENV['PROCESS_TYPE'] || 'unknown'
17
+ COVERBAND_REPORT_PERIOD = (ENV['COVERBAND_REPORT_PERIOD'] || 600).to_i
18
+
19
+ def self.service_disabled_dev_test_env?
20
+ (COVERBAND_ENV == 'test' && !COVERBAND_ENABLE_TEST_MODE) ||
21
+ (COVERBAND_ENV == 'development' && !COVERBAND_ENABLE_DEV_MODE)
22
+ end
16
23
 
17
- if ((COVERBAND_ENV == 'test' && !COVERBAND_ENABLE_TEST_MODE) ||
18
- COVERBAND_ENV == 'development' && !COVERBAND_ENABLE_DEV_MODE
19
- )
24
+ if service_disabled_dev_test_env?
20
25
  def self.report_coverage
21
- # for now disable coverband reporting in test env by default
26
+ # for now disable coverband reporting in test & dev env by default
27
+ if Coverband.configuration.verbose
28
+ puts "Coverband: disabled for #{COVERBAND_ENV}, set COVERBAND_ENABLE_DEV_MODE or COVERBAND_ENABLE_TEST_MODE to enable" if Coverband.configuration.verbose || COVERBAND_ENABLE_DEV_MODE
29
+ end
22
30
  end
23
31
  end
24
32
 
@@ -28,16 +36,40 @@ module Coverband
28
36
  #
29
37
  # NOTES:
30
38
  # * uses net/http to avoid any dependencies
31
- # * currently JSON, but likely better to move to something simpler / faster
39
+ # * currently JSON, but likely better to move to something faster
32
40
  ###
33
41
  class Service < Base
34
- attr_reader :coverband_url, :process_type, :runtime_env
42
+ attr_reader :coverband_url, :process_type, :runtime_env, :hostname, :pid, :stats
35
43
 
36
44
  def initialize(coverband_url, opts = {})
37
45
  super()
38
46
  @coverband_url = coverband_url
39
- @process_type = opts.fetch(:process_type) { COVERBAND_PROCESS_TYPE }
47
+ @process_type = opts.fetch(:process_type) { $PROGRAM_NAME&.split('/')&.last || COVERBAND_PROCESS_TYPE }
48
+ @hostname = opts.fetch(:hostname) { ENV["DYNO"] || Socket.gethostname.force_encoding('utf-8').encode }
40
49
  @runtime_env = opts.fetch(:runtime_env) { COVERBAND_ENV }
50
+ initialize_stats
51
+ end
52
+
53
+ def initialize_stats
54
+ return unless ENV['COVERBAND_STATS_KEY']
55
+ return unless defined?(Dogapi::Client)
56
+
57
+ @stats = Dogapi::Client.new(ENV['COVERBAND_STATS_KEY'])
58
+ end
59
+
60
+ def report_timing(timing)
61
+ return unless @stats
62
+
63
+ @stats.emit_point(
64
+ 'coverband.save.time',
65
+ timing,
66
+ host: hostname,
67
+ env: runtime_env,
68
+ client: "coverband_#{self.class.name.split("::").last}")
69
+ end
70
+
71
+ def logger
72
+ Coverband.configuration.logger
41
73
  end
42
74
 
43
75
  def clear!
@@ -53,28 +85,35 @@ module Coverband
53
85
  0
54
86
  end
55
87
 
56
- # TODO: no longer get by type just get both reports in a single request
88
+ def api_key
89
+ ENV['COVERBAND_API_KEY'] || Coverband.configuration.api_key
90
+ end
91
+
92
+ ###
93
+ # Fetch coverband coverage via the API
94
+ ###
57
95
  def coverage(local_type = nil, opts = {})
58
96
  local_type ||= opts.key?(:override_type) ? opts[:override_type] : type
59
- uri = URI("#{coverband_url}/api/coverage/#{ENV['COVERBAND_ID']}?type=#{local_type}")
60
- req = Net::HTTP::Get.new(uri, 'Content-Type' => 'application/json', 'Coverband-Token' => ENV['COVERBAND_API_KEY'])
97
+ env_filter = opts.key?(:env_filter) ? opts[:env_filter] : 'production'
98
+ uri = URI("#{coverband_url}/api/coverage?type=#{local_type}&env_filter=#{env_filter}",)
99
+ req = Net::HTTP::Get.new(uri, 'Content-Type' => 'application/json', 'Coverband-Token' => api_key)
61
100
  res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == 'https') do |http|
62
101
  http.request(req)
63
102
  end
64
103
  coverage_data = JSON.parse(res.body)
65
- # puts "coverage data: "
66
- # puts coverage_data
67
104
  coverage_data
68
105
  rescue StandardError => e
69
- puts "Coverband: Error while retrieving coverage #{e}"
106
+ logger&.error "Coverband: Error while retrieving coverage #{e}" if Coverband.configuration.verbose || COVERBAND_ENABLE_DEV_MODE
70
107
  end
71
108
 
72
109
  def save_report(report)
73
- #puts caller.join(',')
74
110
  return if report.empty?
75
111
 
112
+ # We set here vs initialize to avoid setting on the primary process vs child processes
113
+ @pid ||= ::Process.pid
114
+
76
115
  # TODO: do we need dup
77
- # TODO: remove timestamps, server will track first_seen
116
+ # TODO: remove upstream timestamps, server will track first_seen
78
117
  Thread.new do
79
118
  data = expand_report(report.dup)
80
119
  full_package = {
@@ -83,12 +122,18 @@ module Coverband
83
122
  tags: {
84
123
  process_type: process_type,
85
124
  app_loading: type == Coverband::EAGER_TYPE,
86
- runtime_env: runtime_env
125
+ runtime_env: runtime_env,
126
+ pid: pid,
127
+ hostname: hostname,
87
128
  },
88
129
  file_coverage: data
89
130
  }
90
131
  }
132
+
133
+ starting = Process.clock_gettime(Process::CLOCK_MONOTONIC)
91
134
  save_coverage(full_package)
135
+ ending = Process.clock_gettime(Process::CLOCK_MONOTONIC)
136
+ report_timing((ending - starting))
92
137
  end&.join
93
138
  end
94
139
 
@@ -99,12 +144,18 @@ module Coverband
99
144
  private
100
145
 
101
146
  def save_coverage(data)
147
+ if api_key.nil?
148
+ puts "Coverband: Error: no Coverband API key was found!"
149
+ return
150
+ end
151
+
102
152
  uri = URI("#{coverband_url}/api/collector")
103
153
  req = Net::HTTP::Post.new(uri,
104
154
  'Content-Type' => 'application/json',
105
- 'Coverband-Token' => ENV['COVERBAND_API_KEY'])
106
- # puts "sending #{data}"
155
+ 'Coverband-Token' => api_key)
107
156
  req.body = { remote_uuid: SecureRandom.uuid, data: data }.to_json
157
+
158
+ logger&.info "Coverband: saving (#{uri}) #{req.body}" if Coverband.configuration.verbose
108
159
  res = Net::HTTP.start(
109
160
  uri.hostname,
110
161
  uri.port,
@@ -116,7 +167,51 @@ module Coverband
116
167
  http.request(req)
117
168
  end
118
169
  rescue StandardError => e
119
- puts "Coverband: Error while saving coverage #{e}"
170
+ logger&.info "Coverband: Error while saving coverage #{e}" if Coverband.configuration.verbose || COVERBAND_ENABLE_DEV_MODE
171
+ end
172
+ end
173
+
174
+ class PersistentService < Service
175
+ attr_reader :http, :stats
176
+
177
+ def initialize(coverband_url, opts = {})
178
+ super
179
+ initiate_http
180
+ end
181
+
182
+ private
183
+
184
+ def initiate_http
185
+ @http = Net::HTTP::Persistent.new name: 'coverband_persistent'
186
+ @http.headers['Content-Type'] = 'application/json'
187
+ @http.headers['Coverband-Token'] = api_key
188
+ @http.open_timeout = COVERBAND_TIMEOUT
189
+ @http.read_timeout = COVERBAND_TIMEOUT
190
+ @http.ssl_timeout = COVERBAND_TIMEOUT
191
+ end
192
+
193
+ def save_coverage(data)
194
+ persistent_attempts = 0
195
+ begin
196
+ if api_key.nil?
197
+ puts "Coverband: Error: no Coverband API key was found!"
198
+ return
199
+ end
200
+
201
+ post_uri = URI("#{coverband_url}/api/collector")
202
+ post = Net::HTTP::Post.new post_uri.path
203
+ body = { remote_uuid: SecureRandom.uuid, data: data }.to_json
204
+ post.body = body
205
+ logger&.info "Coverband: saving (#{post_uri}) #{body}" if Coverband.configuration.verbose
206
+ res = http.request post_uri, post
207
+ rescue Net::HTTP::Persistent::Error => e
208
+ persistent_attempts += 1
209
+ http.shutdown
210
+ initiate_http
211
+ retry if persistent_attempts < 2
212
+ end
213
+ rescue StandardError => e
214
+ logger&.info "Coverband: Error while saving coverage #{e}" if Coverband.configuration.verbose || COVERBAND_ENABLE_DEV_MODE
120
215
  end
121
216
  end
122
217
  end
@@ -150,14 +245,22 @@ module Coverband
150
245
  rescue StandardError => e
151
246
  # we don't want to raise errors if Coverband can't reach redis.
152
247
  # This is a nice to have not a bring the system down
153
- logger&.error "Coverband: view_tracker failed to store, error #{e.class.name}"
248
+ logger&.error "Coverband: view_tracker failed to store, error #{e.class.name}" if Coverband.configuration.verbose || COVERBAND_ENABLE_DEV_MODE
154
249
  end
155
250
 
156
251
  private
157
252
 
253
+ def api_key
254
+ ENV['COVERBAND_API_KEY'] || Coverband.configuration.api_key
255
+ end
256
+
257
+ def logger
258
+ Coverband.configuration.logger
259
+ end
260
+
158
261
  def save_tracked_views(views:, reported_time:)
159
262
  uri = URI("#{COVERBAND_SERVICE_URL}/api/collector")
160
- req = Net::HTTP::Post.new(uri, 'Content-Type' => 'application/json', 'Coverband-Token' => ENV['COVERBAND_API_KEY'])
263
+ req = Net::HTTP::Post.new(uri, 'Content-Type' => 'application/json', 'Coverband-Token' => api_key)
161
264
  data = {
162
265
  collection_type: 'view_tracker_delta',
163
266
  collection_data: {
@@ -174,25 +277,53 @@ module Coverband
174
277
  http.request(req)
175
278
  end
176
279
  rescue StandardError => e
177
- puts "Coverband: Error while saving coverage #{e}"
280
+ logger&.error "Coverband: Error while saving coverage #{e}" if Coverband.configuration.verbose || COVERBAND_ENABLE_DEV_MODE
178
281
  end
179
282
  end
180
283
  end
181
284
  end
182
285
 
286
+ module Coverband
287
+ class Configuration
288
+ attr_accessor :api_key
289
+ end
290
+ end
291
+
292
+ ENV['COVERBAND_DISABLE_AUTO_START'] = COVERBAND_ORIGINAL_START
183
293
  Coverband.configure do |config|
184
- # Use The Test Service Adapter
185
- config.store = Coverband::Adapters::Service.new(COVERBAND_SERVICE_URL)
294
+ # Use the Service Adapter
295
+ if defined?(Net::HTTP::Persistent)
296
+ config.store = Coverband::Adapters::PersistentService.new(Coverband::COVERBAND_SERVICE_URL)
297
+ else
298
+ config.store = Coverband::Adapters::Service.new(Coverband::COVERBAND_SERVICE_URL)
299
+ end
186
300
 
187
301
  # default to tracking views true
188
- config.track_views = ENV['COVERBAND_DISABLE_VIEW_TRACKER'] ? false : true
302
+ config.track_views = if ENV['COVERBAND_DISABLE_VIEW_TRACKER']
303
+ false
304
+ elsif Coverband.service_disabled_dev_test_env?
305
+ false
306
+ else
307
+ true
308
+ end
189
309
 
190
310
  # report every 10m by default
191
- config.background_reporting_sleep_seconds = COVERBAND_ENV == 'production' ? COVERBAND_REPORT_PERIOD : 60
311
+ config.background_reporting_sleep_seconds = Coverband::COVERBAND_ENV == 'production' ? Coverband::COVERBAND_REPORT_PERIOD : 60
192
312
  # add a wiggle to avoid service stampede
193
- config.reporting_wiggle = COVERBAND_ENV == 'production' ? 90 : 6
313
+ config.reporting_wiggle = Coverband::COVERBAND_ENV == 'production' ? 90 : 6
194
314
 
195
- if COVERBAND_ENV == 'test'
315
+ if Coverband::COVERBAND_ENV == 'test'
196
316
  config.background_reporting_enabled = false
197
317
  end
198
318
  end
319
+
320
+ # NOTE: it is really hard to bypass / overload our config we should fix this in Coverband
321
+ # this hopefully detects anyone that has both gems and was trying to configure Coverband themselves.
322
+ if File.exist?('./config/coverband.rb')
323
+ puts "Warning: config/coverband.rb found, this overrides coverband service allowing one to setup open source Coverband" if Coverband.configuration.verbose || COVERBAND_ENABLE_DEV_MODE
324
+ end
325
+
326
+ Coverband.configure('./config/coverband_service.rb') if File.exist?('./config/coverband_service.rb')
327
+ Coverband.start
328
+ require "coverband/utils/railtie" if defined? ::Rails::Railtie
329
+ require "coverband/integrations/resque" if defined? ::Resque
@@ -1,7 +1,7 @@
1
1
  module Coverband
2
2
  module Service
3
3
  module Client
4
- VERSION = '0.0.8'
4
+ VERSION = '0.0.12.rc.1'
5
5
  end
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: coverband-service-client
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.8
4
+ version: 0.0.12.rc.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dan Mayer
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: exe
11
11
  cert_chain: []
12
- date: 2020-05-02 00:00:00.000000000 Z
12
+ date: 2020-06-20 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler
@@ -106,9 +106,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
106
106
  version: '0'
107
107
  required_rubygems_version: !ruby/object:Gem::Requirement
108
108
  requirements:
109
- - - ">="
109
+ - - ">"
110
110
  - !ruby/object:Gem::Version
111
- version: '0'
111
+ version: 1.3.1
112
112
  requirements: []
113
113
  rubygems_version: 3.0.3
114
114
  signing_key: