Module: Txray::Runtime

Defined in:
lib/txray/runtime.rb,
lib/txray/runtime/sink.rb,
lib/txray/runtime/transaction.rb

Defined Under Namespace

Modules: NetHttpGuard, TransactionTimer Classes: Sink, Stack, Transaction, Violation

Constant Summary collapse

IGNORE_KEY =
:txray_ignoring
GEM_ROOT =
File.expand_path("..", __dir__)
DEFAULTS =
{
  threshold_ms: 250,
  on_violation: :log,
  guard_http: true,
  guard_jobs: true,
  guard_mail: true,
  log_path: nil,
  ignore: [],
  logger: nil
}.freeze

Class Attribute Summary collapse

Class Method Summary collapse

Class Attribute Details

.optionsObject (readonly)

Returns the value of attribute options.



28
29
30
# File 'lib/txray/runtime.rb', line 28

def options
  @options
end

Class Method Details

.close_transaction(outcome) ⇒ Object



96
97
98
99
100
101
102
103
104
105
106
# File 'lib/txray/runtime.rb', line 96

def close_transaction(outcome)
  transaction = Stack.pop
  return if transaction.nil? || ignoring?

  duration = transaction.duration_ms
  slow = duration >= @options[:threshold_ms]
  return unless slow || transaction.violations.any?

  report(transaction.to_event(outcome || :commit))
  announce_slow(duration) if slow
end

.ignoreObject



53
54
55
56
57
58
59
# File 'lib/txray/runtime.rb', line 53

def ignore
  previous = Thread.current[IGNORE_KEY]
  Thread.current[IGNORE_KEY] = true
  yield
ensure
  Thread.current[IGNORE_KEY] = previous
end

.ignoring?Boolean

Returns:

  • (Boolean)


61
# File 'lib/txray/runtime.rb', line 61

def ignoring? = Thread.current[IGNORE_KEY] == true

.install(**overrides) ⇒ Object



30
31
32
33
34
35
36
37
38
39
40
41
42
43
# File 'lib/txray/runtime.rb', line 30

def install(**overrides)
  return if @installed

  @installed = true
  @options = DEFAULTS.merge(overrides.compact)
  @ignore = Array(@options[:ignore]).map { |pattern| Regexp.new(pattern.to_s) }
  @sink = Sink.build(@options[:log_path])
  @subscribers = []

  watch_transactions
  watch_jobs if @options[:guard_jobs]
  watch_mail if @options[:guard_mail]
  patch_net_http if @options[:guard_http]
end

.installed?Boolean

Returns:

  • (Boolean)


51
# File 'lib/txray/runtime.rb', line 51

def installed? = @installed == true

.open_transactionObject



92
93
94
# File 'lib/txray/runtime.rb', line 92

def open_transaction
  Stack.push(app_backtrace.first)
end

.report(event) ⇒ Object



88
89
90
# File 'lib/txray/runtime.rb', line 88

def report(event)
  @sink.write(event)
end

.transaction_open?Boolean

Returns:

  • (Boolean)


63
64
65
66
67
68
69
70
71
72
73
# File 'lib/txray/runtime.rb', line 63

def transaction_open?
  return false unless defined?(ActiveRecord::Base)

  pool = ActiveRecord::Base.connection_pool
  return false unless pool.active_connection?

  connection = pool.respond_to?(:lease_connection) ? pool.lease_connection : pool.connection
  connection.transaction_open?
rescue StandardError
  false
end

.uninstallObject



45
46
47
48
49
# File 'lib/txray/runtime.rb', line 45

def uninstall
  @subscribers.to_a.each { |subscriber| ActiveSupport::Notifications.unsubscribe(subscriber) }
  @subscribers = []
  @installed = nil
end

.violation(rule, message, duration_ms: nil) ⇒ Object



75
76
77
78
79
80
81
82
83
84
85
86
# File 'lib/txray/runtime.rb', line 75

def violation(rule, message, duration_ms: nil)
  return if ignoring?

  source = app_backtrace.first
  return if ignored?("#{message} #{source}")

  record = { rule: rule, message: message, duration_ms: duration_ms, source: source }
  open = Stack.current
  open&.record(record)
  report(record.merge(type: "violation", at: Time.now.to_f, pid: Process.pid)) if open.nil?
  announce(rule, message)
end