rorvswild 0.5.1 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 87b6214d8ddec4d743dc4498fae53c2ce5d39531
4
- data.tar.gz: fe6e1d5192ad34f8b2f9c51659a575fd1f73f170
3
+ metadata.gz: 802001256223c866089c33029d0e0b5b4a396bb0
4
+ data.tar.gz: 501c456458c29d982882775b6d106456a1f23483
5
5
  SHA512:
6
- metadata.gz: dde693b8dca1e8ce5a092b08c814387cbd6eaa5286001ef152ef1b81f8893646bfbaaf913ff34ff9295783ab8d6b1de248f76b0ad620efd79347d6a7e237dffd
7
- data.tar.gz: 118a2bb80c5f60e19a140aed778b42bfa362e22de280b091119c413d974164a4f2a08f14a8f6be06129fdecb57dff6f5caf009d6685a181ae7d4de0f809827a9
6
+ metadata.gz: d49be58f9ec73146b3fd62c437c863cbccca35187ccb0668e2ed072fdd0dea733fe1b09cca4a8d2ae77105132fd8483ba94efcb4e2787ed9de00ca506a811237
7
+ data.tar.gz: 4c1afafbc9312d1e4589f0fc20d478e968267cab12534398a03be2cf74b73c83c676479e3918325ae6ba58c7870eebe97200aed69eee2c5adeabf140dcea44a3
@@ -58,8 +58,11 @@ module RorVsWild
58
58
  ActionController::Base.rescue_from(StandardError) { |exception| client.after_exception(exception, self) }
59
59
  end
60
60
 
61
+ Plugin::Redis.setup
62
+ Plugin::Mongo.setup
61
63
  Plugin::Resque.setup
62
64
  Plugin::Sidekiq.setup
65
+ Plugin::NetHttp.setup
63
66
  Kernel.at_exit(&method(:at_exit))
64
67
  ActiveJob::Base.around_perform(&method(:around_active_job)) if defined?(ActiveJob::Base)
65
68
  Delayed::Worker.lifecycle.around(:invoke_job, &method(:around_delayed_job)) if defined?(Delayed::Worker)
@@ -86,7 +89,7 @@ module RorVsWild
86
89
  file, line, method = extract_most_relevant_location(caller)
87
90
  runtime, sql = compute_duration(start, finish), payload[:sql]
88
91
  plan = runtime >= explain_sql_threshold ? explain(payload[:sql], payload[:binds]) : nil
89
- push_query(file: file, line: line, method: method, sql: sql, plan: plan, runtime: runtime)
92
+ push_query(kind: "sql", file: file, line: line, method: method, command: sql, plan: plan, runtime: runtime)
90
93
  rescue => exception
91
94
  log_error(exception)
92
95
  end
@@ -143,6 +146,20 @@ module RorVsWild
143
146
  end
144
147
  end
145
148
 
149
+ def measure_query(kind, command, &block)
150
+ return block.call if @query_started_at # Prevent from recursive queries
151
+ @query_started_at = Time.now.utc
152
+ begin
153
+ result = block.call
154
+ runtime = (Time.now.utc - @query_started_at) * 1000
155
+ file, line, method = extract_most_relevant_location(caller)
156
+ push_query(kind: kind, command: command, file: file, line: line, method: method, runtime: runtime)
157
+ result
158
+ ensure
159
+ @query_started_at = nil
160
+ end
161
+ end
162
+
146
163
  def catch_error(extra_details = nil, &block)
147
164
  begin
148
165
  block.call
@@ -194,12 +211,13 @@ module RorVsWild
194
211
  MEANINGLESS_QUERIES = %w[BEGIN COMMIT].freeze
195
212
 
196
213
  def push_query(query)
197
- hash = queries.find { |hash| hash[:line] == query[:line] && hash[:file] == query[:file] }
198
- queries << hash = {file: query[:file], line: query[:line], runtime: 0, times: 0} if !hash
214
+ return if !queries
215
+ hash = queries.find { |hash| hash[:line] == query[:line] && hash[:file] == query[:file] && hash[:kind] == query[:kind] }
216
+ queries << hash = {kind: query[:kind], file: query[:file], line: query[:line], runtime: 0, times: 0} if !hash
199
217
  hash[:runtime] += query[:runtime]
200
- if !MEANINGLESS_QUERIES.include?(query[:sql])
218
+ if !MEANINGLESS_QUERIES.include?(query[:command])
201
219
  hash[:times] += 1
202
- hash[:sql] ||= query[:sql]
220
+ hash[:command] ||= query[:command]
203
221
  hash[:plan] ||= query[:plan] if query[:plan]
204
222
  end
205
223
  end
@@ -0,0 +1,37 @@
1
+ module RorVsWild
2
+ module Plugin
3
+ class Mongo
4
+ def self.setup
5
+ return if @installed
6
+ return if !defined?(::Mongo::Monitoring::Global)
7
+ ::Mongo::Monitoring::Global.subscribe(::Mongo::Monitoring::COMMAND, Mongo.new)
8
+ @installed = true
9
+ end
10
+
11
+ attr_reader :commands
12
+
13
+ def initialize
14
+ @commands = {}
15
+ end
16
+
17
+ def started(event)
18
+ commands[event.request_id] = event.command
19
+ end
20
+
21
+ def failed(event)
22
+ after_query(event)
23
+ end
24
+
25
+ def succeeded(event)
26
+ after_query(event)
27
+ end
28
+
29
+ def after_query(event)
30
+ runtime = event.duration * 1000
31
+ command = commands.delete(event.request_id).to_s
32
+ file, line, method = RorVsWild.client.extract_most_relevant_location(caller)
33
+ RorVsWild.client.send(:push_query, kind: "mongo", command: command, file: file, line: line, method: method, runtime: runtime)
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,22 @@
1
+ module RorVsWild
2
+ module Plugin
3
+ class NetHttp
4
+ def self.setup
5
+ return if !defined?(Net::HTTP)
6
+ return if Net::HTTP.method_defined?(:request_without_rorvswild)
7
+
8
+ Net::HTTP.class_eval do
9
+ alias_method :request_without_rorvswild, :request
10
+
11
+ def request(req, body = nil, &block)
12
+ scheme = use_ssl? ? "https".freeze : "http".freeze
13
+ url = "#{req.method} #{scheme}://#{address}#{req.path}"
14
+ RorVsWild.client.measure_query("http".freeze, url) do
15
+ request_without_rorvswild(req, body = nil, &block)
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,24 @@
1
+ module RorVsWild
2
+ module Plugin
3
+ class Redis
4
+ def self.setup
5
+ return if !defined?(::Redis)
6
+ return if ::Redis::Client.method_defined?(:process_without_rorvswild)
7
+ ::Redis::Client.class_eval do
8
+ alias_method :process_without_rorvswild, :process
9
+
10
+ def process(commands, &block)
11
+ string = RorVsWild::Plugin::Redis.commands_to_string(commands)
12
+ RorVsWild.client.measure_query("redis".freeze, string) do
13
+ process_without_rorvswild(commands, &block)
14
+ end
15
+ end
16
+ end
17
+ end
18
+
19
+ def self.commands_to_string(commands)
20
+ commands.map { |c| c[0] == :auth ? "auth *****" : c.join(" ".freeze) }.join("\n".freeze)
21
+ end
22
+ end
23
+ end
24
+ end
@@ -1,3 +1,3 @@
1
1
  module RorVsWild
2
- VERSION = "0.5.1".freeze
2
+ VERSION = "0.6.0".freeze
3
3
  end
data/lib/rorvswild.rb CHANGED
@@ -1,7 +1,10 @@
1
1
  require "rorvswild/version"
2
2
  require "rorvswild/location"
3
+ require "rorvswild/plugin/redis"
4
+ require "rorvswild/plugin/mongo"
3
5
  require "rorvswild/plugin/resque"
4
6
  require "rorvswild/plugin/sidekiq"
7
+ require "rorvswild/plugin/net_http"
5
8
  require "rorvswild/client"
6
9
 
7
10
  module RorVsWild
data/test/helper.rb ADDED
@@ -0,0 +1,7 @@
1
+ path = File.expand_path("#{File.dirname(__FILE__)}/../lib")
2
+ $LOAD_PATH.unshift(path)
3
+
4
+ require "rorvswild"
5
+ require "minitest/autorun"
6
+ require "mocha/mini_test"
7
+ require "top_tests"
@@ -0,0 +1,35 @@
1
+ require File.expand_path("#{File.dirname(__FILE__)}/../helper")
2
+
3
+ require "mongo"
4
+
5
+ class RorVsWild::Plugin::MongoTest < Minitest::Test
6
+ Mongo::Logger.logger.level = ::Logger::FATAL
7
+
8
+ def test_callback
9
+ mountains = [
10
+ {name: "Mont Blanc", altitude: 4807},
11
+ {name: "Mont Cervin", altitude: 4478},
12
+ ]
13
+ client.measure_block("mongo") do
14
+ client = Mongo::Client.new('mongodb://127.0.0.1:27017/test')
15
+ mountains.each { |m| client[:mountains].insert_one(m) }
16
+ end
17
+ assert_equal(1, client.send(:queries).size)
18
+ assert_equal(2, client.send(:queries)[0][:times])
19
+ assert_equal("mongo", client.send(:queries)[0][:kind])
20
+ assert_match('{"insert"=>"mountains", "documents"=>', client.send(:queries)[0][:command])
21
+ end
22
+
23
+ private
24
+
25
+ def client
26
+ @client ||= initialize_client(app_root: "/rails/root")
27
+ end
28
+
29
+ def initialize_client(options = {})
30
+ client = RorVsWild::Client.new(options)
31
+ client.stubs(:post_request)
32
+ client.stubs(:post_job)
33
+ client
34
+ end
35
+ end
@@ -0,0 +1,41 @@
1
+ require File.expand_path("#{File.dirname(__FILE__)}/../helper")
2
+
3
+ require "net/http"
4
+
5
+ class RorVsWild::Plugin::NetHttpTest < Minitest::Test
6
+ def test_callback
7
+ client.measure_block("test") { Net::HTTP.get("ruby-lang.org", "/index.html") }
8
+ assert_equal(1, client.send(:queries).size)
9
+ assert_equal(1, client.send(:queries)[0][:times])
10
+ assert_equal("http", client.send(:queries)[0][:kind])
11
+ assert_match("GET http://ruby-lang.org/index.html", client.send(:queries)[0][:command])
12
+ end
13
+
14
+ def test_callback_with_https
15
+ client.measure_block("test") { Net::HTTP.get(URI("https://www.ruby-lang.org/index.html")) }
16
+ assert_match("GET https://www.ruby-lang.org/index.html", client.send(:queries)[0][:command])
17
+ assert_equal("http", client.send(:queries)[0][:kind])
18
+ end
19
+
20
+ def test_nested_query_because_net_http_request_is_recursive_when_connection_is_not_started
21
+ client.measure_block("test") do
22
+ uri = URI("http://www.ruby-lang.org/index.html")
23
+ http = Net::HTTP.new(uri.host, uri.port)
24
+ http.request(Net::HTTP::Get.new(uri.path))
25
+ end
26
+ assert_equal(1, client.send(:queries)[0][:times])
27
+ end
28
+
29
+ private
30
+
31
+ def client
32
+ @client ||= initialize_client(app_root: "/rails/root")
33
+ end
34
+
35
+ def initialize_client(options = {})
36
+ client = RorVsWild::Client.new(options)
37
+ client.stubs(:post_request)
38
+ client.stubs(:post_job)
39
+ client
40
+ end
41
+ end
@@ -0,0 +1,42 @@
1
+ require File.expand_path("#{File.dirname(__FILE__)}/../helper")
2
+
3
+ require "redis"
4
+
5
+ class RorVsWild::Plugin::RedisTest < Minitest::Test
6
+ def test_callback
7
+ client.measure_code("::Redis.new.get('foo')")
8
+ assert_equal(1, client.send(:queries).size)
9
+ assert_equal("redis", client.send(:queries)[0][:kind])
10
+ assert_equal("get foo", client.send(:queries)[0][:command])
11
+ end
12
+
13
+ def test_callback_with_pipeline
14
+ skip
15
+ client.measure_block("pipeline") do
16
+ redis = ::Redis.new
17
+ redis.get("foo")
18
+ redis.set("foo", "bar")
19
+ end
20
+ assert_equal(2, client.send(:queries).size)
21
+ assert_equal("redis", client.send(:queries)[0][:kind])
22
+ assert_equal("get foo", client.send(:queries)[0][:command])
23
+ assert_equal("set foo bar", client.send(:queries)[1][:command])
24
+ end
25
+
26
+ def test_commands_to_string_hide_auth_password
27
+ assert_equal("auth *****", RorVsWild::Plugin::Redis.commands_to_string([[:auth, "SECRET"]]))
28
+ end
29
+
30
+ private
31
+
32
+ def client
33
+ @client ||= initialize_client(app_root: "/rails/root")
34
+ end
35
+
36
+ def initialize_client(options = {})
37
+ client ||= RorVsWild::Client.new(options)
38
+ client.stubs(:post_request)
39
+ client.stubs(:post_job)
40
+ client
41
+ end
42
+ end
@@ -1,11 +1,4 @@
1
- root_path = File.expand_path(File.dirname(File.dirname(__FILE__)))
2
- $LOAD_PATH.unshift(root_path + "/lib")
3
-
4
- require "rorvswild"
5
-
6
- require "minitest/autorun"
7
- require 'mocha/mini_test'
8
- require "top_tests"
1
+ require File.expand_path("#{File.dirname(__FILE__)}/helper")
9
2
 
10
3
  class RorVsWildTest < Minitest::Test
11
4
  include TopTests
@@ -117,11 +110,11 @@ class RorVsWildTest < Minitest::Test
117
110
  def test_push_query
118
111
  client = initialize_client
119
112
  client.send(:data)[:queries] = []
120
- client.send(:push_query, {file: "file", line: 123, sql: "BEGIN", runtime: 10})
121
- client.send(:push_query, {file: "file", line: 123, sql: "SELECT 1", runtime: 10})
122
- client.send(:push_query, {file: "file", line: 123, sql: "SELECT 1", runtime: 10})
123
- client.send(:push_query, {file: "file", line: 123, sql: "COMMIT", runtime: 10})
124
- assert_equal([{file: "file", line: 123, sql: "SELECT 1", runtime: 40, times: 2}], client.send(:queries))
113
+ client.send(:push_query, {kind: "sql", file: "file", line: 123, command: "BEGIN", runtime: 10})
114
+ client.send(:push_query, {kind: "sql", file: "file", line: 123, command: "SELECT 1", runtime: 10})
115
+ client.send(:push_query, {kind: "sql", file: "file", line: 123, command: "SELECT 1", runtime: 10})
116
+ client.send(:push_query, {kind: "sql", file: "file", line: 123, command: "COMMIT", runtime: 10})
117
+ assert_equal([{kind: "sql", file: "file", line: 123, command: "SELECT 1", runtime: 40, times: 2}], client.send(:queries))
125
118
  end
126
119
 
127
120
  def test_after_exception
data/test/run.rb ADDED
@@ -0,0 +1,3 @@
1
+ require File.expand_path("#{File.dirname(__FILE__)}/helper")
2
+
3
+ Dir.glob("**/*_test.rb").each { |file_path| require File.expand_path(file_path) }
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: 0.5.1
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alexis Bernard
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-02-20 00:00:00.000000000 Z
11
+ date: 2017-02-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -43,12 +43,20 @@ files:
43
43
  - lib/rorvswild/client.rb
44
44
  - lib/rorvswild/installer.rb
45
45
  - lib/rorvswild/location.rb
46
+ - lib/rorvswild/plugin/mongo.rb
47
+ - lib/rorvswild/plugin/net_http.rb
48
+ - lib/rorvswild/plugin/redis.rb
46
49
  - lib/rorvswild/plugin/resque.rb
47
50
  - lib/rorvswild/plugin/sidekiq.rb
48
51
  - lib/rorvswild/rails_loader.rb
49
52
  - lib/rorvswild/version.rb
50
53
  - rorvswild.gemspec
54
+ - test/helper.rb
55
+ - test/plugin/mongo_test.rb
56
+ - test/plugin/net_http_test.rb
57
+ - test/plugin/redis_test.rb
51
58
  - test/ror_vs_wild_test.rb
59
+ - test/run.rb
52
60
  homepage: https://www.rorvswild.com
53
61
  licenses:
54
62
  - MIT
@@ -74,5 +82,10 @@ signing_key:
74
82
  specification_version: 4
75
83
  summary: Ruby on Rails app monitoring
76
84
  test_files:
85
+ - test/helper.rb
86
+ - test/plugin/mongo_test.rb
87
+ - test/plugin/net_http_test.rb
88
+ - test/plugin/redis_test.rb
77
89
  - test/ror_vs_wild_test.rb
90
+ - test/run.rb
78
91
  has_rdoc: