opbeat 2.0.0 → 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
@@ -0,0 +1,65 @@
|
|
1
|
+
module Opbeat
|
2
|
+
# @api private
|
3
|
+
module Normalizers
|
4
|
+
|
5
|
+
class Normalizer
|
6
|
+
def self.register name
|
7
|
+
Normalizers.register name, self
|
8
|
+
end
|
9
|
+
|
10
|
+
def initialize config
|
11
|
+
@config = config
|
12
|
+
end
|
13
|
+
|
14
|
+
attr_reader :config
|
15
|
+
end
|
16
|
+
|
17
|
+
class Default < Normalizer
|
18
|
+
def normalize transaction, name, payload
|
19
|
+
:skip
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
DEFAULT = Default.new nil
|
24
|
+
|
25
|
+
def self.register name, cls
|
26
|
+
(@registered ||= {})[name] = cls
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.build config
|
30
|
+
normalizers = @registered.reduce({}) do |coll, kv|
|
31
|
+
name, cls = kv
|
32
|
+
coll[name] = cls.new config
|
33
|
+
coll
|
34
|
+
end
|
35
|
+
|
36
|
+
Container.new(normalizers)
|
37
|
+
end
|
38
|
+
|
39
|
+
class Container
|
40
|
+
def initialize normalizers
|
41
|
+
@normalizers = normalizers
|
42
|
+
end
|
43
|
+
|
44
|
+
def keys
|
45
|
+
@normalizers.keys
|
46
|
+
end
|
47
|
+
|
48
|
+
def normalizer_for name
|
49
|
+
@normalizers[name] || DEFAULT
|
50
|
+
end
|
51
|
+
|
52
|
+
def normalize transaction, name, payload
|
53
|
+
normalizer_for(name).normalize transaction, name, payload
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
%w{
|
58
|
+
action_controller
|
59
|
+
active_record
|
60
|
+
action_view
|
61
|
+
}.each do |f|
|
62
|
+
require "opbeat/normalizers/#{f}"
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Opbeat
|
2
|
+
module Normalizers
|
3
|
+
module ActionController
|
4
|
+
class ProcessAction < Normalizer
|
5
|
+
register 'process_action.action_controller'
|
6
|
+
KIND = 'app.controller.action'.freeze
|
7
|
+
|
8
|
+
def normalize transaction, name, payload
|
9
|
+
transaction.endpoint = endpoint(payload)
|
10
|
+
[transaction.endpoint, KIND, nil]
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def endpoint payload
|
16
|
+
"#{payload[:controller]}##{payload[:action]}"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
module Opbeat
|
2
|
+
module Normalizers
|
3
|
+
module ActionView
|
4
|
+
|
5
|
+
class RenderNormalizer < Normalizer
|
6
|
+
def normalize_render payload, kind
|
7
|
+
signature = path_for(payload[:identifier])
|
8
|
+
|
9
|
+
[signature, kind, nil]
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def path_for identifier
|
15
|
+
return "Unknown template".freeze unless path = identifier
|
16
|
+
return path unless path.start_with?("/")
|
17
|
+
|
18
|
+
path && relative_path(path)
|
19
|
+
end
|
20
|
+
|
21
|
+
def relative_path path
|
22
|
+
root = config.view_paths.find { |p| path.start_with? p }
|
23
|
+
type = :app
|
24
|
+
|
25
|
+
unless root
|
26
|
+
root = Gem.path.find { |p| path.start_with? p }
|
27
|
+
type = :gem
|
28
|
+
end
|
29
|
+
|
30
|
+
return "Absolute path".freeze unless root
|
31
|
+
|
32
|
+
start = root.length
|
33
|
+
start += 1 if path[root.length] == "/".freeze
|
34
|
+
|
35
|
+
if type == :gem
|
36
|
+
"$GEM_PATH/#{path[start, path.length]}"
|
37
|
+
else
|
38
|
+
path[start, path.length]
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
class RenderTemplate < RenderNormalizer
|
44
|
+
register 'render_template.action_view'
|
45
|
+
KIND = 'template.view'.freeze
|
46
|
+
|
47
|
+
def normalize transaction, name, payload
|
48
|
+
normalize_render(payload, KIND)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
class RenderPartial < RenderNormalizer
|
53
|
+
register 'render_partial.action_view'
|
54
|
+
KIND = 'template.view.partial'.freeze
|
55
|
+
|
56
|
+
def normalize transaction, name, payload
|
57
|
+
normalize_render(payload, KIND)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
class RenderCollection < RenderNormalizer
|
62
|
+
register 'render_collection.action_view'
|
63
|
+
KIND = 'template.view.collection'.freeze
|
64
|
+
|
65
|
+
def normalize transaction, name, payload
|
66
|
+
normalize_render(payload, KIND)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'opbeat/sql_summarizer'
|
2
|
+
|
3
|
+
module Opbeat
|
4
|
+
module Normalizers
|
5
|
+
module ActiveRecord
|
6
|
+
class SQL < Normalizer
|
7
|
+
register 'sql.active_record'
|
8
|
+
|
9
|
+
def initialize *args
|
10
|
+
super(*args)
|
11
|
+
adapter = ::ActiveRecord::Base.connection.adapter_name.downcase rescue nil
|
12
|
+
@kind = "db.#{adapter || 'unknown'}.sql".freeze
|
13
|
+
@sql_parser = SqlSummarizer.new config
|
14
|
+
end
|
15
|
+
|
16
|
+
def normalize transaction, name, payload
|
17
|
+
if %w{SCHEMA CACHE}.include? payload[:name]
|
18
|
+
return :skip
|
19
|
+
end
|
20
|
+
|
21
|
+
signature =
|
22
|
+
signature_for(payload[:sql]) || # SELECT FROM "users"
|
23
|
+
payload[:name] || # Users load
|
24
|
+
"SQL".freeze
|
25
|
+
|
26
|
+
if signature == 'SELECT FROM "schema_migrations"'
|
27
|
+
return :skip
|
28
|
+
end
|
29
|
+
|
30
|
+
[signature, @kind, { sql: payload[:sql] }]
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def signature_for sql
|
36
|
+
@sql_parser.signature_for(sql)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Opbeat
|
2
|
+
# @api private
|
3
|
+
class SqlSummarizer
|
4
|
+
CACHE = {}
|
5
|
+
TBL = "[^ ]+".freeze
|
6
|
+
REGEXES = {
|
7
|
+
/^SELECT .* FROM (#{TBL})/i => "SELECT FROM ".freeze,
|
8
|
+
/^INSERT INTO (#{TBL})/i => "INSERT INTO ".freeze,
|
9
|
+
/^UPDATE (#{TBL})/i => "UPDATE ".freeze,
|
10
|
+
/^DELETE FROM (#{TBL})/i => "DELETE FROM ".freeze
|
11
|
+
}.freeze
|
12
|
+
|
13
|
+
def initialize config
|
14
|
+
@config = config
|
15
|
+
end
|
16
|
+
|
17
|
+
def signature_for sql
|
18
|
+
return CACHE[sql] if CACHE[sql]
|
19
|
+
|
20
|
+
REGEXES.find do |regex, sig|
|
21
|
+
if match = sql.match(regex)
|
22
|
+
break sig + match[1]
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'active_support/notifications'
|
2
|
+
require 'opbeat/normalizers'
|
3
|
+
|
4
|
+
module Opbeat
|
5
|
+
# @api private
|
6
|
+
class Subscriber
|
7
|
+
include Logging
|
8
|
+
|
9
|
+
def initialize config, client
|
10
|
+
@config = config
|
11
|
+
@client = client
|
12
|
+
@normalizers = Normalizers.build config
|
13
|
+
end
|
14
|
+
|
15
|
+
attr_reader :config
|
16
|
+
|
17
|
+
def register!
|
18
|
+
unregister! if @subscription
|
19
|
+
@subscription = ActiveSupport::Notifications.subscribe actions_regex, self
|
20
|
+
end
|
21
|
+
|
22
|
+
def unregister!
|
23
|
+
ActiveSupport::Notifications.unsubscribe @subscription
|
24
|
+
@subscription = nil
|
25
|
+
end
|
26
|
+
|
27
|
+
# AS::Notifications API
|
28
|
+
|
29
|
+
class Notification
|
30
|
+
def initialize id, trace
|
31
|
+
@id = id
|
32
|
+
@trace = trace
|
33
|
+
end
|
34
|
+
attr_reader :id, :trace
|
35
|
+
end
|
36
|
+
|
37
|
+
def start name, id, payload
|
38
|
+
return unless transaction = @client.current_transaction
|
39
|
+
|
40
|
+
normalized = @normalizers.normalize(transaction, name, payload)
|
41
|
+
|
42
|
+
trace = nil
|
43
|
+
|
44
|
+
unless normalized == :skip
|
45
|
+
sig, kind, extra = normalized
|
46
|
+
|
47
|
+
trace = Trace.new(transaction, sig, kind, transaction.running_traces, extra)
|
48
|
+
offset = transaction.current_offset
|
49
|
+
|
50
|
+
transaction.traces << trace
|
51
|
+
|
52
|
+
trace.start offset
|
53
|
+
end
|
54
|
+
|
55
|
+
transaction.notifications << Notification.new(id, trace)
|
56
|
+
end
|
57
|
+
|
58
|
+
def finish name, id, payload
|
59
|
+
return unless transaction = @client.current_transaction
|
60
|
+
|
61
|
+
while notification = transaction.notifications.pop
|
62
|
+
if notification.id == id
|
63
|
+
if trace = notification.trace
|
64
|
+
trace.done
|
65
|
+
end
|
66
|
+
return
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
private
|
72
|
+
|
73
|
+
def actions_regex
|
74
|
+
@actions_regex ||= Regexp.new(
|
75
|
+
"(".freeze + @normalizers.keys.join("|".freeze) + ")".freeze
|
76
|
+
)
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
80
|
+
end
|
data/lib/opbeat/tasks.rb
CHANGED
@@ -1,24 +1,26 @@
|
|
1
|
-
# Capistrano tasks for notifying Opbeat of deploys
|
2
1
|
namespace :opbeat do
|
3
|
-
desc "Notify Opbeat of a
|
4
|
-
task :
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
load initializer_file
|
10
|
-
else
|
11
|
-
Rake::Task[:environment].invoke
|
12
|
-
end
|
2
|
+
desc "Notify Opbeat of a release"
|
3
|
+
task :release => :environment do
|
4
|
+
unless rev = ENV["REV"]
|
5
|
+
puts "Please specify a revision in an env variable\n" +
|
6
|
+
"eg. REV=abc123 rake opbeat:release"
|
7
|
+
exit 1
|
13
8
|
end
|
14
|
-
rev = ENV['REV']
|
15
9
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
10
|
+
# empty env means dev
|
11
|
+
ENV["RAILS_ENV"] ||= 'development'
|
12
|
+
|
13
|
+
# log to STDOUT
|
14
|
+
Opbeat::Client.inst.config.logger = Logger.new STDOUT
|
15
|
+
|
16
|
+
unless Opbeat.release({
|
17
|
+
rev: rev,
|
18
|
+
branch: ENV['BRANCH'],
|
19
|
+
status: 'completed'
|
20
|
+
}, inline: true)
|
21
|
+
exit 1 # release returned nil
|
21
22
|
end
|
22
23
|
end
|
23
|
-
end
|
24
24
|
|
25
|
+
task :deployment => :release
|
26
|
+
end
|
data/lib/opbeat/trace.rb
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'opbeat/util'
|
2
|
+
|
3
|
+
module Opbeat
|
4
|
+
class Trace
|
5
|
+
|
6
|
+
DEFAULT_KIND = 'code.custom'.freeze
|
7
|
+
|
8
|
+
def initialize transaction, signature, kind = nil, parents = [], extra = nil
|
9
|
+
@transaction = transaction
|
10
|
+
@signature = signature
|
11
|
+
@kind = kind || DEFAULT_KIND
|
12
|
+
@parents = parents || []
|
13
|
+
@extra = extra
|
14
|
+
|
15
|
+
@timestamp = Util.nearest_minute.to_i
|
16
|
+
end
|
17
|
+
|
18
|
+
attr_accessor :signature, :kind, :parents, :extra
|
19
|
+
attr_reader :transaction, :timestamp, :duration, :relative_start, :start_time
|
20
|
+
|
21
|
+
def start relative_to
|
22
|
+
@start_time = Util.nanos
|
23
|
+
@relative_start = start_time - relative_to
|
24
|
+
|
25
|
+
self
|
26
|
+
end
|
27
|
+
|
28
|
+
def done ms = Util.nanos
|
29
|
+
@duration = ms - start_time
|
30
|
+
|
31
|
+
self
|
32
|
+
end
|
33
|
+
|
34
|
+
def done?
|
35
|
+
!!duration
|
36
|
+
end
|
37
|
+
|
38
|
+
def running?
|
39
|
+
!done?
|
40
|
+
end
|
41
|
+
|
42
|
+
def inspect
|
43
|
+
info = %w{signature kind parents extra timestamp duration relative_start}
|
44
|
+
"<Trace #{info.map { |m| "#{m}:#{send(m).inspect}" }.join(' ')}>"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Opbeat
|
2
|
+
module TraceHelpers
|
3
|
+
module ClassMethods
|
4
|
+
def trace_class_method method, signature, kind
|
5
|
+
__trace_method_on(singleton_class, method, signature, kind)
|
6
|
+
end
|
7
|
+
|
8
|
+
private
|
9
|
+
|
10
|
+
def __trace_method_on(klass, method, signature, kind)
|
11
|
+
klass.class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
12
|
+
alias :"__without_opb_#{method}" :"#{method}"
|
13
|
+
|
14
|
+
def #{method}(*args, &block)
|
15
|
+
Opbeat.trace "#{signature}", "#{kind}" do
|
16
|
+
__without_opb_#{method}(*args, &block)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
RUBY
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.included(kls)
|
24
|
+
kls.class_eval do
|
25
|
+
extend ClassMethods
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
require 'opbeat/util'
|
2
|
+
|
3
|
+
module Opbeat
|
4
|
+
class Transaction
|
5
|
+
|
6
|
+
ROOT_TRACE_NAME = 'transaction'.freeze
|
7
|
+
|
8
|
+
def initialize client, endpoint, kind = 'code.custom', result = nil
|
9
|
+
@client = client
|
10
|
+
@endpoint = endpoint
|
11
|
+
@kind = kind
|
12
|
+
@result = result
|
13
|
+
|
14
|
+
@timestamp = Util.nearest_minute.to_i
|
15
|
+
|
16
|
+
@root_trace = Trace.new(self, ROOT_TRACE_NAME, ROOT_TRACE_NAME)
|
17
|
+
@traces = [@root_trace]
|
18
|
+
@notifications = []
|
19
|
+
|
20
|
+
@start_time = Util.nanos
|
21
|
+
@root_trace.start @start_time
|
22
|
+
end
|
23
|
+
|
24
|
+
attr_accessor :endpoint, :kind, :result, :duration
|
25
|
+
attr_reader :timestamp, :start_time, :traces, :notifications, :root_trace
|
26
|
+
|
27
|
+
def release
|
28
|
+
@client.current_transaction = nil
|
29
|
+
end
|
30
|
+
|
31
|
+
def done result = nil
|
32
|
+
@result = result
|
33
|
+
|
34
|
+
@root_trace.done Util.nanos
|
35
|
+
@duration = @root_trace.duration
|
36
|
+
|
37
|
+
self
|
38
|
+
end
|
39
|
+
|
40
|
+
def done?
|
41
|
+
@root_trace.done?
|
42
|
+
end
|
43
|
+
|
44
|
+
def submit result = nil
|
45
|
+
done result
|
46
|
+
|
47
|
+
release
|
48
|
+
|
49
|
+
@client.submit_transaction self
|
50
|
+
|
51
|
+
self
|
52
|
+
end
|
53
|
+
|
54
|
+
def trace signature, kind = nil, extra = nil, &block
|
55
|
+
trace = Trace.new(self, signature, kind, running_traces, extra)
|
56
|
+
|
57
|
+
rel_time = current_offset
|
58
|
+
|
59
|
+
traces << trace
|
60
|
+
|
61
|
+
trace.start rel_time
|
62
|
+
|
63
|
+
return trace unless block_given?
|
64
|
+
|
65
|
+
begin
|
66
|
+
result = yield trace
|
67
|
+
ensure
|
68
|
+
trace.done
|
69
|
+
end
|
70
|
+
|
71
|
+
result
|
72
|
+
end
|
73
|
+
|
74
|
+
def running_traces
|
75
|
+
traces.select(&:running?)
|
76
|
+
end
|
77
|
+
|
78
|
+
def current_trace
|
79
|
+
traces.reverse.find(&:running?)
|
80
|
+
end
|
81
|
+
|
82
|
+
def current_offset
|
83
|
+
if curr = current_trace
|
84
|
+
return curr.start_time
|
85
|
+
end
|
86
|
+
|
87
|
+
start_time
|
88
|
+
end
|
89
|
+
|
90
|
+
def inspect
|
91
|
+
info = %w{endpoint kind result duration timestamp start_time}
|
92
|
+
<<-TEXT
|
93
|
+
<Transaction #{info.map { |m| "#{m}:#{send(m).inspect}" }.join(' ')}>
|
94
|
+
#{traces.map(&:inspect).join("\n ")}"
|
95
|
+
TEXT
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|
99
|
+
end
|