rubyrun 0.9.5-universal-darwin-8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/LICENSE +13 -0
 - data/README +77 -0
 - data/bin/Rakefile +11 -0
 - data/docs/rubyrun-0.9.5.htm +5937 -0
 - data/docs/rubyrun-0.9.5.pdf +0 -0
 - data/docs/rubyrun-0.9.5_files/colorschememapping.xml +2 -0
 - data/docs/rubyrun-0.9.5_files/filelist.xml +29 -0
 - data/docs/rubyrun-0.9.5_files/header.htm +138 -0
 - data/docs/rubyrun-0.9.5_files/image001.jpg +0 -0
 - data/docs/rubyrun-0.9.5_files/image002.jpg +0 -0
 - data/docs/rubyrun-0.9.5_files/image003.jpg +0 -0
 - data/docs/rubyrun-0.9.5_files/image004.jpg +0 -0
 - data/docs/rubyrun-0.9.5_files/image005.jpg +0 -0
 - data/docs/rubyrun-0.9.5_files/image006.jpg +0 -0
 - data/docs/rubyrun-0.9.5_files/image007.jpg +0 -0
 - data/docs/rubyrun-0.9.5_files/image008.jpg +0 -0
 - data/docs/rubyrun-0.9.5_files/image009.jpg +0 -0
 - data/docs/rubyrun-0.9.5_files/image010.jpg +0 -0
 - data/docs/rubyrun-0.9.5_files/image011.jpg +0 -0
 - data/docs/rubyrun-0.9.5_files/image012.jpg +0 -0
 - data/docs/rubyrun-0.9.5_files/image013.jpg +0 -0
 - data/docs/rubyrun-0.9.5_files/image014.jpg +0 -0
 - data/docs/rubyrun-0.9.5_files/image015.jpg +0 -0
 - data/docs/rubyrun-0.9.5_files/image016.jpg +0 -0
 - data/docs/rubyrun-0.9.5_files/image017.png +0 -0
 - data/docs/rubyrun-0.9.5_files/image018.jpg +0 -0
 - data/docs/rubyrun-0.9.5_files/image019.jpg +0 -0
 - data/docs/rubyrun-0.9.5_files/image020.jpg +0 -0
 - data/docs/rubyrun-0.9.5_files/image021.jpg +0 -0
 - data/docs/rubyrun-0.9.5_files/image022.png +0 -0
 - data/docs/rubyrun-0.9.5_files/themedata.thmx +0 -0
 - data/etc/rubyrun_opts.yml +132 -0
 - data/ext/extconf.rb +5 -0
 - data/ext/rubyrunnative__.c +154 -0
 - data/ext/rubyrunnative__.def +2 -0
 - data/ext/rubyrunnative__.h +36 -0
 - data/ext/rubyrunnative__ppc-darwin.bundle +0 -0
 - data/ext/rubyrunnative__x86-darwin.bundle +0 -0
 - data/ext/rubyrunnative__x86-linux.so +0 -0
 - data/ext/rubyrunnative__x86-mswin32.so +0 -0
 - data/lib/rubyrun/rubyrun.rb +2 -0
 - data/lib/rubyrun/rubyrun_boot__.rb +79 -0
 - data/lib/rubyrun/rubyrun_buffer_mgr__.rb +49 -0
 - data/lib/rubyrun/rubyrun_commander__.rb +196 -0
 - data/lib/rubyrun/rubyrun_dad__.rb +35 -0
 - data/lib/rubyrun/rubyrun_globals.rb +52 -0
 - data/lib/rubyrun/rubyrun_html__.rb +136 -0
 - data/lib/rubyrun/rubyrun_html_writer__.rb +64 -0
 - data/lib/rubyrun/rubyrun_initializer__.rb +313 -0
 - data/lib/rubyrun/rubyrun_instrumentor__.rb +226 -0
 - data/lib/rubyrun/rubyrun_monitor__.rb +238 -0
 - data/lib/rubyrun/rubyrun_report__.rb +109 -0
 - data/lib/rubyrun/rubyrun_rss__.rb +97 -0
 - data/lib/rubyrun/rubyrun_tracer__.rb +79 -0
 - data/lib/rubyrun/rubyrun_utils__.rb +101 -0
 - data/lib/rubyrun/rubyrunnative__.bundle +0 -0
 - metadata +115 -0
 
| 
         @@ -0,0 +1,238 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            #---------------------------------------------------------------#
         
     | 
| 
      
 2 
     | 
    
         
            +
            #                                                               #  
         
     | 
| 
      
 3 
     | 
    
         
            +
            #  (C) Copyright Rubysophic Inc. 2007-2008                      #
         
     | 
| 
      
 4 
     | 
    
         
            +
            #  All rights reserved.                                         #
         
     | 
| 
      
 5 
     | 
    
         
            +
            #                                                               #  
         
     | 
| 
      
 6 
     | 
    
         
            +
            #  Use, duplication or disclosure of the code is not permitted  #
         
     | 
| 
      
 7 
     | 
    
         
            +
            #  unless licensed.                                             #
         
     | 
| 
      
 8 
     | 
    
         
            +
            #                                                               #            
         
     | 
| 
      
 9 
     | 
    
         
            +
            #  Last Updated: 7/09/08                                        #  
         
     | 
| 
      
 10 
     | 
    
         
            +
            #---------------------------------------------------------------#
         
     | 
| 
      
 11 
     | 
    
         
            +
            #                                                               #  
         
     | 
| 
      
 12 
     | 
    
         
            +
            #  RubyRunMonitor__ is responsible for keeping track of         #
         
     | 
| 
      
 13 
     | 
    
         
            +
            #  the response time of a Rails Request and its decomposition.  #
         
     | 
| 
      
 14 
     | 
    
         
            +
            #                                                               #  
         
     | 
| 
      
 15 
     | 
    
         
            +
            #  For instance, a typical WEBrick/RAILS servlet dispatch       #
         
     | 
| 
      
 16 
     | 
    
         
            +
            #  response time components generally break down look roughly   # 
         
     | 
| 
      
 17 
     | 
    
         
            +
            #  like this:           						    #
         
     | 
| 
      
 18 
     | 
    
         
            +
            #                                                               #      
         
     | 
| 
      
 19 
     | 
    
         
            +
            #  SVS   DI   ACT   DB   DB    DB          VI    VI             #    
         
     | 
| 
      
 20 
     | 
    
         
            +
            #  -+-----+----+----+--+--+--+--+--+----+--+----+-+--+---+----+ #
         
     | 
| 
      
 21 
     | 
    
         
            +
            #                     DB'   DB'   DB'  ACT'    VI'  VI' DI' SVS'#            
         
     | 
| 
      
 22 
     | 
    
         
            +
            #  Legend:                                                      #
         
     | 
| 
      
 23 
     | 
    
         
            +
            #   SVS = DispatchServlet.service                               #
         
     | 
| 
      
 24 
     | 
    
         
            +
            #   DI = DispatchServlet.handle_dispatch                        #
         
     | 
| 
      
 25 
     | 
    
         
            +
            #   ACT = controller.action                                     #    
         
     | 
| 
      
 26 
     | 
    
         
            +
            #   DB  = ActiveRecord::ConnectionAdapters::*Adapter.execute    #
         
     | 
| 
      
 27 
     | 
    
         
            +
            #   VI  = ActionView.Base:render_template                       #
         
     | 
| 
      
 28 
     | 
    
         
            +
            #   All apostrophe means "end of event"                         #
         
     | 
| 
      
 29 
     | 
    
         
            +
            #                                                               #
         
     | 
| 
      
 30 
     | 
    
         
            +
            #   Notes:                                                      #  
         
     | 
| 
      
 31 
     | 
    
         
            +
            #   1. mutex held from SVS to SVS'                              #
         
     | 
| 
      
 32 
     | 
    
         
            +
            #   2. Total dispatch time with mutex = SVS' - SVS              #
         
     | 
| 
      
 33 
     | 
    
         
            +
            #   3. Total DBIO time = Sum(DB' - DB)                          #    
         
     | 
| 
      
 34 
     | 
    
         
            +
            #   4. Action Time = ACT' - ACT                                 #
         
     | 
| 
      
 35 
     | 
    
         
            +
            #   5. View time = Sum(VI' - VI)                                #
         
     | 
| 
      
 36 
     | 
    
         
            +
            #   6. View rendering includes template + layout                #
         
     | 
| 
      
 37 
     | 
    
         
            +
            #                                                               #      
         
     | 
| 
      
 38 
     | 
    
         
            +
            #  Another key function is to act as a command agent, responding#
         
     | 
| 
      
 39 
     | 
    
         
            +
            #  to command such as displaying thread status, terminating     #
         
     | 
| 
      
 40 
     | 
    
         
            +
            #  threads with stack tracke and showing object heap info.      #
         
     | 
| 
      
 41 
     | 
    
         
            +
            #                                                               #  
         
     | 
| 
      
 42 
     | 
    
         
            +
            #---------------------------------------------------------------#
         
     | 
| 
      
 43 
     | 
    
         
            +
            module RubyRunMonitor__
         
     | 
| 
      
 44 
     | 
    
         
            +
              
         
     | 
| 
      
 45 
     | 
    
         
            +
              require 'rubyrun_globals'
         
     | 
| 
      
 46 
     | 
    
         
            +
              require 'rubyrun_utils__'
         
     | 
| 
      
 47 
     | 
    
         
            +
              require 'rubyrun_tracer__'
         
     | 
| 
      
 48 
     | 
    
         
            +
              require 'rubyrun_rss__'
         
     | 
| 
      
 49 
     | 
    
         
            +
              require 'rubyrun_buffer_mgr__'
         
     | 
| 
      
 50 
     | 
    
         
            +
              require 'rubyrun_html__'
         
     | 
| 
      
 51 
     | 
    
         
            +
              require 'rubyrun_report__'
         
     | 
| 
      
 52 
     | 
    
         
            +
              require 'rubyrun_commander__'
         
     | 
| 
      
 53 
     | 
    
         
            +
              begin
         
     | 
| 
      
 54 
     | 
    
         
            +
                require 'rubyrunnative__'
         
     | 
| 
      
 55 
     | 
    
         
            +
                $rubyrun_native = true
         
     | 
| 
      
 56 
     | 
    
         
            +
              rescue Exception
         
     | 
| 
      
 57 
     | 
    
         
            +
                $rubyrun_native = false
         
     | 
| 
      
 58 
     | 
    
         
            +
              end  
         
     | 
| 
      
 59 
     | 
    
         
            +
              include RubyRunGlobals
         
     | 
| 
      
 60 
     | 
    
         
            +
              include RubyRunUtils__
         
     | 
| 
      
 61 
     | 
    
         
            +
              include RubyRunTracer__
         
     | 
| 
      
 62 
     | 
    
         
            +
              include RubyRunBufferMgr__
         
     | 
| 
      
 63 
     | 
    
         
            +
              include RubyRunHTML__
         
     | 
| 
      
 64 
     | 
    
         
            +
              include RubyRunReport__
         
     | 
| 
      
 65 
     | 
    
         
            +
              include RubyRunCommander__
         
     | 
| 
      
 66 
     | 
    
         
            +
              
         
     | 
| 
      
 67 
     | 
    
         
            +
              # In response to the presence of a 'cmd_status', 'cmd_soft_kill', 'cmd_hard_kill'
         
     | 
| 
      
 68 
     | 
    
         
            +
              # or 'cmd_object_map' in the work directory, the monitor thread will either
         
     | 
| 
      
 69 
     | 
    
         
            +
              # display thread status, interrupt the threads in different manner, or show object instances
         
     | 
| 
      
 70 
     | 
    
         
            +
              # in memory
         
     | 
| 
      
 71 
     | 
    
         
            +
              def start_thread_monitor
         
     | 
| 
      
 72 
     | 
    
         
            +
                $rubyrun_logger.info "----- RubyRun Thread Monitor started -----"
         
     | 
| 
      
 73 
     | 
    
         
            +
                monitor_thr = Thread.new {
         
     | 
| 
      
 74 
     | 
    
         
            +
                  cycle = $rubyrun_report_timer / RUBYRUN_MONITOR_TIMER
         
     | 
| 
      
 75 
     | 
    
         
            +
                  sleep_count = 0
         
     | 
| 
      
 76 
     | 
    
         
            +
                  loop do
         
     | 
| 
      
 77 
     | 
    
         
            +
                    sleep RUBYRUN_MONITOR_TIMER
         
     | 
| 
      
 78 
     | 
    
         
            +
                    monitor_thr.exit if exit_monitor?
         
     | 
| 
      
 79 
     | 
    
         
            +
                    Thread.new {
         
     | 
| 
      
 80 
     | 
    
         
            +
                      begin
         
     | 
| 
      
 81 
     | 
    
         
            +
                        sleep_count += 1
         
     | 
| 
      
 82 
     | 
    
         
            +
                        sleep_count == cycle ? (dump_reports(true); sleep_count = 0) : dump_reports
         
     | 
| 
      
 83 
     | 
    
         
            +
                        dump_thread_status if thread_status?
         
     | 
| 
      
 84 
     | 
    
         
            +
                        dump_object_map if object_map?
         
     | 
| 
      
 85 
     | 
    
         
            +
                        kill_threads(monitor_thr) if soft_kill? || hard_kill?
         
     | 
| 
      
 86 
     | 
    
         
            +
                      rescue Exception => e
         
     | 
| 
      
 87 
     | 
    
         
            +
                        $stderr.print e.to_s + "\n" + e.backtrace.join("\n")
         
     | 
| 
      
 88 
     | 
    
         
            +
                        exit(-1)
         
     | 
| 
      
 89 
     | 
    
         
            +
                      end
         
     | 
| 
      
 90 
     | 
    
         
            +
                    }
         
     | 
| 
      
 91 
     | 
    
         
            +
                  end
         
     | 
| 
      
 92 
     | 
    
         
            +
                }
         
     | 
| 
      
 93 
     | 
    
         
            +
              end
         
     | 
| 
      
 94 
     | 
    
         
            +
             
         
     | 
| 
      
 95 
     | 
    
         
            +
              # Simulate a thread local storage by using a private hash keyed on thread id.
         
     | 
| 
      
 96 
     | 
    
         
            +
              # Key elements in the hash are, for instance:
         
     | 
| 
      
 97 
     | 
    
         
            +
              # {#{tid} => {:req=>request.object_id, :controller=>name, :action=> name,
         
     | 
| 
      
 98 
     | 
    
         
            +
              #   :action_t=>t, :dbio=>t, :dispatch_t=>t, :view_t=>t, :uncaptured_t=>t,
         
     | 
| 
      
 99 
     | 
    
         
            +
              #   :dispatch_wait_t=>t}}
         
     | 
| 
      
 100 
     | 
    
         
            +
              # Thread local is used to store performance metrics of a RAILS request.
         
     | 
| 
      
 101 
     | 
    
         
            +
              # When the same thread serves a different request, the current thread local
         
     | 
| 
      
 102 
     | 
    
         
            +
              # data needs to be rolled up and re-initialized.
         
     | 
| 
      
 103 
     | 
    
         
            +
              def create_thread_local(tid, request, klass, mid)
         
     | 
| 
      
 104 
     | 
    
         
            +
                return unless ($rubyrun_thread_local[tid] || is_action?(klass, mid))
         
     | 
| 
      
 105 
     | 
    
         
            +
                $rubyrun_thread_local[tid] ||= {}  
         
     | 
| 
      
 106 
     | 
    
         
            +
                init_thread_local(tid, request, klass, mid) unless $rubyrun_thread_local[tid][:req]
         
     | 
| 
      
 107 
     | 
    
         
            +
                if $rubyrun_thread_local[tid][:req] != request.object_id
         
     | 
| 
      
 108 
     | 
    
         
            +
                  roll_up_metrics(tid)
         
     | 
| 
      
 109 
     | 
    
         
            +
                  init_thread_local(tid, request, klass, mid)
         
     | 
| 
      
 110 
     | 
    
         
            +
                end
         
     | 
| 
      
 111 
     | 
    
         
            +
              end
         
     | 
| 
      
 112 
     | 
    
         
            +
              
         
     | 
| 
      
 113 
     | 
    
         
            +
              # Create a place holding global metrics hash for each RAILS application 
         
     | 
| 
      
 114 
     | 
    
         
            +
              # controller class to accumulate performance metrics by action.
         
     | 
| 
      
 115 
     | 
    
         
            +
              # Key elements in the hash are, for instance:
         
     | 
| 
      
 116 
     | 
    
         
            +
              # {#{controller} => {#{action} => [dispatch_t, action_t, dbio_t, view_t, uncap_t, dispatch_wait_t]}}
         
     | 
| 
      
 117 
     | 
    
         
            +
              def create_metrics_hash(klass)
         
     | 
| 
      
 118 
     | 
    
         
            +
                $rubyrun_metrics_hash[klass.to_s.downcase[0..-11]] ||= {}
         
     | 
| 
      
 119 
     | 
    
         
            +
              end  
         
     | 
| 
      
 120 
     | 
    
         
            +
              
         
     | 
| 
      
 121 
     | 
    
         
            +
              # Report timings to thread local after decomposing it into the right component.
         
     | 
| 
      
 122 
     | 
    
         
            +
              # For each action, there are 5 components of Response Time (RT)
         
     | 
| 
      
 123 
     | 
    
         
            +
              #   :dispatch_t, :#{action}_t, :dbio_t, :view_t, :uncaptured_t
         
     | 
| 
      
 124 
     | 
    
         
            +
              def report_rails_timing(klass, mid, t2, t1, tid)
         
     | 
| 
      
 125 
     | 
    
         
            +
                t = t2 - t1
         
     | 
| 
      
 126 
     | 
    
         
            +
                if is_in_hash?($rubyrun_adapter_hash, klass, mid)  
         
     | 
| 
      
 127 
     | 
    
         
            +
                  $rubyrun_thread_local[tid][:dbio_t] += t
         
     | 
| 
      
 128 
     | 
    
         
            +
                elsif is_in_hash?(RUBYRUN_VIEW_HASH, klass, mid)
         
     | 
| 
      
 129 
     | 
    
         
            +
                  $rubyrun_thread_local[tid][:view_t] << t2 << t1
         
     | 
| 
      
 130 
     | 
    
         
            +
                elsif is_in_hash?($rubyrun_outer_dispatch_hash, klass, mid)
         
     | 
| 
      
 131 
     | 
    
         
            +
                  $rubyrun_thread_local[tid][:outer_dispatch_t] << t      
         
     | 
| 
      
 132 
     | 
    
         
            +
                elsif is_in_hash?($rubyrun_inner_dispatch_hash, klass, mid)
         
     | 
| 
      
 133 
     | 
    
         
            +
                  $rubyrun_thread_local[tid][:inner_dispatch_t] << t
         
     | 
| 
      
 134 
     | 
    
         
            +
                elsif is_rails_controller?(klass)
         
     | 
| 
      
 135 
     | 
    
         
            +
                  $rubyrun_thread_local[tid][:action_t] = t
         
     | 
| 
      
 136 
     | 
    
         
            +
                  $rubyrun_thread_local[tid][:scafold_style] = $rubyrun_thread_local[tid][:view_t].empty? ? true : false
         
     | 
| 
      
 137 
     | 
    
         
            +
                elsif is_in?(RUBYRUN_THREAD_END_HASH, klass, mid, 'strict')
         
     | 
| 
      
 138 
     | 
    
         
            +
                  roll_up_metrics(tid, true)   
         
     | 
| 
      
 139 
     | 
    
         
            +
                end
         
     | 
| 
      
 140 
     | 
    
         
            +
              end
         
     | 
| 
      
 141 
     | 
    
         
            +
             
     | 
| 
      
 142 
     | 
    
         
            +
              private
         
     | 
| 
      
 143 
     | 
    
         
            +
                        
         
     | 
| 
      
 144 
     | 
    
         
            +
              # Roll up action metrics to controller_metrics_hash 
         
     | 
| 
      
 145 
     | 
    
         
            +
              # First, roll up the pieces in thread_local
         
     | 
| 
      
 146 
     | 
    
         
            +
              # Then roll up the thread local data to the metrics global hash
         
     | 
| 
      
 147 
     | 
    
         
            +
              def roll_up_metrics(tid, thread_end=false)
         
     | 
| 
      
 148 
     | 
    
         
            +
                ($rubyrun_thread_local[tid].clear; return) if thread_local_incomplete?(tid)
         
     | 
| 
      
 149 
     | 
    
         
            +
                dbio_t = $rubyrun_thread_local[tid][:dbio_t]
         
     | 
| 
      
 150 
     | 
    
         
            +
                outer_dispatch_t = $rubyrun_thread_local[tid][:outer_dispatch_t].max
         
     | 
| 
      
 151 
     | 
    
         
            +
                inner_dispatch_t = $rubyrun_thread_local[tid][:inner_dispatch_t].max
         
     | 
| 
      
 152 
     | 
    
         
            +
                dispatch_wait_t = outer_dispatch_t - inner_dispatch_t
         
     | 
| 
      
 153 
     | 
    
         
            +
                view_t = $rubyrun_thread_local[tid][:view_t].empty? ? 0 : $rubyrun_thread_local[tid][:view_t].max - $rubyrun_thread_local[tid][:view_t].min
         
     | 
| 
      
 154 
     | 
    
         
            +
                action_t = ($rubyrun_thread_local[tid][:action_t])
         
     | 
| 
      
 155 
     | 
    
         
            +
                uncap_t = $rubyrun_thread_local[tid][:scafold_style] ? outer_dispatch_t - view_t - action_t - dispatch_wait_t : outer_dispatch_t - action_t - dispatch_wait_t
         
     | 
| 
      
 156 
     | 
    
         
            +
                $rubyrun_thread_local[tid][:uncaptured_t] = uncap_t 
         
     | 
| 
      
 157 
     | 
    
         
            +
                $rubyrun_thread_local[tid][:dispatch_wait_t] = dispatch_wait_t 
         
     | 
| 
      
 158 
     | 
    
         
            +
                push_current_buffer([tid, Time.now,
         
     | 
| 
      
 159 
     | 
    
         
            +
                                    $rubyrun_thread_local[tid][:url],
         
     | 
| 
      
 160 
     | 
    
         
            +
                                    $rubyrun_thread_local[tid][:controller],
         
     | 
| 
      
 161 
     | 
    
         
            +
                                    $rubyrun_thread_local[tid][:action],
         
     | 
| 
      
 162 
     | 
    
         
            +
                                    outer_dispatch_t, action_t, dbio_t, view_t, uncap_t, dispatch_wait_t])
         
     | 
| 
      
 163 
     | 
    
         
            +
                !thread_end ? $rubyrun_thread_local[tid].clear : $rubyrun_thread_local.delete(tid)
         
     | 
| 
      
 164 
     | 
    
         
            +
              end
         
     | 
| 
      
 165 
     | 
    
         
            +
                  
         
     | 
| 
      
 166 
     | 
    
         
            +
              # Initialize the thread_local hash
         
     | 
| 
      
 167 
     | 
    
         
            +
              def init_thread_local(tid, request, klass, mid)
         
     | 
| 
      
 168 
     | 
    
         
            +
                $rubyrun_thread_local[tid][:req] = request.object_id
         
     | 
| 
      
 169 
     | 
    
         
            +
                $rubyrun_thread_local[tid][:controller] = klass.to_s.split('Controller')[0].downcase
         
     | 
| 
      
 170 
     | 
    
         
            +
                $rubyrun_thread_local[tid][:action] = return_method_name(mid)
         
     | 
| 
      
 171 
     | 
    
         
            +
                $rubyrun_thread_local[tid][:url] = request.protocol + request.host_with_port + request.request_uri
         
     | 
| 
      
 172 
     | 
    
         
            +
                $rubyrun_thread_local[tid][:dbio_t] = 0
         
     | 
| 
      
 173 
     | 
    
         
            +
                $rubyrun_thread_local[tid][:outer_dispatch_t] = []
         
     | 
| 
      
 174 
     | 
    
         
            +
                $rubyrun_thread_local[tid][:inner_dispatch_t] = []
         
     | 
| 
      
 175 
     | 
    
         
            +
                $rubyrun_thread_local[tid][:action_t] = 0
         
     | 
| 
      
 176 
     | 
    
         
            +
                $rubyrun_thread_local[tid][:uncaptured_t] = 0
         
     | 
| 
      
 177 
     | 
    
         
            +
                $rubyrun_thread_local[tid][:view_t] = []
         
     | 
| 
      
 178 
     | 
    
         
            +
                $rubyrun_thread_local[tid][:dispatch_wait_t] = 0
         
     | 
| 
      
 179 
     | 
    
         
            +
                $rubyrun_thread_local[tid][:scafold_style] = false
         
     | 
| 
      
 180 
     | 
    
         
            +
                $rubyrun_host_with_port = request.host_with_port
         
     | 
| 
      
 181 
     | 
    
         
            +
              end
         
     | 
| 
      
 182 
     | 
    
         
            +
              
         
     | 
| 
      
 183 
     | 
    
         
            +
              # Use the data hash returned by the native function to show
         
     | 
| 
      
 184 
     | 
    
         
            +
              # the top frame inside the thread struct (node and orig_func)
         
     | 
| 
      
 185 
     | 
    
         
            +
              def get_top_stack(th_data_hash, thread_id)
         
     | 
| 
      
 186 
     | 
    
         
            +
                th_data_hash.each {|th, top_stack|
         
     | 
| 
      
 187 
     | 
    
         
            +
                  if th.to_s.include?(thread_id)
         
     | 
| 
      
 188 
     | 
    
         
            +
                    return "#{top_stack[0].gsub('rubyrun_', '')}"
         
     | 
| 
      
 189 
     | 
    
         
            +
                    break
         
     | 
| 
      
 190 
     | 
    
         
            +
                  end
         
     | 
| 
      
 191 
     | 
    
         
            +
                }
         
     | 
| 
      
 192 
     | 
    
         
            +
              end
         
     | 
| 
      
 193 
     | 
    
         
            +
                 
         
     | 
| 
      
 194 
     | 
    
         
            +
              # If request aborted, thread_local can be corrupted (half filled)
         
     | 
| 
      
 195 
     | 
    
         
            +
              # Return true if corrupted else false
         
     | 
| 
      
 196 
     | 
    
         
            +
              def thread_local_incomplete? (tid)
         
     | 
| 
      
 197 
     | 
    
         
            +
                $rubyrun_thread_local[tid][:controller].nil? || 
         
     | 
| 
      
 198 
     | 
    
         
            +
                  $rubyrun_thread_local[tid][:action].nil? ||
         
     | 
| 
      
 199 
     | 
    
         
            +
                  $rubyrun_thread_local[tid][:outer_dispatch_t].empty? ||
         
     | 
| 
      
 200 
     | 
    
         
            +
                  $rubyrun_thread_local[tid][:inner_dispatch_t].empty?
         
     | 
| 
      
 201 
     | 
    
         
            +
              end
         
     | 
| 
      
 202 
     | 
    
         
            +
                
         
     | 
| 
      
 203 
     | 
    
         
            +
              # Sort $rubyrun_metrics_hash by response time in descending order
         
     | 
| 
      
 204 
     | 
    
         
            +
              # An array of the following data structure is returned:
         
     | 
| 
      
 205 
     | 
    
         
            +
              # metrics[0] controller/action name
         
     | 
| 
      
 206 
     | 
    
         
            +
              # metrics[1] Array of performance data
         
     | 
| 
      
 207 
     | 
    
         
            +
              # metrics[1][0] resposne time     metrics[1][1] action time
         
     | 
| 
      
 208 
     | 
    
         
            +
              # metrics[1][2] database IO time  metrics[1][3] view time
         
     | 
| 
      
 209 
     | 
    
         
            +
              # metrics[1][4] uncaptured time   metrics[1][5] wait time
         
     | 
| 
      
 210 
     | 
    
         
            +
              # metrics[1][6] request count 
         
     | 
| 
      
 211 
     | 
    
         
            +
              def sort_performance_metrics
         
     | 
| 
      
 212 
     | 
    
         
            +
                results = Hash.new
         
     | 
| 
      
 213 
     | 
    
         
            +
                $rubyrun_metrics_hash.each {|controller, action_metrics|
         
     | 
| 
      
 214 
     | 
    
         
            +
                  next if action_metrics.empty?
         
     | 
| 
      
 215 
     | 
    
         
            +
                  action_metrics.each {|action, metrics|
         
     | 
| 
      
 216 
     | 
    
         
            +
                    results["#{controller}/#{action}"] = metrics
         
     | 
| 
      
 217 
     | 
    
         
            +
                  }
         
     | 
| 
      
 218 
     | 
    
         
            +
                }
         
     | 
| 
      
 219 
     | 
    
         
            +
                results.sort {|a, b| -1*(a[1]<=>b[1])}
         
     | 
| 
      
 220 
     | 
    
         
            +
              end
         
     | 
| 
      
 221 
     | 
    
         
            +
                
         
     | 
| 
      
 222 
     | 
    
         
            +
              # An optimized runtime version of the original is_in? in RubyRunInstrumentor__
         
     | 
| 
      
 223 
     | 
    
         
            +
              # This is used during runtime and not instrumentation, hence something of better
         
     | 
| 
      
 224 
     | 
    
         
            +
              # performance but less general is required. 
         
     | 
| 
      
 225 
     | 
    
         
            +
              def is_in_hash?(hash, klass, mid)
         
     | 
| 
      
 226 
     | 
    
         
            +
                return false if hash.empty?
         
     | 
| 
      
 227 
     | 
    
         
            +
                name = klass.to_s
         
     | 
| 
      
 228 
     | 
    
         
            +
                if hash.has_key?(name)
         
     | 
| 
      
 229 
     | 
    
         
            +
                  return true if hash[name].empty? 
         
     | 
| 
      
 230 
     | 
    
         
            +
                  method_name = return_method_name(mid)
         
     | 
| 
      
 231 
     | 
    
         
            +
                  hash[name].each {|meth_name|
         
     | 
| 
      
 232 
     | 
    
         
            +
                    return true if method_name.downcase == meth_name.downcase 
         
     | 
| 
      
 233 
     | 
    
         
            +
                  }
         
     | 
| 
      
 234 
     | 
    
         
            +
                end
         
     | 
| 
      
 235 
     | 
    
         
            +
                false
         
     | 
| 
      
 236 
     | 
    
         
            +
              end
         
     | 
| 
      
 237 
     | 
    
         
            +
                
         
     | 
| 
      
 238 
     | 
    
         
            +
            end  
         
     | 
| 
         @@ -0,0 +1,109 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            #---------------------------------------------------------------#
         
     | 
| 
      
 2 
     | 
    
         
            +
            #                                                               #  
         
     | 
| 
      
 3 
     | 
    
         
            +
            #  (C) Copyright Rubysophic Inc. 2007-2008                      #
         
     | 
| 
      
 4 
     | 
    
         
            +
            #  All rights reserved.                                         #
         
     | 
| 
      
 5 
     | 
    
         
            +
            #                                                               #  
         
     | 
| 
      
 6 
     | 
    
         
            +
            #  Use, duplication or disclosure of the code is not permitted  #
         
     | 
| 
      
 7 
     | 
    
         
            +
            #  unless licensed.                                             #  
         
     | 
| 
      
 8 
     | 
    
         
            +
            #                                                               #  
         
     | 
| 
      
 9 
     | 
    
         
            +
            #  Last Updated: 7/7/08                                         #  
         
     | 
| 
      
 10 
     | 
    
         
            +
            #---------------------------------------------------------------#
         
     | 
| 
      
 11 
     | 
    
         
            +
            #                                                               #  
         
     | 
| 
      
 12 
     | 
    
         
            +
            # RubyRunReport__ is responsible for generating report data in  #
         
     | 
| 
      
 13 
     | 
    
         
            +
            # RSS or CSV format depending on the type of report.            #   
         
     | 
| 
      
 14 
     | 
    
         
            +
            #                                                               #  
         
     | 
| 
      
 15 
     | 
    
         
            +
            #---------------------------------------------------------------#
         
     | 
| 
      
 16 
     | 
    
         
            +
            module RubyRunReport__
         
     | 
| 
      
 17 
     | 
    
         
            +
              
         
     | 
| 
      
 18 
     | 
    
         
            +
              # Add entries to transaction log CSV file
         
     | 
| 
      
 19 
     | 
    
         
            +
              # metrics structure
         
     | 
| 
      
 20 
     | 
    
         
            +
              # metrics[0] Thread ID      metrics[1] Timestamp of the request
         
     | 
| 
      
 21 
     | 
    
         
            +
              # metrics[2] URL            metrics[3] Controller name
         
     | 
| 
      
 22 
     | 
    
         
            +
              # metrics[4] Action name    metrics[5] Response time
         
     | 
| 
      
 23 
     | 
    
         
            +
              # metrics[6] Action time    metrics[7] Database IO time
         
     | 
| 
      
 24 
     | 
    
         
            +
              # metrics[8] View time      metrics[9] Uncaptured time
         
     | 
| 
      
 25 
     | 
    
         
            +
              # metrics[10] Dispatch wait time
         
     | 
| 
      
 26 
     | 
    
         
            +
              # CSV format is URL, thread ID, timestamp, response time, action time, 
         
     | 
| 
      
 27 
     | 
    
         
            +
              #   database io time, view time, dispatch wait time, uncaptured time
         
     | 
| 
      
 28 
     | 
    
         
            +
              def add_txn_log_csv_item(buffer)
         
     | 
| 
      
 29 
     | 
    
         
            +
                return if buffer.length == 0
         
     | 
| 
      
 30 
     | 
    
         
            +
                $rubyrun_txn_log_reporter.info "\n----- Transaction Log at #{Time.now.ctime} -----"
         
     | 
| 
      
 31 
     | 
    
         
            +
                buffer.each { |metrics|
         
     | 
| 
      
 32 
     | 
    
         
            +
                  $rubyrun_txn_log_reporter.info "#{metrics[2]},#{metrics[0]},#{metrics[1].strftime("%H:%M:%S")}.#{("%.3f" % metrics[1].to_f).split('.')[1]} #{metrics[1].strftime("%m/%d/%y")},#{sprintf("%0.3f", metrics[5])},#{sprintf("%0.3f", metrics[6])},#{sprintf("%0.3f", metrics[7])},#{sprintf("%0.3f", metrics[8])},#{sprintf("%0.3f", metrics[10])},#{sprintf("%0.3f", metrics[9])}"
         
     | 
| 
      
 33 
     | 
    
         
            +
                }
         
     | 
| 
      
 34 
     | 
    
         
            +
              end
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
              # Add an item to performance summary RSS channel
         
     | 
| 
      
 37 
     | 
    
         
            +
              def add_perf_summary_rss_item(req_count)
         
     | 
| 
      
 38 
     | 
    
         
            +
                return unless $rubyrun_host_with_port # Server started but no request yet
         
     | 
| 
      
 39 
     | 
    
         
            +
                # First, Throughput Summary
         
     | 
| 
      
 40 
     | 
    
         
            +
                $rubyrun_throughput.shift if $rubyrun_throughput.length == $rubyrun_report_shift_age
         
     | 
| 
      
 41 
     | 
    
         
            +
                index = $rubyrun_throughput.length
         
     | 
| 
      
 42 
     | 
    
         
            +
                $rubyrun_throughput[index] = [Time.now, req_count.to_f/$rubyrun_report_timer*60]
         
     | 
| 
      
 43 
     | 
    
         
            +
                bar_content = ''
         
     | 
| 
      
 44 
     | 
    
         
            +
                label_content = ''
         
     | 
| 
      
 45 
     | 
    
         
            +
                max = ($rubyrun_throughput.max {|a,b| a[1] <=> b[1]})[1]
         
     | 
| 
      
 46 
     | 
    
         
            +
                max = 1 if max == 0 # Avoid divided by zero below
         
     | 
| 
      
 47 
     | 
    
         
            +
                $rubyrun_throughput.reverse!
         
     | 
| 
      
 48 
     | 
    
         
            +
                $rubyrun_report_shift_age.times { |i|
         
     | 
| 
      
 49 
     | 
    
         
            +
                  if $rubyrun_throughput[i]
         
     | 
| 
      
 50 
     | 
    
         
            +
                    bar_content += sprintf(THROUGHPUT_BAR_TABLE, sprintf('%0.0f',$rubyrun_throughput[i][1]), ($rubyrun_throughput[i][1]*250/max).to_i)
         
     | 
| 
      
 51 
     | 
    
         
            +
                    label_content += sprintf(THROUGHPUT_LABEL_TABLE, $rubyrun_throughput[i][0].strftime("%H:%M %b %d"))        
         
     | 
| 
      
 52 
     | 
    
         
            +
                  else
         
     | 
| 
      
 53 
     | 
    
         
            +
                    bar_content += sprintf(THROUGHPUT_BAR_TABLE, '', 0)
         
     | 
| 
      
 54 
     | 
    
         
            +
                    label_content += sprintf(THROUGHPUT_LABEL_TABLE, '')                
         
     | 
| 
      
 55 
     | 
    
         
            +
                  end
         
     | 
| 
      
 56 
     | 
    
         
            +
                }
         
     | 
| 
      
 57 
     | 
    
         
            +
                $rubyrun_throughput.reverse!    
         
     | 
| 
      
 58 
     | 
    
         
            +
                html_content = THROUGHPUT_HTML.sub(/%THROUGHPUT_BAR_TABLE%/, bar_content)
         
     | 
| 
      
 59 
     | 
    
         
            +
                html_content.sub!(/%THROUGHPUT_LABEL_TABLE%/, label_content)
         
     | 
| 
      
 60 
     | 
    
         
            +
                html_content.sub!(/%APPS_NAME%/,Rails::Configuration.new.root_path.split('/').last)
         
     | 
| 
      
 61 
     | 
    
         
            +
                html_content.sub!(/%TIMESTAMP%/,Time.now.strftime("%H:%M:%S %m/%d/%Y"))  
         
     | 
| 
      
 62 
     | 
    
         
            +
                # Second, Top Slowest Requests
         
     | 
| 
      
 63 
     | 
    
         
            +
                results = sort_performance_metrics
         
     | 
| 
      
 64 
     | 
    
         
            +
                table_content = ''
         
     | 
| 
      
 65 
     | 
    
         
            +
                10.times { |i|
         
     | 
| 
      
 66 
     | 
    
         
            +
                  break unless results[i]
         
     | 
| 
      
 67 
     | 
    
         
            +
                  table_content += sprintf(TOP_SLOWEST_REQUESTS_TABLE, results[i][0],
         
     | 
| 
      
 68 
     | 
    
         
            +
                                          (150*results[i][1][0]/results[0][1][0]).round, results[i][1][0])
         
     | 
| 
      
 69 
     | 
    
         
            +
                }
         
     | 
| 
      
 70 
     | 
    
         
            +
                (html_content << TOP_SLOWEST_REQUESTS_HTML).sub!(/%TOP_SLOWEST_REQUESTS_TABLE%/,table_content)
         
     | 
| 
      
 71 
     | 
    
         
            +
                # Third, Request Performance Breakdown
         
     | 
| 
      
 72 
     | 
    
         
            +
                odd = true
         
     | 
| 
      
 73 
     | 
    
         
            +
                table_content = ''      
         
     | 
| 
      
 74 
     | 
    
         
            +
                results.each { |metrics|
         
     | 
| 
      
 75 
     | 
    
         
            +
                  table_content += sprintf("#{odd ? REQ_PERF_BREAKDOWN_TABLE_ODD : REQ_PERF_BREAKDOWN_TABLE_EVEN}", metrics[0], metrics[1][6], metrics[1][0], metrics[1][1], (metrics[1][1]/metrics[1][0]*100).round, metrics[1][2], (metrics[1][2]/metrics[1][0]*100).round, metrics[1][3], (metrics[1][3]/metrics[1][0]*100).round, metrics[1][5], (metrics[1][5]/metrics[1][0]*100).round, metrics[1][4])
         
     | 
| 
      
 76 
     | 
    
         
            +
                  odd = odd ? false : true
         
     | 
| 
      
 77 
     | 
    
         
            +
                }
         
     | 
| 
      
 78 
     | 
    
         
            +
                (html_content << REQ_PERF_BREAKDOWN_HTML).sub!(/%REQ_PERF_BREAKDOWN_TABLE%/,table_content);
         
     | 
| 
      
 79 
     | 
    
         
            +
                $rubyrun_perf_summary_rss.add_item(RubyRunRSS::RUBYRUN_RSS_PERF_SUMMARY_ITEM_TITLE,
         
     | 
| 
      
 80 
     | 
    
         
            +
                                                   RubyRunRSS::RUBYRUN_RSS_PERF_SUMMARY_ITEM_DESCRIPTION, html_content)
         
     | 
| 
      
 81 
     | 
    
         
            +
              end
         
     | 
| 
      
 82 
     | 
    
         
            +
              
         
     | 
| 
      
 83 
     | 
    
         
            +
              # Create the folder for keeping RSS XML file and HTML files
         
     | 
| 
      
 84 
     | 
    
         
            +
              # Create the RSS channel
         
     | 
| 
      
 85 
     | 
    
         
            +
              def create_rss_channels
         
     | 
| 
      
 86 
     | 
    
         
            +
                rss_folder = $rubyrun_config['RSS_PATH'] ? $rubyrun_config['RSS_PATH'] \
         
     | 
| 
      
 87 
     | 
    
         
            +
                             : "#{Rails::Configuration.new.root_path}/public/#{RubyRunRSS::RUBYRUN_RSS_FOLDER}"
         
     | 
| 
      
 88 
     | 
    
         
            +
                begin
         
     | 
| 
      
 89 
     | 
    
         
            +
                  Dir.mkdir(rss_folder) unless File.exist?(rss_folder)
         
     | 
| 
      
 90 
     | 
    
         
            +
                rescue Exception
         
     | 
| 
      
 91 
     | 
    
         
            +
                  rss_folder = @rubyrun_report_folder
         
     | 
| 
      
 92 
     | 
    
         
            +
                end    
         
     | 
| 
      
 93 
     | 
    
         
            +
                $rubyrun_perf_summary_rss = RubyRunRSS.new \
         
     | 
| 
      
 94 
     | 
    
         
            +
                                            RubyRunRSS::RUBYRUN_RSS_PERF_SUMMARY_CHANNEL_TITLE,
         
     | 
| 
      
 95 
     | 
    
         
            +
                                            RubyRunRSS::RUBYRUN_RSS_PERF_SUMMARY_CHANNEL_DESCRIPTION,
         
     | 
| 
      
 96 
     | 
    
         
            +
                                            rss_folder,
         
     | 
| 
      
 97 
     | 
    
         
            +
                                            RubyRunRSS::RUBYRUN_RSS_PERF_SUMMARY_CHANNEL_FILENAME,
         
     | 
| 
      
 98 
     | 
    
         
            +
                                            RubyRunRSS::RUBYRUN_RSS_PERF_SUMMARY_CHANNEL_ITEM_FILENAME \
         
     | 
| 
      
 99 
     | 
    
         
            +
                                            unless $rubyrun_perf_summary_rss
         
     | 
| 
      
 100 
     | 
    
         
            +
                $rubyrun_throughput = Array.new
         
     | 
| 
      
 101 
     | 
    
         
            +
              end
         
     | 
| 
      
 102 
     | 
    
         
            +
             
     | 
| 
      
 103 
     | 
    
         
            +
              # Create the CSV files 
         
     | 
| 
      
 104 
     | 
    
         
            +
              def create_csv_files
         
     | 
| 
      
 105 
     | 
    
         
            +
                $rubyrun_txn_log_reporter = Logger.new("#{@rubyrun_report_folder}/#{File.basename($0, ".*")}_#{$$.to_s}_txn_log.csv", shift_age = 10, shift_size = 4096000)   
         
     | 
| 
      
 106 
     | 
    
         
            +
                $rubyrun_txn_log_reporter.info "#\n# Format: [URL],[thread ID],[timestamp],[response time],[action time],[database IO time],[view time],[dispatch delay time],[uncaptured time]\n#"
         
     | 
| 
      
 107 
     | 
    
         
            +
              end
         
     | 
| 
      
 108 
     | 
    
         
            +
                
         
     | 
| 
      
 109 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,97 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            #---------------------------------------------------------------#
         
     | 
| 
      
 2 
     | 
    
         
            +
            #                                                               #  
         
     | 
| 
      
 3 
     | 
    
         
            +
            #  (C) Copyright Rubysophic Inc. 2007-2008                      #
         
     | 
| 
      
 4 
     | 
    
         
            +
            #  All rights reserved.                                         #
         
     | 
| 
      
 5 
     | 
    
         
            +
            #                                                               #  
         
     | 
| 
      
 6 
     | 
    
         
            +
            #  Use, duplication or disclosure of the code is not permitted  #
         
     | 
| 
      
 7 
     | 
    
         
            +
            #  unless licensed.                                             #
         
     | 
| 
      
 8 
     | 
    
         
            +
            #  Dynamic Application Discovery                                #                        
         
     | 
| 
      
 9 
     | 
    
         
            +
            #                                                               #            
         
     | 
| 
      
 10 
     | 
    
         
            +
            #  Last Updated: 6/03/08                                        #  
         
     | 
| 
      
 11 
     | 
    
         
            +
            #---------------------------------------------------------------#
         
     | 
| 
      
 12 
     | 
    
         
            +
            #                                                               #  
         
     | 
| 
      
 13 
     | 
    
         
            +
            # RubyRunRSS provides the interfaces for creating RSS channel   #
         
     | 
| 
      
 14 
     | 
    
         
            +
            # and adding items to it.                                       #
         
     | 
| 
      
 15 
     | 
    
         
            +
            #                                                               #  
         
     | 
| 
      
 16 
     | 
    
         
            +
            #---------------------------------------------------------------#
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
            require 'rss/maker'
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
            class RubyRunRSS
         
     | 
| 
      
 21 
     | 
    
         
            +
              RUBYRUN_RSS_VERSION                              = '2.0'
         
     | 
| 
      
 22 
     | 
    
         
            +
              RUBYRUN_RSS_CHANNEL_URL                          = 'http://www.rubysophic.com'
         
     | 
| 
      
 23 
     | 
    
         
            +
              RUBYRUN_RSS_IMAGE_TITLE                          = 'Learn more about RubyRun from Rubysophic'
         
     | 
| 
      
 24 
     | 
    
         
            +
              RUBYRUN_RSS_IMAGE_URL                            = 'http://www.rubysophic.com/images/logo.jpg'
         
     | 
| 
      
 25 
     | 
    
         
            +
              RUBYRUN_RSS_FOLDER                               = 'rubyrun_rss'
         
     | 
| 
      
 26 
     | 
    
         
            +
              RUBYRUN_RSS_PERF_SUMMARY_CHANNEL_TITLE           = 'RubyRun: %s Performance Summary'
         
     | 
| 
      
 27 
     | 
    
         
            +
              RUBYRUN_RSS_PERF_SUMMARY_CHANNEL_ITEM_FILENAME   = 'perf_summary_item'
         
     | 
| 
      
 28 
     | 
    
         
            +
              RUBYRUN_RSS_PERF_SUMMARY_CHANNEL_DESCRIPTION     = 'RubyRun delivers up-to-the-minute performance summary of your application.'
         
     | 
| 
      
 29 
     | 
    
         
            +
              RUBYRUN_RSS_PERF_SUMMARY_CHANNEL_FILENAME        = 'perf_summary.xml'
         
     | 
| 
      
 30 
     | 
    
         
            +
              RUBYRUN_RSS_PERF_SUMMARY_ITEM_TITLE              = 'Performance summary at %s'
         
     | 
| 
      
 31 
     | 
    
         
            +
              RUBYRUN_RSS_PERF_SUMMARY_ITEM_DESCRIPTION        = 'Performance summary of %s at %s'  
         
     | 
| 
      
 32 
     | 
    
         
            +
              
         
     | 
| 
      
 33 
     | 
    
         
            +
              # Constructor of the class.
         
     | 
| 
      
 34 
     | 
    
         
            +
              # RSS XML file and HTML files will be kept in the directory as specified                
         
     | 
| 
      
 35 
     | 
    
         
            +
              def initialize (title, description, directory, rss_filename, html_filename)
         
     | 
| 
      
 36 
     | 
    
         
            +
                @title = title
         
     | 
| 
      
 37 
     | 
    
         
            +
                @description = description
         
     | 
| 
      
 38 
     | 
    
         
            +
                @directory = directory
         
     | 
| 
      
 39 
     | 
    
         
            +
                @rss_filename = rss_filename
         
     | 
| 
      
 40 
     | 
    
         
            +
                @html_filename = html_filename
         
     | 
| 
      
 41 
     | 
    
         
            +
                @apps_name = Rails::Configuration.new.root_path.split('/').last
         
     | 
| 
      
 42 
     | 
    
         
            +
                @rss_xml_destination = "#{@directory}/#{@rss_filename}"
         
     | 
| 
      
 43 
     | 
    
         
            +
                create_channel_content unless File::exists?(@rss_xml_destination)
         
     | 
| 
      
 44 
     | 
    
         
            +
                @rss = load_rss_content
         
     | 
| 
      
 45 
     | 
    
         
            +
              end
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
      
 47 
     | 
    
         
            +
              # Create the RSS channel
         
     | 
| 
      
 48 
     | 
    
         
            +
              def create_channel_content
         
     | 
| 
      
 49 
     | 
    
         
            +
                content = RSS::Maker.make(RUBYRUN_RSS_VERSION) do |m|
         
     | 
| 
      
 50 
     | 
    
         
            +
                  m.channel.title = sprintf(@title, @apps_name)
         
     | 
| 
      
 51 
     | 
    
         
            +
                  m.channel.link = RUBYRUN_RSS_CHANNEL_URL
         
     | 
| 
      
 52 
     | 
    
         
            +
                  m.channel.description = @description
         
     | 
| 
      
 53 
     | 
    
         
            +
                  m.items.do_sort = true # sort items by date
         
     | 
| 
      
 54 
     | 
    
         
            +
                  m.image.title = RUBYRUN_RSS_IMAGE_TITLE
         
     | 
| 
      
 55 
     | 
    
         
            +
                  m.image.width = 140
         
     | 
| 
      
 56 
     | 
    
         
            +
                  m.image.height = 25
         
     | 
| 
      
 57 
     | 
    
         
            +
                  m.image.url = RUBYRUN_RSS_IMAGE_URL
         
     | 
| 
      
 58 
     | 
    
         
            +
                end
         
     | 
| 
      
 59 
     | 
    
         
            +
                File.open(@rss_xml_destination,"w") do |f|
         
     | 
| 
      
 60 
     | 
    
         
            +
                  f.write(content)
         
     | 
| 
      
 61 
     | 
    
         
            +
                end
         
     | 
| 
      
 62 
     | 
    
         
            +
                content.to_s
         
     | 
| 
      
 63 
     | 
    
         
            +
              end
         
     | 
| 
      
 64 
     | 
    
         
            +
             
     | 
| 
      
 65 
     | 
    
         
            +
              # Add an item to the RSS channel
         
     | 
| 
      
 66 
     | 
    
         
            +
              def add_item (title, description, html_content)
         
     | 
| 
      
 67 
     | 
    
         
            +
                filename = "#{@html_filename}_#{Time.now.to_i}#{rand(1000000)}.html"
         
     | 
| 
      
 68 
     | 
    
         
            +
                File.open("#{@directory}/#{filename}", 'w') { |file| file.puts html_content }  
         
     | 
| 
      
 69 
     | 
    
         
            +
                item = RSS::Rss::Channel::Item.new
         
     | 
| 
      
 70 
     | 
    
         
            +
                item.title = sprintf(title, Time.now.strftime("%H:%M:%S"))
         
     | 
| 
      
 71 
     | 
    
         
            +
                item.description = sprintf(description, @apps_name, Time.now.strftime("%H:%M:%S"))
         
     | 
| 
      
 72 
     | 
    
         
            +
                item.link = "http://#{$rubyrun_host_with_port}/#{RUBYRUN_RSS_FOLDER}/#{filename}"
         
     | 
| 
      
 73 
     | 
    
         
            +
                remove_old_item(@rss) if @rss.items.length == $rubyrun_report_shift_age
         
     | 
| 
      
 74 
     | 
    
         
            +
                @rss.items << item
         
     | 
| 
      
 75 
     | 
    
         
            +
                File.open(@rss_xml_destination,"w") do |f|
         
     | 
| 
      
 76 
     | 
    
         
            +
                  f.write(@rss)
         
     | 
| 
      
 77 
     | 
    
         
            +
                end    
         
     | 
| 
      
 78 
     | 
    
         
            +
              end
         
     | 
| 
      
 79 
     | 
    
         
            +
              
         
     | 
| 
      
 80 
     | 
    
         
            +
              private
         
     | 
| 
      
 81 
     | 
    
         
            +
              
         
     | 
| 
      
 82 
     | 
    
         
            +
              # Load the existing RSS XML file. Create a new channel if the channel is blank
         
     | 
| 
      
 83 
     | 
    
         
            +
              def load_rss_content
         
     | 
| 
      
 84 
     | 
    
         
            +
                content = "" # raw content of rss feed will be loaded here
         
     | 
| 
      
 85 
     | 
    
         
            +
                open(@rss_xml_destination) do |s| content = s.read end
         
     | 
| 
      
 86 
     | 
    
         
            +
                content = create_channel_content if content == ''
         
     | 
| 
      
 87 
     | 
    
         
            +
                RSS::Parser.parse(content, false)    
         
     | 
| 
      
 88 
     | 
    
         
            +
              end
         
     | 
| 
      
 89 
     | 
    
         
            +
              
         
     | 
| 
      
 90 
     | 
    
         
            +
              # Remove the last item in the RSS channel
         
     | 
| 
      
 91 
     | 
    
         
            +
              def remove_old_item(rss)
         
     | 
| 
      
 92 
     | 
    
         
            +
                item = rss.items.shift
         
     | 
| 
      
 93 
     | 
    
         
            +
                filename = "#{@directory}/#{item.link.split('/').last}"
         
     | 
| 
      
 94 
     | 
    
         
            +
                File.delete(filename) if File.exists?(filename)
         
     | 
| 
      
 95 
     | 
    
         
            +
              end  
         
     | 
| 
      
 96 
     | 
    
         
            +
              
         
     | 
| 
      
 97 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,79 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            #---------------------------------------------------------------#
         
     | 
| 
      
 2 
     | 
    
         
            +
            #                                                               #  
         
     | 
| 
      
 3 
     | 
    
         
            +
            #  (C) Copyright Rubysophic Inc. 2007-2008                      #
         
     | 
| 
      
 4 
     | 
    
         
            +
            #  All rights reserved.                                         #
         
     | 
| 
      
 5 
     | 
    
         
            +
            #                                                               #  
         
     | 
| 
      
 6 
     | 
    
         
            +
            #  Use, duplication or disclosure of the code is not permitted  #
         
     | 
| 
      
 7 
     | 
    
         
            +
            #  unless licensed.                                             #
         
     | 
| 
      
 8 
     | 
    
         
            +
            #                                                               #            
         
     | 
| 
      
 9 
     | 
    
         
            +
            #  Last Updated: 7/09/08                                        #  
         
     | 
| 
      
 10 
     | 
    
         
            +
            #---------------------------------------------------------------#
         
     | 
| 
      
 11 
     | 
    
         
            +
            #                                                               #  
         
     | 
| 
      
 12 
     | 
    
         
            +
            #  RubyRunTracer__ is the module for tracing a line of data     #
         
     | 
| 
      
 13 
     | 
    
         
            +
            #  in the output destination.                                   #
         
     | 
| 
      
 14 
     | 
    
         
            +
            #                                                               #            
         
     | 
| 
      
 15 
     | 
    
         
            +
            #  The source of the trace can be data from forward-tracing     #
         
     | 
| 
      
 16 
     | 
    
         
            +
            #  or data collected from a stack trace.			                  #
         
     | 
| 
      
 17 
     | 
    
         
            +
            #                                                               #  
         
     | 
| 
      
 18 
     | 
    
         
            +
            #---------------------------------------------------------------#
         
     | 
| 
      
 19 
     | 
    
         
            +
            module RubyRunTracer__
         
     | 
| 
      
 20 
     | 
    
         
            +
              
         
     | 
| 
      
 21 
     | 
    
         
            +
              require 'rubyrun_globals'
         
     | 
| 
      
 22 
     | 
    
         
            +
              require 'rubyrun_utils__'
         
     | 
| 
      
 23 
     | 
    
         
            +
              require 'rubyrun_html__'
         
     | 
| 
      
 24 
     | 
    
         
            +
              include RubyRunGlobals
         
     | 
| 
      
 25 
     | 
    
         
            +
              include RubyRunUtils__
         
     | 
| 
      
 26 
     | 
    
         
            +
              include RubyRunHTML__
         
     | 
| 
      
 27 
     | 
    
         
            +
                
         
     | 
| 
      
 28 
     | 
    
         
            +
              # 1. If arguments are required to trace, try using kernel inspect to print it
         
     | 
| 
      
 29 
     | 
    
         
            +
              # 2. If obejct is required to trace, try using kernel inspect to print it. 
         
     | 
| 
      
 30 
     | 
    
         
            +
              # Otherwise print class name, The inspect can cause recursion and blow up
         
     | 
| 
      
 31 
     | 
    
         
            +
              # ruby. Rescue only delays the issue hence not used here.
         
     | 
| 
      
 32 
     | 
    
         
            +
              # 3. Show the last caller and line 
         
     | 
| 
      
 33 
     | 
    
         
            +
              def enter_trace(tid, type, obj, invoker, klass, mid, *args)
         
     | 
| 
      
 34 
     | 
    
         
            +
                @rubyrun_trace_odd_row = true if @rubyrun_trace_odd_row == nil
         
     | 
| 
      
 35 
     | 
    
         
            +
                cur_time = Time.now
         
     | 
| 
      
 36 
     | 
    
         
            +
                html_content = sprintf("#{@rubyrun_trace_odd_row ? METHOD_TRACE_ODD_ROW : METHOD_TRACE_EVEN_ROW}",
         
     | 
| 
      
 37 
     | 
    
         
            +
                                       "#{cur_time.strftime("%H:%M:%S")}.#{("%.3f" % cur_time.to_f).split('.')[1]} #{cur_time.strftime("%m/%d/%y")}",
         
     | 
| 
      
 38 
     | 
    
         
            +
                                       get_thread_id,
         
     | 
| 
      
 39 
     | 
    
         
            +
                                       "#{type.split(' ').reverse.first}",
         
     | 
| 
      
 40 
     | 
    
         
            +
                                       "#{type.split(' ').length == 3 ? '#3B9C9C' : (@rubyrun_trace_odd_row ? '#AFDCEC' : 'white')}",
         
     | 
| 
      
 41 
     | 
    
         
            +
                                       "#{type.split(' ').length == 1 ? '' : (type.split(' ').length == 3 ? '*'+type.split(' ').reverse[1]+'s' : type.split(' ').reverse[1]+'s')}",
         
     | 
| 
      
 42 
     | 
    
         
            +
                                       klass.to_s,
         
     | 
| 
      
 43 
     | 
    
         
            +
                                       return_method_name(mid),
         
     | 
| 
      
 44 
     | 
    
         
            +
                                       "#{args.each {|arg| arg.inspect} if $rubyrun_debug_args || is_in_hash?($rubyrun_adapter_hash, klass, mid)}",
         
     | 
| 
      
 45 
     | 
    
         
            +
                                       "#{$rubyrun_debug_obj && obj ? obj.inspect : obj.class if obj}",
         
     | 
| 
      
 46 
     | 
    
         
            +
                                       "#{invoker if invoker}")
         
     | 
| 
      
 47 
     | 
    
         
            +
                write_trace(html_content)
         
     | 
| 
      
 48 
     | 
    
         
            +
                @rubyrun_trace_odd_row = !@rubyrun_trace_odd_row
         
     | 
| 
      
 49 
     | 
    
         
            +
              end
         
     | 
| 
      
 50 
     | 
    
         
            +
              
         
     | 
| 
      
 51 
     | 
    
         
            +
              # Write a trace entry to the trace destination
         
     | 
| 
      
 52 
     | 
    
         
            +
              def write_trace(html_content)
         
     | 
| 
      
 53 
     | 
    
         
            +
                begin
         
     | 
| 
      
 54 
     | 
    
         
            +
                  $rubyrun_tracer.info(html_content)
         
     | 
| 
      
 55 
     | 
    
         
            +
                rescue Exception => e
         
     | 
| 
      
 56 
     | 
    
         
            +
                  $rubyrun_logger.warn(e.to_s)
         
     | 
| 
      
 57 
     | 
    
         
            +
                end
         
     | 
| 
      
 58 
     | 
    
         
            +
              end
         
     | 
| 
      
 59 
     | 
    
         
            +
              
         
     | 
| 
      
 60 
     | 
    
         
            +
              # The stack trace global hash is printed out in the rubyrun log in
         
     | 
| 
      
 61 
     | 
    
         
            +
              # thread id order, also showing the top stack of all these
         
     | 
| 
      
 62 
     | 
    
         
            +
              # threads before they were interrupted.
         
     | 
| 
      
 63 
     | 
    
         
            +
              def back_trace_all(th_data_hash)
         
     | 
| 
      
 64 
     | 
    
         
            +
                $rubyrun_thread_dump_reporter.info "----- RubyRun Thread Dump STARTS-----"
         
     | 
| 
      
 65 
     | 
    
         
            +
                $rubyrun_thread_stack.each {|th, stack|
         
     | 
| 
      
 66 
     | 
    
         
            +
                  $rubyrun_thread_dump_reporter.info
         
     | 
| 
      
 67 
     | 
    
         
            +
                  thread_id = get_thread_id(th)
         
     | 
| 
      
 68 
     | 
    
         
            +
                  $rubyrun_thread_dump_reporter.info "Thread ID = #{thread_id}"
         
     | 
| 
      
 69 
     | 
    
         
            +
                  $rubyrun_thread_dump_reporter.info "    Last line before interrupt: #{get_top_stack(th_data_hash, thread_id)}"
         
     | 
| 
      
 70 
     | 
    
         
            +
                  $rubyrun_thread_dump_reporter.info "    Stack trace at interrupt"
         
     | 
| 
      
 71 
     | 
    
         
            +
                  stack.each {|line|
         
     | 
| 
      
 72 
     | 
    
         
            +
                    $rubyrun_thread_dump_reporter.info "\t#{line}"
         
     | 
| 
      
 73 
     | 
    
         
            +
                  }
         
     | 
| 
      
 74 
     | 
    
         
            +
                }
         
     | 
| 
      
 75 
     | 
    
         
            +
                $rubyrun_thread_dump_reporter.info
         
     | 
| 
      
 76 
     | 
    
         
            +
                $rubyrun_thread_dump_reporter.info "----- RubyRun Thread Dump ENDS -----"
         
     | 
| 
      
 77 
     | 
    
         
            +
                $rubyrun_thread_stack.clear
         
     | 
| 
      
 78 
     | 
    
         
            +
              end    
         
     | 
| 
      
 79 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,101 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            #---------------------------------------------------------------#
         
     | 
| 
      
 2 
     | 
    
         
            +
            #                                                               #  
         
     | 
| 
      
 3 
     | 
    
         
            +
            #  (C) Copyright Rubysophic Inc. 2007-2008                      #
         
     | 
| 
      
 4 
     | 
    
         
            +
            #  All rights reserved.                                         #
         
     | 
| 
      
 5 
     | 
    
         
            +
            #                                                               #  
         
     | 
| 
      
 6 
     | 
    
         
            +
            #  Use, duplication or disclosure of the code is not permitted  #
         
     | 
| 
      
 7 
     | 
    
         
            +
            #  unless licensed.                                             #
         
     | 
| 
      
 8 
     | 
    
         
            +
            #                                                               #            
         
     | 
| 
      
 9 
     | 
    
         
            +
            #  Last Updated: 7/09/08                                        #  
         
     | 
| 
      
 10 
     | 
    
         
            +
            #---------------------------------------------------------------#
         
     | 
| 
      
 11 
     | 
    
         
            +
            #                                                               #  
         
     | 
| 
      
 12 
     | 
    
         
            +
            # RubyRunUtils__ is a module that owns common methods shared    #
         
     | 
| 
      
 13 
     | 
    
         
            +
            # by all the other RubyRun modules.                             # 
         
     | 
| 
      
 14 
     | 
    
         
            +
            #                                                               #  
         
     | 
| 
      
 15 
     | 
    
         
            +
            #---------------------------------------------------------------#
         
     | 
| 
      
 16 
     | 
    
         
            +
            module RubyRunUtils__
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
              require 'rubyrun_globals'
         
     | 
| 
      
 19 
     | 
    
         
            +
              include RubyRunGlobals
         
     | 
| 
      
 20 
     | 
    
         
            +
              
         
     | 
| 
      
 21 
     | 
    
         
            +
              # Return a readable thread ID for the current thread of execution
         
     | 
| 
      
 22 
     | 
    
         
            +
              def get_thread_id(th=Thread.current)
         
     | 
| 
      
 23 
     | 
    
         
            +
                th.inspect.split(/Thread:0x/)[1].split(/ .*?>/)[0]
         
     | 
| 
      
 24 
     | 
    
         
            +
              end
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
              # Retrieve caller details (filename, line number, method name)
         
     | 
| 
      
 27 
     | 
    
         
            +
              def get_caller_detail(n=3)
         
     | 
| 
      
 28 
     | 
    
         
            +
                caller(0)[n].gsub("#{RUBYRUN_PREFIX}_", '').gsub('//', '/') 
         
     | 
| 
      
 29 
     | 
    
         
            +
              end
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
              # Environment variable not defined or defined with nil value is deemed to
         
     | 
| 
      
 32 
     | 
    
         
            +
              # be non-existent
         
     | 
| 
      
 33 
     | 
    
         
            +
              def env_var_exists?(var)
         
     | 
| 
      
 34 
     | 
    
         
            +
                ENV[var].nil? || ENV[var] == '' ? false : true
         
     | 
| 
      
 35 
     | 
    
         
            +
              end
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
              # Error exit
         
     | 
| 
      
 38 
     | 
    
         
            +
              def fatal_exit(e)
         
     | 
| 
      
 39 
     | 
    
         
            +
                $stderr.print e.to_s + "\n" + e.backtrace.join("\n")
         
     | 
| 
      
 40 
     | 
    
         
            +
                exit(-1)
         
     | 
| 
      
 41 
     | 
    
         
            +
              end
         
     | 
| 
      
 42 
     | 
    
         
            +
              
         
     | 
| 
      
 43 
     | 
    
         
            +
              # Return true if a Rails Action Controller class 
         
     | 
| 
      
 44 
     | 
    
         
            +
              # A module or object has no superclass hence the rescue clause
         
     | 
| 
      
 45 
     | 
    
         
            +
              def is_rails_controller?(klass)
         
     | 
| 
      
 46 
     | 
    
         
            +
                return true if $rubyrun_controller_classes.include?(klass)
         
     | 
| 
      
 47 
     | 
    
         
            +
                $rubyrun_rails_env ||= ENV['RAILS_ENV']
         
     | 
| 
      
 48 
     | 
    
         
            +
                begin
         
     | 
| 
      
 49 
     | 
    
         
            +
                  ($rubyrun_controller_classes << klass; return true) if $rubyrun_rails_env &&
         
     | 
| 
      
 50 
     | 
    
         
            +
                    klass.to_s[-10, 10] == 'Controller' && is_application_controller(klass)
         
     | 
| 
      
 51 
     | 
    
         
            +
                rescue
         
     | 
| 
      
 52 
     | 
    
         
            +
                end      
         
     | 
| 
      
 53 
     | 
    
         
            +
                false    
         
     | 
| 
      
 54 
     | 
    
         
            +
              end
         
     | 
| 
      
 55 
     | 
    
         
            +
              
         
     | 
| 
      
 56 
     | 
    
         
            +
              # Return true if this is an action method in a controller class
         
     | 
| 
      
 57 
     | 
    
         
            +
              def is_action?(klass, mid)
         
     | 
| 
      
 58 
     | 
    
         
            +
                !klass.private_instance_methods(false).include?(return_method_name(mid))    
         
     | 
| 
      
 59 
     | 
    
         
            +
              end
         
     | 
| 
      
 60 
     | 
    
         
            +
              
         
     | 
| 
      
 61 
     | 
    
         
            +
              # Given a class, it's deemed to be a Rails Action Controller if one of its
         
     | 
| 
      
 62 
     | 
    
         
            +
              # ancestors is ApplicationController
         
     | 
| 
      
 63 
     | 
    
         
            +
              def is_application_controller(klass)
         
     | 
| 
      
 64 
     | 
    
         
            +
                return false unless klass.superclass
         
     | 
| 
      
 65 
     | 
    
         
            +
                if klass.superclass == ApplicationController
         
     | 
| 
      
 66 
     | 
    
         
            +
                  return true
         
     | 
| 
      
 67 
     | 
    
         
            +
                else
         
     | 
| 
      
 68 
     | 
    
         
            +
                  is_application_controller(klass.superclass)
         
     | 
| 
      
 69 
     | 
    
         
            +
                end
         
     | 
| 
      
 70 
     | 
    
         
            +
              end
         
     | 
| 
      
 71 
     | 
    
         
            +
             
     | 
| 
      
 72 
     | 
    
         
            +
              # Return false if the passed in hash is empty
         
     | 
| 
      
 73 
     | 
    
         
            +
              # Return false if the hash doenst even have the class name as a key
         
     | 
| 
      
 74 
     | 
    
         
            +
              # Return true if the hash has the key but the method array is empty
         
     | 
| 
      
 75 
     | 
    
         
            +
              # Return true if the method array has a case-insensitive matching name,
         
     | 
| 
      
 76 
     | 
    
         
            +
              # matching can be exact or 'include'.
         
     | 
| 
      
 77 
     | 
    
         
            +
              # Otherwise return false
         
     | 
| 
      
 78 
     | 
    
         
            +
              def is_in?(hash, klass, mid, mode='loose')
         
     | 
| 
      
 79 
     | 
    
         
            +
                return false if hash.empty?
         
     | 
| 
      
 80 
     | 
    
         
            +
                [klass.to_s, klass.class.to_s, '*'].each {|name|
         
     | 
| 
      
 81 
     | 
    
         
            +
                  if hash.has_key?(name)
         
     | 
| 
      
 82 
     | 
    
         
            +
                    return true if hash[name].empty? 
         
     | 
| 
      
 83 
     | 
    
         
            +
                    method_name = return_method_name(mid)
         
     | 
| 
      
 84 
     | 
    
         
            +
                    hash[name].each {|meth_name|
         
     | 
| 
      
 85 
     | 
    
         
            +
                    case mode
         
     | 
| 
      
 86 
     | 
    
         
            +
                      when 'strict'
         
     | 
| 
      
 87 
     | 
    
         
            +
                        return true if method_name.downcase == meth_name.downcase 
         
     | 
| 
      
 88 
     | 
    
         
            +
                      when 'loose'
         
     | 
| 
      
 89 
     | 
    
         
            +
                        return true if method_name.downcase.include?(meth_name.downcase) 
         
     | 
| 
      
 90 
     | 
    
         
            +
                      end
         
     | 
| 
      
 91 
     | 
    
         
            +
                    }
         
     | 
| 
      
 92 
     | 
    
         
            +
                  end
         
     | 
| 
      
 93 
     | 
    
         
            +
                }
         
     | 
| 
      
 94 
     | 
    
         
            +
                false
         
     | 
| 
      
 95 
     | 
    
         
            +
              end 
         
     | 
| 
      
 96 
     | 
    
         
            +
              
         
     | 
| 
      
 97 
     | 
    
         
            +
              # Return method name since mid can be an method object ID or a string
         
     | 
| 
      
 98 
     | 
    
         
            +
              def return_method_name(mid)
         
     | 
| 
      
 99 
     | 
    
         
            +
                mid.kind_of?(String) ? mid : mid.id2name
         
     | 
| 
      
 100 
     | 
    
         
            +
              end
         
     | 
| 
      
 101 
     | 
    
         
            +
            end
         
     | 
| 
         Binary file 
     |