Skip to content

Instantly share code, notes, and snippets.

@gnarg
Created June 15, 2012 20:33
Show Gist options
  • Select an option

  • Save gnarg/2938578 to your computer and use it in GitHub Desktop.

Select an option

Save gnarg/2938578 to your computer and use it in GitHub Desktop.
ActiveSupport::Notifications instrumentation proof of concept
require 'new_relic/agent/transaction_info'
require 'new_relic/transaction_analysis'
require 'new_relic/transaction_sample'
require 'new_relic/control'
require 'new_relic/new_relic_service'
module NewRelic
class TestAgent
def initialize
@log = Logger.new('log/newrelic_agent.log')
@event_stack = Hash.new {|h,id| h[id] = [] }
# should make a list of event we actually care about, instead of all
ActiveSupport::Notifications.subscribe(/^[^\!].*/, self)
# localhost
@service = NewRelic::Agent::NewRelicService.new('bootstrap_newrelic_admin_license_key_000',
NewRelic::Control::Server.new('127.0.0.1', 8081))
@service.connect(:pid => $$, :host => 'yourmomshouse', :app_name => ['skunkworks'],
:language => 'ruby', :agent_version => '4.0.0')
at_exit { @service.shutdown }
end
def start(name, id, payload)
e = ActiveSupport::Notifications::Event.new(name, Time.now, nil, id, payload)
parent = @event_stack[id].last
parent << e if parent
@event_stack[id].push e
end
def finish(name, id, payload)
params = {}
event = @event_stack[id].pop
event.end = Time.now
# just for proof of concept
if event.name == 'sql.active_record'
event.payload[:backtrace] = caller.join("\n")
end
if event.name =~ /process_action.action_controller/
@log.debug "[NewRelic] #{YAML.dump(event)}"
trace = build_transaction_trace(event)
@log.debug trace.to_s
send_now!(trace)
end
end
protected
def send_now!(trace)
@service.transaction_sample_data([trace])
end
def build_transaction_trace(event)
sample = NewRelic::TransactionSample.new(event.time.to_f, event.object_id)
sample.params[:path] = "Controller/#{event.payload[:controller]}/#{event.payload[:action]}"
sample.params[:uri] = event.payload[:path]
sample.root_segment.end_trace(event.end.to_f - sample.start_time.to_f)
top_segment = sample.create_segment(event.time.to_f - sample.start_time.to_f,
sample.params[:path])
top_segment.end_trace(event.end.to_f - sample.start_time.to_f)
sample.root_segment.add_called_segment(top_segment)
build_transaction_segments(sample, top_segment,
event.instance_variable_get(:@children))
sample
end
def build_transaction_segments(sample, parent, events)
events.each do |event|
segment = sample.create_segment(event.time.to_f - sample.start_time.to_f, event.name)
segment.end_trace(event.end.to_f - sample.start_time.to_f)
[:sql, :backtrace].each do |key|
if event.payload[key]
segment.params[key] = event.payload[key]
end
end
parent.add_called_segment(segment)
# we might have to worry about stack depth
build_transaction_segments(sample, segment, event.instance_variable_get(:@children))
end
end
end
class UrlRule
# :D
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment