apisonator 3.3.1.1 → 3.4.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/CHANGELOG.md +68 -0
- data/Gemfile.base +2 -2
- data/Gemfile.lock +13 -13
- data/Gemfile.on_prem.lock +13 -13
- data/lib/3scale/backend.rb +1 -0
- data/lib/3scale/backend/alert_limit.rb +9 -11
- data/lib/3scale/backend/alerts.rb +94 -47
- data/lib/3scale/backend/configuration.rb +0 -1
- data/lib/3scale/backend/constants.rb +2 -0
- data/lib/3scale/backend/rack.rb +4 -1
- data/lib/3scale/backend/service.rb +3 -35
- data/lib/3scale/backend/stats/aggregator.rb +30 -24
- data/lib/3scale/backend/stats/cleaner.rb +0 -6
- data/lib/3scale/backend/transactor.rb +17 -26
- data/lib/3scale/backend/transactor/status.rb +27 -9
- data/lib/3scale/backend/transactor/usage_report.rb +1 -1
- data/lib/3scale/backend/usage.rb +10 -3
- data/lib/3scale/backend/utilization.rb +83 -0
- data/lib/3scale/backend/validators.rb +7 -0
- data/lib/3scale/backend/validators/oauth_setting.rb +1 -1
- data/lib/3scale/backend/version.rb +1 -1
- data/lib/3scale/prometheus_server.rb +1 -1
- data/licenses.xml +7 -7
- metadata +4 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 356ca549dce065646329337096b0c3233ea3be1fdf599b135c144f5c887e5754
|
|
4
|
+
data.tar.gz: 04af4be3b14ce0299bbefc968349e7f063222d9a61d10557a4ffade0a5c683db
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 850c97fc6f5835da57e1918881aa2f4ce0e086fb550c2bda024b98c9e1e62b829aadb1f0b45dd7b690aa0bd5b5cfb712de1d4914f39eab8caa5107e28c48f600
|
|
7
|
+
data.tar.gz: 0d45268818cd98bf0c8684fe1340544e230c85fdef7d05b4f37d0c1db4d963d21fc2f50455bf1226619276ec6402c3be3af9ee755b783f8ee5d2ec5c300b8e66
|
data/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,74 @@
|
|
|
2
2
|
|
|
3
3
|
Notable changes to Apisonator will be tracked in this document.
|
|
4
4
|
|
|
5
|
+
## 3.4.2 - 2021-06-17
|
|
6
|
+
|
|
7
|
+
### Fixed
|
|
8
|
+
|
|
9
|
+
- Fixed exception raised when TTL = 0 in `UsagesChecked.mark_all_checked`
|
|
10
|
+
([#290](https://github.com/3scale/apisonator/pull/290)).
|
|
11
|
+
|
|
12
|
+
## 3.4.1 - 2021-06-16
|
|
13
|
+
|
|
14
|
+
### Changed
|
|
15
|
+
|
|
16
|
+
- Introduced performance optimizations around alerts detection
|
|
17
|
+
([#287](https://github.com/3scale/apisonator/pull/287)).
|
|
18
|
+
|
|
19
|
+
## 3.4.0 - 2021-06-14
|
|
20
|
+
|
|
21
|
+
### Added
|
|
22
|
+
|
|
23
|
+
- New extension that list the keys of an application
|
|
24
|
+
([#284](https://github.com/3scale/apisonator/pull/284)).
|
|
25
|
+
|
|
26
|
+
### Changed
|
|
27
|
+
|
|
28
|
+
- It is now possible to use OIDC in the auth and authrep endpoints
|
|
29
|
+
([#280](https://github.com/3scale/apisonator/pull/280)).
|
|
30
|
+
- Updated multi-json to 1.15.0
|
|
31
|
+
([#278](https://github.com/3scale/apisonator/pull/278)).
|
|
32
|
+
|
|
33
|
+
### Removed
|
|
34
|
+
|
|
35
|
+
- Deleted unused service attributes related with deleted end-users functionality
|
|
36
|
+
([#277](https://github.com/3scale/apisonator/pull/277)).
|
|
37
|
+
|
|
38
|
+
## 3.3.3 - 2021-03-09
|
|
39
|
+
|
|
40
|
+
### Changed
|
|
41
|
+
|
|
42
|
+
- Check if alerts can be raised before calculating utilization (perf
|
|
43
|
+
optimization) ([#275](https://github.com/3scale/apisonator/pull/275)).
|
|
44
|
+
|
|
45
|
+
### Removed
|
|
46
|
+
|
|
47
|
+
- Stop maintaining unused "current_max" key in Alerts
|
|
48
|
+
([#272](https://github.com/3scale/apisonator/pull/272)).
|
|
49
|
+
|
|
50
|
+
## 3.3.2 - 2021-02-23
|
|
51
|
+
|
|
52
|
+
### Fixed
|
|
53
|
+
|
|
54
|
+
- Fixed nil exception in `Aggregator.process`
|
|
55
|
+
([#269](https://github.com/3scale/apisonator/pull/269)).
|
|
56
|
+
|
|
57
|
+
### Changed
|
|
58
|
+
|
|
59
|
+
- Updated to Ruby 2.7 in Docker images
|
|
60
|
+
([#265](https://github.com/3scale/apisonator/pull/265)) and
|
|
61
|
+
([#266](https://github.com/3scale/apisonator/pull/266)).
|
|
62
|
+
- Updated pry to 0.14.0 and pry-doc to 1.1.0
|
|
63
|
+
([#267](https://github.com/3scale/apisonator/pull/267)).
|
|
64
|
+
- Updated Docker image to be based on RHEL UBI 8
|
|
65
|
+
([#268](https://github.com/3scale/apisonator/pull/268)).
|
|
66
|
+
|
|
67
|
+
### Removed
|
|
68
|
+
|
|
69
|
+
- Removed redundant prometheus config params
|
|
70
|
+
(`listener_prometheus_metrics.enabled` and `listener_prometheus_metrics.port`)
|
|
71
|
+
([#270](https://github.com/3scale/apisonator/pull/270)).
|
|
72
|
+
|
|
5
73
|
## 3.3.1.1 - 2021-02-12
|
|
6
74
|
|
|
7
75
|
### Changed
|
data/Gemfile.base
CHANGED
|
@@ -36,8 +36,8 @@ end
|
|
|
36
36
|
group :development do
|
|
37
37
|
gem 'sshkit'
|
|
38
38
|
gem 'source2swagger', git: 'https://github.com/3scale/source2swagger', branch: 'backend'
|
|
39
|
-
gem 'pry', '~> 0.
|
|
40
|
-
gem 'pry-doc', '~>
|
|
39
|
+
gem 'pry', '~> 0.14'
|
|
40
|
+
gem 'pry-doc', '~> 1.1'
|
|
41
41
|
gem 'license_finder', '~> 5'
|
|
42
42
|
end
|
|
43
43
|
|
data/Gemfile.lock
CHANGED
|
@@ -36,7 +36,7 @@ GIT
|
|
|
36
36
|
PATH
|
|
37
37
|
remote: .
|
|
38
38
|
specs:
|
|
39
|
-
apisonator (3.
|
|
39
|
+
apisonator (3.4.2)
|
|
40
40
|
|
|
41
41
|
GEM
|
|
42
42
|
remote: https://rubygems.org/
|
|
@@ -96,7 +96,7 @@ GEM
|
|
|
96
96
|
chronic (0.10.2)
|
|
97
97
|
codeclimate-test-reporter (0.6.0)
|
|
98
98
|
simplecov (>= 0.7.1, < 1.0.0)
|
|
99
|
-
coderay (1.1.
|
|
99
|
+
coderay (1.1.3)
|
|
100
100
|
concurrent-ruby (1.1.6)
|
|
101
101
|
console (1.8.2)
|
|
102
102
|
daemons (1.2.4)
|
|
@@ -131,13 +131,13 @@ GEM
|
|
|
131
131
|
localhost (1.1.6)
|
|
132
132
|
mapping (1.1.1)
|
|
133
133
|
metaclass (0.0.4)
|
|
134
|
-
method_source (0.
|
|
134
|
+
method_source (1.0.0)
|
|
135
135
|
mini_portile2 (2.4.0)
|
|
136
136
|
minitest (5.14.1)
|
|
137
137
|
mocha (1.3.0)
|
|
138
138
|
metaclass (~> 0.0.1)
|
|
139
139
|
mono_logger (1.1.0)
|
|
140
|
-
multi_json (1.
|
|
140
|
+
multi_json (1.15.0)
|
|
141
141
|
mustache (1.0.5)
|
|
142
142
|
mustermann (1.0.2)
|
|
143
143
|
net-scp (1.2.1)
|
|
@@ -164,15 +164,15 @@ GEM
|
|
|
164
164
|
protocol-hpack (~> 1.4)
|
|
165
165
|
protocol-http (~> 0.15)
|
|
166
166
|
protocol-redis (0.5.0)
|
|
167
|
-
pry (0.
|
|
168
|
-
coderay (~> 1.1
|
|
169
|
-
method_source (~>
|
|
167
|
+
pry (0.14.0)
|
|
168
|
+
coderay (~> 1.1)
|
|
169
|
+
method_source (~> 1.0)
|
|
170
170
|
pry-byebug (3.5.1)
|
|
171
171
|
byebug (~> 9.1)
|
|
172
172
|
pry (~> 0.10)
|
|
173
|
-
pry-doc (
|
|
174
|
-
pry (~> 0.
|
|
175
|
-
yard (~> 0.9)
|
|
173
|
+
pry-doc (1.1.0)
|
|
174
|
+
pry (~> 0.11)
|
|
175
|
+
yard (~> 0.9.11)
|
|
176
176
|
rack (2.1.4)
|
|
177
177
|
rack-protection (2.0.3)
|
|
178
178
|
rack
|
|
@@ -260,7 +260,7 @@ GEM
|
|
|
260
260
|
prometheus-client (~> 1.0)
|
|
261
261
|
yabeda (~> 0.5)
|
|
262
262
|
yajl-ruby (1.3.1)
|
|
263
|
-
yard (0.9.
|
|
263
|
+
yard (0.9.26)
|
|
264
264
|
|
|
265
265
|
PLATFORMS
|
|
266
266
|
ruby
|
|
@@ -284,9 +284,9 @@ DEPENDENCIES
|
|
|
284
284
|
nokogiri (~> 1.10.8)
|
|
285
285
|
pg (= 0.20.0)
|
|
286
286
|
pkg-config (~> 1.1.7)
|
|
287
|
-
pry (~> 0.
|
|
287
|
+
pry (~> 0.14)
|
|
288
288
|
pry-byebug (~> 3.5.1)
|
|
289
|
-
pry-doc (~>
|
|
289
|
+
pry-doc (~> 1.1)
|
|
290
290
|
puma!
|
|
291
291
|
rack (~> 2.1.4)
|
|
292
292
|
rack-test (= 0.8.2)
|
data/Gemfile.on_prem.lock
CHANGED
|
@@ -36,7 +36,7 @@ GIT
|
|
|
36
36
|
PATH
|
|
37
37
|
remote: .
|
|
38
38
|
specs:
|
|
39
|
-
apisonator (3.
|
|
39
|
+
apisonator (3.4.2)
|
|
40
40
|
|
|
41
41
|
GEM
|
|
42
42
|
remote: https://rubygems.org/
|
|
@@ -86,7 +86,7 @@ GEM
|
|
|
86
86
|
byebug (9.1.0)
|
|
87
87
|
codeclimate-test-reporter (0.6.0)
|
|
88
88
|
simplecov (>= 0.7.1, < 1.0.0)
|
|
89
|
-
coderay (1.1.
|
|
89
|
+
coderay (1.1.3)
|
|
90
90
|
concurrent-ruby (1.1.6)
|
|
91
91
|
console (1.8.2)
|
|
92
92
|
daemons (1.2.4)
|
|
@@ -120,13 +120,13 @@ GEM
|
|
|
120
120
|
localhost (1.1.6)
|
|
121
121
|
mapping (1.1.1)
|
|
122
122
|
metaclass (0.0.4)
|
|
123
|
-
method_source (0.
|
|
123
|
+
method_source (1.0.0)
|
|
124
124
|
mini_portile2 (2.4.0)
|
|
125
125
|
minitest (5.14.1)
|
|
126
126
|
mocha (1.3.0)
|
|
127
127
|
metaclass (~> 0.0.1)
|
|
128
128
|
mono_logger (1.1.0)
|
|
129
|
-
multi_json (1.
|
|
129
|
+
multi_json (1.15.0)
|
|
130
130
|
mustache (1.0.5)
|
|
131
131
|
mustermann (1.0.2)
|
|
132
132
|
net-scp (1.2.1)
|
|
@@ -152,15 +152,15 @@ GEM
|
|
|
152
152
|
protocol-hpack (~> 1.4)
|
|
153
153
|
protocol-http (~> 0.15)
|
|
154
154
|
protocol-redis (0.5.0)
|
|
155
|
-
pry (0.
|
|
156
|
-
coderay (~> 1.1
|
|
157
|
-
method_source (~>
|
|
155
|
+
pry (0.14.0)
|
|
156
|
+
coderay (~> 1.1)
|
|
157
|
+
method_source (~> 1.0)
|
|
158
158
|
pry-byebug (3.5.1)
|
|
159
159
|
byebug (~> 9.1)
|
|
160
160
|
pry (~> 0.10)
|
|
161
|
-
pry-doc (
|
|
162
|
-
pry (~> 0.
|
|
163
|
-
yard (~> 0.9)
|
|
161
|
+
pry-doc (1.1.0)
|
|
162
|
+
pry (~> 0.11)
|
|
163
|
+
yard (~> 0.9.11)
|
|
164
164
|
rack (2.1.4)
|
|
165
165
|
rack-protection (2.0.3)
|
|
166
166
|
rack
|
|
@@ -244,7 +244,7 @@ GEM
|
|
|
244
244
|
prometheus-client (~> 1.0)
|
|
245
245
|
yabeda (~> 0.5)
|
|
246
246
|
yajl-ruby (1.3.1)
|
|
247
|
-
yard (0.9.
|
|
247
|
+
yard (0.9.26)
|
|
248
248
|
|
|
249
249
|
PLATFORMS
|
|
250
250
|
ruby
|
|
@@ -265,9 +265,9 @@ DEPENDENCIES
|
|
|
265
265
|
mocha (~> 1.3)
|
|
266
266
|
nokogiri (~> 1.10.8)
|
|
267
267
|
pkg-config (~> 1.1.7)
|
|
268
|
-
pry (~> 0.
|
|
268
|
+
pry (~> 0.14)
|
|
269
269
|
pry-byebug (~> 3.5.1)
|
|
270
|
-
pry-doc (~>
|
|
270
|
+
pry-doc (~> 1.1)
|
|
271
271
|
puma!
|
|
272
272
|
rack (~> 2.1.4)
|
|
273
273
|
rack-test (= 0.8.2)
|
data/lib/3scale/backend.rb
CHANGED
|
@@ -44,6 +44,7 @@ require '3scale/backend/queue_storage'
|
|
|
44
44
|
require '3scale/backend/errors'
|
|
45
45
|
require '3scale/backend/stats'
|
|
46
46
|
require '3scale/backend/usage_limit'
|
|
47
|
+
require '3scale/backend/utilization'
|
|
47
48
|
require '3scale/backend/alerts'
|
|
48
49
|
require '3scale/backend/event_storage'
|
|
49
50
|
require '3scale/backend/worker'
|
|
@@ -1,21 +1,19 @@
|
|
|
1
1
|
module ThreeScale
|
|
2
2
|
module Backend
|
|
3
3
|
class AlertLimit
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
"alerts/service_id:#{service_id}/allowed_set"
|
|
7
|
-
end
|
|
8
|
-
end
|
|
9
|
-
|
|
10
|
-
include KeyHelpers
|
|
11
|
-
extend KeyHelpers
|
|
4
|
+
include Alerts::KeyHelpers
|
|
5
|
+
extend Alerts::KeyHelpers
|
|
12
6
|
|
|
13
7
|
include Storable
|
|
14
8
|
|
|
15
9
|
attr_accessor :service_id, :value
|
|
16
10
|
|
|
17
11
|
def save
|
|
18
|
-
|
|
12
|
+
if valid?
|
|
13
|
+
res = storage.sadd(key_allowed_set(service_id), value.to_i)
|
|
14
|
+
Alerts::UsagesChecked.invalidate_for_service(service_id)
|
|
15
|
+
res
|
|
16
|
+
end
|
|
19
17
|
end
|
|
20
18
|
|
|
21
19
|
def to_hash
|
|
@@ -26,7 +24,7 @@ module ThreeScale
|
|
|
26
24
|
end
|
|
27
25
|
|
|
28
26
|
def self.load_all(service_id)
|
|
29
|
-
values = storage.smembers(
|
|
27
|
+
values = storage.smembers(key_allowed_set(service_id))
|
|
30
28
|
values.map do |value|
|
|
31
29
|
new(service_id: service_id, value: value.to_i)
|
|
32
30
|
end
|
|
@@ -38,7 +36,7 @@ module ThreeScale
|
|
|
38
36
|
end
|
|
39
37
|
|
|
40
38
|
def self.delete(service_id, value)
|
|
41
|
-
storage.srem(
|
|
39
|
+
storage.srem(key_allowed_set(service_id), value.to_i) if valid_value?(value)
|
|
42
40
|
end
|
|
43
41
|
|
|
44
42
|
def self.valid_value?(value)
|
|
@@ -6,11 +6,10 @@ module ThreeScale
|
|
|
6
6
|
|
|
7
7
|
# The compacted hour in the params refers to the
|
|
8
8
|
# TimeHacks.to_compact_s method.
|
|
9
|
-
def alert_keys(service_id, app_id, discrete_utilization
|
|
9
|
+
def alert_keys(service_id, app_id, discrete_utilization)
|
|
10
10
|
{
|
|
11
11
|
already_notified: key_already_notified(service_id, app_id, discrete_utilization),
|
|
12
12
|
allowed: key_allowed_set(service_id),
|
|
13
|
-
current_max: key_current_max(service_id, app_id, compacted_hour_start),
|
|
14
13
|
current_id: key_current_id
|
|
15
14
|
}
|
|
16
15
|
end
|
|
@@ -31,18 +30,19 @@ module ThreeScale
|
|
|
31
30
|
"#{prefix}allowed_set"
|
|
32
31
|
end
|
|
33
32
|
|
|
34
|
-
def key_current_max(service_id, app_id, compacted_hour_start)
|
|
35
|
-
prefix = key_prefix(service_id, app_id)
|
|
36
|
-
"#{prefix}#{compacted_hour_start}/current_max"
|
|
37
|
-
end
|
|
38
|
-
|
|
39
33
|
def key_current_id
|
|
40
34
|
'alerts/current_id'.freeze
|
|
41
35
|
end
|
|
36
|
+
|
|
37
|
+
def key_usage_already_checked(service_id, app_id)
|
|
38
|
+
prefix = key_prefix(service_id, app_id)
|
|
39
|
+
"#{prefix}usage_already_checked"
|
|
40
|
+
end
|
|
42
41
|
end
|
|
43
42
|
|
|
44
43
|
extend self
|
|
45
44
|
extend KeyHelpers
|
|
45
|
+
include Memoizer::Decorator
|
|
46
46
|
|
|
47
47
|
ALERT_TTL = 24*3600 # 1 day (only one message per day)
|
|
48
48
|
## zero must be here and sorted, yes or yes
|
|
@@ -50,67 +50,109 @@ module ThreeScale
|
|
|
50
50
|
FIRST_ALERT_BIN = ALERT_BINS.first
|
|
51
51
|
RALERT_BINS = ALERT_BINS.reverse.freeze
|
|
52
52
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
53
|
+
# This class is useful to reduce the amount of information that we need to
|
|
54
|
+
# fetch from Redis to determine whether an alert should be raised.
|
|
55
|
+
# In summary, alerts are raised at the application level and we need to
|
|
56
|
+
# wait for 24h before raising a new one for the same level (ALERTS_BIN
|
|
57
|
+
# above).
|
|
58
|
+
#
|
|
59
|
+
# This class allows us to check all the usage limits once and then not
|
|
60
|
+
# check all of them again (just the ones in the report job) until:
|
|
61
|
+
# 1) A specific alert has expired (24h passed since it was triggered).
|
|
62
|
+
# 2) A new alert bin is enabled for the service.
|
|
63
|
+
class UsagesChecked
|
|
64
|
+
extend KeyHelpers
|
|
65
|
+
extend StorageHelpers
|
|
66
|
+
include Memoizer::Decorator
|
|
67
|
+
|
|
68
|
+
def self.need_to_check_all?(service_id, app_id)
|
|
69
|
+
!storage.exists(key_usage_already_checked(service_id, app_id))
|
|
70
|
+
end
|
|
71
|
+
memoize :need_to_check_all?
|
|
72
|
+
|
|
73
|
+
def self.mark_all_checked(service_id, app_id)
|
|
74
|
+
ttl = ALERT_BINS.map do |bin|
|
|
75
|
+
ttl = storage.ttl(key_already_notified(service_id, app_id, bin))
|
|
76
|
+
|
|
77
|
+
# Redis returns -2 if key does not exist, and -1 if it exists without
|
|
78
|
+
# a TTL (we know this should not happen for the alert bins).
|
|
79
|
+
# In those cases we should just set the TTL to the max (ALERT_TTL).
|
|
80
|
+
ttl >= 0 ? ttl : ALERT_TTL
|
|
81
|
+
end.min
|
|
82
|
+
|
|
83
|
+
# Setex fails when ttl = 0. Also, if it's 0, we don't need to mark it
|
|
84
|
+
# as checked, because the "already_notified" key for the bin is just
|
|
85
|
+
# about to expire, so we'll need to check all the usages.
|
|
86
|
+
if ttl > 0
|
|
87
|
+
storage.setex(key_usage_already_checked(service_id, app_id), ttl, '1'.freeze)
|
|
88
|
+
Memoizer.clear(Memoizer.build_key(self, :need_to_check_all?, service_id, app_id))
|
|
64
89
|
end
|
|
65
90
|
end
|
|
66
91
|
|
|
67
|
-
|
|
92
|
+
def self.invalidate(service_id, app_id)
|
|
93
|
+
storage.del(key_usage_already_checked(service_id, app_id))
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def self.invalidate_for_service(service_id)
|
|
97
|
+
app_ids = []
|
|
98
|
+
cursor = 0
|
|
99
|
+
|
|
100
|
+
loop do
|
|
101
|
+
cursor, ids = storage.sscan(
|
|
102
|
+
Application.applications_set_key(service_id), cursor, count: SCAN_SLICE
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
app_ids += ids
|
|
68
106
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
107
|
+
break if cursor.to_i == 0
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
invalidate_batch(service_id, app_ids)
|
|
73
111
|
end
|
|
74
112
|
|
|
75
|
-
|
|
113
|
+
def self.invalidate_batch(service_id, app_ids)
|
|
114
|
+
app_ids.each_slice(PIPELINED_SLICE_SIZE) do |ids|
|
|
115
|
+
keys = ids.map { |app_id| key_usage_already_checked(service_id, app_id) }
|
|
116
|
+
storage.del(keys)
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
private_class_method :invalidate_batch
|
|
76
120
|
end
|
|
77
121
|
|
|
78
|
-
def
|
|
79
|
-
|
|
80
|
-
|
|
122
|
+
def can_raise_more_alerts?(service_id, app_id)
|
|
123
|
+
allowed_bins = allowed_set_for_service(service_id).sort
|
|
124
|
+
|
|
125
|
+
return false if allowed_bins.empty?
|
|
81
126
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
127
|
+
# If the bin with the highest value has already been notified, there's
|
|
128
|
+
# no need to notify anything else.
|
|
129
|
+
not notified?(service_id, app_id, allowed_bins.last)
|
|
130
|
+
end
|
|
86
131
|
|
|
87
|
-
|
|
132
|
+
def update_utilization(service_id, app_id, utilization)
|
|
133
|
+
discrete = utilization_discrete(utilization.ratio)
|
|
88
134
|
|
|
89
|
-
|
|
135
|
+
keys = alert_keys(service_id, app_id, discrete)
|
|
136
|
+
|
|
137
|
+
already_alerted, allowed = storage.pipelined do
|
|
90
138
|
storage.get(keys[:already_notified])
|
|
91
139
|
storage.sismember(keys[:allowed], discrete)
|
|
92
|
-
storage.get(keys[:current_max])
|
|
93
|
-
storage.expireat(keys[:current_max], expire_at)
|
|
94
|
-
end
|
|
95
|
-
|
|
96
|
-
## update the status of utilization
|
|
97
|
-
if max_utilization_i > current_max.to_i
|
|
98
|
-
storage.set(keys[:current_max], max_utilization_i)
|
|
99
140
|
end
|
|
100
141
|
|
|
101
142
|
if already_alerted.nil? && allowed && discrete.to_i > 0
|
|
102
|
-
next_id, _ = storage.pipelined do
|
|
143
|
+
next_id, _, _ = storage.pipelined do
|
|
103
144
|
storage.incr(keys[:current_id])
|
|
104
145
|
storage.setex(keys[:already_notified], ALERT_TTL, "1")
|
|
146
|
+
UsagesChecked.invalidate(service_id, app_id)
|
|
105
147
|
end
|
|
106
148
|
|
|
107
149
|
alert = { :id => next_id,
|
|
108
150
|
:utilization => discrete,
|
|
109
|
-
:max_utilization =>
|
|
151
|
+
:max_utilization => utilization.ratio,
|
|
110
152
|
:application_id => app_id,
|
|
111
153
|
:service_id => service_id,
|
|
112
|
-
:timestamp =>
|
|
113
|
-
:limit =>
|
|
154
|
+
:timestamp => Time.now.utc,
|
|
155
|
+
:limit => utilization.to_s }
|
|
114
156
|
|
|
115
157
|
Backend::EventStorage::store(:alert, alert)
|
|
116
158
|
end
|
|
@@ -124,10 +166,15 @@ module ThreeScale
|
|
|
124
166
|
end || FIRST_ALERT_BIN
|
|
125
167
|
end
|
|
126
168
|
|
|
127
|
-
def
|
|
128
|
-
|
|
129
|
-
|
|
169
|
+
def allowed_set_for_service(service_id)
|
|
170
|
+
storage.smembers(key_allowed_set(service_id)).map(&:to_i) # Redis returns strings always
|
|
171
|
+
end
|
|
172
|
+
memoize :allowed_set_for_service
|
|
173
|
+
|
|
174
|
+
def notified?(service_id, app_id, bin)
|
|
175
|
+
storage.get(key_already_notified(service_id, app_id, bin))
|
|
130
176
|
end
|
|
177
|
+
memoize :notified?
|
|
131
178
|
|
|
132
179
|
def storage
|
|
133
180
|
Storage.instance
|
|
@@ -58,7 +58,6 @@ module ThreeScale
|
|
|
58
58
|
config.add_section(:internal_api, :user, :password)
|
|
59
59
|
config.add_section(:master, :metrics)
|
|
60
60
|
config.add_section(:worker_prometheus_metrics, :enabled, :port)
|
|
61
|
-
config.add_section(:listener_prometheus_metrics, :enabled, :port)
|
|
62
61
|
|
|
63
62
|
config.add_section(
|
|
64
63
|
:async_worker,
|
data/lib/3scale/backend/rack.rb
CHANGED
|
@@ -17,7 +17,10 @@ module ThreeScale
|
|
|
17
17
|
|
|
18
18
|
Backend::Logging::External.setup_rack self
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
# Notice that this cannot be specified via config, it needs to be an
|
|
21
|
+
# ENV because the metric server is started in Puma/Falcon
|
|
22
|
+
# "before_fork" and the configuration is not loaded at that point.
|
|
23
|
+
if ENV['CONFIG_LISTENER_PROMETHEUS_METRICS_ENABLED'].to_s.downcase.freeze == 'true'.freeze
|
|
21
24
|
use Rack::Prometheus
|
|
22
25
|
end
|
|
23
26
|
|
|
@@ -4,16 +4,12 @@ module ThreeScale
|
|
|
4
4
|
include Storable
|
|
5
5
|
|
|
6
6
|
# list of attributes to be fetched from storage
|
|
7
|
-
ATTRIBUTES = %i[state referrer_filters_required backend_version
|
|
8
|
-
user_registration_required default_user_plan_id
|
|
9
|
-
default_user_plan_name provider_key].freeze
|
|
7
|
+
ATTRIBUTES = %i[state referrer_filters_required backend_version provider_key].freeze
|
|
10
8
|
private_constant :ATTRIBUTES
|
|
11
9
|
|
|
12
10
|
attr_reader :state
|
|
13
|
-
attr_accessor :provider_key, :id, :backend_version
|
|
14
|
-
|
|
15
|
-
attr_writer :referrer_filters_required, :user_registration_required,
|
|
16
|
-
:default_service
|
|
11
|
+
attr_accessor :provider_key, :id, :backend_version
|
|
12
|
+
attr_writer :referrer_filters_required, :default_service
|
|
17
13
|
|
|
18
14
|
class << self
|
|
19
15
|
include Memoizer::Decorator
|
|
@@ -104,8 +100,6 @@ module ThreeScale
|
|
|
104
100
|
memoize :list
|
|
105
101
|
|
|
106
102
|
def save!(attributes = {})
|
|
107
|
-
massage_set_user_registration_required attributes
|
|
108
|
-
|
|
109
103
|
new(attributes).save!
|
|
110
104
|
end
|
|
111
105
|
|
|
@@ -139,26 +133,10 @@ module ThreeScale
|
|
|
139
133
|
def massage_service_attrs(service_attrs)
|
|
140
134
|
service_attrs[:referrer_filters_required] =
|
|
141
135
|
service_attrs[:referrer_filters_required].to_i > 0
|
|
142
|
-
service_attrs[:user_registration_required] =
|
|
143
|
-
massage_get_user_registration_required(
|
|
144
|
-
service_attrs[:user_registration_required])
|
|
145
136
|
|
|
146
137
|
service_attrs
|
|
147
138
|
end
|
|
148
139
|
|
|
149
|
-
# nil => true, 1 => true, '1' => true, 0 => false, '0' => false
|
|
150
|
-
def massage_get_user_registration_required(value)
|
|
151
|
-
value.nil? ? true : value.to_i > 0
|
|
152
|
-
end
|
|
153
|
-
|
|
154
|
-
def massage_set_user_registration_required(attributes)
|
|
155
|
-
if attributes[:user_registration_required].nil?
|
|
156
|
-
val = storage.get(storage_key(attributes[:id], :user_registration_required))
|
|
157
|
-
attributes[:user_registration_required] =
|
|
158
|
-
(!val.nil? && val.to_i == 0) ? false : true
|
|
159
|
-
end
|
|
160
|
-
end
|
|
161
|
-
|
|
162
140
|
def get_attr(id, attribute)
|
|
163
141
|
storage.get(storage_key(id, attribute))
|
|
164
142
|
end
|
|
@@ -195,10 +173,6 @@ module ThreeScale
|
|
|
195
173
|
@referrer_filters_required
|
|
196
174
|
end
|
|
197
175
|
|
|
198
|
-
def user_registration_required?
|
|
199
|
-
@user_registration_required
|
|
200
|
-
end
|
|
201
|
-
|
|
202
176
|
def save!
|
|
203
177
|
set_as_default_if_needed
|
|
204
178
|
persist
|
|
@@ -227,9 +201,6 @@ module ThreeScale
|
|
|
227
201
|
provider_key: provider_key,
|
|
228
202
|
backend_version: backend_version,
|
|
229
203
|
referrer_filters_required: referrer_filters_required?,
|
|
230
|
-
user_registration_required: user_registration_required?,
|
|
231
|
-
default_user_plan_id: default_user_plan_id,
|
|
232
|
-
default_user_plan_name: default_user_plan_name,
|
|
233
204
|
default_service: default_service?
|
|
234
205
|
}
|
|
235
206
|
end
|
|
@@ -294,9 +265,6 @@ module ThreeScale
|
|
|
294
265
|
|
|
295
266
|
def persist_attributes
|
|
296
267
|
persist_attribute :referrer_filters_required, referrer_filters_required? ? 1 : 0
|
|
297
|
-
persist_attribute :user_registration_required, user_registration_required? ? 1 : 0
|
|
298
|
-
persist_attribute :default_user_plan_id, default_user_plan_id, true
|
|
299
|
-
persist_attribute :default_user_plan_name, default_user_plan_name, true
|
|
300
268
|
persist_attribute :backend_version, backend_version, true
|
|
301
269
|
persist_attribute :provider_key, provider_key
|
|
302
270
|
persist_attribute :state, state.to_s if state
|
|
@@ -59,7 +59,7 @@ module ThreeScale
|
|
|
59
59
|
touched_apps = aggregate(transactions, current_bucket)
|
|
60
60
|
|
|
61
61
|
ApplicationEvents.generate(touched_apps.values)
|
|
62
|
-
update_alerts(
|
|
62
|
+
update_alerts(transactions)
|
|
63
63
|
begin
|
|
64
64
|
ApplicationEvents.ping
|
|
65
65
|
rescue ApplicationEvents::PingFailed => e
|
|
@@ -137,29 +137,35 @@ module ThreeScale
|
|
|
137
137
|
logger.info(MAX_BUCKETS_CREATED_MSG)
|
|
138
138
|
end
|
|
139
139
|
|
|
140
|
-
def update_alerts(
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
140
|
+
def update_alerts(transactions)
|
|
141
|
+
transactions.group_by { |tx| tx.application_id }.each do |app_id, txs|
|
|
142
|
+
service_id = txs.first.service_id # All the txs of an app belong to the same service
|
|
143
|
+
|
|
144
|
+
# Finding the max utilization can be costly because it involves
|
|
145
|
+
# loading usage limits and current usages. That's why before that,
|
|
146
|
+
# we check if there are any alerts that can be raised.
|
|
147
|
+
next unless Alerts.can_raise_more_alerts?(service_id, app_id)
|
|
148
|
+
|
|
149
|
+
begin
|
|
150
|
+
max_utilization = if Alerts::UsagesChecked.need_to_check_all?(service_id, app_id)
|
|
151
|
+
Utilization.max_in_all_metrics(service_id, app_id).tap do
|
|
152
|
+
Alerts::UsagesChecked.mark_all_checked(service_id, app_id)
|
|
153
|
+
end
|
|
154
|
+
else
|
|
155
|
+
# metrics_ids here includes the metrics
|
|
156
|
+
# explicitly reported plus their parents in
|
|
157
|
+
# the hierarchy.
|
|
158
|
+
metric_ids = txs.map { |tx| tx.usage.keys }.flatten.uniq
|
|
159
|
+
Utilization.max_in_metrics(service_id, app_id, metric_ids)
|
|
160
|
+
end
|
|
161
|
+
rescue ApplicationNotFound
|
|
162
|
+
# The app could have been deleted at some point since the job
|
|
163
|
+
# was enqueued. No need to update alerts in that case.
|
|
164
|
+
next
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
if max_utilization && max_utilization.ratio > 0
|
|
168
|
+
Alerts.update_utilization(service_id, app_id, max_utilization)
|
|
163
169
|
end
|
|
164
170
|
end
|
|
165
171
|
end
|
|
@@ -36,12 +36,6 @@ module ThreeScale
|
|
|
36
36
|
KEY_SERVICES_TO_DELETE = 'set_with_services_marked_for_deletion'.freeze
|
|
37
37
|
private_constant :KEY_SERVICES_TO_DELETE
|
|
38
38
|
|
|
39
|
-
SLEEP_BETWEEN_SCANS = 0.01 # In seconds
|
|
40
|
-
private_constant :SLEEP_BETWEEN_SCANS
|
|
41
|
-
|
|
42
|
-
SCAN_SLICE = 500
|
|
43
|
-
private_constant :SCAN_SLICE
|
|
44
|
-
|
|
45
39
|
STATS_KEY_PREFIX = 'stats/'.freeze
|
|
46
40
|
private_constant :STATS_KEY_PREFIX
|
|
47
41
|
|
|
@@ -61,6 +61,8 @@ module ThreeScale
|
|
|
61
61
|
|
|
62
62
|
def validate(oauth, provider_key, report_usage, params, request_info)
|
|
63
63
|
service = Service.load_with_provider_key!(params[:service_id], provider_key)
|
|
64
|
+
oidc_service = !oauth && service.backend_version == 'oauth'.freeze
|
|
65
|
+
|
|
64
66
|
# service_id cannot be taken from params since it might be missing there
|
|
65
67
|
service_id = service.id
|
|
66
68
|
|
|
@@ -70,12 +72,18 @@ module ThreeScale
|
|
|
70
72
|
# significant.
|
|
71
73
|
params[:app_id] = nil if app_id && app_id.empty?
|
|
72
74
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
75
|
+
# While OIDC without an app_id makes little sense, we would break existing
|
|
76
|
+
# behaviour when calling non oauth_auth*.xml endpoints if we returned an
|
|
77
|
+
# error here, so only do this for oauth_auth*.xml endpoints.
|
|
78
|
+
raise ApplicationNotFound.new nil if oauth && app_id.nil?
|
|
79
|
+
|
|
80
|
+
validators = if oidc_service
|
|
81
|
+
Validators::OIDC_VALIDATORS
|
|
82
|
+
elsif oauth
|
|
83
|
+
Validators::OAUTH_VALIDATORS
|
|
84
|
+
else
|
|
85
|
+
Validators::VALIDATORS
|
|
86
|
+
end
|
|
79
87
|
|
|
80
88
|
params[:user_key] = nil if params[:user_key] && params[:user_key].empty?
|
|
81
89
|
application = Application.load_by_id_or_user_key!(service_id,
|
|
@@ -98,8 +106,9 @@ module ThreeScale
|
|
|
98
106
|
# hierarchy parameter adds information in the response needed
|
|
99
107
|
# to derive which limits affect directly or indirectly the
|
|
100
108
|
# metrics for which authorization is requested.
|
|
101
|
-
hierarchy: extensions[:hierarchy] == '1',
|
|
102
|
-
flat_usage: extensions[:flat_usage] == '1'
|
|
109
|
+
hierarchy: extensions[:hierarchy] == '1'.freeze,
|
|
110
|
+
flat_usage: extensions[:flat_usage] == '1'.freeze,
|
|
111
|
+
list_app_keys: extensions[:list_app_keys] == '1'.freeze
|
|
103
112
|
}
|
|
104
113
|
|
|
105
114
|
application.load_metric_names
|
|
@@ -108,24 +117,6 @@ module ThreeScale
|
|
|
108
117
|
apply_validators(validators, status_attrs, params)
|
|
109
118
|
end
|
|
110
119
|
|
|
111
|
-
def get_token_ids(token, service_id, app_id)
|
|
112
|
-
begin
|
|
113
|
-
token_aid = OAuth::Token::Storage.get_credentials(token, service_id)
|
|
114
|
-
rescue AccessTokenInvalid => e
|
|
115
|
-
# Yep, well, er. Someone specified that it is OK to have an
|
|
116
|
-
# invalid token if an app_id is specified. Somehow passing in
|
|
117
|
-
# a user_key is still not enough, though...
|
|
118
|
-
raise e if app_id.nil?
|
|
119
|
-
end
|
|
120
|
-
|
|
121
|
-
# We only take the token ids into account if we had no parameter ids
|
|
122
|
-
if app_id.nil?
|
|
123
|
-
app_id = token_aid
|
|
124
|
-
end
|
|
125
|
-
|
|
126
|
-
app_id
|
|
127
|
-
end
|
|
128
|
-
|
|
129
120
|
def do_authorize(method, provider_key, params, context_info)
|
|
130
121
|
notify_authorize(provider_key)
|
|
131
122
|
validate(method == :oauth_authorize, provider_key, false, params, context_info[:request])
|
|
@@ -8,17 +8,23 @@ module ThreeScale
|
|
|
8
8
|
# We only use 'redirect_uri' if a request sent such a param. See #397.
|
|
9
9
|
REDIRECT_URI_FIELD = 'redirect_url'.freeze
|
|
10
10
|
private_constant :REDIRECT_URI_FIELD
|
|
11
|
+
# Maximum number of keys to list when using the list_app_keys extension
|
|
12
|
+
# At the time of writing System/Porta has a limit of 5 different app_keys
|
|
13
|
+
# at any given moment, but this could change anytime.
|
|
14
|
+
LIST_APP_KEYS_MAX = 256
|
|
15
|
+
private_constant :LIST_APP_KEYS_MAX
|
|
11
16
|
|
|
12
17
|
def initialize(attributes)
|
|
13
|
-
@service_id
|
|
14
|
-
@application
|
|
15
|
-
@oauth
|
|
16
|
-
@usage
|
|
17
|
-
@predicted_usage
|
|
18
|
-
@values
|
|
19
|
-
@timestamp
|
|
20
|
-
@hierarchy_ext
|
|
21
|
-
@flat_usage_ext
|
|
18
|
+
@service_id = attributes[:service_id]
|
|
19
|
+
@application = attributes[:application]
|
|
20
|
+
@oauth = attributes[:oauth]
|
|
21
|
+
@usage = attributes[:usage]
|
|
22
|
+
@predicted_usage = attributes[:predicted_usage]
|
|
23
|
+
@values = filter_values(attributes[:values] || {})
|
|
24
|
+
@timestamp = attributes[:timestamp] || Time.now.getutc
|
|
25
|
+
@hierarchy_ext = attributes[:hierarchy]
|
|
26
|
+
@flat_usage_ext = attributes[:flat_usage]
|
|
27
|
+
@list_app_keys_ext = attributes[:list_app_keys]
|
|
22
28
|
|
|
23
29
|
raise 'service_id not specified' if @service_id.nil?
|
|
24
30
|
raise ':application is required' if @application.nil?
|
|
@@ -106,6 +112,7 @@ module ThreeScale
|
|
|
106
112
|
add_plan_section(xml, 'plan'.freeze, plan_name)
|
|
107
113
|
add_reports_section(xml, application_usage_reports)
|
|
108
114
|
hierarchy_reports.concat application_usage_reports if hierarchy_reports
|
|
115
|
+
add_app_keys_section xml if @list_app_keys_ext
|
|
109
116
|
end
|
|
110
117
|
|
|
111
118
|
if hierarchy_reports
|
|
@@ -161,6 +168,17 @@ module ThreeScale
|
|
|
161
168
|
xml << '</hierarchy>'.freeze
|
|
162
169
|
end
|
|
163
170
|
|
|
171
|
+
def add_app_keys_section(xml)
|
|
172
|
+
xml << '<app_keys app="'.freeze
|
|
173
|
+
xml << @application.id << '" svc="'.freeze
|
|
174
|
+
xml << @service_id << '">'.freeze
|
|
175
|
+
@application.keys.take(LIST_APP_KEYS_MAX).each do |key|
|
|
176
|
+
xml << '<key id="'.freeze
|
|
177
|
+
xml << key << '"/>'.freeze
|
|
178
|
+
end
|
|
179
|
+
xml << '</app_keys>'.freeze
|
|
180
|
+
end
|
|
181
|
+
|
|
164
182
|
# helper to iterate over reports and get relevant hierarchy info
|
|
165
183
|
def with_report_and_hierarchy(reports)
|
|
166
184
|
reports.each do |ur|
|
data/lib/3scale/backend/usage.rb
CHANGED
|
@@ -3,12 +3,19 @@ module ThreeScale
|
|
|
3
3
|
class Usage
|
|
4
4
|
class << self
|
|
5
5
|
def application_usage(application, timestamp)
|
|
6
|
-
usage(application, timestamp) do |metric_id, instance_period|
|
|
6
|
+
usage(application.usage_limits, timestamp) do |metric_id, instance_period|
|
|
7
7
|
Stats::Keys.application_usage_value_key(
|
|
8
8
|
application.service_id, application.id, metric_id, instance_period)
|
|
9
9
|
end
|
|
10
10
|
end
|
|
11
11
|
|
|
12
|
+
def application_usage_for_limits(application, timestamp, usage_limits)
|
|
13
|
+
usage(usage_limits, timestamp) do |metric_id, instance_period|
|
|
14
|
+
Stats::Keys.application_usage_value_key(
|
|
15
|
+
application.service_id, application.id, metric_id, instance_period)
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
12
19
|
def is_set?(usage_str)
|
|
13
20
|
usage_str && usage_str[0] == '#'.freeze
|
|
14
21
|
end
|
|
@@ -25,7 +32,7 @@ module ThreeScale
|
|
|
25
32
|
|
|
26
33
|
private
|
|
27
34
|
|
|
28
|
-
def usage(
|
|
35
|
+
def usage(usage_limits, timestamp)
|
|
29
36
|
# The timestamp does not change, so we can generate all the
|
|
30
37
|
# instantiated periods just once.
|
|
31
38
|
# This is important. Without this, the code can generate many instance
|
|
@@ -33,7 +40,7 @@ module ThreeScale
|
|
|
33
40
|
# time.
|
|
34
41
|
instance_periods = Period::instance_periods_for_ts(timestamp)
|
|
35
42
|
|
|
36
|
-
pairs = metric_period_pairs
|
|
43
|
+
pairs = metric_period_pairs usage_limits
|
|
37
44
|
return {} if pairs.empty?
|
|
38
45
|
|
|
39
46
|
keys = pairs.map do |(metric_id, period)|
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
module ThreeScale
|
|
2
|
+
module Backend
|
|
3
|
+
class Utilization
|
|
4
|
+
include Comparable
|
|
5
|
+
|
|
6
|
+
attr_reader :metric_id, :period, :max_value, :current_value
|
|
7
|
+
|
|
8
|
+
def initialize(limit, current_value)
|
|
9
|
+
@metric_id = limit.metric_id
|
|
10
|
+
@period = limit.period
|
|
11
|
+
@max_value = limit.value
|
|
12
|
+
@current_value = current_value
|
|
13
|
+
@encoded = encoded(limit, current_value)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def ratio
|
|
17
|
+
return 0 if max_value == 0 # Disabled metric
|
|
18
|
+
current_value/max_value.to_f
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# Returns in the format needed by the Alerts class.
|
|
22
|
+
def to_s
|
|
23
|
+
@encoded
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def <=>(other)
|
|
27
|
+
# Consider "disabled" the lowest ones
|
|
28
|
+
if ratio == 0 && other.ratio == 0
|
|
29
|
+
return max_value <=> other.max_value
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
ratio <=> other.ratio
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# Note: this can return nil
|
|
36
|
+
def self.max_in_all_metrics(service_id, app_id)
|
|
37
|
+
application = Backend::Application.load!(service_id, app_id)
|
|
38
|
+
|
|
39
|
+
usage = Usage.application_usage(application, Time.now.getutc)
|
|
40
|
+
|
|
41
|
+
status = Transactor::Status.new(service_id: service_id,
|
|
42
|
+
application: application,
|
|
43
|
+
values: usage)
|
|
44
|
+
|
|
45
|
+
# Preloads all the metric names to avoid fetching them one by one when
|
|
46
|
+
# generating the usage reports
|
|
47
|
+
application.load_metric_names
|
|
48
|
+
|
|
49
|
+
max = status.application_usage_reports.map do |usage_report|
|
|
50
|
+
Utilization.new(usage_report.usage_limit, usage_report.current_value)
|
|
51
|
+
end.max
|
|
52
|
+
|
|
53
|
+
# Avoid returning a utilization for disabled metrics
|
|
54
|
+
max && max.max_value > 0 ? max : nil
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# Note: this can return nil
|
|
58
|
+
def self.max_in_metrics(service_id, app_id, metric_ids)
|
|
59
|
+
application = Backend::Application.load!(service_id, app_id)
|
|
60
|
+
|
|
61
|
+
limits = UsageLimit.load_for_affecting_metrics(
|
|
62
|
+
service_id, application.plan_id, metric_ids
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
usage = Usage.application_usage_for_limits(application, Time.now.getutc, limits)
|
|
66
|
+
|
|
67
|
+
max = limits.map do |limit|
|
|
68
|
+
Utilization.new(limit, usage[limit.period][limit.metric_id])
|
|
69
|
+
end.max
|
|
70
|
+
|
|
71
|
+
# Avoid returning a utilization for disabled metrics
|
|
72
|
+
max && max.max_value > 0 ? max : nil
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
private
|
|
76
|
+
|
|
77
|
+
def encoded(limit, current_value)
|
|
78
|
+
metric_name = Metric.load_name(limit.service_id, limit.metric_id)
|
|
79
|
+
"#{metric_name} per #{limit.period}: #{current_value}/#{limit.value}"
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
@@ -21,6 +21,13 @@ module ThreeScale
|
|
|
21
21
|
OAUTH_VALIDATORS = ([Validators::OauthSetting,
|
|
22
22
|
Validators::OauthKey,
|
|
23
23
|
Validators::RedirectURI] + COMMON_VALIDATORS).freeze
|
|
24
|
+
|
|
25
|
+
# OIDC specific validators will only check app keys when app_key is given.
|
|
26
|
+
#
|
|
27
|
+
# No need to add OauthSetting, since we need to check that to tell
|
|
28
|
+
# OIDC apart from the rest when calling authrep.xml (note lack of
|
|
29
|
+
# the oauth_ prefix).
|
|
30
|
+
OIDC_VALIDATORS = ([Validators::OauthKey] + COMMON_VALIDATORS).freeze
|
|
24
31
|
end
|
|
25
32
|
end
|
|
26
33
|
end
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
require_relative '../3scale/backend/listener_metrics'
|
|
5
5
|
|
|
6
6
|
# Config is not loaded at this point, so read ENV instead.
|
|
7
|
-
if ENV['CONFIG_LISTENER_PROMETHEUS_METRICS_ENABLED'].to_s == 'true'
|
|
7
|
+
if ENV['CONFIG_LISTENER_PROMETHEUS_METRICS_ENABLED'].to_s.downcase.freeze == 'true'.freeze
|
|
8
8
|
prometheus_port = ENV['CONFIG_LISTENER_PROMETHEUS_METRICS_PORT']
|
|
9
9
|
ThreeScale::Backend::ListenerMetrics.start_metrics_server(prometheus_port)
|
|
10
10
|
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.4.2</version>
|
|
27
27
|
<licenses>
|
|
28
28
|
<license>
|
|
29
29
|
<name>Apache 2.0</name>
|
|
@@ -233,7 +233,7 @@
|
|
|
233
233
|
</dependency>
|
|
234
234
|
<dependency>
|
|
235
235
|
<packageName>coderay</packageName>
|
|
236
|
-
<version>1.1.
|
|
236
|
+
<version>1.1.3</version>
|
|
237
237
|
<licenses>
|
|
238
238
|
<license>
|
|
239
239
|
<name>MIT</name>
|
|
@@ -421,7 +421,7 @@
|
|
|
421
421
|
</dependency>
|
|
422
422
|
<dependency>
|
|
423
423
|
<packageName>method_source</packageName>
|
|
424
|
-
<version>0.
|
|
424
|
+
<version>1.0.0</version>
|
|
425
425
|
<licenses>
|
|
426
426
|
<license>
|
|
427
427
|
<name>MIT</name>
|
|
@@ -475,7 +475,7 @@
|
|
|
475
475
|
</dependency>
|
|
476
476
|
<dependency>
|
|
477
477
|
<packageName>multi_json</packageName>
|
|
478
|
-
<version>1.
|
|
478
|
+
<version>1.15.0</version>
|
|
479
479
|
<licenses>
|
|
480
480
|
<license>
|
|
481
481
|
<name>MIT</name>
|
|
@@ -679,7 +679,7 @@
|
|
|
679
679
|
</dependency>
|
|
680
680
|
<dependency>
|
|
681
681
|
<packageName>pry</packageName>
|
|
682
|
-
<version>0.
|
|
682
|
+
<version>0.14.0</version>
|
|
683
683
|
<licenses>
|
|
684
684
|
<license>
|
|
685
685
|
<name>MIT</name>
|
|
@@ -699,7 +699,7 @@
|
|
|
699
699
|
</dependency>
|
|
700
700
|
<dependency>
|
|
701
701
|
<packageName>pry-doc</packageName>
|
|
702
|
-
<version>
|
|
702
|
+
<version>1.1.0</version>
|
|
703
703
|
<licenses>
|
|
704
704
|
<license>
|
|
705
705
|
<name>MIT</name>
|
|
@@ -1143,7 +1143,7 @@
|
|
|
1143
1143
|
</dependency>
|
|
1144
1144
|
<dependency>
|
|
1145
1145
|
<packageName>yard</packageName>
|
|
1146
|
-
<version>0.9.
|
|
1146
|
+
<version>0.9.26</version>
|
|
1147
1147
|
<licenses>
|
|
1148
1148
|
<license>
|
|
1149
1149
|
<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.4.2
|
|
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: 2021-
|
|
19
|
+
date: 2021-06-17 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.
|
|
@@ -164,6 +164,7 @@ files:
|
|
|
164
164
|
- lib/3scale/backend/usage_limit.rb
|
|
165
165
|
- lib/3scale/backend/use_cases/provider_key_change_use_case.rb
|
|
166
166
|
- lib/3scale/backend/util.rb
|
|
167
|
+
- lib/3scale/backend/utilization.rb
|
|
167
168
|
- lib/3scale/backend/validators.rb
|
|
168
169
|
- lib/3scale/backend/validators/base.rb
|
|
169
170
|
- lib/3scale/backend/validators/key.rb
|
|
@@ -207,8 +208,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
207
208
|
- !ruby/object:Gem::Version
|
|
208
209
|
version: 1.3.7
|
|
209
210
|
requirements: []
|
|
210
|
-
|
|
211
|
-
rubygems_version: 2.7.8
|
|
211
|
+
rubygems_version: 3.2.10
|
|
212
212
|
signing_key:
|
|
213
213
|
specification_version: 4
|
|
214
214
|
summary: 3scale web service management system backend
|