apisonator 3.0.0 → 3.2.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 +4 -4
- data/CHANGELOG.md +67 -0
- data/Gemfile.base +2 -2
- data/Gemfile.lock +10 -9
- data/Gemfile.on_prem.lock +10 -9
- data/app/api/internal/service_tokens.rb +8 -0
- data/lib/3scale/backend/configuration.rb +1 -3
- data/lib/3scale/backend/listener_metrics.rb +67 -8
- data/lib/3scale/backend/rack/prometheus.rb +9 -1
- data/lib/3scale/backend/storage_async/client.rb +1 -1
- data/lib/3scale/backend/transactor.rb +31 -4
- data/lib/3scale/backend/transactor/notify_batcher.rb +6 -2
- data/lib/3scale/backend/transactor/notify_job.rb +37 -17
- data/lib/3scale/backend/version.rb +1 -1
- data/licenses.xml +6 -6
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 1f414f062cdabb59cdcc29b67a862a4400baa6e8d92ebeec909907ed881aa806
|
|
4
|
+
data.tar.gz: 2db24643307830c7cb2cef21da16a51aae8f9336b7bf35f90d4f22f82d15ff45
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 71ad48dc02408cab0de7f8264832489a08b935f55b47139a81ee7228cd71c783d8ebe81c7737c9b3035327535bd9b561784838486194e4b2ab808bb740fad753
|
|
7
|
+
data.tar.gz: 843744f70251b4d26365ab1fe2a4e7c73444b57629f3815c6043bbe467c70835050fdaabdd458e47323a11fb4294b01d1674dd5215f09b6647518adcfbf484da
|
data/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,73 @@
|
|
|
2
2
|
|
|
3
3
|
Notable changes to Apisonator will be tracked in this document.
|
|
4
4
|
|
|
5
|
+
## 3.2.1 - 2021-01-22
|
|
6
|
+
|
|
7
|
+
### Fixed
|
|
8
|
+
|
|
9
|
+
- Reports of 0 hits no longer generate unnecessary stats keys in Redis
|
|
10
|
+
([#247](https://github.com/3scale/apisonator/pull/247)).
|
|
11
|
+
|
|
12
|
+
## 3.2.0 - 2021-01-19
|
|
13
|
+
|
|
14
|
+
### Added
|
|
15
|
+
|
|
16
|
+
- New endpoint in the internal API to get the provider key for a given (token,
|
|
17
|
+
service_id) pair ([#243](https://github.com/3scale/apisonator/pull/243)).
|
|
18
|
+
|
|
19
|
+
### Changed
|
|
20
|
+
|
|
21
|
+
- The config file used when running in a Docker image now parses "1" and "true"
|
|
22
|
+
(case-insensitive) as true
|
|
23
|
+
([#245](https://github.com/3scale/apisonator/pull/245)).
|
|
24
|
+
|
|
25
|
+
### Fixed
|
|
26
|
+
|
|
27
|
+
- Fixed some metrics of the internal API that were not being counted
|
|
28
|
+
correctly([#244](https://github.com/3scale/apisonator/pull/244)).
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
## 3.1.0 - 2020-10-14
|
|
32
|
+
|
|
33
|
+
### Added
|
|
34
|
+
|
|
35
|
+
- Prometheus metrics for the internal API
|
|
36
|
+
([#236](https://github.com/3scale/apisonator/pull/236)).
|
|
37
|
+
- Docs with a detailed explanation about how counter updates are performed
|
|
38
|
+
([#239](https://github.com/3scale/apisonator/pull/239)).
|
|
39
|
+
|
|
40
|
+
### Changed
|
|
41
|
+
|
|
42
|
+
- NotifyJobs are run only when the service ID is explicitly defined
|
|
43
|
+
([#238](https://github.com/3scale/apisonator/pull/238)).
|
|
44
|
+
|
|
45
|
+
### Fixed
|
|
46
|
+
|
|
47
|
+
- Fixed corner case that raised "TransactionTimestampNotWithinRange" in notify
|
|
48
|
+
jobs ([#235](https://github.com/3scale/apisonator/pull/235)).
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
## 3.0.1.1 - 2020-07-28
|
|
52
|
+
|
|
53
|
+
### Changed
|
|
54
|
+
|
|
55
|
+
- Updated json gem to v2.3.1
|
|
56
|
+
([#232](https://github.com/3scale/apisonator/pull/232)).
|
|
57
|
+
|
|
58
|
+
## 3.0.1 - 2020-07-14
|
|
59
|
+
|
|
60
|
+
### Fixed
|
|
61
|
+
|
|
62
|
+
- The Prometheus counter of "5xx" errors has been fixed
|
|
63
|
+
([#230](https://github.com/3scale/apisonator/pull/230)).
|
|
64
|
+
|
|
65
|
+
### Changed
|
|
66
|
+
|
|
67
|
+
- Gem updates: rack to v2.1.4
|
|
68
|
+
([#228](https://github.com/3scale/apisonator/pull/228)) and async-redis to
|
|
69
|
+
v0.5.0 ([#229](https://github.com/3scale/apisonator/pull/229)).
|
|
70
|
+
|
|
71
|
+
|
|
5
72
|
## 3.0.0 - 2020-06-19
|
|
6
73
|
|
|
7
74
|
### Removed
|
data/Gemfile.base
CHANGED
|
@@ -53,13 +53,13 @@ gem 'rake', '~> 13.0'
|
|
|
53
53
|
gem 'builder', '= 3.2.3'
|
|
54
54
|
# Use a patched resque to allow reusing their Airbrake Failure class
|
|
55
55
|
gem 'resque', git: 'https://github.com/3scale/resque', branch: '3scale'
|
|
56
|
-
gem 'rack', '~> 2.
|
|
56
|
+
gem 'rack', '~> 2.1.4'
|
|
57
57
|
gem 'sinatra', '~> 2.0.3'
|
|
58
58
|
gem 'sinatra-contrib', '~> 2.0.3'
|
|
59
59
|
# Optional external error logging services
|
|
60
60
|
gem 'bugsnag', '~> 6', require: nil
|
|
61
61
|
gem 'yabeda-prometheus', '~> 0.5.0'
|
|
62
|
-
gem 'async-redis', '~> 0.
|
|
62
|
+
gem 'async-redis', '~> 0.5'
|
|
63
63
|
gem 'falcon', '~> 0.35'
|
|
64
64
|
|
|
65
65
|
# Use a patched redis-rb that fixes an issue when trying to connect with
|
data/Gemfile.lock
CHANGED
|
@@ -35,7 +35,7 @@ GIT
|
|
|
35
35
|
PATH
|
|
36
36
|
remote: .
|
|
37
37
|
specs:
|
|
38
|
-
apisonator (3.
|
|
38
|
+
apisonator (3.2.1)
|
|
39
39
|
|
|
40
40
|
GEM
|
|
41
41
|
remote: https://rubygems.org/
|
|
@@ -66,14 +66,15 @@ GEM
|
|
|
66
66
|
async-http-cache (0.1.5)
|
|
67
67
|
async-http
|
|
68
68
|
protocol-http (~> 0.14)
|
|
69
|
-
async-io (1.27.
|
|
69
|
+
async-io (1.27.7)
|
|
70
70
|
async (~> 1.14)
|
|
71
71
|
async-pool (0.2.0)
|
|
72
72
|
async (~> 1.8)
|
|
73
|
-
async-redis (0.
|
|
73
|
+
async-redis (0.5.0)
|
|
74
74
|
async (~> 1.8)
|
|
75
75
|
async-io (~> 1.10)
|
|
76
|
-
|
|
76
|
+
async-pool (~> 0.2)
|
|
77
|
+
protocol-redis (~> 0.5.0)
|
|
77
78
|
async-rspec (1.13.0)
|
|
78
79
|
rspec (~> 3.0)
|
|
79
80
|
rspec-files (~> 1.0)
|
|
@@ -118,7 +119,7 @@ GEM
|
|
|
118
119
|
i18n (1.8.2)
|
|
119
120
|
concurrent-ruby (~> 1.0)
|
|
120
121
|
jmespath (1.3.1)
|
|
121
|
-
json (2.1
|
|
122
|
+
json (2.3.1)
|
|
122
123
|
license_finder (5.9.2)
|
|
123
124
|
bundler
|
|
124
125
|
rubyzip
|
|
@@ -161,7 +162,7 @@ GEM
|
|
|
161
162
|
protocol-http2 (0.11.6)
|
|
162
163
|
protocol-hpack (~> 1.4)
|
|
163
164
|
protocol-http (~> 0.15)
|
|
164
|
-
protocol-redis (0.
|
|
165
|
+
protocol-redis (0.5.0)
|
|
165
166
|
pry (0.11.3)
|
|
166
167
|
coderay (~> 1.1.0)
|
|
167
168
|
method_source (~> 0.9.0)
|
|
@@ -171,7 +172,7 @@ GEM
|
|
|
171
172
|
pry-doc (0.11.1)
|
|
172
173
|
pry (~> 0.9)
|
|
173
174
|
yard (~> 0.9)
|
|
174
|
-
rack (2.
|
|
175
|
+
rack (2.1.4)
|
|
175
176
|
rack-protection (2.0.3)
|
|
176
177
|
rack
|
|
177
178
|
rack-test (0.8.2)
|
|
@@ -266,7 +267,7 @@ PLATFORMS
|
|
|
266
267
|
DEPENDENCIES
|
|
267
268
|
airbrake (= 4.3.1)
|
|
268
269
|
apisonator!
|
|
269
|
-
async-redis (~> 0.
|
|
270
|
+
async-redis (~> 0.5)
|
|
270
271
|
async-rspec
|
|
271
272
|
aws-sdk (= 2.4.2)
|
|
272
273
|
benchmark-ips (~> 2.7.2)
|
|
@@ -286,7 +287,7 @@ DEPENDENCIES
|
|
|
286
287
|
pry-byebug (~> 3.5.1)
|
|
287
288
|
pry-doc (~> 0.11.1)
|
|
288
289
|
puma!
|
|
289
|
-
rack (~> 2.
|
|
290
|
+
rack (~> 2.1.4)
|
|
290
291
|
rack-test (~> 0.8.2)
|
|
291
292
|
rake (~> 13.0)
|
|
292
293
|
redis!
|
data/Gemfile.on_prem.lock
CHANGED
|
@@ -35,7 +35,7 @@ GIT
|
|
|
35
35
|
PATH
|
|
36
36
|
remote: .
|
|
37
37
|
specs:
|
|
38
|
-
apisonator (3.
|
|
38
|
+
apisonator (3.2.1)
|
|
39
39
|
|
|
40
40
|
GEM
|
|
41
41
|
remote: https://rubygems.org/
|
|
@@ -63,14 +63,15 @@ GEM
|
|
|
63
63
|
async-http-cache (0.1.5)
|
|
64
64
|
async-http
|
|
65
65
|
protocol-http (~> 0.14)
|
|
66
|
-
async-io (1.27.
|
|
66
|
+
async-io (1.27.7)
|
|
67
67
|
async (~> 1.14)
|
|
68
68
|
async-pool (0.2.0)
|
|
69
69
|
async (~> 1.8)
|
|
70
|
-
async-redis (0.
|
|
70
|
+
async-redis (0.5.0)
|
|
71
71
|
async (~> 1.8)
|
|
72
72
|
async-io (~> 1.10)
|
|
73
|
-
|
|
73
|
+
async-pool (~> 0.2)
|
|
74
|
+
protocol-redis (~> 0.5.0)
|
|
74
75
|
async-rspec (1.13.0)
|
|
75
76
|
rspec (~> 3.0)
|
|
76
77
|
rspec-files (~> 1.0)
|
|
@@ -107,7 +108,7 @@ GEM
|
|
|
107
108
|
hiredis (0.6.3)
|
|
108
109
|
i18n (1.8.2)
|
|
109
110
|
concurrent-ruby (~> 1.0)
|
|
110
|
-
json (2.1
|
|
111
|
+
json (2.3.1)
|
|
111
112
|
license_finder (5.9.2)
|
|
112
113
|
bundler
|
|
113
114
|
rubyzip
|
|
@@ -149,7 +150,7 @@ GEM
|
|
|
149
150
|
protocol-http2 (0.11.6)
|
|
150
151
|
protocol-hpack (~> 1.4)
|
|
151
152
|
protocol-http (~> 0.15)
|
|
152
|
-
protocol-redis (0.
|
|
153
|
+
protocol-redis (0.5.0)
|
|
153
154
|
pry (0.11.3)
|
|
154
155
|
coderay (~> 1.1.0)
|
|
155
156
|
method_source (~> 0.9.0)
|
|
@@ -159,7 +160,7 @@ GEM
|
|
|
159
160
|
pry-doc (0.11.1)
|
|
160
161
|
pry (~> 0.9)
|
|
161
162
|
yard (~> 0.9)
|
|
162
|
-
rack (2.
|
|
163
|
+
rack (2.1.4)
|
|
163
164
|
rack-protection (2.0.3)
|
|
164
165
|
rack
|
|
165
166
|
rack-test (0.8.2)
|
|
@@ -249,7 +250,7 @@ PLATFORMS
|
|
|
249
250
|
|
|
250
251
|
DEPENDENCIES
|
|
251
252
|
apisonator!
|
|
252
|
-
async-redis (~> 0.
|
|
253
|
+
async-redis (~> 0.5)
|
|
253
254
|
async-rspec
|
|
254
255
|
benchmark-ips (~> 2.7.2)
|
|
255
256
|
bugsnag (~> 6)
|
|
@@ -267,7 +268,7 @@ DEPENDENCIES
|
|
|
267
268
|
pry-byebug (~> 3.5.1)
|
|
268
269
|
pry-doc (~> 0.11.1)
|
|
269
270
|
puma!
|
|
270
|
-
rack (~> 2.
|
|
271
|
+
rack (~> 2.1.4)
|
|
271
272
|
rack-test (~> 0.8.2)
|
|
272
273
|
rake (~> 13.0)
|
|
273
274
|
redis!
|
|
@@ -7,6 +7,14 @@ module ThreeScale
|
|
|
7
7
|
ServiceToken.exists?(token, service_id) ? 200 : 404
|
|
8
8
|
end
|
|
9
9
|
|
|
10
|
+
get '/:token/:service_id/provider_key' do |token, service_id|
|
|
11
|
+
if ServiceToken.exists?(token, service_id)
|
|
12
|
+
{ status: :found, provider_key: Service.provider_key_for(service_id) }.to_json
|
|
13
|
+
else
|
|
14
|
+
respond_with_404('token/service combination not found'.freeze)
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
10
18
|
post '/' do
|
|
11
19
|
check_tokens_param!
|
|
12
20
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
require '3scale/backend/configuration/loader'
|
|
2
2
|
require '3scale/backend/environment'
|
|
3
3
|
require '3scale/backend/configurable'
|
|
4
|
+
require '3scale/backend/errors'
|
|
4
5
|
|
|
5
6
|
module ThreeScale
|
|
6
7
|
module Backend
|
|
@@ -77,9 +78,6 @@ module ThreeScale
|
|
|
77
78
|
master_metrics = [:transactions, :transactions_authorize]
|
|
78
79
|
config.master.metrics = Struct.new(*master_metrics).new
|
|
79
80
|
|
|
80
|
-
# Default config
|
|
81
|
-
config.master_service_id = 1
|
|
82
|
-
|
|
83
81
|
# This setting controls whether the listener can create event buckets in
|
|
84
82
|
# Redis. We do not want all the listeners creating buckets yet, as we do
|
|
85
83
|
# not know exactly the rate at which we can send events to Kinesis
|
|
@@ -4,14 +4,36 @@ require 'rack'
|
|
|
4
4
|
module ThreeScale
|
|
5
5
|
module Backend
|
|
6
6
|
class ListenerMetrics
|
|
7
|
-
|
|
7
|
+
AUTH_AND_REPORT_REQUEST_TYPES = {
|
|
8
8
|
'/transactions/authorize.xml' => 'authorize',
|
|
9
9
|
'/transactions/oauth_authorize.xml' => 'authorize_oauth',
|
|
10
10
|
'/transactions/authrep.xml' => 'authrep',
|
|
11
11
|
'/transactions/oauth_authrep.xml' => 'authrep_oauth',
|
|
12
12
|
'/transactions.xml' => 'report'
|
|
13
13
|
}
|
|
14
|
-
private_constant :
|
|
14
|
+
private_constant :AUTH_AND_REPORT_REQUEST_TYPES
|
|
15
|
+
|
|
16
|
+
# Only the first match is taken into account, that's why for example,
|
|
17
|
+
# "/\/services\/.*\/stats/" needs to appear before "/\/services/"
|
|
18
|
+
INTERNAL_API_PATHS = [
|
|
19
|
+
[/\/services\/.*\/alert_limits/, 'alerts'.freeze],
|
|
20
|
+
[/\/services\/.*\/applications\/.*\/keys/, 'application_keys'.freeze],
|
|
21
|
+
[/\/services\/.*\/applications\/.*\/referrer_filters/, 'application_referrer_filters'.freeze],
|
|
22
|
+
[/\/services\/.*\/applications\/.*\/utilization/, 'utilization'.freeze],
|
|
23
|
+
[/\/services\/.*\/applications/, 'applications'.freeze],
|
|
24
|
+
[/\/services\/.*\/errors/, 'errors'.freeze],
|
|
25
|
+
[/\/events/, 'events'.freeze],
|
|
26
|
+
[/\/services\/.*\/metrics/, 'metrics'.freeze],
|
|
27
|
+
[/\/service_tokens/, 'service_tokens'.freeze],
|
|
28
|
+
[/\/services\/.*\/stats/, 'stats'.freeze],
|
|
29
|
+
[/\/services\/.*\/plans\/.*\/usagelimits/, 'usage_limits'.freeze],
|
|
30
|
+
[/\/services/, 'services'.freeze],
|
|
31
|
+
].freeze
|
|
32
|
+
private_constant :INTERNAL_API_PATHS
|
|
33
|
+
|
|
34
|
+
# Most requests will be under 100ms, so use a higher granularity from there
|
|
35
|
+
TIME_BUCKETS = [0.01, 0.02, 0.03, 0.04, 0.05, 0.06, 0.07, 0.08, 0.09, 0.1, 0.25, 0.5, 0.75, 1]
|
|
36
|
+
private_constant :TIME_BUCKETS
|
|
15
37
|
|
|
16
38
|
class << self
|
|
17
39
|
ERRORS_4XX_TO_TRACK = Set[403, 404, 409].freeze
|
|
@@ -27,9 +49,12 @@ module ThreeScale
|
|
|
27
49
|
end
|
|
28
50
|
|
|
29
51
|
def report_resp_code(path, resp_code)
|
|
30
|
-
|
|
52
|
+
req_type = req_type(path)
|
|
53
|
+
prometheus_group = prometheus_group(req_type)
|
|
54
|
+
|
|
55
|
+
Yabeda.send(prometheus_group).response_codes.increment(
|
|
31
56
|
{
|
|
32
|
-
request_type:
|
|
57
|
+
request_type: req_type,
|
|
33
58
|
resp_code: code_group(resp_code)
|
|
34
59
|
},
|
|
35
60
|
by: 1
|
|
@@ -37,8 +62,11 @@ module ThreeScale
|
|
|
37
62
|
end
|
|
38
63
|
|
|
39
64
|
def report_response_time(path, request_time)
|
|
40
|
-
|
|
41
|
-
|
|
65
|
+
req_type = req_type(path)
|
|
66
|
+
prometheus_group = prometheus_group(req_type)
|
|
67
|
+
|
|
68
|
+
Yabeda.send(prometheus_group).response_times.measure(
|
|
69
|
+
{ request_type: req_type },
|
|
42
70
|
request_time
|
|
43
71
|
)
|
|
44
72
|
end
|
|
@@ -69,8 +97,21 @@ module ThreeScale
|
|
|
69
97
|
comment 'Response times'
|
|
70
98
|
unit :seconds
|
|
71
99
|
tags %i[request_type]
|
|
72
|
-
|
|
73
|
-
|
|
100
|
+
buckets TIME_BUCKETS
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
group :apisonator_listener_internal_api do
|
|
105
|
+
counter :response_codes do
|
|
106
|
+
comment 'Response codes'
|
|
107
|
+
tags %i[request_type resp_code]
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
histogram :response_times do
|
|
111
|
+
comment 'Response times'
|
|
112
|
+
unit :seconds
|
|
113
|
+
tags %i[request_type]
|
|
114
|
+
buckets TIME_BUCKETS
|
|
74
115
|
end
|
|
75
116
|
end
|
|
76
117
|
end
|
|
@@ -93,6 +134,24 @@ module ThreeScale
|
|
|
93
134
|
'unknown'.freeze
|
|
94
135
|
end
|
|
95
136
|
end
|
|
137
|
+
|
|
138
|
+
def req_type(path)
|
|
139
|
+
AUTH_AND_REPORT_REQUEST_TYPES[path] || internal_api_req_type(path)
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
def internal_api_req_type(path)
|
|
143
|
+
(_regex, type) = INTERNAL_API_PATHS.find { |(regex, _)| regex.match path }
|
|
144
|
+
type
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
# Returns the group as defined in .define_metrics
|
|
148
|
+
def prometheus_group(request_type)
|
|
149
|
+
if AUTH_AND_REPORT_REQUEST_TYPES.values.include? request_type
|
|
150
|
+
:apisonator_listener
|
|
151
|
+
else
|
|
152
|
+
:apisonator_listener_internal_api
|
|
153
|
+
end
|
|
154
|
+
end
|
|
96
155
|
end
|
|
97
156
|
end
|
|
98
157
|
end
|
|
@@ -8,7 +8,15 @@ module ThreeScale
|
|
|
8
8
|
|
|
9
9
|
def call(env)
|
|
10
10
|
began_at = Time.now.getutc
|
|
11
|
-
|
|
11
|
+
|
|
12
|
+
begin
|
|
13
|
+
status, header, body = @app.call(env)
|
|
14
|
+
rescue Exception => e
|
|
15
|
+
ListenerMetrics.report_resp_code(env['REQUEST_PATH'], 500)
|
|
16
|
+
ListenerMetrics.report_response_time(env['REQUEST_PATH'], Time.now - began_at)
|
|
17
|
+
raise e
|
|
18
|
+
end
|
|
19
|
+
|
|
12
20
|
ListenerMetrics.report_resp_code(env['REQUEST_PATH'], status)
|
|
13
21
|
ListenerMetrics.report_response_time(env['REQUEST_PATH'], Time.now - began_at)
|
|
14
22
|
[status, header, body]
|
|
@@ -20,8 +20,14 @@ module ThreeScale
|
|
|
20
20
|
def report(provider_key, service_id, transactions, context_info = {})
|
|
21
21
|
service = Service.load_with_provider_key!(service_id, provider_key)
|
|
22
22
|
|
|
23
|
-
|
|
24
|
-
|
|
23
|
+
# A usage of 0 does not affect rate-limits or stats, so we do not need
|
|
24
|
+
# to report it.
|
|
25
|
+
filtered_transactions = filter_usages_with_0(transactions.clone)
|
|
26
|
+
|
|
27
|
+
return if filtered_transactions.empty?
|
|
28
|
+
|
|
29
|
+
report_enqueue(service.id, filtered_transactions, context_info)
|
|
30
|
+
notify_report(provider_key, filtered_transactions.size)
|
|
25
31
|
end
|
|
26
32
|
|
|
27
33
|
def authorize(provider_key, params, context_info = {})
|
|
@@ -137,9 +143,17 @@ module ThreeScale
|
|
|
137
143
|
|
|
138
144
|
usage = params[:usage]
|
|
139
145
|
|
|
140
|
-
|
|
146
|
+
filtered_usage = filter_metrics_without_inc(usage.clone) if usage
|
|
147
|
+
|
|
148
|
+
if ((filtered_usage && !filtered_usage.empty?) || params[:log]) && status.authorized?
|
|
141
149
|
application_id = status.application.id
|
|
142
|
-
|
|
150
|
+
|
|
151
|
+
report_enqueue(
|
|
152
|
+
status.service_id,
|
|
153
|
+
{ 0 => {"app_id" => application_id, "usage" => filtered_usage, "log" => params[:log] } },
|
|
154
|
+
request: { extensions: request_info[:extensions] }
|
|
155
|
+
)
|
|
156
|
+
|
|
143
157
|
notify_authrep(provider_key, usage ? 1 : 0)
|
|
144
158
|
else
|
|
145
159
|
notify_authorize(provider_key)
|
|
@@ -182,6 +196,19 @@ module ThreeScale
|
|
|
182
196
|
end
|
|
183
197
|
end
|
|
184
198
|
|
|
199
|
+
def filter_usages_with_0(transactions)
|
|
200
|
+
# There are plenty of existing tests using both a string and a symbol
|
|
201
|
+
# when accessing the usage.
|
|
202
|
+
transactions.delete_if do |_idx, tx|
|
|
203
|
+
(usage = tx['usage'.freeze] || tx[:usage]) or next
|
|
204
|
+
filter_metrics_without_inc(usage).empty?
|
|
205
|
+
end
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
def filter_metrics_without_inc(usage)
|
|
209
|
+
usage.delete_if { |_metric, delta| delta.to_s == '0'.freeze }
|
|
210
|
+
end
|
|
211
|
+
|
|
185
212
|
def storage
|
|
186
213
|
Storage.instance
|
|
187
214
|
end
|
|
@@ -30,9 +30,13 @@ module ThreeScale
|
|
|
30
30
|
end
|
|
31
31
|
|
|
32
32
|
def notify(provider_key, usage)
|
|
33
|
-
#
|
|
33
|
+
# We need the master service ID to report its metrics. If it's not
|
|
34
|
+
# set, we don't need to notify anything.
|
|
35
|
+
# Batch several notifications together so that we can process just one
|
|
34
36
|
# job for a group of them.
|
|
35
|
-
|
|
37
|
+
unless configuration.master_service_id.to_s.empty?
|
|
38
|
+
notify_batch(provider_key, usage)
|
|
39
|
+
end
|
|
36
40
|
end
|
|
37
41
|
|
|
38
42
|
def notify_batch(provider_key, usage)
|
|
@@ -7,8 +7,6 @@ module ThreeScale
|
|
|
7
7
|
extend Configurable
|
|
8
8
|
@queue = :main
|
|
9
9
|
|
|
10
|
-
InvalidMasterServiceId = Class.new(ThreeScale::Backend::Error)
|
|
11
|
-
|
|
12
10
|
class << self
|
|
13
11
|
def perform_logged(provider_key, usage, timestamp, _enqueue_time)
|
|
14
12
|
application_id = Application.load_id_by_key(master_service_id, provider_key)
|
|
@@ -16,12 +14,42 @@ module ThreeScale
|
|
|
16
14
|
if application_id && Application.exists?(master_service_id, application_id)
|
|
17
15
|
master_metrics = Metric.load_all(master_service_id)
|
|
18
16
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
17
|
+
begin
|
|
18
|
+
ProcessJob.perform([{
|
|
19
|
+
service_id: master_service_id,
|
|
20
|
+
application_id: application_id,
|
|
21
|
+
timestamp: timestamp,
|
|
22
|
+
usage: master_metrics.process_usage(usage)
|
|
23
|
+
}])
|
|
24
|
+
rescue MetricInvalid => e
|
|
25
|
+
# This happens when the master account in Porta does not have
|
|
26
|
+
# the notify metrics defined (by default "transactions" and
|
|
27
|
+
# "transactions/authorize"). These metrics need to be created in
|
|
28
|
+
# Porta, Apisonator does not have a way to guarantee that
|
|
29
|
+
# they're defined.
|
|
30
|
+
# Notice that this rescue prevents the job from being retried.
|
|
31
|
+
# Apisonator can't know when the metrics will be created (if
|
|
32
|
+
# ever) so it's better to log the error rather than retrying
|
|
33
|
+
# these jobs for an undefined period of time.
|
|
34
|
+
Worker.logger.notify(e)
|
|
35
|
+
return [false, "#{e}"]
|
|
36
|
+
rescue TransactionTimestampNotWithinRange => e
|
|
37
|
+
# This is very unlikely to happen. The timestamps in a notify
|
|
38
|
+
# job are not set by users, they are set by the listeners. If
|
|
39
|
+
# this error happens it might mean that:
|
|
40
|
+
# a) The worker started processing this job way after the
|
|
41
|
+
# listener produced it. This can happen for example if we make
|
|
42
|
+
# some requests to a listener with no workers. The listeners
|
|
43
|
+
# will enqueue some notify jobs. If we start a worker hours
|
|
44
|
+
# later, we might see this error.
|
|
45
|
+
# b) There's some kind of clock skew issue.
|
|
46
|
+
# c) There's a bug.
|
|
47
|
+
#
|
|
48
|
+
# We can't raise here, because then, the job will be retried,
|
|
49
|
+
# but it's going to fail always if it has an old timestamp.
|
|
50
|
+
Worker.logger.notify(e)
|
|
51
|
+
return [false, "#{provider_key} #{application_id} #{e}"]
|
|
52
|
+
end
|
|
25
53
|
end
|
|
26
54
|
[true, "#{provider_key} #{application_id || '--'}"]
|
|
27
55
|
end
|
|
@@ -29,15 +57,7 @@ module ThreeScale
|
|
|
29
57
|
private
|
|
30
58
|
|
|
31
59
|
def master_service_id
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
unless value
|
|
35
|
-
raise InvalidMasterServiceId,
|
|
36
|
-
"Can't find master service id. Make sure the \"master_service_id\" "\
|
|
37
|
-
'configuration value is set correctly'
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
value.to_s
|
|
60
|
+
configuration.master_service_id.to_s
|
|
41
61
|
end
|
|
42
62
|
end
|
|
43
63
|
end
|
data/licenses.xml
CHANGED
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
</dependency>
|
|
24
24
|
<dependency>
|
|
25
25
|
<packageName>apisonator</packageName>
|
|
26
|
-
<version>3.
|
|
26
|
+
<version>3.2.1</version>
|
|
27
27
|
<licenses>
|
|
28
28
|
<license>
|
|
29
29
|
<name>Apache 2.0</name>
|
|
@@ -73,7 +73,7 @@
|
|
|
73
73
|
</dependency>
|
|
74
74
|
<dependency>
|
|
75
75
|
<packageName>async-io</packageName>
|
|
76
|
-
<version>1.27.
|
|
76
|
+
<version>1.27.7</version>
|
|
77
77
|
<licenses>
|
|
78
78
|
<license>
|
|
79
79
|
<name>MIT</name>
|
|
@@ -93,7 +93,7 @@
|
|
|
93
93
|
</dependency>
|
|
94
94
|
<dependency>
|
|
95
95
|
<packageName>async-redis</packageName>
|
|
96
|
-
<version>0.
|
|
96
|
+
<version>0.5.0</version>
|
|
97
97
|
<licenses>
|
|
98
98
|
<license>
|
|
99
99
|
<name>MIT</name>
|
|
@@ -371,7 +371,7 @@
|
|
|
371
371
|
</dependency>
|
|
372
372
|
<dependency>
|
|
373
373
|
<packageName>json</packageName>
|
|
374
|
-
<version>2.1
|
|
374
|
+
<version>2.3.1</version>
|
|
375
375
|
<licenses>
|
|
376
376
|
<license>
|
|
377
377
|
<name>ruby</name>
|
|
@@ -669,7 +669,7 @@
|
|
|
669
669
|
</dependency>
|
|
670
670
|
<dependency>
|
|
671
671
|
<packageName>protocol-redis</packageName>
|
|
672
|
-
<version>0.
|
|
672
|
+
<version>0.5.0</version>
|
|
673
673
|
<licenses>
|
|
674
674
|
<license>
|
|
675
675
|
<name>MIT</name>
|
|
@@ -719,7 +719,7 @@
|
|
|
719
719
|
</dependency>
|
|
720
720
|
<dependency>
|
|
721
721
|
<packageName>rack</packageName>
|
|
722
|
-
<version>2.
|
|
722
|
+
<version>2.1.4</version>
|
|
723
723
|
<licenses>
|
|
724
724
|
<license>
|
|
725
725
|
<name>MIT</name>
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: apisonator
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 3.
|
|
4
|
+
version: 3.2.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Adam Ciganek
|
|
@@ -16,7 +16,7 @@ authors:
|
|
|
16
16
|
autorequire:
|
|
17
17
|
bindir: bin
|
|
18
18
|
cert_chain: []
|
|
19
|
-
date:
|
|
19
|
+
date: 2021-01-22 00:00:00.000000000 Z
|
|
20
20
|
dependencies: []
|
|
21
21
|
description: This gem provides a daemon that handles authorization and reporting of
|
|
22
22
|
web services managed by 3scale.
|