apisonator 3.3.0 → 3.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +68 -0
- data/Gemfile.base +8 -4
- data/Gemfile.lock +18 -17
- data/Gemfile.on_prem.lock +18 -17
- data/app/api/internal/stats.rb +6 -25
- data/lib/3scale/backend/alert_limit.rb +5 -11
- data/lib/3scale/backend/alerts.rb +24 -22
- data/lib/3scale/backend/configuration.rb +1 -7
- data/lib/3scale/backend/errors.rb +0 -6
- data/lib/3scale/backend/rack.rb +4 -1
- data/lib/3scale/backend/service.rb +3 -35
- data/lib/3scale/backend/stats.rb +0 -4
- data/lib/3scale/backend/stats/aggregator.rb +10 -0
- data/lib/3scale/backend/stats/aggregators/base.rb +8 -1
- data/lib/3scale/backend/stats/period_commons.rb +0 -3
- data/lib/3scale/backend/transactor.rb +17 -26
- data/lib/3scale/backend/transactor/status.rb +27 -9
- 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 +8 -8
- metadata +3 -8
- data/lib/3scale/backend/stats/delete_job_def.rb +0 -60
- data/lib/3scale/backend/stats/key_generator.rb +0 -73
- data/lib/3scale/backend/stats/partition_eraser_job.rb +0 -58
- data/lib/3scale/backend/stats/partition_generator_job.rb +0 -46
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7a260bc57e82268c54885b58a12c79d28c9b7c53f8fb5e48182c887488888184
|
4
|
+
data.tar.gz: 7dbed84c520c06e914d15e99f6e1b78365a1b695d8cf8e1fd66a58c02fa36fa9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4d0bdd90d90972bc416faf04a852ff56c3895da1cb191b264617f71add2f22c5942d928d85c9877faceab4f00e7fe26955dfeed7c6cbc615a8fe555b7c6e251a
|
7
|
+
data.tar.gz: 22b6dbdb74d73117ba7358d231b5f747f54746687e452285b77883df4b352d20d59b3997b38a0c5c7b6cba9bce618b41900d6a0ee3ea1e169727470bce8158cb
|
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.0 - 2021-06-14
|
6
|
+
|
7
|
+
### Added
|
8
|
+
|
9
|
+
- New extension that list the keys of an application
|
10
|
+
([#284](https://github.com/3scale/apisonator/pull/284)).
|
11
|
+
|
12
|
+
### Changed
|
13
|
+
|
14
|
+
- It is now possible to use OIDC in the auth and authrep endpoints
|
15
|
+
([#280](https://github.com/3scale/apisonator/pull/280)).
|
16
|
+
- Updated multi-json to 1.15.0
|
17
|
+
([#278](https://github.com/3scale/apisonator/pull/278)).
|
18
|
+
|
19
|
+
### Removed
|
20
|
+
|
21
|
+
- Deleted unused service attributes related with deleted end-users functionality
|
22
|
+
([#277](https://github.com/3scale/apisonator/pull/277)).
|
23
|
+
|
24
|
+
## 3.3.3 - 2021-03-09
|
25
|
+
|
26
|
+
### Changed
|
27
|
+
|
28
|
+
- Check if alerts can be raised before calculating utilization (perf
|
29
|
+
optimization) ([#275](https://github.com/3scale/apisonator/pull/275)).
|
30
|
+
|
31
|
+
### Removed
|
32
|
+
|
33
|
+
- Stop maintaining unused "current_max" key in Alerts
|
34
|
+
([#272](https://github.com/3scale/apisonator/pull/272)).
|
35
|
+
|
36
|
+
## 3.3.2 - 2021-02-23
|
37
|
+
|
38
|
+
### Fixed
|
39
|
+
|
40
|
+
- Fixed nil exception in `Aggregator.process`
|
41
|
+
([#269](https://github.com/3scale/apisonator/pull/269)).
|
42
|
+
|
43
|
+
### Changed
|
44
|
+
|
45
|
+
- Updated to Ruby 2.7 in Docker images
|
46
|
+
([#265](https://github.com/3scale/apisonator/pull/265)) and
|
47
|
+
([#266](https://github.com/3scale/apisonator/pull/266)).
|
48
|
+
- Updated pry to 0.14.0 and pry-doc to 1.1.0
|
49
|
+
([#267](https://github.com/3scale/apisonator/pull/267)).
|
50
|
+
- Updated Docker image to be based on RHEL UBI 8
|
51
|
+
([#268](https://github.com/3scale/apisonator/pull/268)).
|
52
|
+
|
53
|
+
### Removed
|
54
|
+
|
55
|
+
- Removed redundant prometheus config params
|
56
|
+
(`listener_prometheus_metrics.enabled` and `listener_prometheus_metrics.port`)
|
57
|
+
([#270](https://github.com/3scale/apisonator/pull/270)).
|
58
|
+
|
59
|
+
## 3.3.1.1 - 2021-02-12
|
60
|
+
|
61
|
+
### Changed
|
62
|
+
|
63
|
+
- Updated our Puma fork to v4.3.7
|
64
|
+
([#261](https://github.com/3scale/apisonator/pull/261)).
|
65
|
+
|
66
|
+
## 3.3.1 - 2021-02-11
|
67
|
+
|
68
|
+
### Fixed
|
69
|
+
|
70
|
+
- Usages with `#0` (set to 0) no longer generate unnecessary stats keys in Redis
|
71
|
+
([#258](https://github.com/3scale/apisonator/pull/258)).
|
72
|
+
|
5
73
|
## 3.3.0 - 2021-02-09
|
6
74
|
|
7
75
|
### Added
|
data/Gemfile.base
CHANGED
@@ -15,11 +15,15 @@ platform :ruby do
|
|
15
15
|
end
|
16
16
|
|
17
17
|
group :test do
|
18
|
+
# Newer versions of rack-test don't work well with rspec-api-documentation.
|
19
|
+
# See https://github.com/rack/rack-test/pull/223 &
|
20
|
+
# https://github.com/zipmark/rspec_api_documentation/issues/342
|
21
|
+
gem 'rack-test', '= 0.8.2'
|
22
|
+
|
18
23
|
gem 'benchmark-ips', '~> 2.7.2'
|
19
24
|
gem 'mocha', '~> 1.3'
|
20
25
|
gem 'nokogiri', '~> 1.10.8'
|
21
26
|
gem 'pkg-config', '~> 1.1.7'
|
22
|
-
gem 'rack-test', '~> 0.8.2'
|
23
27
|
gem 'resque_unit', '~> 0.4.4', source: 'https://rubygems.org'
|
24
28
|
gem 'test-unit', '~> 3.2.6'
|
25
29
|
gem 'resque_spec', '~> 0.17.0'
|
@@ -32,8 +36,8 @@ end
|
|
32
36
|
group :development do
|
33
37
|
gem 'sshkit'
|
34
38
|
gem 'source2swagger', git: 'https://github.com/3scale/source2swagger', branch: 'backend'
|
35
|
-
gem 'pry', '~> 0.
|
36
|
-
gem 'pry-doc', '~>
|
39
|
+
gem 'pry', '~> 0.14'
|
40
|
+
gem 'pry-doc', '~> 1.1'
|
37
41
|
gem 'license_finder', '~> 5'
|
38
42
|
end
|
39
43
|
|
@@ -42,7 +46,7 @@ group :development, :test do
|
|
42
46
|
end
|
43
47
|
|
44
48
|
# Default server by platform
|
45
|
-
gem 'puma', git: 'https://github.com/3scale/puma',
|
49
|
+
gem 'puma', git: 'https://github.com/3scale/puma', branch: '3scale-4.3.7'
|
46
50
|
# gems required by the runner
|
47
51
|
gem 'gli', '~> 2.16.1', require: nil
|
48
52
|
# Workers
|
data/Gemfile.lock
CHANGED
@@ -1,9 +1,10 @@
|
|
1
1
|
GIT
|
2
2
|
remote: https://github.com/3scale/puma
|
3
|
-
revision:
|
4
|
-
|
3
|
+
revision: c0601d08695839b8ffd0f380e91c3b91c1e8b754
|
4
|
+
branch: 3scale-4.3.7
|
5
5
|
specs:
|
6
|
-
puma (
|
6
|
+
puma (4.3.7)
|
7
|
+
nio4r (~> 2.0)
|
7
8
|
|
8
9
|
GIT
|
9
10
|
remote: https://github.com/3scale/redis-rb
|
@@ -35,7 +36,7 @@ GIT
|
|
35
36
|
PATH
|
36
37
|
remote: .
|
37
38
|
specs:
|
38
|
-
apisonator (3.
|
39
|
+
apisonator (3.4.0)
|
39
40
|
|
40
41
|
GEM
|
41
42
|
remote: https://rubygems.org/
|
@@ -95,7 +96,7 @@ GEM
|
|
95
96
|
chronic (0.10.2)
|
96
97
|
codeclimate-test-reporter (0.6.0)
|
97
98
|
simplecov (>= 0.7.1, < 1.0.0)
|
98
|
-
coderay (1.1.
|
99
|
+
coderay (1.1.3)
|
99
100
|
concurrent-ruby (1.1.6)
|
100
101
|
console (1.8.2)
|
101
102
|
daemons (1.2.4)
|
@@ -130,13 +131,13 @@ GEM
|
|
130
131
|
localhost (1.1.6)
|
131
132
|
mapping (1.1.1)
|
132
133
|
metaclass (0.0.4)
|
133
|
-
method_source (0.
|
134
|
+
method_source (1.0.0)
|
134
135
|
mini_portile2 (2.4.0)
|
135
136
|
minitest (5.14.1)
|
136
137
|
mocha (1.3.0)
|
137
138
|
metaclass (~> 0.0.1)
|
138
139
|
mono_logger (1.1.0)
|
139
|
-
multi_json (1.
|
140
|
+
multi_json (1.15.0)
|
140
141
|
mustache (1.0.5)
|
141
142
|
mustermann (1.0.2)
|
142
143
|
net-scp (1.2.1)
|
@@ -163,15 +164,15 @@ GEM
|
|
163
164
|
protocol-hpack (~> 1.4)
|
164
165
|
protocol-http (~> 0.15)
|
165
166
|
protocol-redis (0.5.0)
|
166
|
-
pry (0.
|
167
|
-
coderay (~> 1.1
|
168
|
-
method_source (~>
|
167
|
+
pry (0.14.0)
|
168
|
+
coderay (~> 1.1)
|
169
|
+
method_source (~> 1.0)
|
169
170
|
pry-byebug (3.5.1)
|
170
171
|
byebug (~> 9.1)
|
171
172
|
pry (~> 0.10)
|
172
|
-
pry-doc (
|
173
|
-
pry (~> 0.
|
174
|
-
yard (~> 0.9)
|
173
|
+
pry-doc (1.1.0)
|
174
|
+
pry (~> 0.11)
|
175
|
+
yard (~> 0.9.11)
|
175
176
|
rack (2.1.4)
|
176
177
|
rack-protection (2.0.3)
|
177
178
|
rack
|
@@ -259,7 +260,7 @@ GEM
|
|
259
260
|
prometheus-client (~> 1.0)
|
260
261
|
yabeda (~> 0.5)
|
261
262
|
yajl-ruby (1.3.1)
|
262
|
-
yard (0.9.
|
263
|
+
yard (0.9.26)
|
263
264
|
|
264
265
|
PLATFORMS
|
265
266
|
ruby
|
@@ -283,12 +284,12 @@ DEPENDENCIES
|
|
283
284
|
nokogiri (~> 1.10.8)
|
284
285
|
pg (= 0.20.0)
|
285
286
|
pkg-config (~> 1.1.7)
|
286
|
-
pry (~> 0.
|
287
|
+
pry (~> 0.14)
|
287
288
|
pry-byebug (~> 3.5.1)
|
288
|
-
pry-doc (~>
|
289
|
+
pry-doc (~> 1.1)
|
289
290
|
puma!
|
290
291
|
rack (~> 2.1.4)
|
291
|
-
rack-test (
|
292
|
+
rack-test (= 0.8.2)
|
292
293
|
rake (~> 13.0)
|
293
294
|
redis!
|
294
295
|
redis-namespace (~> 1.8.0)
|
data/Gemfile.on_prem.lock
CHANGED
@@ -1,9 +1,10 @@
|
|
1
1
|
GIT
|
2
2
|
remote: https://github.com/3scale/puma
|
3
|
-
revision:
|
4
|
-
|
3
|
+
revision: c0601d08695839b8ffd0f380e91c3b91c1e8b754
|
4
|
+
branch: 3scale-4.3.7
|
5
5
|
specs:
|
6
|
-
puma (
|
6
|
+
puma (4.3.7)
|
7
|
+
nio4r (~> 2.0)
|
7
8
|
|
8
9
|
GIT
|
9
10
|
remote: https://github.com/3scale/redis-rb
|
@@ -35,7 +36,7 @@ GIT
|
|
35
36
|
PATH
|
36
37
|
remote: .
|
37
38
|
specs:
|
38
|
-
apisonator (3.
|
39
|
+
apisonator (3.4.0)
|
39
40
|
|
40
41
|
GEM
|
41
42
|
remote: https://rubygems.org/
|
@@ -85,7 +86,7 @@ GEM
|
|
85
86
|
byebug (9.1.0)
|
86
87
|
codeclimate-test-reporter (0.6.0)
|
87
88
|
simplecov (>= 0.7.1, < 1.0.0)
|
88
|
-
coderay (1.1.
|
89
|
+
coderay (1.1.3)
|
89
90
|
concurrent-ruby (1.1.6)
|
90
91
|
console (1.8.2)
|
91
92
|
daemons (1.2.4)
|
@@ -119,13 +120,13 @@ GEM
|
|
119
120
|
localhost (1.1.6)
|
120
121
|
mapping (1.1.1)
|
121
122
|
metaclass (0.0.4)
|
122
|
-
method_source (0.
|
123
|
+
method_source (1.0.0)
|
123
124
|
mini_portile2 (2.4.0)
|
124
125
|
minitest (5.14.1)
|
125
126
|
mocha (1.3.0)
|
126
127
|
metaclass (~> 0.0.1)
|
127
128
|
mono_logger (1.1.0)
|
128
|
-
multi_json (1.
|
129
|
+
multi_json (1.15.0)
|
129
130
|
mustache (1.0.5)
|
130
131
|
mustermann (1.0.2)
|
131
132
|
net-scp (1.2.1)
|
@@ -151,15 +152,15 @@ GEM
|
|
151
152
|
protocol-hpack (~> 1.4)
|
152
153
|
protocol-http (~> 0.15)
|
153
154
|
protocol-redis (0.5.0)
|
154
|
-
pry (0.
|
155
|
-
coderay (~> 1.1
|
156
|
-
method_source (~>
|
155
|
+
pry (0.14.0)
|
156
|
+
coderay (~> 1.1)
|
157
|
+
method_source (~> 1.0)
|
157
158
|
pry-byebug (3.5.1)
|
158
159
|
byebug (~> 9.1)
|
159
160
|
pry (~> 0.10)
|
160
|
-
pry-doc (
|
161
|
-
pry (~> 0.
|
162
|
-
yard (~> 0.9)
|
161
|
+
pry-doc (1.1.0)
|
162
|
+
pry (~> 0.11)
|
163
|
+
yard (~> 0.9.11)
|
163
164
|
rack (2.1.4)
|
164
165
|
rack-protection (2.0.3)
|
165
166
|
rack
|
@@ -243,7 +244,7 @@ GEM
|
|
243
244
|
prometheus-client (~> 1.0)
|
244
245
|
yabeda (~> 0.5)
|
245
246
|
yajl-ruby (1.3.1)
|
246
|
-
yard (0.9.
|
247
|
+
yard (0.9.26)
|
247
248
|
|
248
249
|
PLATFORMS
|
249
250
|
ruby
|
@@ -264,12 +265,12 @@ DEPENDENCIES
|
|
264
265
|
mocha (~> 1.3)
|
265
266
|
nokogiri (~> 1.10.8)
|
266
267
|
pkg-config (~> 1.1.7)
|
267
|
-
pry (~> 0.
|
268
|
+
pry (~> 0.14)
|
268
269
|
pry-byebug (~> 3.5.1)
|
269
|
-
pry-doc (~>
|
270
|
+
pry-doc (~> 1.1)
|
270
271
|
puma!
|
271
272
|
rack (~> 2.1.4)
|
272
|
-
rack-test (
|
273
|
+
rack-test (= 0.8.2)
|
273
274
|
rake (~> 13.0)
|
274
275
|
redis!
|
275
276
|
redis-namespace (~> 1.8.0)
|
data/app/api/internal/stats.rb
CHANGED
@@ -6,32 +6,13 @@ module ThreeScale
|
|
6
6
|
respond_with_404('service not found') unless Service.exists?(params[:service_id])
|
7
7
|
end
|
8
8
|
|
9
|
-
# This
|
10
|
-
#
|
11
|
-
|
12
|
-
delete '' do |service_id|
|
13
|
-
delete_stats_job_attrs = api_params Stats::DeleteJobDef
|
14
|
-
delete_stats_job_attrs[:service_id] = service_id
|
15
|
-
delete_stats_job_attrs[:from] = delete_stats_job_attrs[:from].to_i
|
16
|
-
delete_stats_job_attrs[:to] = delete_stats_job_attrs[:to].to_i
|
17
|
-
begin
|
18
|
-
Stats::DeleteJobDef.new(delete_stats_job_attrs).run_async
|
19
|
-
rescue DeleteServiceStatsValidationError => e
|
20
|
-
[400, headers, { status: :error, error: e.message }.to_json]
|
21
|
-
else
|
22
|
-
{ status: :to_be_deleted }.to_json
|
23
|
-
end
|
24
|
-
=end
|
25
|
-
|
26
|
-
# This is an alternative to the above. It just adds the service to a
|
27
|
-
# Redis set to marked is as "to be deleted".
|
28
|
-
# Later a script can read that set and actually delete the keys.
|
29
|
-
# Read the docs of the Stats::Cleaner class for more details.
|
9
|
+
# This adds the service to a Redis set to mark is as "to be deleted".
|
10
|
+
# Later a script can read that set and actually delete the keys. Read
|
11
|
+
# the docs of the Stats::Cleaner class for more details.
|
30
12
|
#
|
31
|
-
# Notice that this method ignores the "from" and "to" parameters
|
32
|
-
# system calls this method, they're always
|
33
|
-
#
|
34
|
-
# implementation of the option above easier.
|
13
|
+
# Notice that this method ignores the "from" and "to" parameters used in
|
14
|
+
# previous versions. When system calls this method, they're always
|
15
|
+
# interested in deleting all the keys.
|
35
16
|
delete '' do |service_id|
|
36
17
|
Stats::Cleaner.mark_service_to_be_deleted(service_id)
|
37
18
|
{ status: :to_be_deleted }.to_json
|
@@ -1,21 +1,15 @@
|
|
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
|
-
storage.sadd(
|
12
|
+
storage.sadd(key_allowed_set(service_id), value.to_i) if valid?
|
19
13
|
end
|
20
14
|
|
21
15
|
def to_hash
|
@@ -26,7 +20,7 @@ module ThreeScale
|
|
26
20
|
end
|
27
21
|
|
28
22
|
def self.load_all(service_id)
|
29
|
-
values = storage.smembers(
|
23
|
+
values = storage.smembers(key_allowed_set(service_id))
|
30
24
|
values.map do |value|
|
31
25
|
new(service_id: service_id, value: value.to_i)
|
32
26
|
end
|
@@ -38,7 +32,7 @@ module ThreeScale
|
|
38
32
|
end
|
39
33
|
|
40
34
|
def self.delete(service_id, value)
|
41
|
-
storage.srem(
|
35
|
+
storage.srem(key_allowed_set(service_id), value.to_i) if valid_value?(value)
|
42
36
|
end
|
43
37
|
|
44
38
|
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,11 +30,6 @@ 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
|
@@ -43,6 +37,7 @@ module ThreeScale
|
|
43
37
|
|
44
38
|
extend self
|
45
39
|
extend KeyHelpers
|
40
|
+
include Memoizer::Decorator
|
46
41
|
|
47
42
|
ALERT_TTL = 24*3600 # 1 day (only one message per day)
|
48
43
|
## zero must be here and sorted, yes or yes
|
@@ -50,6 +45,16 @@ module ThreeScale
|
|
50
45
|
FIRST_ALERT_BIN = ALERT_BINS.first
|
51
46
|
RALERT_BINS = ALERT_BINS.reverse.freeze
|
52
47
|
|
48
|
+
def can_raise_more_alerts?(service_id, app_id)
|
49
|
+
allowed_bins = allowed_set_for_service(service_id).sort
|
50
|
+
|
51
|
+
return false if allowed_bins.empty?
|
52
|
+
|
53
|
+
# If the bin with the highest value has already been notified, there's
|
54
|
+
# no need to notify anything else.
|
55
|
+
not notified?(service_id, app_id, allowed_bins.last)
|
56
|
+
end
|
57
|
+
|
53
58
|
def utilization(app_usage_reports)
|
54
59
|
max_utilization = -1.0
|
55
60
|
max_record = nil
|
@@ -77,25 +82,12 @@ module ThreeScale
|
|
77
82
|
|
78
83
|
def update_utilization(service_id, app_id, max_utilization, max_record, timestamp)
|
79
84
|
discrete = utilization_discrete(max_utilization)
|
80
|
-
max_utilization_i = (max_utilization * 100.0).round
|
81
85
|
|
82
|
-
|
83
|
-
period_hour = Period::Boundary.hour_start(timestamp).to_compact_s
|
84
|
-
# UNIX timestamp for key expiration - add 1 day + 5 mins
|
85
|
-
expire_at = (beginning_of_day + 86700).to_i
|
86
|
+
keys = alert_keys(service_id, app_id, discrete)
|
86
87
|
|
87
|
-
|
88
|
-
|
89
|
-
already_alerted, allowed, current_max, _ = storage.pipelined do
|
88
|
+
already_alerted, allowed = storage.pipelined do
|
90
89
|
storage.get(keys[:already_notified])
|
91
90
|
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
91
|
end
|
100
92
|
|
101
93
|
if already_alerted.nil? && allowed && discrete.to_i > 0
|
@@ -129,6 +121,16 @@ module ThreeScale
|
|
129
121
|
"#{record.current_value}/#{record.max_value}"
|
130
122
|
end
|
131
123
|
|
124
|
+
def allowed_set_for_service(service_id)
|
125
|
+
storage.smembers(key_allowed_set(service_id)).map(&:to_i) # Redis returns strings always
|
126
|
+
end
|
127
|
+
memoize :allowed_set_for_service
|
128
|
+
|
129
|
+
def notified?(service_id, app_id, bin)
|
130
|
+
storage.get(key_already_notified(service_id, app_id, bin))
|
131
|
+
end
|
132
|
+
memoize :notified?
|
133
|
+
|
132
134
|
def storage
|
133
135
|
Storage.instance
|
134
136
|
end
|
@@ -32,8 +32,6 @@ module ThreeScale
|
|
32
32
|
|
33
33
|
CONFIG_DELETE_STATS_BATCH_SIZE = 50
|
34
34
|
private_constant :CONFIG_DELETE_STATS_BATCH_SIZE
|
35
|
-
CONFIG_DELETE_STATS_PARTITION_BATCH_SIZE = 1000
|
36
|
-
private_constant :CONFIG_DELETE_STATS_PARTITION_BATCH_SIZE
|
37
35
|
|
38
36
|
@configuration = Configuration::Loader.new
|
39
37
|
|
@@ -54,13 +52,12 @@ module ThreeScale
|
|
54
52
|
config.add_section(:analytics_redis, :server,
|
55
53
|
:connect_timeout, :read_timeout, :write_timeout)
|
56
54
|
config.add_section(:hoptoad, :service, :api_key)
|
57
|
-
config.add_section(:stats, :bucket_size, :delete_batch_size
|
55
|
+
config.add_section(:stats, :bucket_size, :delete_batch_size)
|
58
56
|
config.add_section(:redshift, :host, :port, :dbname, :user, :password)
|
59
57
|
config.add_section(:statsd, :host, :port)
|
60
58
|
config.add_section(:internal_api, :user, :password)
|
61
59
|
config.add_section(:master, :metrics)
|
62
60
|
config.add_section(:worker_prometheus_metrics, :enabled, :port)
|
63
|
-
config.add_section(:listener_prometheus_metrics, :enabled, :port)
|
64
61
|
|
65
62
|
config.add_section(
|
66
63
|
:async_worker,
|
@@ -125,9 +122,6 @@ module ThreeScale
|
|
125
122
|
config.stats.delete_batch_size = parse_int(config.stats.delete_batch_size,
|
126
123
|
CONFIG_DELETE_STATS_BATCH_SIZE)
|
127
124
|
|
128
|
-
config.stats.delete_partition_batch_size = parse_int(config.stats.delete_partition_batch_size,
|
129
|
-
CONFIG_DELETE_STATS_PARTITION_BATCH_SIZE)
|
130
|
-
|
131
125
|
# often we don't have a log_file setting - generate it here from
|
132
126
|
# the log_path setting.
|
133
127
|
log_file = config.log_file
|
@@ -292,12 +292,6 @@ module ThreeScale
|
|
292
292
|
end
|
293
293
|
end
|
294
294
|
|
295
|
-
class DeleteServiceStatsValidationError < Error
|
296
|
-
def initialize(service_id, msg)
|
297
|
-
super "Delete stats job context validation error. Service: #{service_id}. Error: #{msg}"
|
298
|
-
end
|
299
|
-
end
|
300
|
-
|
301
295
|
class EndUsersNoLongerSupported < BadRequest
|
302
296
|
def initialize
|
303
297
|
super 'End-users are no longer supported, do not specify the user_id parameter'.freeze
|
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
|
data/lib/3scale/backend/stats.rb
CHANGED
@@ -1,8 +1,4 @@
|
|
1
1
|
require '3scale/backend/stats/codes_commons'
|
2
2
|
require '3scale/backend/stats/period_commons'
|
3
3
|
require '3scale/backend/stats/aggregator'
|
4
|
-
require '3scale/backend/stats/delete_job_def'
|
5
|
-
require '3scale/backend/stats/key_generator'
|
6
|
-
require '3scale/backend/stats/partition_generator_job'
|
7
|
-
require '3scale/backend/stats/partition_eraser_job'
|
8
4
|
require '3scale/backend/stats/cleaner'
|
@@ -145,6 +145,16 @@ module ThreeScale
|
|
145
145
|
application = Backend::Application.load(service_id,
|
146
146
|
values[:application_id])
|
147
147
|
|
148
|
+
# The app could have been deleted at some point since the job was
|
149
|
+
# enqueued. No need to update alerts in that case.
|
150
|
+
next unless application
|
151
|
+
|
152
|
+
# The operations below are costly. They load all the usage limits
|
153
|
+
# and current usages to find the current utilization levels.
|
154
|
+
# That's why before that, we check if there are any alerts that
|
155
|
+
# can be raised.
|
156
|
+
next unless Alerts.can_raise_more_alerts?(service_id, values[:application_id])
|
157
|
+
|
148
158
|
application.load_metric_names
|
149
159
|
usage = Usage.application_usage(application, current_timestamp)
|
150
160
|
status = Transactor::Status.new(service_id: service_id,
|
@@ -20,7 +20,14 @@ module ThreeScale
|
|
20
20
|
key = counter_key(prefix_key, granularity.new(timestamp))
|
21
21
|
expire_time = Stats::PeriodCommons.expire_time_for_granularity(granularity)
|
22
22
|
|
23
|
-
|
23
|
+
# We don't need to store stats keys set to 0. It wastes Redis
|
24
|
+
# memory because for rate-limiting and stats, a key of set to 0
|
25
|
+
# is equivalent to a key that does not exist.
|
26
|
+
if cmd == :set && value == 0
|
27
|
+
storage.del(key)
|
28
|
+
else
|
29
|
+
store_key(cmd, key, value, expire_time)
|
30
|
+
end
|
24
31
|
|
25
32
|
unless Stats::PeriodCommons::EXCLUDED_FOR_BUCKETS.include?(granularity)
|
26
33
|
keys_for_bucket << key
|
@@ -12,9 +12,6 @@ module ThreeScale
|
|
12
12
|
GRANULARITY_EXPIRATION_TIME = { Period[:minute] => 180 }.freeze
|
13
13
|
private_constant :GRANULARITY_EXPIRATION_TIME
|
14
14
|
|
15
|
-
PERMANENT_SERVICE_GRANULARITIES = (SERVICE_GRANULARITIES - GRANULARITY_EXPIRATION_TIME.keys).freeze
|
16
|
-
PERMANENT_EXPANDED_GRANULARITIES = (EXPANDED_GRANULARITIES - GRANULARITY_EXPIRATION_TIME.keys).freeze
|
17
|
-
|
18
15
|
# We are not going to send metrics with granularity 'eternity' or
|
19
16
|
# 'week' to Kinesis, so there is no point in storing them in Redis
|
20
17
|
# buckets.
|
@@ -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|
|
@@ -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.0</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>
|
@@ -709,7 +709,7 @@
|
|
709
709
|
</dependency>
|
710
710
|
<dependency>
|
711
711
|
<packageName>puma</packageName>
|
712
|
-
<version>
|
712
|
+
<version>4.3.7</version>
|
713
713
|
<licenses>
|
714
714
|
<license>
|
715
715
|
<name>New BSD</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.0
|
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-14 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.
|
@@ -136,11 +136,7 @@ files:
|
|
136
136
|
- lib/3scale/backend/stats/bucket_storage.rb
|
137
137
|
- lib/3scale/backend/stats/cleaner.rb
|
138
138
|
- lib/3scale/backend/stats/codes_commons.rb
|
139
|
-
- lib/3scale/backend/stats/delete_job_def.rb
|
140
|
-
- lib/3scale/backend/stats/key_generator.rb
|
141
139
|
- lib/3scale/backend/stats/keys.rb
|
142
|
-
- lib/3scale/backend/stats/partition_eraser_job.rb
|
143
|
-
- lib/3scale/backend/stats/partition_generator_job.rb
|
144
140
|
- lib/3scale/backend/stats/period_commons.rb
|
145
141
|
- lib/3scale/backend/stats/stats_parser.rb
|
146
142
|
- lib/3scale/backend/stats/storage.rb
|
@@ -211,8 +207,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
211
207
|
- !ruby/object:Gem::Version
|
212
208
|
version: 1.3.7
|
213
209
|
requirements: []
|
214
|
-
|
215
|
-
rubygems_version: 2.7.8
|
210
|
+
rubygems_version: 3.2.10
|
216
211
|
signing_key:
|
217
212
|
specification_version: 4
|
218
213
|
summary: 3scale web service management system backend
|
@@ -1,60 +0,0 @@
|
|
1
|
-
module ThreeScale
|
2
|
-
module Backend
|
3
|
-
module Stats
|
4
|
-
class DeleteJobDef
|
5
|
-
ATTRIBUTES = %i[service_id applications metrics from to context_info].freeze
|
6
|
-
private_constant :ATTRIBUTES
|
7
|
-
attr_reader(*ATTRIBUTES)
|
8
|
-
|
9
|
-
def self.attribute_names
|
10
|
-
ATTRIBUTES
|
11
|
-
end
|
12
|
-
|
13
|
-
def initialize(params = {})
|
14
|
-
ATTRIBUTES.each do |key|
|
15
|
-
instance_variable_set("@#{key}".to_sym, params[key]) unless params[key].nil?
|
16
|
-
end
|
17
|
-
validate
|
18
|
-
end
|
19
|
-
|
20
|
-
def run_async
|
21
|
-
Resque.enqueue(PartitionGeneratorJob, Time.now.getutc.to_f, service_id, applications,
|
22
|
-
metrics, from, to, context_info)
|
23
|
-
end
|
24
|
-
|
25
|
-
def to_json
|
26
|
-
to_hash.to_json
|
27
|
-
end
|
28
|
-
|
29
|
-
def to_hash
|
30
|
-
Hash[ATTRIBUTES.collect { |key| [key, send(key)] }]
|
31
|
-
end
|
32
|
-
|
33
|
-
private
|
34
|
-
|
35
|
-
def validate
|
36
|
-
# from and to valid epoch times
|
37
|
-
raise_validation_error('from field not integer') unless from.is_a? Integer
|
38
|
-
raise_validation_error('from field is zero') if from.zero?
|
39
|
-
raise_validation_error('to field not integer') unless to.is_a? Integer
|
40
|
-
raise_validation_error('to field is zero') if to.zero?
|
41
|
-
raise_validation_error('from < to fields') if Time.at(to) < Time.at(from)
|
42
|
-
# application is array
|
43
|
-
raise_validation_error('applications field') unless applications.is_a? Array
|
44
|
-
raise_validation_error('applications values') unless applications.all? do |x|
|
45
|
-
x.is_a?(String) || x.is_a?(Integer)
|
46
|
-
end
|
47
|
-
# metrics is array
|
48
|
-
raise_validation_error('metrics field') unless metrics.is_a? Array
|
49
|
-
raise_validation_error('metrics values') unless metrics.all? do |x|
|
50
|
-
x.is_a?(String) || x.is_a?(Integer)
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
def raise_validation_error(msg)
|
55
|
-
raise DeleteServiceStatsValidationError.new(service_id, msg)
|
56
|
-
end
|
57
|
-
end
|
58
|
-
end
|
59
|
-
end
|
60
|
-
end
|
@@ -1,73 +0,0 @@
|
|
1
|
-
module ThreeScale
|
2
|
-
module Backend
|
3
|
-
module Stats
|
4
|
-
class KeyGenerator
|
5
|
-
attr_reader :service_id, :applications, :metrics, :from, :to
|
6
|
-
|
7
|
-
def initialize(service_id:, applications: [], metrics: [], from:, to:, **)
|
8
|
-
@service_id = service_id
|
9
|
-
@applications = applications
|
10
|
-
@metrics = metrics
|
11
|
-
@from = from
|
12
|
-
@to = to
|
13
|
-
end
|
14
|
-
|
15
|
-
def keys
|
16
|
-
response_code_service_keys +
|
17
|
-
response_code_application_keys +
|
18
|
-
usage_service_keys +
|
19
|
-
usage_application_keys
|
20
|
-
end
|
21
|
-
|
22
|
-
private
|
23
|
-
|
24
|
-
def periods(granularities)
|
25
|
-
granularities.flat_map do |granularity|
|
26
|
-
(Period[granularity].new(Time.at(from))..Period[granularity].new(Time.at(to))).to_a
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
def response_codes
|
31
|
-
CodesCommons::TRACKED_CODES + CodesCommons::TRACKED_CODE_GROUPS
|
32
|
-
end
|
33
|
-
|
34
|
-
def response_code_service_keys
|
35
|
-
periods(PeriodCommons::PERMANENT_SERVICE_GRANULARITIES).flat_map do |period|
|
36
|
-
response_codes.flat_map do |response_code|
|
37
|
-
Keys.service_response_code_value_key(service_id, response_code, period)
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
def response_code_application_keys
|
43
|
-
periods(PeriodCommons::PERMANENT_EXPANDED_GRANULARITIES).flat_map do |period|
|
44
|
-
response_codes.flat_map do |response_code|
|
45
|
-
applications.flat_map do |application|
|
46
|
-
Keys.application_response_code_value_key(service_id, application,
|
47
|
-
response_code, period)
|
48
|
-
end
|
49
|
-
end
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
def usage_service_keys
|
54
|
-
periods(PeriodCommons::PERMANENT_SERVICE_GRANULARITIES).flat_map do |period|
|
55
|
-
metrics.flat_map do |metric|
|
56
|
-
Keys.service_usage_value_key(service_id, metric, period)
|
57
|
-
end
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
|
-
def usage_application_keys
|
62
|
-
periods(PeriodCommons::PERMANENT_EXPANDED_GRANULARITIES).flat_map do |period|
|
63
|
-
metrics.flat_map do |metric|
|
64
|
-
applications.flat_map do |application|
|
65
|
-
Keys.application_usage_value_key(service_id, application, metric, period)
|
66
|
-
end
|
67
|
-
end
|
68
|
-
end
|
69
|
-
end
|
70
|
-
end
|
71
|
-
end
|
72
|
-
end
|
73
|
-
end
|
@@ -1,58 +0,0 @@
|
|
1
|
-
module ThreeScale
|
2
|
-
module Backend
|
3
|
-
module Stats
|
4
|
-
# Job for deleting service stats
|
5
|
-
# Perform actual key deletion from a key partition definition
|
6
|
-
class PartitionEraserJob < BackgroundJob
|
7
|
-
# low priority queue
|
8
|
-
@queue = :stats
|
9
|
-
|
10
|
-
class << self
|
11
|
-
include StorageHelpers
|
12
|
-
include Configurable
|
13
|
-
|
14
|
-
def perform_logged(_enqueue_time, service_id, applications, metrics,
|
15
|
-
from, to, offset, length, context_info = {})
|
16
|
-
job = DeleteJobDef.new(
|
17
|
-
service_id: service_id,
|
18
|
-
applications: applications,
|
19
|
-
metrics: metrics,
|
20
|
-
from: from,
|
21
|
-
to: to
|
22
|
-
)
|
23
|
-
|
24
|
-
validate_job(job, offset, length)
|
25
|
-
|
26
|
-
stats_key_gen = KeyGenerator.new(job.to_hash)
|
27
|
-
|
28
|
-
stats_key_gen.keys.drop(offset).take(length).each_slice(configuration.stats.delete_batch_size) do |slice|
|
29
|
-
storage.del(slice)
|
30
|
-
end
|
31
|
-
|
32
|
-
[true, { job: job.to_hash, offset: offset, lenght: length }.to_json]
|
33
|
-
rescue Backend::Error => error
|
34
|
-
[false, "#{service_id} #{error}"]
|
35
|
-
end
|
36
|
-
|
37
|
-
private
|
38
|
-
|
39
|
-
def validate_job(job, offset, length)
|
40
|
-
unless offset.is_a? Integer
|
41
|
-
raise DeleteServiceStatsValidationError.new(job.service_id, 'offset field value ' \
|
42
|
-
"[#{offset}] validation error")
|
43
|
-
end
|
44
|
-
|
45
|
-
unless length.is_a? Integer
|
46
|
-
raise DeleteServiceStatsValidationError.new(job.service_id, 'length field value ' \
|
47
|
-
"[#{length}] validation error")
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
def enqueue_time(args)
|
52
|
-
args[0]
|
53
|
-
end
|
54
|
-
end
|
55
|
-
end
|
56
|
-
end
|
57
|
-
end
|
58
|
-
end
|
@@ -1,46 +0,0 @@
|
|
1
|
-
module ThreeScale
|
2
|
-
module Backend
|
3
|
-
module Stats
|
4
|
-
# Job for deleting service stats
|
5
|
-
# Maps delete job definition to a set of non overlapping key set partitions
|
6
|
-
class PartitionGeneratorJob < BackgroundJob
|
7
|
-
# low priority queue
|
8
|
-
@queue = :stats
|
9
|
-
|
10
|
-
class << self
|
11
|
-
include Configurable
|
12
|
-
|
13
|
-
def perform_logged(_enqueue_time, service_id, applications, metrics,
|
14
|
-
from, to, context_info = {})
|
15
|
-
job = DeleteJobDef.new(
|
16
|
-
service_id: service_id,
|
17
|
-
applications: applications,
|
18
|
-
metrics: metrics,
|
19
|
-
from: from,
|
20
|
-
to: to
|
21
|
-
)
|
22
|
-
|
23
|
-
stats_key_gen = KeyGenerator.new(job.to_hash)
|
24
|
-
|
25
|
-
# Generate partitions
|
26
|
-
0.step(stats_key_gen.keys.count, configuration.stats.delete_partition_batch_size).each do |idx|
|
27
|
-
Resque.enqueue(PartitionEraserJob, Time.now.getutc.to_f, service_id, applications,
|
28
|
-
metrics, from, to, idx,
|
29
|
-
configuration.stats.delete_partition_batch_size, context_info)
|
30
|
-
end
|
31
|
-
|
32
|
-
[true, job.to_json]
|
33
|
-
rescue Backend::Error => error
|
34
|
-
[false, "#{service_id} #{error}"]
|
35
|
-
end
|
36
|
-
|
37
|
-
private
|
38
|
-
|
39
|
-
def enqueue_time(args)
|
40
|
-
args[0]
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|