lavin 0.2.0 → 0.3.0
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
- checksums.yaml.gz.sig +0 -0
- data/lib/lavin/client.rb +7 -0
- data/lib/lavin/error.rb +4 -0
- data/lib/lavin/failure.rb +15 -0
- data/lib/lavin/hook.rb +7 -5
- data/lib/lavin/http_client.rb +14 -6
- data/lib/lavin/runner.rb +1 -1
- data/lib/lavin/statistics.rb +28 -11
- data/lib/lavin/stats.rb +9 -3
- data/lib/lavin/step.rb +5 -3
- data/lib/lavin/user.rb +2 -0
- data/lib/lavin/version.rb +1 -1
- data/lib/lavin/web_server.rb +15 -0
- data/lib/lavin/worker.rb +9 -5
- data.tar.gz.sig +0 -0
- metadata +3 -2
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 52a0a48c405e0aff4b816ff7bf91b27e8407929a838db819f8777d222b4f7674
|
4
|
+
data.tar.gz: 4acb3c0a928acd45ecbd8137089433e69cdc8235919a0db6fefefb40418bfd82
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e2fe666e13f22d13dc4f085e8ab7e78c2242a973bd9b0d58054e0b4ada2cc17d1ca924e4103a3c55408bd88c4d1cd3efa8b3449cee7fd8a5d36794392218779c
|
7
|
+
data.tar.gz: b1f7f478a288492082a4f02462d345ce42703316638b3d6aee7848a92a539b22b750105e5e70fdf2ffe662ac26ed68a4f6a32c63154b18ba4faf96dee917b16b
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data/lib/lavin/client.rb
CHANGED
@@ -5,6 +5,13 @@ require 'async/http/internet'
|
|
5
5
|
module Lavin
|
6
6
|
class Client
|
7
7
|
class Error < Lavin::Error; end
|
8
|
+
|
9
|
+
class ServerError < Error
|
10
|
+
def initialize(status)
|
11
|
+
super("Server responded with status: #{status}")
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
8
15
|
class NoCurrentAsyncTaskError < Error
|
9
16
|
def initialize(msg = nil)
|
10
17
|
super(msg || "Trying to create a client outside of an Async task")
|
data/lib/lavin/error.rb
CHANGED
data/lib/lavin/hook.rb
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
#
|
3
2
|
|
4
3
|
module Lavin
|
5
4
|
class Hook
|
6
|
-
attr_reader :user, :block
|
5
|
+
attr_reader :user, :block, :type
|
7
6
|
|
8
|
-
def initialize(user:, &block)
|
7
|
+
def initialize(user:, type: :before, &block)
|
9
8
|
@user = user
|
10
9
|
@block = block
|
10
|
+
@type = type
|
11
11
|
end
|
12
12
|
|
13
13
|
def run(context: nil)
|
@@ -19,9 +19,11 @@ module Lavin
|
|
19
19
|
report_statistics = context.client.report_statistics
|
20
20
|
context.client.report_statistics = false
|
21
21
|
context.instance_exec(&block)
|
22
|
+
rescue RecoverableError
|
22
23
|
rescue => error
|
23
|
-
puts "Caught
|
24
|
-
puts error.backtrace
|
24
|
+
puts "Caught #{error.class} in #{type} hook: #{error.message}"
|
25
|
+
puts error.backtrace unless error.is_a? IrrecoverableError
|
26
|
+
throw :failure
|
25
27
|
ensure
|
26
28
|
context.client.report_statistics = report_statistics
|
27
29
|
end
|
data/lib/lavin/http_client.rb
CHANGED
@@ -17,27 +17,35 @@ module Lavin
|
|
17
17
|
end
|
18
18
|
|
19
19
|
def get(url, headers: {})
|
20
|
-
|
20
|
+
request(:get, url:, headers:)
|
21
21
|
end
|
22
22
|
|
23
23
|
def head(url, headers: {})
|
24
|
-
|
24
|
+
request(:head, url:, headers:)
|
25
25
|
end
|
26
26
|
|
27
27
|
def post(url, headers: {}, body: nil)
|
28
|
-
|
28
|
+
request(:post, url:, headers:, body:)
|
29
29
|
end
|
30
30
|
|
31
31
|
def put(url, headers: {}, body: nil)
|
32
|
-
|
32
|
+
request(:put, url:, headers:, body:)
|
33
33
|
end
|
34
34
|
|
35
35
|
def patch(url, headers: {}, body: nil)
|
36
|
-
|
36
|
+
request(:patch, url:, headers:, body:)
|
37
37
|
end
|
38
38
|
|
39
39
|
def delete(url, headers: {})
|
40
|
-
|
40
|
+
request(:delete, url:, headers:)
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
def request(method, url:, headers:, body: nil)
|
46
|
+
client.request(method, url:, headers:, body:).tap do |response|
|
47
|
+
raise Lavin::Client::ServerError, response[:status] if response[:status] > 499
|
48
|
+
end
|
41
49
|
end
|
42
50
|
end
|
43
51
|
end
|
data/lib/lavin/runner.rb
CHANGED
data/lib/lavin/statistics.rb
CHANGED
@@ -53,6 +53,7 @@ module Lavin
|
|
53
53
|
key = [user, step_name]
|
54
54
|
data[:steps][key][:success] += 1 unless failure
|
55
55
|
data[:steps][key][:failure] += 1 if failure
|
56
|
+
data[:failures][failure.to_s] += 1 if failure
|
56
57
|
end
|
57
58
|
|
58
59
|
def stats
|
@@ -62,9 +63,11 @@ module Lavin
|
|
62
63
|
requests = data[:requests].map do |(method, url), requests|
|
63
64
|
durations = []
|
64
65
|
statuses = []
|
66
|
+
failed_requests = 0
|
65
67
|
requests.each do |request|
|
66
68
|
durations << request[:duration]
|
67
69
|
statuses << request[:status]
|
70
|
+
failed_requests += 1 if request[:failure]
|
68
71
|
end
|
69
72
|
min_duration = durations.min
|
70
73
|
max_duration = durations.max
|
@@ -75,9 +78,10 @@ module Lavin
|
|
75
78
|
url: url,
|
76
79
|
requests: requests.size,
|
77
80
|
statuses: statuses.tally,
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
+
failed_requests:,
|
82
|
+
avg_duration:,
|
83
|
+
min_duration:,
|
84
|
+
max_duration:
|
81
85
|
}
|
82
86
|
end
|
83
87
|
|
@@ -87,7 +91,8 @@ module Lavin
|
|
87
91
|
rate: duration ? format("%.2f", total_requests / duration) : 0,
|
88
92
|
step_summary: data[:step_summary],
|
89
93
|
steps: data[:steps],
|
90
|
-
requests: requests
|
94
|
+
requests: requests,
|
95
|
+
failures: data[:failures]
|
91
96
|
).tap do |stats|
|
92
97
|
# FIXME remove!
|
93
98
|
puts "Calculated stats in #{Time.now - time}s"
|
@@ -101,7 +106,7 @@ module Lavin
|
|
101
106
|
|
102
107
|
show_steps(values) do |(user, step), hash|
|
103
108
|
format(
|
104
|
-
"%-
|
109
|
+
"%-48<user_step>s %8<success>d %8<failure>d",
|
105
110
|
user_step: "#{user}.#{step}",
|
106
111
|
**hash
|
107
112
|
)
|
@@ -113,6 +118,10 @@ module Lavin
|
|
113
118
|
**request_values
|
114
119
|
)
|
115
120
|
end
|
121
|
+
|
122
|
+
show_failures(values) do |message, count|
|
123
|
+
format("%-64<message>s %6<count>d", message:, count:)
|
124
|
+
end
|
116
125
|
end
|
117
126
|
|
118
127
|
private
|
@@ -141,7 +150,8 @@ module Lavin
|
|
141
150
|
failure: 0
|
142
151
|
},
|
143
152
|
steps: Hash.new { |h, k| h[k] = {success: 0, failure: 0} },
|
144
|
-
requests: Hash.new { |h, k| h[k] = [] }
|
153
|
+
requests: Hash.new { |h, k| h[k] = [] },
|
154
|
+
failures: Hash.new { |h, k| h[k] = 0 }
|
145
155
|
}
|
146
156
|
end
|
147
157
|
|
@@ -155,26 +165,25 @@ module Lavin
|
|
155
165
|
|
156
166
|
Total number of steps: #{values.total_steps}
|
157
167
|
Step success rate: #{format("%.2f %%", 100 * values.successful_steps.to_f / values.total_steps)}
|
158
|
-
|
159
168
|
RESULT
|
160
169
|
end
|
161
170
|
|
162
171
|
def show_steps(values)
|
163
172
|
puts format(
|
164
|
-
"%-
|
173
|
+
"\n%-48<user_step>s %8<success>s %8<failure>s",
|
165
174
|
user_step: "Steps",
|
166
175
|
success: "Success",
|
167
176
|
failure: "Failure"
|
168
177
|
)
|
169
|
-
divider = "-" *
|
178
|
+
divider = "-" * 66
|
170
179
|
puts divider
|
171
180
|
values.each_step { |step_values| puts yield step_values }
|
172
|
-
puts
|
181
|
+
puts divider
|
173
182
|
end
|
174
183
|
|
175
184
|
def show_table(values)
|
176
185
|
puts format(
|
177
|
-
"%-6<method>s %-100<url>s %-6<requests>s %12<avg_duration>s %12<min_duration>s %12<max_duration>s",
|
186
|
+
"\n%-6<method>s %-100<url>s %-6<requests>s %12<avg_duration>s %12<min_duration>s %12<max_duration>s",
|
178
187
|
method: "Method",
|
179
188
|
url: "URL",
|
180
189
|
requests: "Requests",
|
@@ -188,6 +197,14 @@ module Lavin
|
|
188
197
|
values.each_request { |request_values| puts yield request_values }
|
189
198
|
puts divider
|
190
199
|
end
|
200
|
+
|
201
|
+
def show_failures(values)
|
202
|
+
puts format("\n%-64<message>s %6<count>s", message: "Failures", count: "Count")
|
203
|
+
divider = "-" * 71
|
204
|
+
puts divider
|
205
|
+
values.each_failure { |failures| puts yield failures }
|
206
|
+
puts divider
|
207
|
+
end
|
191
208
|
end
|
192
209
|
end
|
193
210
|
end
|
data/lib/lavin/stats.rb
CHANGED
@@ -2,15 +2,16 @@
|
|
2
2
|
|
3
3
|
module Lavin
|
4
4
|
class Stats
|
5
|
-
attr_reader :duration, :total_requests, :rate, :requests, :step_summary, :steps
|
5
|
+
attr_reader :duration, :total_requests, :rate, :requests, :step_summary, :steps, :failures
|
6
6
|
|
7
|
-
def initialize(duration:, total_requests:, rate:, requests: [], step_summary: {}, steps: [])
|
7
|
+
def initialize(duration:, total_requests:, rate:, requests: [], step_summary: {}, steps: [], failures: [])
|
8
8
|
@duration = duration
|
9
9
|
@total_requests = total_requests
|
10
10
|
@rate = rate
|
11
11
|
@requests = requests
|
12
12
|
@step_summary = step_summary
|
13
13
|
@steps = steps
|
14
|
+
@failures = failures
|
14
15
|
end
|
15
16
|
|
16
17
|
def empty?
|
@@ -24,7 +25,8 @@ module Lavin
|
|
24
25
|
rate:,
|
25
26
|
requests:,
|
26
27
|
step_summary:,
|
27
|
-
steps
|
28
|
+
steps:,
|
29
|
+
failures:
|
28
30
|
}
|
29
31
|
end
|
30
32
|
|
@@ -47,5 +49,9 @@ module Lavin
|
|
47
49
|
def each_request(&block)
|
48
50
|
requests.each(&block)
|
49
51
|
end
|
52
|
+
|
53
|
+
def each_failure(&block)
|
54
|
+
failures.each(&block)
|
55
|
+
end
|
50
56
|
end
|
51
57
|
end
|
data/lib/lavin/step.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
|
2
|
+
|
3
|
+
require 'lavin/error'
|
3
4
|
|
4
5
|
module Lavin
|
5
6
|
class Step
|
@@ -22,9 +23,10 @@ module Lavin
|
|
22
23
|
def call(context:)
|
23
24
|
context.instance_exec(&block)
|
24
25
|
Statistics.register_step(user: user.name, step_name: name)
|
26
|
+
rescue IrrecoverableError => error
|
27
|
+
Statistics.register_step(user: user.name, step_name: name, failure: error.message)
|
28
|
+
throw :failure
|
25
29
|
rescue => error
|
26
|
-
puts "Caught an error - #{error.class}: #{error.message}"
|
27
|
-
puts error.backtrace
|
28
30
|
Statistics.register_step(user: user.name, step_name: name, failure: error.message)
|
29
31
|
end
|
30
32
|
end
|
data/lib/lavin/user.rb
CHANGED
@@ -4,6 +4,7 @@ require "set"
|
|
4
4
|
require "lavin/user_config"
|
5
5
|
require "lavin/worker"
|
6
6
|
require "lavin/http_client"
|
7
|
+
require "lavin/failure"
|
7
8
|
|
8
9
|
module Lavin
|
9
10
|
class User
|
@@ -12,6 +13,7 @@ module Lavin
|
|
12
13
|
subclass.include UserConfig
|
13
14
|
subclass.include Worker
|
14
15
|
subclass.include HttpClient
|
16
|
+
subclass.include Failure
|
15
17
|
all_personas << subclass
|
16
18
|
end
|
17
19
|
|
data/lib/lavin/version.rb
CHANGED
data/lib/lavin/web_server.rb
CHANGED
@@ -40,6 +40,11 @@ module Lavin
|
|
40
40
|
redirect to('/statistics')
|
41
41
|
end
|
42
42
|
|
43
|
+
post '/stop' do
|
44
|
+
Lavin::Runner.stop
|
45
|
+
redirect to('/statistics')
|
46
|
+
end
|
47
|
+
|
43
48
|
get '/statistics' do
|
44
49
|
stats = Statistics.stats
|
45
50
|
running = Lavin::Runner.running?
|
@@ -50,6 +55,16 @@ module Lavin
|
|
50
55
|
end
|
51
56
|
end
|
52
57
|
|
58
|
+
get '/failures' do
|
59
|
+
stats = Statistics.stats
|
60
|
+
running = Lavin::Runner.running?
|
61
|
+
if stats.empty? && !running
|
62
|
+
redirect to('/')
|
63
|
+
else
|
64
|
+
erb :failures, locals: {stats:, running:}
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
53
68
|
get '/edit' do
|
54
69
|
persona = find_persona
|
55
70
|
raise Sinatra::NotFound unless persona
|
data/lib/lavin/worker.rb
CHANGED
@@ -9,13 +9,13 @@ module Lavin
|
|
9
9
|
def before(&block)
|
10
10
|
return @before unless block
|
11
11
|
|
12
|
-
@before = Hook.new(user: self, &block)
|
12
|
+
@before = Hook.new(user: self, type: :before, &block)
|
13
13
|
end
|
14
14
|
|
15
15
|
def after(&block)
|
16
16
|
return @after unless block
|
17
17
|
|
18
|
-
@after = Hook.new(user: self, &block)
|
18
|
+
@after = Hook.new(user: self, type: :after, &block)
|
19
19
|
end
|
20
20
|
|
21
21
|
def steps
|
@@ -40,11 +40,15 @@ module Lavin
|
|
40
40
|
end
|
41
41
|
|
42
42
|
def run
|
43
|
-
|
43
|
+
catch(:failure) do
|
44
|
+
self.class.before.run(context: self).then { Runner.yield } if self.class.before
|
44
45
|
|
45
|
-
|
46
|
+
run_step until finished?
|
47
|
+
end
|
46
48
|
|
47
|
-
|
49
|
+
catch(:failure) do
|
50
|
+
self.class.after.run(context: self).then { Runner.yield } if self.class.after
|
51
|
+
end
|
48
52
|
end
|
49
53
|
|
50
54
|
private
|
data.tar.gz.sig
CHANGED
Binary file
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: lavin
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sammy Henningsson
|
@@ -29,7 +29,7 @@ cert_chain:
|
|
29
29
|
DVzXaUnsmwP+jQ1PkDa5q8ibBzMd2c6Hmm87UDqPxZtML0bF9SjrpbyLMjwtXaMA
|
30
30
|
WDPp0ajpdUZ9GPHsrVNYXiOfQIqcmlmpYVsH1o7vuneUIcIDMrnMDChh
|
31
31
|
-----END CERTIFICATE-----
|
32
|
-
date: 2022-
|
32
|
+
date: 2022-11-02 00:00:00.000000000 Z
|
33
33
|
dependencies:
|
34
34
|
- !ruby/object:Gem::Dependency
|
35
35
|
name: async
|
@@ -113,6 +113,7 @@ files:
|
|
113
113
|
- lib/lavin.rb
|
114
114
|
- lib/lavin/client.rb
|
115
115
|
- lib/lavin/error.rb
|
116
|
+
- lib/lavin/failure.rb
|
116
117
|
- lib/lavin/hook.rb
|
117
118
|
- lib/lavin/http_client.rb
|
118
119
|
- lib/lavin/runner.rb
|
metadata.gz.sig
CHANGED
Binary file
|