opbeat 2.0.0 → 3.0.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
- data/.gitignore +4 -3
- data/.travis.yml +19 -28
- data/.yardopts +3 -0
- data/Gemfile +4 -2
- data/HISTORY.md +3 -0
- data/LICENSE +7 -196
- data/README.md +96 -177
- data/Rakefile +19 -13
- data/gemfiles/Gemfile.base +28 -0
- data/gemfiles/Gemfile.rails-3.2.x +3 -0
- data/gemfiles/Gemfile.rails-4.0.x +3 -0
- data/gemfiles/Gemfile.rails-4.1.x +3 -0
- data/gemfiles/Gemfile.rails-4.2.x +3 -0
- data/lib/opbeat.rb +113 -93
- data/lib/opbeat/capistrano.rb +3 -4
- data/lib/opbeat/client.rb +243 -82
- data/lib/opbeat/configuration.rb +51 -64
- data/lib/opbeat/data_builders.rb +16 -0
- data/lib/opbeat/data_builders/error.rb +27 -0
- data/lib/opbeat/data_builders/transactions.rb +85 -0
- data/lib/opbeat/error.rb +1 -2
- data/lib/opbeat/error_message.rb +71 -0
- data/lib/opbeat/error_message/exception.rb +12 -0
- data/lib/opbeat/error_message/http.rb +62 -0
- data/lib/opbeat/error_message/stacktrace.rb +75 -0
- data/lib/opbeat/error_message/user.rb +23 -0
- data/lib/opbeat/filter.rb +53 -43
- data/lib/opbeat/http_client.rb +141 -0
- data/lib/opbeat/injections.rb +83 -0
- data/lib/opbeat/injections/json.rb +19 -0
- data/lib/opbeat/injections/net_http.rb +43 -0
- data/lib/opbeat/injections/redis.rb +23 -0
- data/lib/opbeat/injections/sequel.rb +32 -0
- data/lib/opbeat/injections/sinatra.rb +56 -0
- data/lib/opbeat/{capistrano → integration}/capistrano2.rb +6 -6
- data/lib/opbeat/{capistrano → integration}/capistrano3.rb +3 -3
- data/lib/opbeat/{integrations → integration}/delayed_job.rb +6 -11
- data/lib/opbeat/integration/rails/inject_exceptions_catcher.rb +23 -0
- data/lib/opbeat/integration/railtie.rb +53 -0
- data/lib/opbeat/integration/resque.rb +16 -0
- data/lib/opbeat/integration/sidekiq.rb +38 -0
- data/lib/opbeat/line_cache.rb +21 -0
- data/lib/opbeat/logging.rb +37 -0
- data/lib/opbeat/middleware.rb +59 -0
- data/lib/opbeat/normalizers.rb +65 -0
- data/lib/opbeat/normalizers/action_controller.rb +21 -0
- data/lib/opbeat/normalizers/action_view.rb +71 -0
- data/lib/opbeat/normalizers/active_record.rb +41 -0
- data/lib/opbeat/sql_summarizer.rb +27 -0
- data/lib/opbeat/subscriber.rb +80 -0
- data/lib/opbeat/tasks.rb +20 -18
- data/lib/opbeat/trace.rb +47 -0
- data/lib/opbeat/trace_helpers.rb +29 -0
- data/lib/opbeat/transaction.rb +99 -0
- data/lib/opbeat/util.rb +26 -0
- data/lib/opbeat/util/constantize.rb +54 -0
- data/lib/opbeat/util/inspector.rb +75 -0
- data/lib/opbeat/version.rb +1 -1
- data/lib/opbeat/worker.rb +55 -0
- data/opbeat.gemspec +6 -14
- data/spec/opbeat/client_spec.rb +216 -29
- data/spec/opbeat/configuration_spec.rb +34 -38
- data/spec/opbeat/data_builders/error_spec.rb +43 -0
- data/spec/opbeat/data_builders/transactions_spec.rb +51 -0
- data/spec/opbeat/error_message/exception_spec.rb +22 -0
- data/spec/opbeat/error_message/http_spec.rb +65 -0
- data/spec/opbeat/error_message/stacktrace_spec.rb +56 -0
- data/spec/opbeat/error_message/user_spec.rb +28 -0
- data/spec/opbeat/error_message_spec.rb +78 -0
- data/spec/opbeat/filter_spec.rb +21 -99
- data/spec/opbeat/http_client_spec.rb +64 -0
- data/spec/opbeat/injections/net_http_spec.rb +37 -0
- data/spec/opbeat/injections/sequel_spec.rb +33 -0
- data/spec/opbeat/injections/sinatra_spec.rb +13 -0
- data/spec/opbeat/injections_spec.rb +49 -0
- data/spec/opbeat/integration/delayed_job_spec.rb +35 -0
- data/spec/opbeat/integration/json_spec.rb +41 -0
- data/spec/opbeat/integration/rails_spec.rb +88 -0
- data/spec/opbeat/integration/redis_spec.rb +20 -0
- data/spec/opbeat/integration/resque_spec.rb +42 -0
- data/spec/opbeat/integration/sidekiq_spec.rb +40 -0
- data/spec/opbeat/integration/sinatra_spec.rb +66 -0
- data/spec/opbeat/line_cache_spec.rb +38 -0
- data/spec/opbeat/logging_spec.rb +47 -0
- data/spec/opbeat/middleware_spec.rb +32 -0
- data/spec/opbeat/normalizers/action_controller_spec.rb +32 -0
- data/spec/opbeat/normalizers/action_view_spec.rb +77 -0
- data/spec/opbeat/normalizers/active_record_spec.rb +70 -0
- data/spec/opbeat/normalizers_spec.rb +16 -0
- data/spec/opbeat/sql_summarizer_spec.rb +6 -0
- data/spec/opbeat/subscriber_spec.rb +83 -0
- data/spec/opbeat/trace_spec.rb +43 -0
- data/spec/opbeat/transaction_spec.rb +98 -0
- data/spec/opbeat/util/inspector_spec.rb +40 -0
- data/spec/opbeat/util_spec.rb +20 -0
- data/spec/opbeat/worker_spec.rb +54 -0
- data/spec/opbeat_spec.rb +49 -0
- data/spec/spec_helper.rb +79 -6
- metadata +89 -149
- data/Makefile +0 -3
- data/gemfiles/rails30.gemfile +0 -9
- data/gemfiles/rails31.gemfile +0 -9
- data/gemfiles/rails32.gemfile +0 -9
- data/gemfiles/rails40.gemfile +0 -9
- data/gemfiles/rails41.gemfile +0 -9
- data/gemfiles/rails42.gemfile +0 -9
- data/gemfiles/ruby192_rails31.gemfile +0 -10
- data/gemfiles/ruby192_rails32.gemfile +0 -10
- data/gemfiles/sidekiq31.gemfile +0 -11
- data/lib/opbeat/better_attr_accessor.rb +0 -44
- data/lib/opbeat/event.rb +0 -223
- data/lib/opbeat/integrations/resque.rb +0 -22
- data/lib/opbeat/integrations/sidekiq.rb +0 -32
- data/lib/opbeat/interfaces.rb +0 -35
- data/lib/opbeat/interfaces/exception.rb +0 -16
- data/lib/opbeat/interfaces/http.rb +0 -57
- data/lib/opbeat/interfaces/message.rb +0 -19
- data/lib/opbeat/interfaces/stack_trace.rb +0 -50
- data/lib/opbeat/linecache.rb +0 -25
- data/lib/opbeat/logger.rb +0 -21
- data/lib/opbeat/rack.rb +0 -46
- data/lib/opbeat/rails/middleware/debug_exceptions_catcher.rb +0 -22
- data/lib/opbeat/railtie.rb +0 -26
- data/spec/opbeat/better_attr_accessor_spec.rb +0 -99
- data/spec/opbeat/event_spec.rb +0 -138
- data/spec/opbeat/integrations/delayed_job_spec.rb +0 -38
- data/spec/opbeat/logger_spec.rb +0 -55
- data/spec/opbeat/opbeat_spec.rb +0 -64
- data/spec/opbeat/rack_spec.rb +0 -117
data/Rakefile
CHANGED
|
@@ -1,19 +1,25 @@
|
|
|
1
|
-
require 'rake'
|
|
2
1
|
require 'rubygems/package_task'
|
|
3
|
-
|
|
4
2
|
gemspec = Gem::Specification.load(Dir['*.gemspec'].first)
|
|
5
|
-
|
|
6
3
|
Gem::PackageTask.new(gemspec).define
|
|
7
4
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
spec.pattern = 'spec/**/*_spec.rb'
|
|
12
|
-
end
|
|
13
|
-
rescue LoadError
|
|
14
|
-
task :spec do
|
|
15
|
-
abort "Rspec is not available. bundle install to run unit tests"
|
|
16
|
-
end
|
|
5
|
+
require 'rspec/core/rake_task'
|
|
6
|
+
RSpec::Core::RakeTask.new(:spec) do |spec|
|
|
7
|
+
spec.pattern = 'spec/**/*_spec.rb'
|
|
17
8
|
end
|
|
18
|
-
|
|
19
9
|
task :default => :spec
|
|
10
|
+
|
|
11
|
+
require 'yard'
|
|
12
|
+
YARD::Rake::YardocTask.new
|
|
13
|
+
|
|
14
|
+
task :mem_profile do
|
|
15
|
+
require 'memory_profiler'
|
|
16
|
+
$:.unshift Dir.pwd + '/lib'
|
|
17
|
+
|
|
18
|
+
filename = "profile-#{Time.now.to_i}.txt"
|
|
19
|
+
|
|
20
|
+
MemoryProfiler.report(allow_files: /opbeat/i) do
|
|
21
|
+
require 'opbeat'
|
|
22
|
+
end.pretty_print(to_file: filename)
|
|
23
|
+
|
|
24
|
+
filename
|
|
25
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
source "http://rubygems.org"
|
|
2
|
+
|
|
3
|
+
gemspec path: File.expand_path('../..', __FILE__)
|
|
4
|
+
|
|
5
|
+
gem 'rake'
|
|
6
|
+
gem 'rspec'
|
|
7
|
+
gem 'timecop'
|
|
8
|
+
gem 'webmock'
|
|
9
|
+
gem 'rack-test'
|
|
10
|
+
|
|
11
|
+
gem 'yard'
|
|
12
|
+
gem 'simplecov'
|
|
13
|
+
|
|
14
|
+
# external libs
|
|
15
|
+
|
|
16
|
+
gem 'sinatra'
|
|
17
|
+
gem 'redis'
|
|
18
|
+
gem 'fakeredis'
|
|
19
|
+
gem 'sqlite3'
|
|
20
|
+
gem 'sequel'
|
|
21
|
+
|
|
22
|
+
gem 'delayed_job', require: false
|
|
23
|
+
gem 'resque', require: false
|
|
24
|
+
|
|
25
|
+
unless RUBY_VERSION.to_i <= 1
|
|
26
|
+
gem 'sidekiq', require: false
|
|
27
|
+
end
|
|
28
|
+
|
data/lib/opbeat.rb
CHANGED
|
@@ -1,121 +1,141 @@
|
|
|
1
1
|
require 'opbeat/version'
|
|
2
2
|
require 'opbeat/configuration'
|
|
3
|
-
|
|
3
|
+
|
|
4
|
+
require 'opbeat/logging'
|
|
4
5
|
require 'opbeat/client'
|
|
5
|
-
require 'opbeat/
|
|
6
|
-
require 'opbeat/
|
|
7
|
-
|
|
8
|
-
require 'opbeat/
|
|
9
|
-
require 'opbeat/interfaces/stack_trace'
|
|
10
|
-
require 'opbeat/interfaces/http'
|
|
6
|
+
require 'opbeat/error'
|
|
7
|
+
require 'opbeat/trace_helpers'
|
|
8
|
+
|
|
9
|
+
require 'opbeat/middleware'
|
|
11
10
|
|
|
12
|
-
require 'opbeat/
|
|
13
|
-
require 'opbeat/integrations/sidekiq'
|
|
11
|
+
require 'opbeat/integration/railtie' if defined?(Rails)
|
|
14
12
|
|
|
15
|
-
require 'opbeat/
|
|
13
|
+
require 'opbeat/injections'
|
|
14
|
+
require 'opbeat/injections/net_http'
|
|
15
|
+
require 'opbeat/injections/redis'
|
|
16
|
+
require 'opbeat/injections/sinatra'
|
|
17
|
+
require 'opbeat/injections/sequel'
|
|
16
18
|
|
|
19
|
+
require 'opbeat/integration/delayed_job'
|
|
20
|
+
require 'opbeat/integration/sidekiq'
|
|
21
|
+
require 'opbeat/integration/resque'
|
|
17
22
|
|
|
18
23
|
module Opbeat
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
24
|
+
# Start the Opbeat client
|
|
25
|
+
#
|
|
26
|
+
# @param conf [Configuration] An Configuration object
|
|
27
|
+
def self.start! conf
|
|
28
|
+
Client.start! conf
|
|
29
|
+
end
|
|
23
30
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
31
|
+
# Stop the Opbeat client
|
|
32
|
+
def self.stop!
|
|
33
|
+
Client.stop!
|
|
34
|
+
end
|
|
27
35
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
36
|
+
def self.started?
|
|
37
|
+
!!Client.inst
|
|
38
|
+
end
|
|
31
39
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
40
|
+
# Start a new transaction or return the currently running
|
|
41
|
+
#
|
|
42
|
+
# @param endpoint [String] A description of the transaction, eg `ExamplesController#index`
|
|
43
|
+
# @param kind [String] The kind of the transaction, eg `app.request.get` or `db.mysql2.query`
|
|
44
|
+
# @param result [Object] Result of the transaction, eq `200` for a HTTP server
|
|
45
|
+
# @yield [Transaction] Optional block encapsulating transaction
|
|
46
|
+
# @return [Transaction] Unless block given
|
|
47
|
+
def self.transaction endpoint, kind = nil, result = nil, &block
|
|
48
|
+
unless client
|
|
49
|
+
return yield if block_given?
|
|
50
|
+
return nil
|
|
35
51
|
end
|
|
36
52
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
def configuration
|
|
40
|
-
@configuration ||= Configuration.new
|
|
41
|
-
end
|
|
53
|
+
client.transaction endpoint, kind, result, &block
|
|
54
|
+
end
|
|
42
55
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
56
|
+
# Starts a new trace under the current Transaction
|
|
57
|
+
#
|
|
58
|
+
# @param signature [String] A description of the trace, eq `SELECT FROM "users"`
|
|
59
|
+
# @param kind [String] The kind of trace, eq `db.mysql2.query`
|
|
60
|
+
# @param extra [Hash] Extra information about the trace
|
|
61
|
+
# @yield [Trace] Optional block encapsulating trace
|
|
62
|
+
# @return [Trace] Unless block given
|
|
63
|
+
def self.trace signature, kind = nil, extra = nil, &block
|
|
64
|
+
unless client
|
|
65
|
+
return yield if block_given?
|
|
66
|
+
return nil
|
|
54
67
|
end
|
|
55
68
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
69
|
+
client.trace signature, kind, extra, &block
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def self.flush_transactions
|
|
73
|
+
unless client
|
|
74
|
+
return yield if block_given?
|
|
75
|
+
return nil
|
|
63
76
|
end
|
|
64
77
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
rescue Exception => e
|
|
79
|
-
self.captureException(e)
|
|
80
|
-
raise
|
|
81
|
-
end
|
|
82
|
-
else
|
|
83
|
-
# Install at_exit hook
|
|
84
|
-
at_exit do
|
|
85
|
-
if $!
|
|
86
|
-
logger.debug "Caught a post-mortem exception: #{$!.inspect}"
|
|
87
|
-
self.capture_exception($!)
|
|
88
|
-
end
|
|
89
|
-
end
|
|
90
|
-
end
|
|
78
|
+
client.flush_transactions
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# Send an exception to Opbeat
|
|
82
|
+
#
|
|
83
|
+
# @param exception [Exception]
|
|
84
|
+
# @param opts [Hash]
|
|
85
|
+
# @option opts [Hash] :rack_env A rack env object
|
|
86
|
+
# @return [Net::HTTPResponse]
|
|
87
|
+
def self.report exception, opts = {}
|
|
88
|
+
unless client
|
|
89
|
+
return yield if block_given?
|
|
90
|
+
return nil
|
|
91
91
|
end
|
|
92
92
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
93
|
+
client.report exception, opts
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
# Send an exception to Opbeat
|
|
97
|
+
#
|
|
98
|
+
# @param message [String]
|
|
99
|
+
# @param opts [Hash]
|
|
100
|
+
# @return [Net::HTTPResponse]
|
|
101
|
+
def self.report_message message, opts = {}
|
|
102
|
+
unless client
|
|
103
|
+
return yield if block_given?
|
|
104
|
+
return nil
|
|
102
105
|
end
|
|
103
106
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
107
|
+
client.report_message message, opts
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
# Captures any exceptions raised inside the block
|
|
111
|
+
#
|
|
112
|
+
def self.capture &block
|
|
113
|
+
unless client
|
|
114
|
+
return yield if block_given?
|
|
115
|
+
return nil
|
|
112
116
|
end
|
|
113
117
|
|
|
114
|
-
|
|
115
|
-
|
|
118
|
+
client.capture(&block)
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
# Notify Opbeat of a release
|
|
122
|
+
#
|
|
123
|
+
# @param rel [Hash]
|
|
124
|
+
# @option rel [String] :rev Revision
|
|
125
|
+
# @option rel [String] :branch
|
|
126
|
+
# @return [Net::HTTPResponse]
|
|
127
|
+
def self.release rel, opts = {}
|
|
128
|
+
unless client
|
|
129
|
+
return yield if block_given?
|
|
130
|
+
return nil
|
|
116
131
|
end
|
|
117
132
|
|
|
118
|
-
|
|
119
|
-
|
|
133
|
+
client.release rel, opts
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
private
|
|
137
|
+
|
|
138
|
+
def self.client
|
|
139
|
+
Client.inst
|
|
120
140
|
end
|
|
121
141
|
end
|
data/lib/opbeat/capistrano.rb
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
require 'capistrano'
|
|
2
2
|
require 'capistrano/version'
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
load File.expand_path('../capistrano/capistrano3.rb', __FILE__)
|
|
4
|
+
if Capistrano::VERSION.to_i <= 2
|
|
5
|
+
require 'opbeat/integration/capistrano2'
|
|
7
6
|
else
|
|
8
|
-
|
|
7
|
+
require 'opbeat/integration/capistrano3'
|
|
9
8
|
end
|
data/lib/opbeat/client.rb
CHANGED
|
@@ -1,122 +1,283 @@
|
|
|
1
|
-
require '
|
|
2
|
-
require '
|
|
3
|
-
require '
|
|
4
|
-
require '
|
|
5
|
-
|
|
6
|
-
require 'opbeat/
|
|
7
|
-
require 'opbeat/
|
|
8
|
-
require 'opbeat/
|
|
1
|
+
require 'thread'
|
|
2
|
+
require 'opbeat/subscriber'
|
|
3
|
+
require 'opbeat/http_client'
|
|
4
|
+
require 'opbeat/worker'
|
|
5
|
+
require 'opbeat/transaction'
|
|
6
|
+
require 'opbeat/trace'
|
|
7
|
+
require 'opbeat/error_message'
|
|
8
|
+
require 'opbeat/data_builders'
|
|
9
9
|
|
|
10
10
|
module Opbeat
|
|
11
|
+
# @api private
|
|
12
|
+
class Client
|
|
13
|
+
include Logging
|
|
14
|
+
|
|
15
|
+
KEY = :__opbeat_transaction_key
|
|
16
|
+
LOCK = Mutex.new
|
|
11
17
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
18
|
+
class TransactionInfo
|
|
19
|
+
def current
|
|
20
|
+
Thread.current[KEY]
|
|
21
|
+
end
|
|
22
|
+
def current= transaction
|
|
23
|
+
Thread.current[KEY] = transaction
|
|
24
|
+
end
|
|
17
25
|
end
|
|
18
26
|
|
|
19
|
-
|
|
20
|
-
return true if @status == :online
|
|
27
|
+
# life cycle
|
|
21
28
|
|
|
22
|
-
|
|
23
|
-
|
|
29
|
+
def self.inst
|
|
30
|
+
@instance
|
|
31
|
+
end
|
|
24
32
|
|
|
25
|
-
|
|
33
|
+
def self.start! config = nil
|
|
34
|
+
return @instance if @instance
|
|
35
|
+
|
|
36
|
+
LOCK.synchronize do
|
|
37
|
+
return @instance if @instance
|
|
38
|
+
@instance = new(config).start!
|
|
39
|
+
end
|
|
26
40
|
end
|
|
27
41
|
|
|
28
|
-
def
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
42
|
+
def self.stop!
|
|
43
|
+
LOCK.synchronize do
|
|
44
|
+
return unless @instance
|
|
45
|
+
|
|
46
|
+
@instance.stop!
|
|
47
|
+
@instance = nil
|
|
48
|
+
end
|
|
32
49
|
end
|
|
33
50
|
|
|
34
|
-
def
|
|
35
|
-
@
|
|
36
|
-
|
|
37
|
-
@
|
|
51
|
+
def initialize config
|
|
52
|
+
@config = config
|
|
53
|
+
|
|
54
|
+
@http_client = HttpClient.new config
|
|
55
|
+
@queue = Queue.new
|
|
56
|
+
|
|
57
|
+
@data_builders = Struct.new(:transactions, :error_message).new(
|
|
58
|
+
DataBuilders::Transactions.new(config),
|
|
59
|
+
DataBuilders::Error.new(config)
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
unless config.disable_performance
|
|
63
|
+
@transaction_info = TransactionInfo.new
|
|
64
|
+
@subscriber = Subscriber.new config, self
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
@pending_transactions = []
|
|
68
|
+
@last_sent_transactions = Time.now.utc
|
|
38
69
|
end
|
|
39
|
-
end
|
|
40
70
|
|
|
41
|
-
|
|
71
|
+
attr_reader :config, :queue, :pending_transactions
|
|
42
72
|
|
|
43
|
-
|
|
73
|
+
def start!
|
|
74
|
+
info "Starting client"
|
|
44
75
|
|
|
45
|
-
|
|
46
|
-
attr_accessor :state
|
|
76
|
+
@subscriber.register! if @subscriber
|
|
47
77
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
raise Error.new('No secret token specified') unless conf.secret_token
|
|
51
|
-
raise Error.new('No organization ID specified') unless conf.organization_id
|
|
52
|
-
raise Error.new('No app ID specified') unless conf.app_id
|
|
78
|
+
self
|
|
79
|
+
end
|
|
53
80
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
@auth_header = 'Bearer ' + conf.secret_token
|
|
81
|
+
def stop!
|
|
82
|
+
flush_transactions
|
|
83
|
+
kill_worker
|
|
84
|
+
unregister! if @subscriber
|
|
59
85
|
end
|
|
60
86
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
87
|
+
at_exit do
|
|
88
|
+
stop!
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
# metrics
|
|
92
|
+
|
|
93
|
+
def current_transaction
|
|
94
|
+
@transaction_info.current
|
|
69
95
|
end
|
|
70
96
|
|
|
71
|
-
def
|
|
72
|
-
|
|
73
|
-
event_hash = @filter.process_event_hash(event_hash)
|
|
74
|
-
return MultiJson.encode(event_hash)
|
|
97
|
+
def current_transaction= transaction
|
|
98
|
+
@transaction_info.current = transaction
|
|
75
99
|
end
|
|
76
100
|
|
|
77
|
-
def
|
|
101
|
+
def transaction endpoint, kind = nil, result = nil, &block
|
|
102
|
+
if config.disable_performance
|
|
103
|
+
return yield if block_given?
|
|
104
|
+
return nil
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
if transaction = current_transaction
|
|
108
|
+
yield transaction if block_given?
|
|
109
|
+
return transaction
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
transaction = Transaction.new self, endpoint, kind, result
|
|
113
|
+
|
|
114
|
+
self.current_transaction = transaction
|
|
115
|
+
return transaction unless block_given?
|
|
116
|
+
|
|
78
117
|
begin
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
118
|
+
yield transaction
|
|
119
|
+
|
|
120
|
+
ensure
|
|
121
|
+
self.current_transaction = nil
|
|
122
|
+
transaction.done
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
transaction
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def trace *args, &block
|
|
129
|
+
if config.disable_performance
|
|
130
|
+
return yield if block_given?
|
|
131
|
+
return nil
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
unless transaction = current_transaction
|
|
135
|
+
return yield if block_given?
|
|
136
|
+
return
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
transaction.trace(*args, &block)
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
def submit_transaction transaction
|
|
143
|
+
ensure_worker_running
|
|
144
|
+
|
|
145
|
+
if config.debug_traces
|
|
146
|
+
unless transaction.endpoint == 'Rack'
|
|
147
|
+
debug { Util::Inspector.new.transaction transaction, include_parents: true }
|
|
85
148
|
end
|
|
86
|
-
|
|
87
|
-
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
@pending_transactions << transaction
|
|
152
|
+
|
|
153
|
+
if should_send_transactions?
|
|
154
|
+
flush_transactions
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
def flush_transactions
|
|
159
|
+
return if @pending_transactions.empty?
|
|
160
|
+
|
|
161
|
+
data = @data_builders.transactions.build(@pending_transactions)
|
|
162
|
+
enqueue Worker::PostRequest.new('/transactions/', data)
|
|
163
|
+
|
|
164
|
+
@last_sent_transactions = Time.now.utc
|
|
165
|
+
@pending_transactions = []
|
|
166
|
+
|
|
167
|
+
true
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
# errors
|
|
171
|
+
|
|
172
|
+
def report exception, opts = {}
|
|
173
|
+
return if config.disable_errors
|
|
174
|
+
return unless exception
|
|
175
|
+
|
|
176
|
+
unless exception.backtrace
|
|
177
|
+
exception.set_backtrace caller
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
error_message = ErrorMessage.from_exception(config, exception, opts)
|
|
181
|
+
data = @data_builders.error_message.build error_message
|
|
182
|
+
enqueue Worker::PostRequest.new('/errors/', data)
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
def report_message message, opts = {}
|
|
186
|
+
return if config.disable_errors
|
|
187
|
+
|
|
188
|
+
error_message = ErrorMessage.new(config, message, opts)
|
|
189
|
+
data = @data_builders.error_message.build error_message
|
|
190
|
+
enqueue Worker::PostRequest.new('/errors/', data)
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
def capture &block
|
|
194
|
+
unless block_given?
|
|
195
|
+
return Kernel.at_exit do
|
|
196
|
+
if $!
|
|
197
|
+
debug $!.inspect
|
|
198
|
+
report $!
|
|
199
|
+
end
|
|
88
200
|
end
|
|
89
|
-
|
|
90
|
-
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
begin
|
|
204
|
+
yield
|
|
205
|
+
rescue Error => e
|
|
206
|
+
raise # Don't capture Opbeat errors
|
|
207
|
+
rescue Exception => e
|
|
208
|
+
report e
|
|
91
209
|
raise
|
|
92
210
|
end
|
|
211
|
+
end
|
|
93
212
|
|
|
94
|
-
|
|
95
|
-
|
|
213
|
+
# releases
|
|
214
|
+
|
|
215
|
+
def release rel, opts = {}
|
|
216
|
+
rev = rel[:rev]
|
|
217
|
+
if opts[:inline]
|
|
218
|
+
debug "Sending release #{rev}"
|
|
219
|
+
@http_client.post '/releases/', rel
|
|
220
|
+
else
|
|
221
|
+
debug "Enqueuing release #{rev}"
|
|
222
|
+
enqueue Worker::PostRequest.new('/releases/', rel)
|
|
223
|
+
end
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
private
|
|
227
|
+
|
|
228
|
+
def enqueue request
|
|
229
|
+
@queue << request
|
|
96
230
|
end
|
|
97
231
|
|
|
98
|
-
def
|
|
99
|
-
return
|
|
100
|
-
|
|
101
|
-
|
|
232
|
+
def start_worker
|
|
233
|
+
return if worker_running?
|
|
234
|
+
|
|
235
|
+
if config.disable_worker
|
|
102
236
|
return
|
|
103
237
|
end
|
|
104
238
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
239
|
+
info "Starting worker in thread"
|
|
240
|
+
|
|
241
|
+
@worker_thread = Thread.new do
|
|
242
|
+
begin
|
|
243
|
+
Worker.new(config, @queue, @http_client).run
|
|
244
|
+
rescue => e
|
|
245
|
+
fatal "Failed booting worker:\n#{e.inspect}"
|
|
246
|
+
debug e.backtrace.join("\n")
|
|
247
|
+
raise
|
|
248
|
+
end
|
|
112
249
|
end
|
|
113
|
-
response
|
|
114
250
|
end
|
|
115
251
|
|
|
116
|
-
def
|
|
117
|
-
|
|
118
|
-
|
|
252
|
+
def kill_worker
|
|
253
|
+
return unless worker_running?
|
|
254
|
+
@queue << Worker::StopMessage.new
|
|
255
|
+
@worker_thread.join 1
|
|
256
|
+
@worker_thread = nil
|
|
119
257
|
end
|
|
120
|
-
end
|
|
121
258
|
|
|
259
|
+
def ensure_worker_running
|
|
260
|
+
return if worker_running?
|
|
261
|
+
|
|
262
|
+
LOCK.synchronize do
|
|
263
|
+
return if worker_running?
|
|
264
|
+
start_worker
|
|
265
|
+
end
|
|
266
|
+
end
|
|
267
|
+
|
|
268
|
+
def worker_running?
|
|
269
|
+
@worker_thread && @worker_thread.alive?
|
|
270
|
+
end
|
|
271
|
+
|
|
272
|
+
def unregister!
|
|
273
|
+
@subscriber.unregister!
|
|
274
|
+
end
|
|
275
|
+
|
|
276
|
+
def should_send_transactions?
|
|
277
|
+
return true if config.transaction_post_interval.nil?
|
|
278
|
+
|
|
279
|
+
Time.now.utc - @last_sent_transactions > config.transaction_post_interval
|
|
280
|
+
end
|
|
281
|
+
|
|
282
|
+
end
|
|
122
283
|
end
|