coverband-service-client 0.0.9 → 0.0.12.rc.2

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: 613941985d4fb60122f3e35a84c5139a7aa1395008a443b3a3478eef59df2b30
4
- data.tar.gz: 03eabff6d96401aede1ed1263fdc26a400e93fc4e26ad164977e6b77a4b9a4a7
3
+ metadata.gz: ecee5d46bea965ae3675532f956d99ad2617f1892dcf59cd302f080faf03acc1
4
+ data.tar.gz: 9bde9ec5901ed84880692ded71d617d94e887cfb818e86bb4c3f7607f4f64f9e
5
5
  SHA512:
6
- metadata.gz: 2d800e7c8abc0056866a6f9f96b1c89b9c1fc2ebcd7f5bdc17477199445f5740cc968d795cca1ad9a2ca9951480f32b8960f8e4729e975c2f19eea69aa57c8e7
7
- data.tar.gz: 32d5360aa6a50d722d53481f22736e8c47c05844b9372fdd3d1e993ea2209fbdd3043e66dd2c016aad04df7195cffeb124d9fa8ca4bd66ce361f75462a368ffa
6
+ metadata.gz: 77e703011dcb88cdcb8e7fb107aca73c13419b4e1ed9bf72a47d67c7cb6847e80c2b477d7866ce030264578ee426e889b7789b46d5bc7b8e42b841b68ada7787
7
+ data.tar.gz: a7277f954c3b6c1b418ab2230a41652e71788ddc68a6c8183325931f023b8b9bc52fcb56be51e4a1eb31a67ae3bc23509a197dfafa41a5b02f2e32b58f59a376
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- coverband-service-client (0.0.9)
4
+ coverband-service-client (0.0.12.rc.2)
5
5
  coverband (~> 4.2.4)
6
6
 
7
7
  GEM
@@ -1,5 +1,8 @@
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'
@@ -7,7 +10,7 @@ require 'securerandom'
7
10
  module Coverband
8
11
  COVERBAND_ENV = ENV['RACK_ENV'] || ENV['RAILS_ENV'] || (defined?(Rails) ? Rails.env : 'unknown')
9
12
  COVERBAND_SERVICE_URL = ENV['COVERBAND_URL'] || 'https://coverband.io'
10
- COVERBAND_TIMEOUT = (COVERBAND_ENV == 'development') ? 5 : 1
13
+ COVERBAND_TIMEOUT = (COVERBAND_ENV == 'development') ? 5 : 2
11
14
  COVERBAND_ENABLE_DEV_MODE = ENV['COVERBAND_ENABLE_DEV_MODE'] || false
12
15
  COVERBAND_ENABLE_TEST_MODE = ENV['COVERBAND_ENABLE_TEST_MODE'] || false
13
16
  COVERBAND_PROCESS_TYPE = ENV['PROCESS_TYPE'] || 'unknown'
@@ -22,7 +25,7 @@ module Coverband
22
25
  def self.report_coverage
23
26
  # for now disable coverband reporting in test & dev env by default
24
27
  if Coverband.configuration.verbose
25
- puts "Coverband: disabled for #{COVERBAND_ENV}, set COVERBAND_ENABLE_DEV_MODE or COVERBAND_ENABLE_TEST_MODE to enable"
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
26
29
  end
27
30
  end
28
31
  end
@@ -33,16 +36,37 @@ module Coverband
33
36
  #
34
37
  # NOTES:
35
38
  # * uses net/http to avoid any dependencies
36
- # * currently JSON, but likely better to move to something simpler / faster
39
+ # * currently JSON, but likely better to move to something faster
37
40
  ###
38
41
  class Service < Base
39
- attr_reader :coverband_url, :process_type, :runtime_env
42
+ attr_reader :coverband_url, :process_type, :runtime_env, :hostname, :pid, :stats
40
43
 
41
44
  def initialize(coverband_url, opts = {})
42
45
  super()
43
46
  @coverband_url = coverband_url
44
- @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 }
49
+ @hostname = @hostname.gsub("'",'').gsub("’",'')
45
50
  @runtime_env = opts.fetch(:runtime_env) { COVERBAND_ENV }
51
+ initialize_stats
52
+ end
53
+
54
+ def initialize_stats
55
+ return unless ENV['COVERBAND_STATS_KEY']
56
+ return unless defined?(Dogapi::Client)
57
+
58
+ @stats = Dogapi::Client.new(ENV['COVERBAND_STATS_KEY'])
59
+ end
60
+
61
+ def report_timing(timing)
62
+ return unless @stats
63
+
64
+ @stats.emit_point(
65
+ 'coverband.save.time',
66
+ timing,
67
+ host: hostname,
68
+ device: "coverband_#{self.class.name.split("::").last}",
69
+ options: {tags: [runtime_env]})
46
70
  end
47
71
 
48
72
  def logger
@@ -66,27 +90,31 @@ module Coverband
66
90
  ENV['COVERBAND_API_KEY'] || Coverband.configuration.api_key
67
91
  end
68
92
 
69
- # TODO: no longer get by type just get both reports in a single request
93
+ ###
94
+ # Fetch coverband coverage via the API
95
+ ###
70
96
  def coverage(local_type = nil, opts = {})
71
97
  local_type ||= opts.key?(:override_type) ? opts[:override_type] : type
72
- uri = URI("#{coverband_url}/api/coverage/#{ENV['COVERBAND_ID']}?type=#{local_type}")
98
+ env_filter = opts.key?(:env_filter) ? opts[:env_filter] : 'production'
99
+ uri = URI("#{coverband_url}/api/coverage?type=#{local_type}&env_filter=#{env_filter}",)
73
100
  req = Net::HTTP::Get.new(uri, 'Content-Type' => 'application/json', 'Coverband-Token' => api_key)
74
101
  res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == 'https') do |http|
75
102
  http.request(req)
76
103
  end
77
104
  coverage_data = JSON.parse(res.body)
78
- # puts "coverage data: "
79
- # puts coverage_data
80
105
  coverage_data
81
106
  rescue StandardError => e
82
- puts "Coverband: Error while retrieving coverage #{e}"
107
+ logger&.error "Coverband: Error while retrieving coverage #{e}" if Coverband.configuration.verbose || COVERBAND_ENABLE_DEV_MODE
83
108
  end
84
109
 
85
110
  def save_report(report)
86
111
  return if report.empty?
87
112
 
113
+ # We set here vs initialize to avoid setting on the primary process vs child processes
114
+ @pid ||= ::Process.pid
115
+
88
116
  # TODO: do we need dup
89
- # TODO: remove timestamps, server will track first_seen
117
+ # TODO: remove upstream timestamps, server will track first_seen
90
118
  Thread.new do
91
119
  data = expand_report(report.dup)
92
120
  full_package = {
@@ -95,12 +123,18 @@ module Coverband
95
123
  tags: {
96
124
  process_type: process_type,
97
125
  app_loading: type == Coverband::EAGER_TYPE,
98
- runtime_env: runtime_env
126
+ runtime_env: runtime_env,
127
+ pid: pid,
128
+ hostname: hostname,
99
129
  },
100
130
  file_coverage: data
101
131
  }
102
132
  }
133
+
134
+ starting = Process.clock_gettime(Process::CLOCK_MONOTONIC)
103
135
  save_coverage(full_package)
136
+ ending = Process.clock_gettime(Process::CLOCK_MONOTONIC)
137
+ report_timing((ending - starting))
104
138
  end&.join
105
139
  end
106
140
 
@@ -113,16 +147,16 @@ module Coverband
113
147
  def save_coverage(data)
114
148
  if api_key.nil?
115
149
  puts "Coverband: Error: no Coverband API key was found!"
150
+ return
116
151
  end
117
152
 
118
153
  uri = URI("#{coverband_url}/api/collector")
119
- logger&.info "Coverband: saving #{uri}" if Coverband.configuration.verbose
120
154
  req = Net::HTTP::Post.new(uri,
121
155
  'Content-Type' => 'application/json',
122
156
  'Coverband-Token' => api_key)
123
157
  req.body = { remote_uuid: SecureRandom.uuid, data: data }.to_json
124
158
 
125
- logger&.info "Coverband: saving #{req.body}" if Coverband.configuration.verbose
159
+ logger&.info "Coverband: saving (#{uri}) #{req.body}" if Coverband.configuration.verbose
126
160
  res = Net::HTTP.start(
127
161
  uri.hostname,
128
162
  uri.port,
@@ -134,7 +168,51 @@ module Coverband
134
168
  http.request(req)
135
169
  end
136
170
  rescue StandardError => e
137
- puts "Coverband: Error while saving coverage #{e}"
171
+ logger&.info "Coverband: Error while saving coverage #{e}" if Coverband.configuration.verbose || COVERBAND_ENABLE_DEV_MODE
172
+ end
173
+ end
174
+
175
+ class PersistentService < Service
176
+ attr_reader :http, :stats
177
+
178
+ def initialize(coverband_url, opts = {})
179
+ super
180
+ initiate_http
181
+ end
182
+
183
+ private
184
+
185
+ def initiate_http
186
+ @http = Net::HTTP::Persistent.new name: 'coverband_persistent'
187
+ @http.headers['Content-Type'] = 'application/json'
188
+ @http.headers['Coverband-Token'] = api_key
189
+ @http.open_timeout = COVERBAND_TIMEOUT
190
+ @http.read_timeout = COVERBAND_TIMEOUT
191
+ @http.ssl_timeout = COVERBAND_TIMEOUT
192
+ end
193
+
194
+ def save_coverage(data)
195
+ persistent_attempts = 0
196
+ begin
197
+ if api_key.nil?
198
+ puts "Coverband: Error: no Coverband API key was found!"
199
+ return
200
+ end
201
+
202
+ post_uri = URI("#{coverband_url}/api/collector")
203
+ post = Net::HTTP::Post.new post_uri.path
204
+ body = { remote_uuid: SecureRandom.uuid, data: data }.to_json
205
+ post.body = body
206
+ logger&.info "Coverband: saving (#{post_uri}) #{body}" if Coverband.configuration.verbose
207
+ res = http.request post_uri, post
208
+ rescue Net::HTTP::Persistent::Error => e
209
+ persistent_attempts += 1
210
+ http.shutdown
211
+ initiate_http
212
+ retry if persistent_attempts < 2
213
+ end
214
+ rescue StandardError => e
215
+ logger&.info "Coverband: Error while saving coverage #{e}" if Coverband.configuration.verbose || COVERBAND_ENABLE_DEV_MODE
138
216
  end
139
217
  end
140
218
  end
@@ -168,18 +246,22 @@ module Coverband
168
246
  rescue StandardError => e
169
247
  # we don't want to raise errors if Coverband can't reach redis.
170
248
  # This is a nice to have not a bring the system down
171
- logger&.error "Coverband: view_tracker failed to store, error #{e.class.name}"
249
+ logger&.error "Coverband: view_tracker failed to store, error #{e.class.name}" if Coverband.configuration.verbose || COVERBAND_ENABLE_DEV_MODE
172
250
  end
173
251
 
174
252
  private
175
253
 
254
+ def api_key
255
+ ENV['COVERBAND_API_KEY'] || Coverband.configuration.api_key
256
+ end
257
+
176
258
  def logger
177
259
  Coverband.configuration.logger
178
260
  end
179
261
 
180
262
  def save_tracked_views(views:, reported_time:)
181
263
  uri = URI("#{COVERBAND_SERVICE_URL}/api/collector")
182
- req = Net::HTTP::Post.new(uri, 'Content-Type' => 'application/json', 'Coverband-Token' => ENV['COVERBAND_API_KEY'])
264
+ req = Net::HTTP::Post.new(uri, 'Content-Type' => 'application/json', 'Coverband-Token' => api_key)
183
265
  data = {
184
266
  collection_type: 'view_tracker_delta',
185
267
  collection_data: {
@@ -196,7 +278,7 @@ module Coverband
196
278
  http.request(req)
197
279
  end
198
280
  rescue StandardError => e
199
- puts "Coverband: Error while saving coverage #{e}"
281
+ logger&.error "Coverband: Error while saving coverage #{e}" if Coverband.configuration.verbose || COVERBAND_ENABLE_DEV_MODE
200
282
  end
201
283
  end
202
284
  end
@@ -208,9 +290,14 @@ module Coverband
208
290
  end
209
291
  end
210
292
 
293
+ ENV['COVERBAND_DISABLE_AUTO_START'] = COVERBAND_ORIGINAL_START
211
294
  Coverband.configure do |config|
212
- # Use The Test Service Adapter
213
- config.store = Coverband::Adapters::Service.new(Coverband::COVERBAND_SERVICE_URL)
295
+ # Use the Service Adapter
296
+ if defined?(Net::HTTP::Persistent)
297
+ config.store = Coverband::Adapters::PersistentService.new(Coverband::COVERBAND_SERVICE_URL)
298
+ else
299
+ config.store = Coverband::Adapters::Service.new(Coverband::COVERBAND_SERVICE_URL)
300
+ end
214
301
 
215
302
  # default to tracking views true
216
303
  config.track_views = if ENV['COVERBAND_DISABLE_VIEW_TRACKER']
@@ -234,7 +321,10 @@ end
234
321
  # NOTE: it is really hard to bypass / overload our config we should fix this in Coverband
235
322
  # this hopefully detects anyone that has both gems and was trying to configure Coverband themselves.
236
323
  if File.exist?('./config/coverband.rb')
237
- puts "Warning: config/coverband.rb found, this overrides coverband service allowing one to setup open source Coverband"
324
+ 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
238
325
  end
239
326
 
240
327
  Coverband.configure('./config/coverband_service.rb') if File.exist?('./config/coverband_service.rb')
328
+ Coverband.start
329
+ require "coverband/utils/railtie" if defined? ::Rails::Railtie
330
+ 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.9'
4
+ VERSION = '0.0.12.rc.2'
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.9
4
+ version: 0.0.12.rc.2
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-17 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: