rorvswild 1.5.0 → 1.5.5
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/README.md +28 -2
- data/lib/rorvswild.rb +18 -4
- data/lib/rorvswild/agent.rb +21 -26
- data/lib/rorvswild/client.rb +7 -2
- data/lib/rorvswild/installer.rb +1 -0
- data/lib/rorvswild/locator.rb +4 -4
- data/lib/rorvswild/plugin/action_controller.rb +9 -19
- data/lib/rorvswild/plugin/active_job.rb +12 -2
- data/lib/rorvswild/plugin/middleware.rb +31 -0
- data/lib/rorvswild/queue.rb +0 -1
- data/lib/rorvswild/section.rb +5 -4
- data/lib/rorvswild/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c48c5689b1cc41d4954efcf44a2c415ee4a803da60f6beb36424f9103d06d72e
|
4
|
+
data.tar.gz: 62da47461a2d4dc9e182aebe765d6dda46e188ea57687bcd8298e61acf8d51d6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e00fa04cd7566a8f64fe7d69ebc2a36acabec87619eee6e05ef2534ea429614a2be1ac7cd102b45440f5aa81333cdc6595f30b77c277ef7b7c2b832785ac48b8
|
7
|
+
data.tar.gz: 8e1b010d4057131da1178041640b095dea3f90c685f50d4f8c15fcda2ab0257c37cce986e72a5eca68154ecb39d78f1fd3e5912d2493f9a03400182b676563af
|
data/README.md
CHANGED
@@ -32,11 +32,11 @@ Signup on https://www.rorvswild.com and create an app to get one.
|
|
32
32
|
|
33
33
|
* Add in your Gemfile `gem "rorvswild"`
|
34
34
|
* Run `bundle install` in you terminal
|
35
|
-
* Run `rorvswild-
|
35
|
+
* Run `rorvswild-install API_KEY` in you terminal
|
36
36
|
* Deploy/Restart your app
|
37
37
|
* Make a few requests and refresh your app page on rorvswild.com to view the dashboard.
|
38
38
|
|
39
|
-
The `rorvswild-
|
39
|
+
The `rorvswild-install` command creates a `config/rorvswild.yml` file.
|
40
40
|
|
41
41
|
If you prefer to use an initializer, you can do the following:
|
42
42
|
|
@@ -167,6 +167,32 @@ Finally here is the list of all plugins you can ignore :
|
|
167
167
|
- Resque
|
168
168
|
- Sidekiq
|
169
169
|
|
170
|
+
#### Change logger
|
171
|
+
|
172
|
+
By default RorVsWild uses `Rails.logger` or standard output. However in some cases you want to isolate RorVsWild's logs.
|
173
|
+
To do that, you have to specifiy the log destination via the `logger` option :
|
174
|
+
|
175
|
+
```yaml
|
176
|
+
# config/rorvswild.yml
|
177
|
+
production:
|
178
|
+
api_key: API_KEY
|
179
|
+
logger: log/rorvswild.yml
|
180
|
+
```
|
181
|
+
|
182
|
+
Here is the equivalent if you prefer initialising RorVsWild manually :
|
183
|
+
|
184
|
+
```ruby
|
185
|
+
# config/initializers/rorvswild.rb
|
186
|
+
RorVsWild.start(api_key: "API_KEY", logger: "log/rorvswild.log")
|
187
|
+
```
|
188
|
+
|
189
|
+
In the case you want a custom logger such as Syslog, you can only do it by initialising it manually :
|
190
|
+
|
191
|
+
```ruby
|
192
|
+
# config/initializers/rorvswild.rb
|
193
|
+
RorVsWild.start(api_key: "API_KEY", logger: Logger::Syslog.new)
|
194
|
+
```
|
195
|
+
|
170
196
|
## Contributing
|
171
197
|
|
172
198
|
1. Fork it ( https://github.com/[my-github-username]/rorvswild/fork )
|
data/lib/rorvswild.rb
CHANGED
@@ -20,7 +20,7 @@ module RorVsWild
|
|
20
20
|
end
|
21
21
|
|
22
22
|
def self.logger
|
23
|
-
@logger ||=
|
23
|
+
@logger ||= initialize_logger
|
24
24
|
end
|
25
25
|
|
26
26
|
def self.measure_code(code)
|
@@ -39,17 +39,31 @@ module RorVsWild
|
|
39
39
|
agent.record_error(exception, extra_details) if agent
|
40
40
|
end
|
41
41
|
|
42
|
-
def self.initialize_logger(destination)
|
43
|
-
if destination
|
42
|
+
def self.initialize_logger(destination = nil)
|
43
|
+
if destination.respond_to?(:info) && destination.respond_to?(:warn) && destination.respond_to?(:error)
|
44
|
+
destination
|
45
|
+
elsif destination
|
44
46
|
Logger.new(destination)
|
45
47
|
elsif defined?(Rails)
|
46
|
-
|
48
|
+
Rails.logger
|
49
|
+
else
|
50
|
+
Logger.new(STDOUT)
|
47
51
|
end
|
48
52
|
end
|
49
53
|
|
50
54
|
def self.clock_milliseconds
|
51
55
|
Process.clock_gettime(Process::CLOCK_MONOTONIC, :millisecond)
|
52
56
|
end
|
57
|
+
|
58
|
+
def self.check
|
59
|
+
api_key = RorVsWild.agent.config[:api_key]
|
60
|
+
return puts "You API key is missing and has to be defined in config/rorvswild.yml." if !api_key || api_key.empty?
|
61
|
+
puts case response = agent.client.post("/jobs", jobs: [{sections: [], name: "RorVsWild.check", runtime: 0}])
|
62
|
+
when Net::HTTPOK then "Connection to RorVsWild works fine !"
|
63
|
+
when Net::HTTPUnauthorized then "Wrong API key"
|
64
|
+
else puts "Something went wrong: #{response.inspect}"
|
65
|
+
end
|
66
|
+
end
|
53
67
|
end
|
54
68
|
|
55
69
|
if defined?(Rails)
|
data/lib/rorvswild/agent.rb
CHANGED
@@ -37,7 +37,7 @@ module RorVsWild
|
|
37
37
|
for name in RorVsWild::Plugin.constants
|
38
38
|
next if config[:ignore_plugins] && config[:ignore_plugins].include?(name.to_s)
|
39
39
|
if (plugin = RorVsWild::Plugin.const_get(name)).respond_to?(:setup)
|
40
|
-
RorVsWild.logger.info("
|
40
|
+
RorVsWild.logger.info("Setup RorVsWild::Plugin::#{name}")
|
41
41
|
plugin.setup
|
42
42
|
end
|
43
43
|
end
|
@@ -48,11 +48,11 @@ module RorVsWild
|
|
48
48
|
end
|
49
49
|
|
50
50
|
def measure_block(name, kind = "code".freeze, &block)
|
51
|
-
|
51
|
+
current_data ? measure_section(name, kind: kind, &block) : measure_job(name, &block)
|
52
52
|
end
|
53
53
|
|
54
54
|
def measure_section(name, kind: "code", appendable_command: false, &block)
|
55
|
-
return block.call unless
|
55
|
+
return block.call unless current_data
|
56
56
|
begin
|
57
57
|
RorVsWild::Section.start do |section|
|
58
58
|
section.appendable_command = appendable_command
|
@@ -66,29 +66,27 @@ module RorVsWild
|
|
66
66
|
end
|
67
67
|
|
68
68
|
def measure_job(name, parameters: nil, &block)
|
69
|
-
return measure_section(name, &block) if
|
69
|
+
return measure_section(name, &block) if current_data # For recursive jobs
|
70
70
|
return block.call if ignored_job?(name)
|
71
|
-
initialize_data
|
71
|
+
initialize_data[:name] = name
|
72
72
|
begin
|
73
73
|
block.call
|
74
74
|
rescue Exception => ex
|
75
75
|
push_exception(ex, parameters: parameters)
|
76
76
|
raise
|
77
77
|
ensure
|
78
|
-
|
78
|
+
current_data[:runtime] = RorVsWild.clock_milliseconds - current_data[:started_at]
|
79
79
|
post_job
|
80
80
|
end
|
81
81
|
end
|
82
82
|
|
83
|
-
def start_request
|
84
|
-
|
85
|
-
initialize_data(payload[:name])
|
86
|
-
data[:path] = payload[:path]
|
83
|
+
def start_request
|
84
|
+
current_data || initialize_data
|
87
85
|
end
|
88
86
|
|
89
87
|
def stop_request
|
90
|
-
return unless
|
91
|
-
|
88
|
+
return unless current_data
|
89
|
+
current_data[:runtime] = RorVsWild.clock_milliseconds - current_data[:started_at]
|
92
90
|
post_request
|
93
91
|
end
|
94
92
|
|
@@ -107,21 +105,21 @@ module RorVsWild
|
|
107
105
|
|
108
106
|
def push_exception(exception, options = nil)
|
109
107
|
return if ignored_exception?(exception)
|
110
|
-
|
111
|
-
|
112
|
-
|
108
|
+
current_data[:error] = exception_to_hash(exception)
|
109
|
+
current_data[:error].merge!(options) if options
|
110
|
+
current_data[:error]
|
113
111
|
end
|
114
112
|
|
115
|
-
def
|
116
|
-
Thread.current[:rorvswild_data]
|
113
|
+
def current_data
|
114
|
+
Thread.current[:rorvswild_data]
|
117
115
|
end
|
118
116
|
|
119
117
|
def add_section(section)
|
120
|
-
return unless
|
121
|
-
if sibling =
|
118
|
+
return unless current_data[:sections]
|
119
|
+
if sibling = current_data[:sections].find { |s| s.sibling?(section) }
|
122
120
|
sibling.merge(section)
|
123
121
|
else
|
124
|
-
|
122
|
+
current_data[:sections] << section
|
125
123
|
end
|
126
124
|
end
|
127
125
|
|
@@ -139,11 +137,8 @@ module RorVsWild
|
|
139
137
|
|
140
138
|
private
|
141
139
|
|
142
|
-
def initialize_data
|
143
|
-
|
144
|
-
data[:sections] = []
|
145
|
-
data[:section_stack] = []
|
146
|
-
data[:started_at] = RorVsWild.clock_milliseconds
|
140
|
+
def initialize_data
|
141
|
+
Thread.current[:rorvswild_data] = {sections: [], section_stack: [], started_at: RorVsWild.clock_milliseconds}
|
147
142
|
end
|
148
143
|
|
149
144
|
def cleanup_data
|
@@ -153,7 +148,7 @@ module RorVsWild
|
|
153
148
|
end
|
154
149
|
|
155
150
|
def post_request
|
156
|
-
queue.push_request(
|
151
|
+
(data = cleanup_data) && data[:name] && queue.push_request(data)
|
157
152
|
end
|
158
153
|
|
159
154
|
def post_job
|
data/lib/rorvswild/client.rb
CHANGED
@@ -21,12 +21,13 @@ module RorVsWild
|
|
21
21
|
@connection_count = 0
|
22
22
|
@mutex = Mutex.new
|
23
23
|
@config = config
|
24
|
+
@headers = {"Content-Type" => "application/json", "X-Gem-Version" => RorVsWild::VERSION}
|
25
|
+
@headers["X-Rails-Version"] = Rails.version if defined?(Rails)
|
24
26
|
end
|
25
27
|
|
26
28
|
def post(path, data)
|
27
29
|
uri = URI(api_url + path)
|
28
|
-
post = Net::HTTP::Post.new(uri.path,
|
29
|
-
post.content_type = "application/json".freeze
|
30
|
+
post = Net::HTTP::Post.new(uri.path, @headers)
|
30
31
|
post.basic_auth(nil, api_key)
|
31
32
|
post.body = data.to_json
|
32
33
|
transmit(post)
|
@@ -46,6 +47,7 @@ module RorVsWild
|
|
46
47
|
|
47
48
|
def take_or_create_connection
|
48
49
|
if http = take_connection
|
50
|
+
http.start unless http.active?
|
49
51
|
http
|
50
52
|
elsif @connection_count < max_connections
|
51
53
|
@connection_count += 1
|
@@ -57,6 +59,8 @@ module RorVsWild
|
|
57
59
|
if http = take_or_create_connection
|
58
60
|
http.request(request)
|
59
61
|
end
|
62
|
+
rescue Exception => ex
|
63
|
+
RorVsWild.logger.error(ex.full_message)
|
60
64
|
ensure
|
61
65
|
release_connection(http)
|
62
66
|
end
|
@@ -65,6 +69,7 @@ module RorVsWild
|
|
65
69
|
uri = URI(api_url)
|
66
70
|
http = Net::HTTP.new(uri.host, uri.port)
|
67
71
|
http.open_timeout = timeout
|
72
|
+
http.keep_alive_timeout = 5
|
68
73
|
|
69
74
|
if uri.scheme == HTTPS
|
70
75
|
# Disable peer verification while there is a memory leak with OpenSSL
|
data/lib/rorvswild/installer.rb
CHANGED
data/lib/rorvswild/locator.rb
CHANGED
@@ -34,15 +34,15 @@ module RorVsWild
|
|
34
34
|
end
|
35
35
|
|
36
36
|
def relative_path(path)
|
37
|
-
path.
|
37
|
+
path.start_with?(current_path) ? path.sub(current_path, "".freeze) : path
|
38
38
|
end
|
39
39
|
|
40
40
|
def relevant_path?(path)
|
41
|
-
path.
|
41
|
+
path.start_with?(current_path) && !irrelevant_path?(path)
|
42
42
|
end
|
43
43
|
|
44
44
|
def irrelevant_path?(path)
|
45
|
-
|
45
|
+
path.start_with?(*irrelevant_paths)
|
46
46
|
end
|
47
47
|
|
48
48
|
def irrelevant_paths
|
@@ -52,7 +52,7 @@ module RorVsWild
|
|
52
52
|
private
|
53
53
|
|
54
54
|
def initialize_irrelevant_paths
|
55
|
-
array = ["RUBYLIB", "GEM_HOME", "GEM_PATH", "
|
55
|
+
array = ["RUBYLIB", "GEM_HOME", "GEM_PATH", "BUNDLER_ORIG_GEM_PATH"].flat_map do |name|
|
56
56
|
ENV[name].split(":".freeze) if ENV[name]
|
57
57
|
end
|
58
58
|
array += [heroku_ruby_lib_path] if File.exists?(heroku_ruby_lib_path)
|
@@ -4,29 +4,21 @@ module RorVsWild
|
|
4
4
|
def self.setup
|
5
5
|
return if @installed
|
6
6
|
return unless defined?(::ActionController::Base)
|
7
|
-
ActiveSupport::Notifications.subscribe("process_action.action_controller", new)
|
8
7
|
::ActionController::Base.around_action(&method(:around_action))
|
9
8
|
::ActionController::Base.rescue_from(StandardError) { |ex| RorVsWild::Plugin::ActionController.after_exception(ex, self) }
|
10
9
|
@installed = true
|
11
10
|
end
|
12
11
|
|
13
|
-
def self.after_exception(exception, controller)
|
14
|
-
if hash = RorVsWild.agent.push_exception(exception)
|
15
|
-
hash[:session] = controller.session.to_hash
|
16
|
-
hash[:parameters] = controller.request.filtered_parameters
|
17
|
-
hash[:environment_variables] = extract_http_headers(controller.request.filtered_env)
|
18
|
-
end
|
19
|
-
raise exception
|
20
|
-
end
|
21
|
-
|
22
12
|
def self.around_action(controller, block)
|
13
|
+
controller_action = "#{controller.class}##{controller.action_name}"
|
14
|
+
return block.call if RorVsWild.agent.ignored_request?(controller_action)
|
23
15
|
begin
|
24
16
|
RorVsWild::Section.start do |section|
|
25
17
|
method_name = controller.method_for_action(controller.action_name)
|
26
18
|
section.file, section.line = controller.method(method_name).source_location
|
27
19
|
section.file = RorVsWild.agent.locator.relative_path(section.file)
|
28
20
|
section.command = "#{controller.class}##{method_name}"
|
29
|
-
|
21
|
+
RorVsWild.agent.current_data[:name] = controller_action
|
30
22
|
end
|
31
23
|
block.call
|
32
24
|
ensure
|
@@ -34,15 +26,13 @@ module RorVsWild
|
|
34
26
|
end
|
35
27
|
end
|
36
28
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
29
|
+
def self.after_exception(exception, controller)
|
30
|
+
if hash = RorVsWild.agent.push_exception(exception)
|
31
|
+
hash[:session] = controller.session.to_hash
|
32
|
+
hash[:parameters] = controller.request.filtered_parameters
|
33
|
+
hash[:environment_variables] = extract_http_headers(controller.request.filtered_env)
|
41
34
|
end
|
42
|
-
|
43
|
-
|
44
|
-
def finish(name, id, payload)
|
45
|
-
RorVsWild.agent.stop_request
|
35
|
+
raise exception
|
46
36
|
end
|
47
37
|
|
48
38
|
def self.extract_http_headers(headers)
|
@@ -1,6 +1,6 @@
|
|
1
1
|
module RorVsWild
|
2
2
|
module Plugin
|
3
|
-
|
3
|
+
class ActiveJob
|
4
4
|
def self.setup
|
5
5
|
return if @installed
|
6
6
|
return unless defined?(::ActiveJob::Base)
|
@@ -9,7 +9,17 @@ module RorVsWild
|
|
9
9
|
end
|
10
10
|
|
11
11
|
def self.around_perform(job, block)
|
12
|
-
RorVsWild.agent.measure_job(job.class.name, parameters: job.arguments
|
12
|
+
RorVsWild.agent.measure_job(job.class.name, parameters: job.arguments) do
|
13
|
+
begin
|
14
|
+
section = RorVsWild::Section.start
|
15
|
+
section.command = "#{job.class}#perform"
|
16
|
+
section.file, section.line = job.method(:perform).source_location
|
17
|
+
section.file = RorVsWild.agent.locator.relative_path(section.file)
|
18
|
+
block.call
|
19
|
+
ensure
|
20
|
+
RorVsWild::Section.stop
|
21
|
+
end
|
22
|
+
end
|
13
23
|
end
|
14
24
|
end
|
15
25
|
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module RorVsWild
|
2
|
+
module Plugin
|
3
|
+
class Middleware
|
4
|
+
def self.setup
|
5
|
+
return if @installed
|
6
|
+
Rails.application.config.middleware.unshift(RorVsWild::Plugin::Middleware, nil) if defined?(Rails)
|
7
|
+
@installed = true
|
8
|
+
end
|
9
|
+
|
10
|
+
def initialize(app, config)
|
11
|
+
@app, @config = app, config
|
12
|
+
end
|
13
|
+
|
14
|
+
def call(env)
|
15
|
+
RorVsWild.agent.start_request
|
16
|
+
RorVsWild.agent.current_data[:path] = env["ORIGINAL_FULLPATH".freeze]
|
17
|
+
section = RorVsWild::Section.start
|
18
|
+
section.file, section.line = rails_engine_location
|
19
|
+
section.command = "Rails::Engine#call".freeze
|
20
|
+
@app.call(env)
|
21
|
+
ensure
|
22
|
+
RorVsWild::Section.stop
|
23
|
+
RorVsWild.agent.stop_request
|
24
|
+
end
|
25
|
+
|
26
|
+
def rails_engine_location
|
27
|
+
@rails_engine_location = ::Rails::Engine.instance_method(:call).source_location
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
data/lib/rorvswild/queue.rb
CHANGED
data/lib/rorvswild/section.rb
CHANGED
@@ -6,12 +6,12 @@ module RorVsWild
|
|
6
6
|
def self.start(&block)
|
7
7
|
section = Section.new
|
8
8
|
block.call(section) if block_given?
|
9
|
-
stack.push(section)
|
9
|
+
stack && stack.push(section)
|
10
10
|
section
|
11
11
|
end
|
12
12
|
|
13
13
|
def self.stop(&block)
|
14
|
-
section = stack.pop
|
14
|
+
return unless stack && section = stack.pop
|
15
15
|
block.call(section) if block_given?
|
16
16
|
section.total_runtime = RorVsWild.clock_milliseconds - section.started_at
|
17
17
|
current.children_runtime += section.total_runtime if current
|
@@ -19,17 +19,18 @@ module RorVsWild
|
|
19
19
|
end
|
20
20
|
|
21
21
|
def self.stack
|
22
|
-
RorVsWild.agent.data[:section_stack]
|
22
|
+
(data = RorVsWild.agent.current_data) && data[:section_stack]
|
23
23
|
end
|
24
24
|
|
25
25
|
def self.current
|
26
|
-
stack.last
|
26
|
+
(sections = stack) && sections.last
|
27
27
|
end
|
28
28
|
|
29
29
|
def initialize
|
30
30
|
@calls = 1
|
31
31
|
@total_runtime = 0
|
32
32
|
@children_runtime = 0
|
33
|
+
@kind = "code".freeze
|
33
34
|
@started_at = RorVsWild.clock_milliseconds
|
34
35
|
location = RorVsWild.agent.locator.find_most_relevant_location(caller_locations)
|
35
36
|
@file = RorVsWild.agent.locator.relative_path(location.path)
|
data/lib/rorvswild/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rorvswild
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.5.
|
4
|
+
version: 1.5.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Alexis Bernard
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-05-29 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: Performances and quality insights for rails developers.
|
14
14
|
email:
|
@@ -46,6 +46,7 @@ files:
|
|
46
46
|
- lib/rorvswild/plugin/delayed_job.rb
|
47
47
|
- lib/rorvswild/plugin/elasticsearch.rb
|
48
48
|
- lib/rorvswild/plugin/faktory.rb
|
49
|
+
- lib/rorvswild/plugin/middleware.rb
|
49
50
|
- lib/rorvswild/plugin/mongo.rb
|
50
51
|
- lib/rorvswild/plugin/net_http.rb
|
51
52
|
- lib/rorvswild/plugin/redis.rb
|