rorvswild 1.0.1 → 1.1.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 3f8e0e177bc8b3c9645a79f0b4d39fcf27ed804f
4
- data.tar.gz: 31e58a5359e4b691d80d23c23dddfaedb9a3fc76
3
+ metadata.gz: 97aed7e941905d99050aa05b33a2d318b49e1e74
4
+ data.tar.gz: ed86f80358c77f008f3e72301f99c175de6988d3
5
5
  SHA512:
6
- metadata.gz: 39a57beba2498edf1ea8e1790a45991f434cfe89e925717a55c0353500d1d62a4068149510ebb24e197d82c9fa10ae9252bedea1316a0ad17694244688501382
7
- data.tar.gz: bd19b326fb647010c5fba1db667804c50742b12c97ff97d58509a99b7922aed9e80ce170a78165cee50e0a9cc96a8eab45b0d046a0a03e6c964bf904d8739a50
6
+ metadata.gz: b2fd50627532be3543aeb2b1279bcb2e513f1a459749d53e59efd08a434bf5a863167279e446e8a574bc2d608e842f4f862cd50a8f23bbdb6eedebfa3251c192
7
+ data.tar.gz: c6ce663a5ba4c0e15b3da29b875a13ec607aada3d2de8855fb8ed305b6da1d0246579234405aa7e9570b1fb6f3a017f96f265eca32f6980c57929558fa45830e
data/Gemfile CHANGED
@@ -13,3 +13,5 @@ gem "actionpack"
13
13
  gem "activejob"
14
14
 
15
15
  gem "delayed_job"
16
+ gem "sidekiq"
17
+ gem "resque"
@@ -6,33 +6,32 @@ module RorVsWild
6
6
 
7
7
  def self.default_config
8
8
  {
9
- api_url: "https://www.rorvswild.com/api",
9
+ api_url: "https://www.rorvswild.com/api/v1",
10
10
  ignored_exceptions: [],
11
11
  }
12
12
  end
13
13
 
14
14
  attr_reader :api_url, :api_key, :app_id, :app_root, :ignored_exceptions
15
15
 
16
- attr_reader :app_root_regex, :client
16
+ attr_reader :app_root_regex, :client, :queue
17
17
 
18
18
  def initialize(config)
19
19
  config = self.class.default_config.merge(config)
20
20
  @ignored_exceptions = config[:ignored_exceptions]
21
21
  @app_root = config[:app_root]
22
- @logger = config[:logger]
23
22
  @client = Client.new(config)
23
+ @queue = Queue.new(client)
24
24
  cleanup_data
25
25
 
26
26
  if defined?(Rails)
27
- @logger ||= Rails.logger
28
27
  @app_root ||= Rails.root.to_s
29
28
  config = Rails.application.config
30
29
  @ignored_exceptions ||= %w[ActionController::RoutingError] + config.action_dispatch.rescue_responses.map { |(key,value)| key }
31
30
  end
32
31
 
33
- @logger ||= Logger.new(STDERR)
34
32
  @app_root_regex = app_root ? /\A#{app_root}/ : nil
35
33
 
34
+ RorVsWild.logger.info("Start RorVsWild #{RorVsWild::VERSION} from #{app_root}")
36
35
  setup_plugins
37
36
  end
38
37
 
@@ -75,13 +74,13 @@ module RorVsWild
75
74
  end
76
75
  end
77
76
 
78
- def measure_job(name, &block)
77
+ def measure_job(name, parameters: nil, &block)
79
78
  return block.call if data[:name] # Prevent from recursive jobs
80
79
  initialize_data(name)
81
80
  begin
82
81
  block.call
83
82
  rescue Exception => ex
84
- data[:error] = exception_to_hash(ex) if !ignored_exception?(ex)
83
+ push_exception(ex, parameters: parameters)
85
84
  raise
86
85
  ensure
87
86
  data[:runtime] = (Time.now - data[:started_at]) * 1000
@@ -114,9 +113,11 @@ module RorVsWild
114
113
  post_error(exception_to_hash(exception, extra_details))
115
114
  end
116
115
 
117
- def push_exception(exception)
116
+ def push_exception(exception, options = nil)
118
117
  return if ignored_exception?(exception)
119
118
  data[:error] = exception_to_hash(exception)
119
+ data[:error].merge!(options) if options
120
+ data[:error]
120
121
  end
121
122
 
122
123
  def data
@@ -152,11 +153,11 @@ module RorVsWild
152
153
  end
153
154
 
154
155
  def post_request
155
- client.post_async("/requests".freeze, request: cleanup_data)
156
+ queue.push_request(cleanup_data)
156
157
  end
157
158
 
158
159
  def post_job
159
- client.post_async("/jobs".freeze, job: cleanup_data)
160
+ queue.push_job(cleanup_data)
160
161
  end
161
162
 
162
163
  def post_error(hash)
@@ -9,7 +9,7 @@ module RorVsWild
9
9
  end
10
10
 
11
11
  def self.around_perform(job, block)
12
- RorVsWild.measure_block(job.class.name, &block)
12
+ RorVsWild.agent.measure_job(job.class.name, parameters: job.arguments, &block)
13
13
  end
14
14
  end
15
15
  end
@@ -9,7 +9,7 @@ module RorVsWild
9
9
  end
10
10
 
11
11
  def self.around_perform(job, &block)
12
- RorVsWild.measure_block(job.name) { block.call(job) }
12
+ RorVsWild.agent.measure_job(job.name, parameters: job.payload_object) { block.call(job) }
13
13
  end
14
14
  end
15
15
  end
@@ -6,7 +6,7 @@ module RorVsWild
6
6
  end
7
7
 
8
8
  def around_perform_rorvswild(*args, &block)
9
- RorVsWild.measure_block(to_s, &block)
9
+ RorVsWild.agent.measure_job(to_s, parameters: args, &block)
10
10
  end
11
11
  end
12
12
  end
@@ -11,7 +11,8 @@ module RorVsWild
11
11
 
12
12
  def call(worker, item, queue, &block)
13
13
  # Wrapped contains the real class name of the ActiveJob wrapper
14
- RorVsWild.measure_block(item["wrapped".freeze] || item["class".freeze], &block)
14
+ name = item["wrapped".freeze] || item["class".freeze]
15
+ RorVsWild.agent.measure_job(name, parameters: item["args".freeze], &block)
15
16
  end
16
17
  end
17
18
  end
@@ -0,0 +1,71 @@
1
+ module RorVsWild
2
+ class Queue
3
+ SLEEP_TIME = 10
4
+ FLUSH_TRESHOLD = 10
5
+
6
+ attr_reader :mutex, :thread, :client
7
+ attr_reader :requests, :jobs
8
+
9
+ def initialize(client)
10
+ @jobs = []
11
+ @requests = []
12
+ @client = client
13
+ @mutex = Mutex.new
14
+ end
15
+
16
+ def push_job(data)
17
+ push_to(jobs, data)
18
+ end
19
+
20
+ def push_request(data)
21
+ push_to(requests, data)
22
+ end
23
+
24
+ def push_to(array, data)
25
+ mutex.synchronize do
26
+ wakeup_thread if array.push(data).size >= FLUSH_TRESHOLD
27
+ end
28
+ end
29
+
30
+ def pull_jobs
31
+ mutex.synchronize do
32
+ if jobs.size > 0
33
+ result = jobs
34
+ @jobs = []
35
+ return result
36
+ end
37
+ end
38
+ end
39
+
40
+ def pull_requests
41
+ mutex.synchronize do
42
+ if requests.size > 0
43
+ result = requests
44
+ @requests = []
45
+ return result
46
+ end
47
+ end
48
+ end
49
+
50
+ def flush_indefinetely
51
+ sleep(SLEEP_TIME) and flush while true
52
+ rescue Exception => ex
53
+ RorVsWild.logger.error(ex)
54
+ raise
55
+ end
56
+
57
+ def flush
58
+ RorVsWild.logger.info("flush")
59
+ data = pull_jobs and client.post("/jobs", jobs: data)
60
+ data = pull_requests and client.post("/requests", requests: data)
61
+ end
62
+
63
+ def start_thread
64
+ @thread = Thread.new { flush_indefinetely }
65
+ end
66
+
67
+ def wakeup_thread
68
+ (thread && thread.alive?) ? thread.wakeup : start_thread
69
+ end
70
+ end
71
+ end
@@ -1,3 +1,3 @@
1
1
  module RorVsWild
2
- VERSION = "1.0.1".freeze
2
+ VERSION = "1.1.0".freeze
3
3
  end
data/lib/rorvswild.rb CHANGED
@@ -3,17 +3,26 @@ require "rorvswild/location"
3
3
  require "rorvswild/section"
4
4
  require "rorvswild/client"
5
5
  require "rorvswild/plugins"
6
+ require "rorvswild/queue"
6
7
  require "rorvswild/agent"
7
8
 
8
9
  module RorVsWild
9
10
  def self.start(config)
11
+ @logger = initialize_logger(config[:logger])
10
12
  @agent = Agent.new(config)
13
+ rescue Exception => ex
14
+ logger.error(ex)
15
+ raise
11
16
  end
12
17
 
13
18
  def self.agent
14
19
  @agent
15
20
  end
16
21
 
22
+ def self.logger
23
+ @logger ||= Logger.new(STDOUT)
24
+ end
25
+
17
26
  def self.measure_code(code)
18
27
  agent ? agent.measure_code(code) : eval(code)
19
28
  end
@@ -29,6 +38,14 @@ module RorVsWild
29
38
  def self.record_error(exception, extra_details = nil)
30
39
  agent.record_error(exception, extra_details) if agent
31
40
  end
41
+
42
+ def self.initialize_logger(destination)
43
+ if destination
44
+ Logger.new(destination)
45
+ elsif defined?(Rails)
46
+ Logger.new(Rails.root + "log/rorvswild.log")
47
+ end
48
+ end
32
49
  end
33
50
 
34
51
  if defined?(Rails)
@@ -2,7 +2,6 @@ require File.expand_path("#{File.dirname(__FILE__)}/helper")
2
2
 
3
3
  class RorVsWild::MeasureNestedSectionsTest < Minitest::Test
4
4
  include RorVsWildAgentHelper
5
- include TopTests
6
5
 
7
6
  def test_measure_section
8
7
  result = agent.measure_block("root") do
@@ -8,14 +8,25 @@ class RorVsWild::Plugin::ActiveJobTest < Minitest::Test
8
8
  class SampleJob < ::ActiveJob::Base
9
9
  queue_as :default
10
10
 
11
- def perform
11
+ def perform(arg)
12
+ raise "Exception" unless arg
12
13
  end
13
14
  end
14
15
 
15
16
  def test_callback
16
17
  ActiveJob::Base.logger = Logger.new("/dev/null")
17
18
  agent.expects(:post_job)
18
- SampleJob.perform_now
19
+ SampleJob.perform_now(1)
20
+ assert_equal("RorVsWild::Plugin::ActiveJobTest::SampleJob", agent.data[:name])
21
+ end
22
+
23
+ def test_callback_on_exception
24
+ ActiveJob::Base.logger = Logger.new("/dev/null")
25
+ agent.expects(:post_job)
26
+ SampleJob.perform_now(false)
27
+ rescue
28
+ ensure
29
+ assert_equal([false], agent.data[:error][:parameters])
19
30
  end
20
31
  end
21
32
 
@@ -6,30 +6,39 @@ class RorVsWild::Plugin::DelayedJobTest < Minitest::Test
6
6
  include RorVsWildAgentHelper
7
7
 
8
8
  class SampleJob
9
+ def initialize(arg)
10
+ @arg = arg
11
+ end
12
+
9
13
  def perform
14
+ raise "Exception" unless @arg
10
15
  end
11
16
  end
12
17
 
18
+ Delayed::Worker.delay_jobs = false
19
+
13
20
  class SampleBackend
14
21
  include Delayed::Backend::Base
15
22
 
16
- attr_accessor :id, :attempts
23
+ attr_accessor :handler
17
24
 
18
25
  def initialize(options)
19
- end
20
-
21
- def payload_object
22
- SampleJob.new
23
- end
24
-
25
- def destroy
26
+ @payload_object = options[:payload_object]
26
27
  end
27
28
  end
28
29
 
29
30
  def test_callback
30
31
  agent.expects(:post_job)
31
- Delayed::Worker.delay_jobs = false
32
- SampleBackend.enqueue(SampleJob.new)
32
+ SampleBackend.enqueue(SampleJob.new(true))
33
+ assert_equal("RorVsWild::Plugin::DelayedJobTest::SampleJob", agent.data[:name])
34
+ end
35
+
36
+ def test_callback_on_exception
37
+ agent.expects(:post_job)
38
+ SampleBackend.enqueue(job = SampleJob.new(false))
39
+ rescue
40
+ ensure
41
+ assert_equal(job, agent.data[:error][:parameters])
33
42
  end
34
43
  end
35
44
 
@@ -0,0 +1,32 @@
1
+ require File.expand_path("#{File.dirname(__FILE__)}/../helper")
2
+
3
+ require "resque"
4
+
5
+ class RorVsWild::Plugin::ResqueTest < Minitest::Test
6
+ include RorVsWildAgentHelper
7
+
8
+ Resque.inline = true
9
+
10
+ class SampleJob < Resque::Job
11
+ @queue = :default
12
+
13
+ def self.perform(arg)
14
+ raise "Exception" unless arg
15
+ end
16
+ end
17
+
18
+ def test_callback
19
+ agent.expects(:post_job)
20
+ Resque.enqueue(SampleJob, true)
21
+ assert_equal("RorVsWild::Plugin::ResqueTest::SampleJob", agent.data[:name])
22
+ end
23
+
24
+ def test_callback_on_exception
25
+ agent.expects(:post_job)
26
+ Resque.enqueue(SampleJob, false)
27
+ rescue
28
+ ensure
29
+ assert_equal([false], agent.data[:error][:parameters])
30
+ end
31
+ end
32
+
@@ -0,0 +1,36 @@
1
+ require File.expand_path("#{File.dirname(__FILE__)}/../helper")
2
+
3
+ require "sidekiq"
4
+ require "sidekiq/testing"
5
+
6
+ class RorVsWild::Plugin::SidekiqTest < Minitest::Test
7
+ include RorVsWildAgentHelper
8
+
9
+ Sidekiq::Testing.server_middleware do |chain|
10
+ chain.add(RorVsWild::Plugin::Sidekiq)
11
+ end
12
+
13
+ class SampleJob
14
+ include ::Sidekiq::Worker
15
+
16
+ # SampleSidekiqJob.perform_async(1)
17
+ def perform(arg)
18
+ raise "Exception" unless arg
19
+ end
20
+ end
21
+
22
+ def test_callback
23
+ agent.expects(:post_job)
24
+ Sidekiq::Testing.inline! { SampleJob.perform_async(1) }
25
+ assert_equal("RorVsWild::Plugin::SidekiqTest::SampleJob", agent.data[:name])
26
+ end
27
+
28
+ def test_callback_on_exception
29
+ agent.expects(:post_job)
30
+ Sidekiq::Testing.inline! { SampleJob.perform_async(false) }
31
+ rescue
32
+ ensure
33
+ assert_equal([false], agent.data[:error][:parameters])
34
+ end
35
+ end
36
+
@@ -0,0 +1,52 @@
1
+ require File.expand_path("#{File.dirname(__FILE__)}/helper")
2
+
3
+ class QueueTest < Minitest::Test
4
+ def test_push_job
5
+ queue.thread.expects(:wakeup)
6
+ 10.times { queue.push_job(1) }
7
+ assert_equal(10, queue.jobs.size)
8
+ end
9
+
10
+ def test_push_request
11
+ queue.thread.expects(:wakeup)
12
+ 10.times { queue.push_request(1) }
13
+ assert_equal(10, queue.requests.size)
14
+ end
15
+
16
+ def test_pull_jobs
17
+ queue.push_job(1)
18
+ assert_equal([1], queue.pull_jobs)
19
+ refute(queue.pull_jobs)
20
+ end
21
+
22
+ def test_pull_requests
23
+ queue.push_request(1)
24
+ assert_equal([1], queue.pull_requests)
25
+ refute(queue.pull_requests)
26
+ end
27
+
28
+ def test_flush_when_jobs_are_present
29
+ queue.client.expects(:post)
30
+ queue.push_job(1)
31
+ queue.flush
32
+ end
33
+
34
+ def test_flush_when_requests_are_present
35
+ queue.client.expects(:post)
36
+ queue.push_request(1)
37
+ queue.flush
38
+ end
39
+
40
+ def test_flush_when_empty
41
+ queue.client.expects(:post).never
42
+ queue.flush
43
+ end
44
+
45
+ def queue
46
+ @queue ||= RorVsWild::Queue.new(client)
47
+ end
48
+
49
+ def client
50
+ @client ||= RorVsWild::Client.new({})
51
+ end
52
+ end
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.0.1
4
+ version: 1.1.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-07-14 00:00:00.000000000 Z
11
+ date: 2017-08-02 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Performances and quality insights for rails developers.
14
14
  email:
@@ -42,6 +42,7 @@ files:
42
42
  - lib/rorvswild/plugin/resque.rb
43
43
  - lib/rorvswild/plugin/sidekiq.rb
44
44
  - lib/rorvswild/plugins.rb
45
+ - lib/rorvswild/queue.rb
45
46
  - lib/rorvswild/rails_loader.rb
46
47
  - lib/rorvswild/section.rb
47
48
  - lib/rorvswild/version.rb
@@ -57,6 +58,9 @@ files:
57
58
  - test/plugin/mongo_test.rb
58
59
  - test/plugin/net_http_test.rb
59
60
  - test/plugin/redis_test.rb
61
+ - test/plugin/resque_test.rb
62
+ - test/plugin/sidekiq_test.rb
63
+ - test/queue_test.rb
60
64
  - test/rorvswild_test.rb
61
65
  - test/run.rb
62
66
  - test/section_test.rb
@@ -96,6 +100,9 @@ test_files:
96
100
  - test/plugin/mongo_test.rb
97
101
  - test/plugin/net_http_test.rb
98
102
  - test/plugin/redis_test.rb
103
+ - test/plugin/resque_test.rb
104
+ - test/plugin/sidekiq_test.rb
105
+ - test/queue_test.rb
99
106
  - test/rorvswild_test.rb
100
107
  - test/run.rb
101
108
  - test/section_test.rb