class Mmtrix::Agent::Transaction
This class represents a single transaction (usually mapping to one web request or background job invocation) instrumented by the Ruby agent.
@api public
Constants
- APDEX_ALL_METRIC
- APDEX_F
- APDEX_METRIC
- APDEX_OTHER_METRIC
- APDEX_OTHER_TXN_METRIC_PREFIX
- APDEX_S
- APDEX_T
- APDEX_TXN_METRIC_PREFIX
- CONTROLLER_MIDDLEWARE_PREFIX
- CONTROLLER_PREFIX
- EMPTY_SUMMARY_METRICS
- FAILED_TO_STOP_MESSAGE
- GRAPE_PREFIX
- GUID_LENGTH
- HEX_DIGITS
- JRUBY_CPU_TIME_ERROR
- MIDDLEWARE_PREFIX
- MIDDLEWARE_SUMMARY_METRICS
- NESTED_TRACE_STOP_OPTIONS
- OTHER_SUMMARY_METRIC
- OTHER_TRANSACTION_PREFIX
- QUEUE_TIME_METRIC
- RACK_PREFIX
- SINATRA_PREFIX
- SUBTRANSACTION_PREFIX
for nested transactions
- TASK_PREFIX
- TRACE_OPTIONS_SCOPED
- TRACE_OPTIONS_UNSCOPED
- TRANSACTION_NAMING_SOURCES
- WEB_SUMMARY_METRIC
- WEB_TRANSACTION_CATEGORIES
Attributes
A Time instance used for calculating the apdex score, which might end up being @start, or it might be further upstream if we can find a request header for the queue entry time
Fields for tracking synthetics requests
A Time instance for the start time, never nil
Fields for tracking synthetics requests
Populated with the trace sample once this transaction is completed.
Public Class Methods
Indicate that you don’t want to keep the currently saved transaction information
# File lib/mmtrix/agent/transaction.rb, line 182 def self.abort_transaction! #THREAD_LOCAL_ACCESS state = Mmtrix::Agent::TransactionState.tl_get txn = state.current_transaction txn.abort_transaction!(state) if txn end
# File lib/mmtrix/agent/transaction.rb, line 222 def self.add_agent_attribute(key, value, default_destinations) if txn = tl_current txn.add_agent_attribute(key, value, default_destinations) else Mmtrix::Agent.logger.debug "Attempted to add agent attribute: #{key} without transaction" end end
# File lib/mmtrix/agent/transaction.rb, line 209 def self.apdex_bucket(duration, failed, apdex_t) case when failed :apdex_f when duration <= apdex_t :apdex_s when duration <= 4 * apdex_t :apdex_t else :apdex_f end end
# File lib/mmtrix/agent/transaction.rb, line 234 def self.merge_untrusted_agent_attributes(attributes, prefix, default_destinations) if txn = tl_current txn.merge_untrusted_agent_attributes(attributes, prefix, default_destinations) else Mmtrix::Agent.logger.debug "Attempted to merge untrusted attributes without transaction" end end
# File lib/mmtrix/agent/transaction.rb, line 172 def self.nested_transaction_name(name) if name.start_with?(CONTROLLER_PREFIX) || name.start_with?(OTHER_TRANSACTION_PREFIX) "#{SUBTRANSACTION_PREFIX}#{name}" else name end end
# File lib/mmtrix/agent/transaction.rb, line 258 def initialize(category, options) @frame_stack = [] @has_children = false self.default_name = options[:transaction_name] @overridden_name = nil @frozen_name = nil @category = category @start_time = Time.now @apdex_start = options[:apdex_start_time] || @start_time @jruby_cpu_start = jruby_cpu_time @process_cpu_start = process_cpu @gc_start_snapshot = Mmtrix::Agent::StatsEngine::GCProfiler.take_snapshot @filtered_params = options[:filtered_params] || {} @exceptions = {} @metrics = TransactionMetrics.new @guid = generate_guid @cat_path_hashes = nil @ignore_this_transaction = false @ignore_apdex = false @ignore_enduser = false @attributes = Attributes.new(Mmtrix::Agent.instance.attribute_filter) merge_request_parameters(@filtered_params) if request = options[:request] @request_path = path_from_request(request) @referer = referer_from_request(request) end end
See Mmtrix::Agent.notice_error
for options and commentary
# File lib/mmtrix/agent/transaction.rb, line 189 def self.notice_error(e, options={}) #THREAD_LOCAL_ACCESS state = Mmtrix::Agent::TransactionState.tl_get txn = state.current_transaction if txn txn.notice_error(e, options) elsif Mmtrix::Agent.instance Mmtrix::Agent.instance.error_collector.notice_error(e, options) end end
Returns truthy if the current in-progress transaction is considered a a web transaction (as opposed to, e.g., a background transaction).
@api public
# File lib/mmtrix/agent/transaction.rb, line 204 def self.recording_web_transaction? #THREAD_LOCAL_ACCESS txn = tl_current txn && txn.recording_web_transaction? end
# File lib/mmtrix/agent/transaction.rb, line 76 def self.set_default_transaction_name(name, category = nil, node_name = nil) #THREAD_LOCAL_ACCESS txn = tl_current name = txn.make_transaction_name(name, category) txn.name_last_frame(node_name || name) txn.set_default_transaction_name(name, category) end
# File lib/mmtrix/agent/transaction.rb, line 83 def self.set_overriding_transaction_name(name, category = nil) #THREAD_LOCAL_ACCESS txn = tl_current return unless txn name = txn.make_transaction_name(name, category) txn.name_last_frame(name) txn.set_overriding_transaction_name(name, category) end
# File lib/mmtrix/agent/transaction.rb, line 108 def self.start(state, category, options) category ||= :controller txn = state.current_transaction if txn txn.create_nested_frame(state, category, options) else txn = start_new_transaction(state, category, options) end txn rescue => e Mmtrix::Agent.logger.error("Exception during Transaction.start", e) nil end
# File lib/mmtrix/agent/transaction.rb, line 124 def self.start_new_transaction(state, category, options) txn = Transaction.new(category, options) state.reset(txn) txn.start(state) txn end
# File lib/mmtrix/agent/transaction.rb, line 133 def self.stop(state, end_time=Time.now) txn = state.current_transaction if txn.nil? Mmtrix::Agent.logger.error(FAILED_TO_STOP_MESSAGE) return end nested_frame = txn.frame_stack.pop if txn.frame_stack.empty? txn.stop(state, end_time, nested_frame) state.reset else nested_name = nested_transaction_name(nested_frame.name) if nested_name.start_with?(MIDDLEWARE_PREFIX) summary_metrics = MIDDLEWARE_SUMMARY_METRICS else summary_metrics = EMPTY_SUMMARY_METRICS end Mmtrix::Agent::MethodTracerHelpers.trace_execution_scoped_footer( state, nested_frame.start_time.to_f, nested_name, summary_metrics, nested_frame, NESTED_TRACE_STOP_OPTIONS, end_time.to_f) end :transaction_stopped rescue => e state.reset Mmtrix::Agent.logger.error("Exception during Transaction.stop", e) nil end
Return the currently active transaction, or nil.
# File lib/mmtrix/agent/transaction.rb, line 72 def self.tl_current TransactionState.tl_get.current_transaction end
# File lib/mmtrix/agent/transaction.rb, line 93 def self.wrap(state, name, category, options = {}) Transaction.start(state, category, options.merge(:transaction_name => name)) begin # We shouldn't raise from Transaction.start, but only wrap the yield # to be absolutely sure we don't report agent problems as app errors yield rescue => e Transaction.notice_error(e) raise e ensure Transaction.stop(state) end end
Public Instance Methods
Call this to ensure that the current transaction trace is not saved To fully ignore all metrics and errors, use ignore! instead.
# File lib/mmtrix/agent/transaction.rb, line 424 def abort_transaction!(state) @ignore_trace = true end
# File lib/mmtrix/agent/transaction.rb, line 230 def add_agent_attribute(key, value, default_destinations) @attributes.add_agent_attribute(key, value, default_destinations) end
# File lib/mmtrix/agent/transaction.rb, line 810 def add_custom_attributes(p) attributes.merge_custom_attributes(p) end
# File lib/mmtrix/agent/transaction.rb, line 752 def apdex_bucket(duration, current_apdex_t) self.class.apdex_bucket(duration, had_error?, current_apdex_t) end
# File lib/mmtrix/agent/transaction.rb, line 785 def apdex_t transaction_specific_apdex_t || Agent.config[:apdex_t] end
# File lib/mmtrix/agent/transaction.rb, line 642 def append_apdex_perf_zone(duration, payload) if recording_web_transaction? bucket = apdex_bucket(duration, apdex_t) elsif background_apdex_t = transaction_specific_apdex_t bucket = apdex_bucket(duration, background_apdex_t) end return unless bucket bucket_str = case bucket when :apdex_s then APDEX_S when :apdex_t then APDEX_T when :apdex_f then APDEX_F else nil end payload[:apdex_perf_zone] = bucket_str if bucket_str end
# File lib/mmtrix/agent/transaction.rb, line 660 def append_cat_info(state, duration, payload) return unless include_guid?(state, duration) payload[:guid] = guid return unless state.is_cross_app? trip_id = cat_trip_id(state) path_hash = cat_path_hash(state) referring_path_hash = cat_referring_path_hash(state) payload[:cat_trip_id] = trip_id if trip_id payload[:cat_referring_path_hash] = referring_path_hash if referring_path_hash if path_hash payload[:cat_path_hash] = path_hash alternate_path_hashes = cat_path_hashes - [path_hash] unless alternate_path_hashes.empty? payload[:cat_alternate_path_hashes] = alternate_path_hashes end end end
# File lib/mmtrix/agent/transaction.rb, line 690 def append_referring_transaction_guid_to(state, payload) referring_guid = Mmtrix::Agent.instance.cross_app_monitor.client_referring_transaction_guid(state) if referring_guid payload[:referring_transaction_guid] = referring_guid end end
# File lib/mmtrix/agent/transaction.rb, line 682 def append_synthetics_to(state, payload) return unless is_synthetics_request? payload[:synthetics_resource_id] = synthetics_resource_id payload[:synthetics_job_id] = synthetics_job_id payload[:synthetics_monitor_id] = synthetics_monitor_id end
# File lib/mmtrix/agent/transaction.rb, line 514 def assign_agent_attributes if referer add_agent_attribute(:'request.headers.referer', referer, Mmtrix::Agent::AttributeFilter::DST_ERROR_COLLECTOR) end if http_response_code add_agent_attribute(:httpResponseCode, http_response_code.to_s, Mmtrix::Agent::AttributeFilter::DST_TRANSACTION_TRACER| Mmtrix::Agent::AttributeFilter::DST_TRANSACTION_EVENTS| Mmtrix::Agent::AttributeFilter::DST_ERROR_COLLECTOR) end end
# File lib/mmtrix/agent/transaction.rb, line 528 def assign_intrinsics(state) if gc_time = calculate_gc_time attributes.add_intrinsic_attribute(:gc_time, gc_time) end if burn = cpu_burn attributes.add_intrinsic_attribute(:cpu_time, burn) end if is_synthetics_request? attributes.add_intrinsic_attribute(:synthetics_resource_id, synthetics_resource_id) attributes.add_intrinsic_attribute(:synthetics_job_id, synthetics_job_id) attributes.add_intrinsic_attribute(:synthetics_monitor_id, synthetics_monitor_id) end if state.is_cross_app? attributes.add_intrinsic_attribute(:trip_id, cat_trip_id(state)) attributes.add_intrinsic_attribute(:path_hash, cat_path_hash(state)) end end
# File lib/mmtrix/agent/transaction.rb, line 439 def background_summary_metrics segments = @frozen_name.split('/') if segments.size > 2 ["OtherTransaction/#{segments[1]}/all", OTHER_SUMMARY_METRIC] else [] end end
# File lib/mmtrix/agent/transaction.rb, line 370 def best_name @frozen_name || @overridden_name || @default_name || Mmtrix::Agent::UNKNOWN_METRIC end
# File lib/mmtrix/agent/transaction.rb, line 549 def calculate_gc_time gc_stop_snapshot = Mmtrix::Agent::StatsEngine::GCProfiler.take_snapshot Mmtrix::Agent::StatsEngine::GCProfiler.record_delta(gc_start_snapshot, gc_stop_snapshot) end
# File lib/mmtrix/agent/transaction.rb, line 590 def cat_path_hash(state) referring_path_hash = cat_referring_path_hash(state) || '0' seed = referring_path_hash.to_i(16) result = Mmtrix::Agent.instance.cross_app_monitor.path_hash(best_name, seed) record_cat_path_hash(result) result end
# File lib/mmtrix/agent/transaction.rb, line 605 def cat_referring_path_hash(state) Mmtrix::Agent.instance.cross_app_monitor.client_referring_transaction_path_hash(state) end
# File lib/mmtrix/agent/transaction.rb, line 586 def cat_trip_id(state) Mmtrix::Agent.instance.cross_app_monitor.client_referring_transaction_trip_id(state) || guid end
# File lib/mmtrix/agent/transaction.rb, line 497 def commit!(state, end_time, outermost_node_name) assign_agent_attributes assign_intrinsics(state) @transaction_trace = transaction_sampler.on_finishing_transaction(state, self, end_time) sql_sampler.on_finishing_transaction(state, @frozen_name) record_summary_metrics(outermost_node_name, end_time) record_apdex(state, end_time) unless ignore_apdex? record_queue_time record_exceptions merge_metrics send_transaction_finished_event(state, start_time, end_time) end
# File lib/mmtrix/agent/transaction.rb, line 829 def cpu_burn normal_cpu_burn || jruby_cpu_burn end
# File lib/mmtrix/agent/transaction.rb, line 319 def create_nested_frame(state, category, options) @has_children = true if options[:filtered_params] && !options[:filtered_params].empty? @filtered_params = options[:filtered_params] merge_request_parameters(options[:filtered_params]) end frame_stack.push Mmtrix::Agent::MethodTracerHelpers.trace_execution_scoped_header(state, Time.now.to_f) name_last_frame(options[:transaction_name]) set_default_transaction_name(options[:transaction_name], category) end
# File lib/mmtrix/agent/transaction.rb, line 315 def default_name=(name) @default_name = Helper.correctly_encoded(name) end
# File lib/mmtrix/agent/transaction.rb, line 387 def freeze_name_and_execute_if_not_ignored if !name_frozen? name = promoted_transaction_name(best_name) name = Mmtrix::Agent.instance.transaction_rules.rename(name) @name_frozen = true if name.nil? ignore! @frozen_name = best_name else @frozen_name = name end end if block_given? && !@ignore_this_transaction yield end end
# File lib/mmtrix/agent/transaction.rb, line 745 def had_error? @exceptions.each do |exception, _| return true unless Mmtrix::Agent.instance.error_collector.error_is_ignored?(exception) end false end
# File lib/mmtrix/agent/transaction.rb, line 843 def ignore! @ignore_this_transaction = true end
# File lib/mmtrix/agent/transaction.rb, line 847 def ignore? @ignore_this_transaction end
# File lib/mmtrix/agent/transaction.rb, line 851 def ignore_apdex! @ignore_apdex = true end
# File lib/mmtrix/agent/transaction.rb, line 855 def ignore_apdex? @ignore_apdex end
# File lib/mmtrix/agent/transaction.rb, line 859 def ignore_enduser! @ignore_enduser = true end
# File lib/mmtrix/agent/transaction.rb, line 863 def ignore_enduser? @ignore_enduser end
# File lib/mmtrix/agent/transaction.rb, line 867 def ignore_trace? @ignore_trace end
# File lib/mmtrix/agent/transaction.rb, line 582 def include_guid?(state, duration) state.is_cross_app? || is_synthetics_request? end
# File lib/mmtrix/agent/transaction.rb, line 366 def influences_transaction_name?(category) !category || frame_stack.size == 1 || similar_category?(category) end
This transaction-local hash may be used as temprory storage by instrumentation that needs to pass data from one instrumentation point to another.
For example, if both A and B are instrumented, and A calls B but some piece of state needed by the instrumentation at B is only available at A, the instrumentation at A may write into the hash, call through, and then remove the key afterwards, allowing the instrumentation at B to read the value in between.
Keys should be symbols, and care should be taken to not generate key names dynamically, and to ensure that keys are removed upon return from the method that creates them.
# File lib/mmtrix/agent/transaction.rb, line 307 def instrumentation_state @instrumentation_state ||= {} end
# File lib/mmtrix/agent/transaction.rb, line 609 def is_synthetics_request? synthetics_payload != nil && raw_synthetics_header != nil end
# File lib/mmtrix/agent/transaction.rb, line 838 def jruby_cpu_burn return unless @jruby_cpu_start jruby_cpu_time - @jruby_cpu_start end
# File lib/mmtrix/agent/transaction.rb, line 361 def log_frozen_name(name) Mmtrix::Agent.logger.warn("Attempted to rename transaction to '#{name}' after transaction name was already frozen as '#{@frozen_name}'.") nil end
# File lib/mmtrix/agent/transaction.rb, line 336 def make_transaction_name(name, category=nil) namer = Instrumentation::ControllerInstrumentation::TransactionNamer "#{namer.prefix_for_category(self, category)}#{name}" end
# File lib/mmtrix/agent/transaction.rb, line 697 def merge_metrics Mmtrix::Agent.instance.stats_engine.merge_transaction_metrics!(@metrics, best_name) end
# File lib/mmtrix/agent/transaction.rb, line 332 def merge_request_parameters(params) merge_untrusted_agent_attributes(params, :'request.parameters', AttributeFilter::DST_NONE) end
# File lib/mmtrix/agent/transaction.rb, line 242 def merge_untrusted_agent_attributes(attributes, prefix, default_destinations) @attributes.merge_untrusted_agent_attributes(attributes, prefix, default_destinations) end
# File lib/mmtrix/agent/transaction.rb, line 406 def name_frozen? @frozen_name ? true : false end
# File lib/mmtrix/agent/transaction.rb, line 357 def name_last_frame(name) frame_stack.last.name = name end
# File lib/mmtrix/agent/transaction.rb, line 375 def name_set? (@overridden_name || @default_name) ? true : false end
# File lib/mmtrix/agent/transaction.rb, line 448 def needs_middleware_summary_metrics?(name) name.start_with?(MIDDLEWARE_PREFIX) end
# File lib/mmtrix/agent/transaction.rb, line 833 def normal_cpu_burn return unless @process_cpu_start process_cpu - @process_cpu_start end
# File lib/mmtrix/agent/transaction.rb, line 311 def overridden_name=(name) @overridden_name = Helper.correctly_encoded(name) end
# File lib/mmtrix/agent/transaction.rb, line 379 def promoted_transaction_name(name) if name.start_with?(MIDDLEWARE_PREFIX) "#{CONTROLLER_PREFIX}#{name}" else name end end
# File lib/mmtrix/agent/transaction.rb, line 722 def queue_time @apdex_start ? @start_time - @apdex_start : 0 end
# File lib/mmtrix/agent/transaction.rb, line 756 def record_apdex(state, end_time=Time.now) return unless state.is_execution_traced? freeze_name_and_execute_if_not_ignored do total_duration = end_time - apdex_start action_duration = end_time - start_time if recording_web_transaction? record_apdex_metrics(APDEX_METRIC, APDEX_TXN_METRIC_PREFIX, total_duration, action_duration, apdex_t) else record_apdex_metrics(APDEX_OTHER_METRIC, APDEX_OTHER_TXN_METRIC_PREFIX, total_duration, action_duration, transaction_specific_apdex_t) end end end
# File lib/mmtrix/agent/transaction.rb, line 773 def record_apdex_metrics(rollup_metric, transaction_prefix, total_duration, action_duration, current_apdex_t) return unless current_apdex_t apdex_bucket_global = apdex_bucket(total_duration, current_apdex_t) apdex_bucket_txn = apdex_bucket(action_duration, current_apdex_t) @metrics.record_unscoped(rollup_metric, apdex_bucket_global, current_apdex_t) @metrics.record_unscoped(APDEX_ALL_METRIC, apdex_bucket_global, current_apdex_t) txn_apdex_metric = @frozen_name.sub(/^[^\/]+\//, transaction_prefix) @metrics.record_unscoped(txn_apdex_metric, apdex_bucket_txn, current_apdex_t) end
# File lib/mmtrix/agent/transaction.rb, line 598 def record_cat_path_hash(hash) @cat_path_hashes ||= [] if @cat_path_hashes.size < 10 && !@cat_path_hashes.include?(hash) @cat_path_hashes << hash end end
# File lib/mmtrix/agent/transaction.rb, line 701 def record_exceptions @exceptions.each do |exception, options| options[:uri] ||= request_path if request_path options[:metric] = best_name options[:attributes] = @attributes agent.error_collector.notice_error(exception, options) end end
# File lib/mmtrix/agent/transaction.rb, line 726 def record_queue_time value = queue_time if value > 0.0 if value < MethodTracerHelpers::MAX_ALLOWED_METRIC_DURATION @metrics.record_unscoped(QUEUE_TIME_METRIC, value) else ::Mmtrix::Agent.logger.log_once(:warn, :too_high_queue_time, "Not recording unreasonably large queue time of #{value} s") end end end
The summary metrics recorded by this method all end up with a duration equal to the transaction itself, and an exclusive time of zero.
# File lib/mmtrix/agent/transaction.rb, line 556 def record_summary_metrics(outermost_node_name, end_time) metrics = summary_metrics metrics << @frozen_name unless @frozen_name == outermost_node_name @metrics.record_unscoped(metrics, end_time.to_f - start_time.to_f, 0) end
# File lib/mmtrix/agent/transaction.rb, line 817 def recording_web_transaction? web_category?(@category) end
This event is fired when the transaction is fully completed. The metric values and sampler can’t be successfully modified from this event.
# File lib/mmtrix/agent/transaction.rb, line 564 def send_transaction_finished_event(state, start_time, end_time) duration = end_time.to_f - start_time.to_f payload = { :name => @frozen_name, :bucket => recording_web_transaction? ? :request : :background, :start_timestamp => start_time.to_f, :duration => duration, :metrics => @metrics, :attributes => @attributes, } append_cat_info(state, duration, payload) append_apdex_perf_zone(duration, payload) append_synthetics_to(state, payload) append_referring_transaction_guid_to(state, payload) agent.events.notify(:transaction_finished, payload) end
# File lib/mmtrix/agent/transaction.rb, line 341 def set_default_transaction_name(name, category) return log_frozen_name(name) if name_frozen? if influences_transaction_name?(category) self.default_name = name @category = category if category end end
# File lib/mmtrix/agent/transaction.rb, line 349 def set_overriding_transaction_name(name, category) return log_frozen_name(name) if name_frozen? if influences_transaction_name?(category) self.overridden_name = name @category = category if category end end
# File lib/mmtrix/agent/transaction.rb, line 825 def similar_category?(category) web_category?(@category) == web_category?(category) end
# File lib/mmtrix/agent/transaction.rb, line 410 def start(state) return if !state.is_execution_traced? transaction_sampler.on_start_transaction(state, start_time) sql_sampler.on_start_transaction(state, start_time, request_path) Mmtrix::Agent.instance.events.notify(:start_transaction) Mmtrix::Agent::BusyCalculator.dispatcher_start(start_time) frame_stack.push Mmtrix::Agent::MethodTracerHelpers.trace_execution_scoped_header(state, start_time.to_f) name_last_frame @default_name end
# File lib/mmtrix/agent/transaction.rb, line 452 def stop(state, end_time, outermost_frame) return if !state.is_execution_traced? freeze_name_and_execute_if_not_ignored ignore! if user_defined_rules_ignore? if @has_children name = Transaction.nested_transaction_name(outermost_frame.name) trace_options = TRACE_OPTIONS_SCOPED else name = @frozen_name trace_options = TRACE_OPTIONS_UNSCOPED end # These metrics are recorded here instead of in record_summary_metrics # in order to capture the exclusive time associated with the outer-most # TT node. if needs_middleware_summary_metrics?(name) summary_metrics_with_exclusive_time = MIDDLEWARE_SUMMARY_METRICS else summary_metrics_with_exclusive_time = EMPTY_SUMMARY_METRICS end Mmtrix::Agent::MethodTracerHelpers.trace_execution_scoped_footer( state, start_time.to_f, name, summary_metrics_with_exclusive_time, outermost_frame, trace_options, end_time.to_f) Mmtrix::Agent::BusyCalculator.dispatcher_finish(end_time) commit!(state, end_time, name) unless @ignore_this_transaction end
# File lib/mmtrix/agent/transaction.rb, line 431 def summary_metrics if @frozen_name.start_with?(CONTROLLER_PREFIX) [WEB_SUMMARY_METRIC] else background_summary_metrics end end
# File lib/mmtrix/agent/transaction.rb, line 618 def synthetics_account_id info = synthetics_payload or return nil info[1] end
# File lib/mmtrix/agent/transaction.rb, line 628 def synthetics_job_id info = synthetics_payload or return nil info[3] end
# File lib/mmtrix/agent/transaction.rb, line 633 def synthetics_monitor_id info = synthetics_payload or return nil info[4] end
# File lib/mmtrix/agent/transaction.rb, line 623 def synthetics_resource_id info = synthetics_payload or return nil info[2] end
# File lib/mmtrix/agent/transaction.rb, line 613 def synthetics_version info = synthetics_payload or return nil info[0] end
# File lib/mmtrix/agent/transaction.rb, line 789 def transaction_specific_apdex_t key = :web_transactions_apdex Agent.config[key] && Agent.config[key][best_name] end
# File lib/mmtrix/agent/transaction.rb, line 488 def user_defined_rules_ignore? return unless request_path return if (rules = Mmtrix::Agent.config[:"rules.ignore_url_regexes"]).empty? rules.any? do |rule| request_path.match(rule) end end
# File lib/mmtrix/agent/transaction.rb, line 821 def web_category?(category) WEB_TRANSACTION_CATEGORIES.include?(category) end
# File lib/mmtrix/agent/transaction.rb, line 794 def with_database_metric_name(model, method, product=nil) previous = self.instrumentation_state[:datastore_override] model_name = case model when Class model.name when String model else model.to_s end self.instrumentation_state[:datastore_override] = [method, model_name, product] yield ensure self.instrumentation_state[:datastore_override] = previous end
Private Instance Methods
# File lib/mmtrix/agent/transaction.rb, line 894 def agent Mmtrix::Agent.instance end
generate a random 64 bit uuid
# File lib/mmtrix/agent/transaction.rb, line 910 def generate_guid guid = '' GUID_LENGTH.times do |a| guid << HEX_DIGITS[rand(16)] end guid end
# File lib/mmtrix/agent/transaction.rb, line 880 def jruby_cpu_time return nil unless @@java_classes_loaded threadMBean = Java::JavaLangManagement::ManagementFactory.getThreadMXBean() return nil unless threadMBean.isCurrentThreadCpuTimeSupported java_utime = threadMBean.getCurrentThreadUserTime() # ns -1 == java_utime ? 0.0 : java_utime/1e9 rescue => e ::Mmtrix::Agent.logger.log_once(:warn, :jruby_cpu_time, JRUBY_CPU_TIME_ERROR, e) ::Mmtrix::Agent.logger.debug(JRUBY_CPU_TIME_ERROR, e) nil end
In practice we expect req to be a Rack::Request or ActionController::AbstractRequest (for older Rails versions). But anything that responds to path can be passed to perform_action_with_mmtrix_trace.
We don’t expect the path to include a query string, however older test helpers for rails construct the PATH_INFO enviroment variable improperly and we’re generally being defensive.
# File lib/mmtrix/agent/transaction.rb, line 933 def path_from_request(req) path = req.path path = HTTPClients::URIUtil.strip_query_string(path) path.empty? ? "/" : path end
# File lib/mmtrix/agent/transaction.rb, line 873 def process_cpu return nil if defined? JRuby p = Process.times p.stime + p.utime end
Make a safe attempt to get the referer from a request object, generally successful when it’s a Rack
request.
# File lib/mmtrix/agent/transaction.rb, line 920 def referer_from_request(req) if req && req.respond_to?(:referer) && req.referer HTTPClients::URIUtil.strip_query_string(req.referer.to_s) end end
# File lib/mmtrix/agent/transaction.rb, line 902 def sql_sampler agent.sql_sampler end
# File lib/mmtrix/agent/transaction.rb, line 898 def transaction_sampler agent.transaction_sampler end