Created
June 15, 2012 20:33
-
-
Save gnarg/2938578 to your computer and use it in GitHub Desktop.
ActiveSupport::Notifications instrumentation proof of concept
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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