supergood 0.1.1 → 0.1.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 +4 -4
- data/Gemfile.lock +1 -1
- data/lib/supergood/api.rb +31 -40
- data/lib/supergood/client.rb +35 -25
- data/lib/supergood/constants.rb +10 -2
- data/lib/supergood/utils.rb +4 -0
- data/lib/supergood/vendors/http.rb +49 -23
- data/lib/supergood/vendors/net-http.rb +53 -28
- data/lib/supergood/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a0cdb2377e5748a6ed76d61765fe3b15b648f397a97d6c9cdd28b592d68fd323
|
4
|
+
data.tar.gz: '099acaa41f71ef93c745960d9ec046b6643f68501fd95d140a1dd7c62eec76d1'
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2c15df0347deb5fcb0a0fdf04054595f8c4c9ef8b4da4fabc7879d6098fbe9595c507902ed6f7ccab95b47877f139d9121a1ecea885cb5f814ec86942cb37b3b
|
7
|
+
data.tar.gz: 97beed9cd863cd1175756b3084601a40f53928c205b3a3583ca04931a88f6a4804041b8506dfd7277f4232ed1bb7bad3a6eaf5494fe847955dff22439e1882c7
|
data/Gemfile.lock
CHANGED
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(
|
7
|
+
def initialize(client_id, client_secret, base_url)
|
8
8
|
@base_url = base_url
|
9
|
-
@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
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
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
|
-
|
42
|
-
|
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
|
-
@
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
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
|
data/lib/supergood/client.rb
CHANGED
@@ -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(
|
18
|
-
supergood_client_id =
|
19
|
-
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 =
|
30
|
-
|
31
|
-
|
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
|
-
|
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
|
|
data/lib/supergood/constants.rb
CHANGED
@@ -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
|
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
|
data/lib/supergood/utils.rb
CHANGED
@@ -1,33 +1,59 @@
|
|
1
1
|
module Supergood
|
2
2
|
module Vendor
|
3
3
|
module HTTPrb
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
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
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
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
|
-
|
37
|
-
|
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
|
-
|
41
|
-
|
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
|
data/lib/supergood/version.rb
CHANGED