lib/scout_rails/store.rb in scout_rails-0.0.4 vs lib/scout_rails/store.rb in scout_rails-0.0.5.debug.pre

- old
+ new

@@ -18,12 +18,14 @@ end # Called when the last stack item completes for the current transaction to clear # for the next run. def reset_transaction! + Thread::current[:scout_stack_unbalanced] = nil Thread::current[:scout_scope_name] = nil @transaction_hash = Hash.new + @stack = Array.new end # Called at the start of Tracer#instrument: # (1) Either finds an existing MetricStats object in the metric_hash or # initialize a new one. An existing MetricStats object is present if this +metric_name+ has already been instrumented. @@ -36,11 +38,21 @@ end def stop_recording(sanity_check_item, options={}) item = stack.pop stack_empty = stack.empty? - raise "items not equal: #{item.inspect} / #{sanity_check_item.inspect}" if item != sanity_check_item + # unbalanced stack - if it's unbalanced, the item is popped but nothing happens. + if Thread::current[:scout_stack_unbalanced] + return + end + # unbalanced stack check - unreproducable cases have seen this occur. when it does, sets a Thread variable + # so we ignore further recordings. +Store#reset_transaction!+ resets this. + if item != sanity_check_item + ScoutRails::Agent.instance.logger.warn "Scope [#{Thread::current[:scout_scope_name]}] Popped off stack: #{item.inspect} Expected: #{sanity_check_item.inspect}. Aborting." + Thread::current[:scout_stack_unbalanced] = true + return + end duration = Time.now - item.start_time if last=stack.last last.children_time += duration end meta = ScoutRails::MetricMeta.new(item.metric_name, :desc => options[:desc]) @@ -56,21 +68,33 @@ transaction_hash[meta] = stat if stack_empty aggs=aggregate_calls(transaction_hash.dup,meta) store_sample(options[:uri],transaction_hash.dup.merge(aggs),meta,stat) - # ugly attempt to see if deep dup is the issue + # deep duplicate duplicate = aggs.dup duplicate.each_pair do |k,v| duplicate[k.dup] = v.dup end merge_data(duplicate.merge({meta.dup => stat.dup})) # aggregrates + controller end end + # Returns the top-level category names used in the +metrics+ hash. + def categories(metrics) + cats = Set.new + metrics.keys.each do |meta| + next if meta.scope.nil? # ignore controller + if match=meta.metric_name.match(/\A([\w|\d]+)\//) + cats << match[1] + end + end # metrics.each + cats + end + # Takes a metric_hash of calls and generates aggregates for ActiveRecord and View calls. def aggregate_calls(metrics,parent_meta) - categories = %w(ActiveRecord View) + categories = categories(metrics) aggregates = {} categories.each do |cat| agg_meta=ScoutRails::MetricMeta.new("#{cat}/all") agg_meta.scope = parent_meta.metric_name agg_stats = ScoutRails::MetricStats.new \ No newline at end of file