supergood 0.1.1 → 0.1.2

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
  SHA256:
3
- metadata.gz: a5cc6a38a2204140f0764b5875faa3a86e40770b12b9783b2c62d79349a587e2
4
- data.tar.gz: 776779840ec476c214c227d86de870fe6834738776c22ae14e5acf21c446adc7
3
+ metadata.gz: a0cdb2377e5748a6ed76d61765fe3b15b648f397a97d6c9cdd28b592d68fd323
4
+ data.tar.gz: '099acaa41f71ef93c745960d9ec046b6643f68501fd95d140a1dd7c62eec76d1'
5
5
  SHA512:
6
- metadata.gz: 21dd980b5e7a766943b055d414112155687672fdaac6842d823f9f4920196ad2ea5012454ed6d38f5a27ae8151aa7d8da682c5d73b7b2032cb314f68802f447b
7
- data.tar.gz: 3ae1572a26f4cba3416892c8faa3dc806580cbe4411edac101a8389364ac0dcef1950e6f09bd557a0cad5d00c90589c95cb1b852b68f3e712cd36b27fd266014
6
+ metadata.gz: 2c15df0347deb5fcb0a0fdf04054595f8c4c9ef8b4da4fabc7879d6098fbe9595c507902ed6f7ccab95b47877f139d9121a1ecea885cb5f814ec86942cb37b3b
7
+ data.tar.gz: 97beed9cd863cd1175756b3084601a40f53928c205b3a3583ca04931a88f6a4804041b8506dfd7277f4232ed1bb7bad3a6eaf5494fe847955dff22439e1882c7
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- supergood (0.1.0)
4
+ supergood (0.1.1)
5
5
  rudash (~> 4.0, >= 4.0.2)
6
6
 
7
7
  GEM
data/lib/supergood/api.rb CHANGED
@@ -4,9 +4,17 @@ Dotenv.load
4
4
 
5
5
  module Supergood
6
6
  class Api
7
- def initialize(header_options, base_url)
7
+ def initialize(client_id, client_secret, base_url)
8
8
  @base_url = base_url
9
- @header_options = header_options
9
+ @header_options = {
10
+ 'Content-Type' => 'application/json',
11
+ 'Authorization' => 'Basic ' + Base64.encode64(client_id + ':' + client_secret).gsub(/\n/, '')
12
+ }
13
+ @local_only = client_id == LOCAL_CLIENT_ID && client_secret == LOCAL_CLIENT_SECRET
14
+ end
15
+
16
+ def header_options
17
+ @header_options
10
18
  end
11
19
 
12
20
  def log
@@ -17,50 +25,33 @@ module Supergood
17
25
  @log = logger
18
26
  end
19
27
 
20
- def set_event_sink_endpoint(endpoint)
21
- @event_sink_endpoint = endpoint
22
- end
23
-
24
- def set_error_sink_endpoint(endpoint)
25
- @error_sink_endpoint = endpoint
26
- end
27
-
28
28
  def post_events(payload)
29
- uri = URI(@base_url + @event_sink_endpoint)
30
- response = Net::HTTP.post(uri, payload.to_json, @header_options)
31
- if response.code == '200'
32
- return JSON.parse(response.body, symbolize_names: true)
33
- elsif response.code == '401'
34
- raise SupergoodException.new ERRORS[:UNAUTHORIZED]
35
- elsif response.code != '200' && response.code != '201'
36
- raise SupergoodException.new ERRORS[:POSTING_EVENTS]
29
+ if @local_only
30
+ @log.debug(payload)
31
+ else
32
+ uri = URI(@base_url + '/api/events')
33
+ response = Net::HTTP.post(uri, payload.to_json, @header_options)
34
+ if response.code == '200'
35
+ return JSON.parse(response.body, symbolize_names: true)
36
+ elsif response.code == '401'
37
+ raise SupergoodException.new ERRORS[:UNAUTHORIZED]
38
+ elsif response.code != '200' && response.code != '201'
39
+ raise SupergoodException.new ERRORS[:POSTING_EVENTS]
40
+ end
37
41
  end
38
42
  end
39
43
 
40
44
  def post_errors(payload)
41
- uri = URI(@base_url + @error_sink_endpoint)
42
- response = Net::HTTP.post(uri, payload.to_json, @header_options)
43
- if response.code == '200'
44
- return JSON.parse(response.body, symbolize_names: true)
45
+ if @local_only
46
+ @log.debug(payload)
45
47
  else
46
- @log.warn(ERRORS[:POSTING_ERRORS])
47
- end
48
- end
49
-
50
- def fetch_config
51
- uri = URI(@base_url + '/api/config')
52
- request = Net::HTTP::Get.new(uri)
53
- response = Net::HTTP.start(uri.hostname, uri.port) do |http|
54
- request['Content-Type'] = 'application/json'
55
- request['Authorization'] = @header_options['Authorization']
56
- http.request(request)
57
- end
58
- if response.code == '200'
59
- return JSON.parse(response.body, symbolize_names: true)
60
- elsif response.code == '401'
61
- raise SupergoodException.new ERRORS[:UNAUTHORIZED]
62
- elsif response.code != '200' && response.code != '201'
63
- raise SupergoodException.new ERRORS[:FETCHING_CONFIG]
48
+ uri = URI(@base_url + '/api/errors')
49
+ response = Net::HTTP.post(uri, payload.to_json, @header_options)
50
+ if response.code == '200'
51
+ return JSON.parse(response.body, symbolize_names: true)
52
+ else
53
+ @log.warn(ERRORS[:POSTING_ERRORS])
54
+ end
64
55
  end
65
56
  end
66
57
  end
@@ -12,11 +12,10 @@ Dotenv.load
12
12
  module Supergood
13
13
 
14
14
  DEFAULT_SUPERGOOD_BASE_URL = 'https://dashboard.supergood.ai'
15
-
16
15
  class << self
17
- def init(supergood_client_id=nil, supergood_client_secret=nil, base_url=nil)
18
- supergood_client_id = supergood_client_id || ENV['SUPERGOOD_CLIENT_ID']
19
- supergood_client_secret = supergood_client_secret || ENV['SUPERGOOD_CLIENT_SECRET']
16
+ def init(config={})
17
+ supergood_client_id = config[:client_id] || ENV['SUPERGOOD_CLIENT_ID']
18
+ supergood_client_secret = config[:client_secret] || ENV['SUPERGOOD_CLIENT_SECRET']
20
19
 
21
20
  if !supergood_client_id
22
21
  raise SupergoodException.new ERRORS[:NO_CLIENT_ID]
@@ -26,27 +25,27 @@ module Supergood
26
25
  raise SupergoodException.new ERRORS[:NO_CLIENT_SECRET]
27
26
  end
28
27
 
29
- @base_url = base_url || ENV['SUPERGOOD_BASE_URL'] || DEFAULT_SUPERGOOD_BASE_URL
30
- header_options = {
31
- 'Content-Type' => 'application/json',
32
- 'Authorization' => 'Basic ' + Base64.encode64(supergood_client_id + ':' + supergood_client_secret).gsub(/\n/, '')
33
- }
28
+ @base_url = ENV['SUPERGOOD_BASE_URL'] || DEFAULT_SUPERGOOD_BASE_URL
29
+ @api = Supergood::Api.new(supergood_client_id, supergood_client_secret, @base_url)
30
+ @config = Supergood::Utils.make_config(config)
34
31
 
35
- @api = Supergood::Api.new(header_options, @base_url)
36
- @config = @api.fetch_config
37
32
  @ignored_domains = @config[:ignoredDomains]
38
33
  @keys_to_hash = @config[:keysToHash]
39
- @logger = Supergood::Logger.new(@api, @config, header_options)
34
+ @logger = Supergood::Logger.new(@api, @config, @api.header_options)
40
35
 
41
- @api.set_error_sink_endpoint(@config[:errorSinkEndpoint])
42
- @api.set_event_sink_endpoint(@config[:eventSinkEndpoint])
43
36
  @api.set_logger(@logger)
44
37
 
45
38
  @request_cache = {}
46
39
  @response_cache = {}
47
40
 
48
41
  @interval_thread = set_interval(@config[:flushInterval]) { flush_cache }
49
- log.debug("Using config %s" % @config.inspect)
42
+
43
+ @http_clients = [
44
+ Supergood::Vendor::NetHTTP,
45
+ Supergood::Vendor::HTTPrb
46
+ ]
47
+
48
+ patch_all()
50
49
  self
51
50
  end
52
51
 
@@ -76,6 +75,7 @@ module Supergood
76
75
  api.post_events(data)
77
76
  rescue => e
78
77
  log.error(data, e, e.message)
78
+ cleanup()
79
79
  ensure
80
80
  @response_cache.clear
81
81
  @request_cache.clear if force
@@ -83,10 +83,27 @@ module Supergood
83
83
 
84
84
  end
85
85
 
86
+ def cleanup()
87
+ @interval_thread.kill
88
+ unpatch_all()
89
+ end
90
+
86
91
  def close(force = true)
87
92
  log.debug('Cleaning up, flushing cache gracefully.')
88
- @interval_thread.kill
89
93
  flush_cache(force)
94
+ cleanup()
95
+ end
96
+
97
+ def patch_all
98
+ @http_clients.each do |client|
99
+ client.patch
100
+ end
101
+ end
102
+
103
+ def unpatch_all
104
+ @http_clients.each do |client|
105
+ client.unpatch
106
+ end
90
107
  end
91
108
 
92
109
  def set_interval(delay)
@@ -98,14 +115,6 @@ module Supergood
98
115
  end
99
116
  end
100
117
 
101
- def self.intercept(*args, &block)
102
- instance.intercept(*args, &block)
103
- end
104
-
105
- def self.instance
106
- @instance ||= Supergood.new
107
- end
108
-
109
118
  def intercept(request)
110
119
  request_id = SecureRandom.uuid
111
120
  requested_at = Time.now
@@ -138,6 +147,7 @@ module Supergood
138
147
  }
139
148
  rescue => e
140
149
  log.error({ request: request }, e, ERRORS[:CACHING_REQUEST])
150
+ cleanup()
141
151
  end
142
152
  end
143
153
 
@@ -159,11 +169,11 @@ module Supergood
159
169
  }), @keys_to_hash)
160
170
  @request_cache.delete(request_id)
161
171
  rescue => e
162
- puts e
163
172
  log.error(
164
173
  { request: request_payload, response: response_payload },
165
174
  e, ERRORS[:CACHING_RESPONSE]
166
175
  )
176
+ cleanup()
167
177
  end
168
178
  end
169
179
 
@@ -4,9 +4,8 @@ ERRORS = {
4
4
  DUMPING_DATA_TO_DISK: 'Error Dumping Data to Disk',
5
5
  POSTING_EVENTS: 'Error Posting Events',
6
6
  POSTING_ERRORS: 'Error Posting Errors',
7
- FETCHING_CONFIG: 'Error Fetching Config',
8
7
  WRITING_TO_DISK: 'Error writing to disk',
9
- TEST_ERROR: 'Test Error for Testing Purposes',
8
+ TEST_ERROR: 'Test Error for Testing Purpos es',
10
9
  UNAUTHORIZED: 'Unauthorized: Invalid Client ID or Secret. Exiting.',
11
10
  NO_CLIENT_ID:
12
11
  'No Client ID Provided, set SUPERGOOD_CLIENT_ID or pass it as an argument',
@@ -14,8 +13,17 @@ ERRORS = {
14
13
  'No Client Secret Provided, set SUPERGOOD_CLIENT_SECRET or pass it as an argument'
15
14
  };
16
15
 
16
+ LOCAL_CLIENT_ID = 'local-client-id';
17
+ LOCAL_CLIENT_SECRET = 'local-client-secret';
18
+
17
19
  DEFAULT_SUPERGOOD_BYTE_LIMIT = 500000
18
20
 
21
+ DEFAULT_CONFIG = {
22
+ keysToHash: [],
23
+ flushInterval: 1000,
24
+ ignoredDomains: []
25
+ }
26
+
19
27
  # GZIP_START_BYTES = b'\x1f\x8b'
20
28
 
21
29
  class SupergoodException < StandardError
@@ -68,5 +68,9 @@ module Supergood
68
68
  def self.request_url(http, request)
69
69
  URI::DEFAULT_PARSER.unescape("http#{"s" if http.use_ssl?}://#{http.address}#{request.path}")
70
70
  end
71
+
72
+ def self.make_config(config)
73
+ return DEFAULT_CONFIG.merge(config)
74
+ end
71
75
  end
72
76
  end
@@ -1,33 +1,59 @@
1
1
  module Supergood
2
2
  module Vendor
3
3
  module HTTPrb
4
- if defined?(HTTP::Client)
5
- HTTP::Client.class_eval {
6
- alias original_perform perform
7
- def perform(original_request_payload, original_options)
8
- request = {
9
- headers: original_request_payload.headers.to_hash,
10
- method: original_request_payload.verb.upcase.to_s,
11
- body: Supergood::Utils.safe_parse_json(original_request_payload.body.source),
12
- url: original_request_payload.uri.to_s,
13
- path: original_request_payload.uri.path,
14
- search: original_request_payload.uri.query,
15
- domain: original_request_payload.uri.host
16
- }
17
- Supergood.intercept(request) do
18
- original_response = original_perform(original_request_payload, original_options)
19
- status, statusText = original_response.status.to_s.split(' ')
20
- {
21
- headers: original_response.headers.to_hash,
22
- status: status,
23
- statusText: statusText,
24
- body: Supergood::Utils.safe_parse_json(original_response),
25
- original_response: original_response
4
+ def self.patch
5
+ if !self.existing_patch?
6
+
7
+ block = lambda do |x|
8
+ alias original_perform perform
9
+ def perform(original_request_payload, original_options)
10
+ request = {
11
+ headers: original_request_payload.headers.to_hash,
12
+ method: original_request_payload.verb.upcase.to_s,
13
+ body: Supergood::Utils.safe_parse_json(original_request_payload.body.source),
14
+ url: original_request_payload.uri.to_s,
15
+ path: original_request_payload.uri.path,
16
+ search: original_request_payload.uri.query,
17
+ domain: original_request_payload.uri.host
26
18
  }
19
+ Supergood.intercept(request) do
20
+ original_response = original_perform(original_request_payload, original_options)
21
+ status, statusText = original_response.status.to_s.split(' ')
22
+ {
23
+ headers: original_response.headers.to_hash,
24
+ status: status,
25
+ statusText: statusText,
26
+ body: Supergood::Utils.safe_parse_json(original_response),
27
+ original_response: original_response
28
+ }
29
+ end
27
30
  end
28
31
  end
29
- }
32
+
33
+ if defined?(HTTP::Client)
34
+ HTTP::Client.class_eval(&block)
35
+ end
36
+
37
+ end
38
+ end
39
+
40
+ def self.unpatch
41
+ if self.existing_patch?
42
+ block = lambda do |x|
43
+ alias perform original_perform
44
+ end
45
+
46
+ if defined?(HTTP::Client)
47
+ HTTP::Client.class_eval(&block)
48
+ HTTP::Client.undef_method :original_perform
49
+ end
50
+ end
30
51
  end
52
+
53
+ def self.existing_patch?
54
+ defined?(HTTP::Client) && HTTP::Client.method_defined?(:original_perform)
55
+ end
56
+
31
57
  end
32
58
  end
33
59
  end
@@ -5,41 +5,66 @@ require 'uri'
5
5
  module Supergood
6
6
  module Vendor
7
7
  module NetHTTP
8
- block = lambda do |x|
9
- alias original_request_method request
10
- def request(original_request_payload, body = nil, &block)
11
- http = self;
12
- url = Supergood::Utils.request_url(http, original_request_payload)
13
- uri = URI.parse(url)
14
- request = {
15
- headers: Supergood::Utils.get_header(original_request_payload),
16
- method: original_request_payload.method,
17
- body: original_request_payload.body,
18
- url: url,
19
- path: original_request_payload.path,
20
- search: uri.query,
21
- domain: uri.host,
22
- }
23
- Supergood.intercept(request) do
24
- original_response = original_request_method(original_request_payload, body, &block)
25
- {
26
- headers: Supergood::Utils.get_header(original_response),
27
- status: original_response.code,
28
- statusText: original_response.message,
29
- body: original_response.body,
30
- original_response: original_response
31
- }
8
+ def self.patch
9
+ if !self.existing_patch?
10
+ block = lambda do |x|
11
+ alias original_request_method request
12
+ def request(original_request_payload, body = nil, &block)
13
+ http = self;
14
+ url = Supergood::Utils.request_url(http, original_request_payload)
15
+ uri = URI.parse(url)
16
+ request = {
17
+ headers: Supergood::Utils.get_header(original_request_payload),
18
+ method: original_request_payload.method,
19
+ body: original_request_payload.body,
20
+ url: url,
21
+ path: original_request_payload.path,
22
+ search: uri.query,
23
+ domain: uri.host,
24
+ }
25
+ Supergood.intercept(request) do
26
+ original_response = original_request_method(original_request_payload, body, &block)
27
+ {
28
+ headers: Supergood::Utils.get_header(original_response),
29
+ status: original_response.code,
30
+ statusText: original_response.message,
31
+ body: original_response.body,
32
+ original_response: original_response
33
+ }
34
+ end
35
+ end
32
36
  end
37
+
38
+ if defined?(Net::HTTP)
39
+ Net::HTTP.class_eval(&block)
40
+ elsif defined?(::WebMock)
41
+ WebMock::HttpLibAdapters::NetHttpAdapter.instance_variable_get("@webMockNetHTTP").class_eval(&block)
42
+ end
43
+
33
44
  end
34
45
  end
35
46
 
36
- if defined?(Net::HTTP)
37
- Net::HTTP.class_eval(&block)
47
+ def self.unpatch
48
+ if self.existing_patch?
49
+ block = lambda do |x|
50
+ alias request original_request_method
51
+ end
52
+
53
+ if defined?(Net::HTTP)
54
+ Net::HTTP.class_eval(&block)
55
+ Net::HTTP.undef_method :original_request_method
56
+ elsif defined?(::WebMock)
57
+ WebMock::HttpLibAdapters::NetHttpAdapter.instance_variable_get("@webMockNetHTTP").class_eval(&block)
58
+ WebMock::HttpLibAdapters::NetHttpAdapter.instance_variable_get("@webMockNetHTTP").undef_method :original_request_method
59
+ end
60
+ end
38
61
  end
39
62
 
40
- if defined?(::WebMock)
41
- WebMock::HttpLibAdapters::NetHttpAdapter.instance_variable_get("@webMockNetHTTP").class_eval(&block)
63
+ def self.existing_patch?
64
+ (defined?(Net::HTTP) && Net::HTTP.method_defined?(:original_request_method)) ||
65
+ (defined?(::Webmock) && WebMock::HttpLibAdapters::NetHttpAdapter.instance_variable_get("@webMockNetHTTP").method_defined?(:original_request_method))
42
66
  end
67
+
43
68
  end
44
69
  end
45
70
  end
@@ -1,3 +1,3 @@
1
1
  module Supergood
2
- VERSION = '0.1.1'.freeze
2
+ VERSION = '0.1.2'.freeze
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: supergood
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alex Klarfeld