Module: NewRelic::Agent::StatsEngine::Transactions

Included in:
NewRelic::Agent::StatsEngine
Defined in:
lib/new_relic/agent/stats_engine/transactions.rb

Overview

Handles pushing and popping elements onto an internal stack that tracks where time should be allocated in Transaction Traces

Defined Under Namespace

Modules: Shim

Instance Method Summary collapse

Instance Method Details

#end_transactionObject

Try to clean up gracefully, otherwise we leave things hanging around on thread locals. If it looks like a transaction is still in progress, then maybe this is an inner transaction and is ignored.



114
115
116
117
118
119
120
121
# File 'lib/new_relic/agent/stats_engine/transactions.rb', line 114

def end_transaction
  stack = scope_stack

  if stack && stack.empty?
    Thread::current[:newrelic_scope_stack] = nil
    Thread::current[:newrelic_scope_name] = nil
  end
end

#pop_scope(expected_scope, name, time = Time.now.to_f) ⇒ Object

Pops a scope off the transaction stack - this updates the transaction sampler that we’ve finished execution of a traced method expected_scope should be the ScopeStackElement that was returned by the corresponding push_scope call. name is the name that will be applied to the generated transaction trace segment.



58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
# File 'lib/new_relic/agent/stats_engine/transactions.rb', line 58

def pop_scope(expected_scope, name, time=Time.now.to_f)
  stack = scope_stack
  scope = stack.pop
  fail "unbalanced pop from blame stack, got #{scope ? scope.tag : 'nil'}, expected #{expected_scope ? expected_scope.tag : 'nil'}" if scope != expected_scope

  if !stack.empty?
    if scope.deduct_call_time_from_parent
      stack.last.children_time += (time - scope.start_time)
    else
      stack.last.children_time += scope.children_time
    end
  end
  transaction_sampler.notice_pop_scope(name, time) if sampler_enabled?
  scope.name = name
  scope
end

#push_scope(tag, time = Time.now.to_f, deduct_call_time_from_parent = true) ⇒ Object

Pushes a scope onto the transaction stack - this generates a TransactionSample::Segment at the end of transaction execution The generated segment will not be named until the corresponding pop_scope call is made. tag should be a Symbol, and is only used for debugging purposes to identify this scope if the stack gets corrupted.



44
45
46
47
48
49
50
# File 'lib/new_relic/agent/stats_engine/transactions.rb', line 44

def push_scope(tag, time = Time.now.to_f, deduct_call_time_from_parent = true)
  stack = scope_stack
  transaction_sampler.notice_push_scope(time) if sampler_enabled?
  scope = ScopeStackElement.new(tag, time, deduct_call_time_from_parent)
  stack.push scope
  scope
end

#sampler_enabled?Boolean

Returns:

  • (Boolean)


75
76
77
# File 'lib/new_relic/agent/stats_engine/transactions.rb', line 75

def sampler_enabled?
  Agent.config[:'transaction_tracer.enabled'] || Agent.config[:developer_mode]
end

#scope_nameObject

Returns the current scope name from the thread local



101
102
103
# File 'lib/new_relic/agent/stats_engine/transactions.rb', line 101

def scope_name
  Thread::current[:newrelic_scope_name]
end

#scope_name=(transaction) ⇒ Object

set the name of the transaction for the current thread, which will be used to define the scope of all traced methods called on this thread until the scope stack is empty.

currently the transaction name is the name of the controller action that is invoked via the dispatcher, but conceivably we could use other transaction names in the future if the traced application does more than service http request via controller actions



96
97
98
# File 'lib/new_relic/agent/stats_engine/transactions.rb', line 96

def scope_name=(transaction)
  Thread::current[:newrelic_scope_name] = transaction
end

#scope_stackObject

Returns the current scope stack, memoized to a thread local variable



128
129
130
# File 'lib/new_relic/agent/stats_engine/transactions.rb', line 128

def scope_stack
  Thread::current[:newrelic_scope_stack] ||= []
end

#start_transactionObject

Start a new transaction, unless one is already in progress



106
107
108
# File 'lib/new_relic/agent/stats_engine/transactions.rb', line 106

def start_transaction
  NewRelic::Agent.instance.events.notify(:start_transaction)
end

#transaction_samplerObject



79
80
81
# File 'lib/new_relic/agent/stats_engine/transactions.rb', line 79

def transaction_sampler
  Agent.instance.transaction_sampler
end

#transaction_sampler=(sampler) ⇒ Object

deprecated–used to add transaction sampler, now we always look to the agent



84
85
86
# File 'lib/new_relic/agent/stats_engine/transactions.rb', line 84

def transaction_sampler= sampler
  NewRelic::Agent.logger.warn("NewRelic::Agent::StatsEngine#transaction_sampler is deprecated")
end

#transaction_stats_hashObject



123
124
125
# File 'lib/new_relic/agent/stats_engine/transactions.rb', line 123

def transaction_stats_hash
  Transaction.current && Transaction.current.stats_hash
end