rubyrun 0.9.0-mswin32

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.
Files changed (96) hide show
  1. data/LICENSE +13 -0
  2. data/README +77 -0
  3. data/Rakefile +241 -0
  4. data/bin/confgure +2 -0
  5. data/docs/rubyrun-0.9.0.htm +6344 -0
  6. data/docs/rubyrun-0.9.0.pdf +0 -0
  7. data/docs/rubyrun-0.9.0_files/colorschememapping.xml +2 -0
  8. data/docs/rubyrun-0.9.0_files/filelist.xml +29 -0
  9. data/docs/rubyrun-0.9.0_files/header.htm +141 -0
  10. data/docs/rubyrun-0.9.0_files/image001.jpg +0 -0
  11. data/docs/rubyrun-0.9.0_files/image002.jpg +0 -0
  12. data/docs/rubyrun-0.9.0_files/image003.jpg +0 -0
  13. data/docs/rubyrun-0.9.0_files/image004.jpg +0 -0
  14. data/docs/rubyrun-0.9.0_files/image005.jpg +0 -0
  15. data/docs/rubyrun-0.9.0_files/image006.jpg +0 -0
  16. data/docs/rubyrun-0.9.0_files/image007.jpg +0 -0
  17. data/docs/rubyrun-0.9.0_files/image008.jpg +0 -0
  18. data/docs/rubyrun-0.9.0_files/image009.jpg +0 -0
  19. data/docs/rubyrun-0.9.0_files/image010.jpg +0 -0
  20. data/docs/rubyrun-0.9.0_files/image011.jpg +0 -0
  21. data/docs/rubyrun-0.9.0_files/image012.jpg +0 -0
  22. data/docs/rubyrun-0.9.0_files/image013.jpg +0 -0
  23. data/docs/rubyrun-0.9.0_files/image014.jpg +0 -0
  24. data/docs/rubyrun-0.9.0_files/image015.jpg +0 -0
  25. data/docs/rubyrun-0.9.0_files/image016.jpg +0 -0
  26. data/docs/rubyrun-0.9.0_files/image017.png +0 -0
  27. data/docs/rubyrun-0.9.0_files/image018.jpg +0 -0
  28. data/docs/rubyrun-0.9.0_files/image019.jpg +0 -0
  29. data/docs/rubyrun-0.9.0_files/image020.jpg +0 -0
  30. data/docs/rubyrun-0.9.0_files/image021.jpg +0 -0
  31. data/docs/rubyrun-0.9.0_files/image022.png +0 -0
  32. data/docs/rubyrun-0.9.0_files/themedata.thmx +0 -0
  33. data/etc/rubyrun_opts.yml +132 -0
  34. data/ext/extconf.rb +4 -0
  35. data/ext/rubyrunnative__.bundle +0 -0
  36. data/ext/rubyrunnative__.c +154 -0
  37. data/ext/rubyrunnative__.def +2 -0
  38. data/ext/rubyrunnative__.h +36 -0
  39. data/ext/rubyrunnative__.so +0 -0
  40. data/ext/rubyrunnative__linux.so +0 -0
  41. data/html/classes/Module.html +174 -0
  42. data/html/classes/Object.html +151 -0
  43. data/html/classes/RubyRunBufferMgr__.html +182 -0
  44. data/html/classes/RubyRunCommander__.html +578 -0
  45. data/html/classes/RubyRunDad__.html +144 -0
  46. data/html/classes/RubyRunGlobals.html +248 -0
  47. data/html/classes/RubyRunHTMLWriter/RubyRunHTMLDevice.html +157 -0
  48. data/html/classes/RubyRunHTMLWriter.html +186 -0
  49. data/html/classes/RubyRunHTML__.html +198 -0
  50. data/html/classes/RubyRunInitializer__.html +821 -0
  51. data/html/classes/RubyRunInstrumentor__.html +576 -0
  52. data/html/classes/RubyRunMonitor__.html +298 -0
  53. data/html/classes/RubyRunRSS.html +302 -0
  54. data/html/classes/RubyRunReport__.html +294 -0
  55. data/html/classes/RubyRunTracer__.html +253 -0
  56. data/html/classes/RubyRunUtils__.html +376 -0
  57. data/html/created.rid +1 -0
  58. data/html/files/LICENSE.html +119 -0
  59. data/html/files/README.html +197 -0
  60. data/html/files/lib/rubyrun/rubyrun_buffer_mgr___rb.html +101 -0
  61. data/html/files/lib/rubyrun/rubyrun_commander___rb.html +101 -0
  62. data/html/files/lib/rubyrun/rubyrun_dad___rb.html +101 -0
  63. data/html/files/lib/rubyrun/rubyrun_globals_rb.html +101 -0
  64. data/html/files/lib/rubyrun/rubyrun_html___rb.html +101 -0
  65. data/html/files/lib/rubyrun/rubyrun_html_writer___rb.html +108 -0
  66. data/html/files/lib/rubyrun/rubyrun_initializer___rb.html +112 -0
  67. data/html/files/lib/rubyrun/rubyrun_instrumentor___rb.html +116 -0
  68. data/html/files/lib/rubyrun/rubyrun_monitor___rb.html +116 -0
  69. data/html/files/lib/rubyrun/rubyrun_rb.html +121 -0
  70. data/html/files/lib/rubyrun/rubyrun_report___rb.html +101 -0
  71. data/html/files/lib/rubyrun/rubyrun_rss___rb.html +108 -0
  72. data/html/files/lib/rubyrun/rubyrun_tracer___rb.html +110 -0
  73. data/html/files/lib/rubyrun/rubyrun_utils___rb.html +108 -0
  74. data/html/files/lib/rubyrunm_rb.html +116 -0
  75. data/html/fr_class_index.html +42 -0
  76. data/html/fr_file_index.html +43 -0
  77. data/html/fr_method_index.html +96 -0
  78. data/html/index.html +24 -0
  79. data/html/rdoc-style.css +208 -0
  80. data/lib/rubyrun/rubyrun.rb +78 -0
  81. data/lib/rubyrun/rubyrun_buffer_mgr__.rb +49 -0
  82. data/lib/rubyrun/rubyrun_commander__.rb +196 -0
  83. data/lib/rubyrun/rubyrun_dad__.rb +35 -0
  84. data/lib/rubyrun/rubyrun_globals.rb +51 -0
  85. data/lib/rubyrun/rubyrun_html__.rb +136 -0
  86. data/lib/rubyrun/rubyrun_html_writer__.rb +64 -0
  87. data/lib/rubyrun/rubyrun_initializer__.rb +286 -0
  88. data/lib/rubyrun/rubyrun_instrumentor__.rb +226 -0
  89. data/lib/rubyrun/rubyrun_monitor__.rb +237 -0
  90. data/lib/rubyrun/rubyrun_report__.rb +109 -0
  91. data/lib/rubyrun/rubyrun_rss__.rb +97 -0
  92. data/lib/rubyrun/rubyrun_tracer__.rb +79 -0
  93. data/lib/rubyrun/rubyrun_utils__.rb +98 -0
  94. data/lib/rubyrun/rubyrunnative__.so +0 -0
  95. data/lib/rubyrunm.rb +10 -0
  96. metadata +149 -0
@@ -0,0 +1,208 @@
1
+
2
+ body {
3
+ font-family: Verdana,Arial,Helvetica,sans-serif;
4
+ font-size: 90%;
5
+ margin: 0;
6
+ margin-left: 40px;
7
+ padding: 0;
8
+ background: white;
9
+ }
10
+
11
+ h1,h2,h3,h4 { margin: 0; color: #efefef; background: transparent; }
12
+ h1 { font-size: 150%; }
13
+ h2,h3,h4 { margin-top: 1em; }
14
+
15
+ a { background: #eef; color: #039; text-decoration: none; }
16
+ a:hover { background: #039; color: #eef; }
17
+
18
+ /* Override the base stylesheet's Anchor inside a table cell */
19
+ td > a {
20
+ background: transparent;
21
+ color: #039;
22
+ text-decoration: none;
23
+ }
24
+
25
+ /* and inside a section title */
26
+ .section-title > a {
27
+ background: transparent;
28
+ color: #eee;
29
+ text-decoration: none;
30
+ }
31
+
32
+ /* === Structural elements =================================== */
33
+
34
+ div#index {
35
+ margin: 0;
36
+ margin-left: -40px;
37
+ padding: 0;
38
+ font-size: 90%;
39
+ }
40
+
41
+
42
+ div#index a {
43
+ margin-left: 0.7em;
44
+ }
45
+
46
+ div#index .section-bar {
47
+ margin-left: 0px;
48
+ padding-left: 0.7em;
49
+ background: #ccc;
50
+ font-size: small;
51
+ }
52
+
53
+
54
+ div#classHeader, div#fileHeader {
55
+ width: auto;
56
+ color: white;
57
+ padding: 0.5em 1.5em 0.5em 1.5em;
58
+ margin: 0;
59
+ margin-left: -40px;
60
+ border-bottom: 3px solid #006;
61
+ }
62
+
63
+ div#classHeader a, div#fileHeader a {
64
+ background: inherit;
65
+ color: white;
66
+ }
67
+
68
+ div#classHeader td, div#fileHeader td {
69
+ background: inherit;
70
+ color: white;
71
+ }
72
+
73
+
74
+ div#fileHeader {
75
+ background: #057;
76
+ }
77
+
78
+ div#classHeader {
79
+ background: #048;
80
+ }
81
+
82
+
83
+ .class-name-in-header {
84
+ font-size: 180%;
85
+ font-weight: bold;
86
+ }
87
+
88
+
89
+ div#bodyContent {
90
+ padding: 0 1.5em 0 1.5em;
91
+ }
92
+
93
+ div#description {
94
+ padding: 0.5em 1.5em;
95
+ background: #efefef;
96
+ border: 1px dotted #999;
97
+ }
98
+
99
+ div#description h1,h2,h3,h4,h5,h6 {
100
+ color: #125;;
101
+ background: transparent;
102
+ }
103
+
104
+ div#validator-badges {
105
+ text-align: center;
106
+ }
107
+ div#validator-badges img { border: 0; }
108
+
109
+ div#copyright {
110
+ color: #333;
111
+ background: #efefef;
112
+ font: 0.75em sans-serif;
113
+ margin-top: 5em;
114
+ margin-bottom: 0;
115
+ padding: 0.5em 2em;
116
+ }
117
+
118
+
119
+ /* === Classes =================================== */
120
+
121
+ table.header-table {
122
+ color: white;
123
+ font-size: small;
124
+ }
125
+
126
+ .type-note {
127
+ font-size: small;
128
+ color: #DEDEDE;
129
+ }
130
+
131
+ .xxsection-bar {
132
+ background: #eee;
133
+ color: #333;
134
+ padding: 3px;
135
+ }
136
+
137
+ .section-bar {
138
+ color: #333;
139
+ border-bottom: 1px solid #999;
140
+ margin-left: -20px;
141
+ }
142
+
143
+
144
+ .section-title {
145
+ background: #79a;
146
+ color: #eee;
147
+ padding: 3px;
148
+ margin-top: 2em;
149
+ margin-left: -30px;
150
+ border: 1px solid #999;
151
+ }
152
+
153
+ .top-aligned-row { vertical-align: top }
154
+ .bottom-aligned-row { vertical-align: bottom }
155
+
156
+ /* --- Context section classes ----------------------- */
157
+
158
+ .context-row { }
159
+ .context-item-name { font-family: monospace; font-weight: bold; color: black; }
160
+ .context-item-value { font-size: small; color: #448; }
161
+ .context-item-desc { color: #333; padding-left: 2em; }
162
+
163
+ /* --- Method classes -------------------------- */
164
+ .method-detail {
165
+ background: #efefef;
166
+ padding: 0;
167
+ margin-top: 0.5em;
168
+ margin-bottom: 1em;
169
+ border: 1px dotted #ccc;
170
+ }
171
+ .method-heading {
172
+ color: black;
173
+ background: #ccc;
174
+ border-bottom: 1px solid #666;
175
+ padding: 0.2em 0.5em 0 0.5em;
176
+ }
177
+ .method-signature { color: black; background: inherit; }
178
+ .method-name { font-weight: bold; }
179
+ .method-args { font-style: italic; }
180
+ .method-description { padding: 0 0.5em 0 0.5em; }
181
+
182
+ /* --- Source code sections -------------------- */
183
+
184
+ a.source-toggle { font-size: 90%; }
185
+ div.method-source-code {
186
+ background: #262626;
187
+ color: #ffdead;
188
+ margin: 1em;
189
+ padding: 0.5em;
190
+ border: 1px dashed #999;
191
+ overflow: hidden;
192
+ }
193
+
194
+ div.method-source-code pre { color: #ffdead; overflow: hidden; }
195
+
196
+ /* --- Ruby keyword styles --------------------- */
197
+
198
+ .standalone-code { background: #221111; color: #ffdead; overflow: hidden; }
199
+
200
+ .ruby-constant { color: #7fffd4; background: transparent; }
201
+ .ruby-keyword { color: #00ffff; background: transparent; }
202
+ .ruby-ivar { color: #eedd82; background: transparent; }
203
+ .ruby-operator { color: #00ffee; background: transparent; }
204
+ .ruby-identifier { color: #ffdead; background: transparent; }
205
+ .ruby-node { color: #ffa07a; background: transparent; }
206
+ .ruby-comment { color: #b22222; font-weight: bold; background: transparent; }
207
+ .ruby-regexp { color: #ffa07a; background: transparent; }
208
+ .ruby-value { color: #7fffd4; background: transparent; }
@@ -0,0 +1,78 @@
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
+ # RubyRun bootstrap code. #
13
+ # #
14
+ # To invoke RubyRun for Rails or a Ruby script, use command #
15
+ # line option -r. #
16
+ # #
17
+ # ruby -rrubyrun script/server <webrick> #
18
+ # #
19
+ # To remove RubyRun, simply remove the -r option. #
20
+ # #
21
+ # Generally no other code change is needed to run RubyRun. #
22
+ # #
23
+ #---------------------------------------------------------------#
24
+
25
+ # BEGIN section of the code is always executed first.
26
+ # 1. Intiialize globals, requires and includes
27
+ # 2. Intitialize RubyRun runtime environment
28
+ # Note. For $rubyrun_current_buffer, 1 - primary, 2 - secondary
29
+ BEGIN {
30
+ require 'rubyrun_globals'
31
+ require 'rubyrun_instrumentor__'
32
+ require 'rubyrun_monitor__'
33
+ require 'rubyrun_initializer__'
34
+ include RubyRunGlobals
35
+ include RubyRunInitializer__
36
+ include RubyRunInstrumentor__
37
+ include RubyRunMonitor__
38
+ $rubyrun_include_hash = {}
39
+ $rubyrun_exclude_hash = {}
40
+ $rubyrun_thread_stack = {}
41
+ $rubyrun_metrics_hash = {}
42
+ $rubyrun_thread_local = {}
43
+ $rubyrun_file_date_hash = {}
44
+ $rubyrun_prime_buffer = []
45
+ $rubyrun_alt_buffer = []
46
+ $rubyrun_controller_classes = []
47
+ $rubyrun_current_buffer = 1
48
+ $rubyrun_lock = Monitor.new
49
+ init_rubyrun
50
+ }
51
+
52
+ # RubyRun uses 2 traps to get control from the interpreter
53
+ # to decide if a method should be instrumented or passed
54
+ #
55
+ # 1. When an instance method is added when a module/class is
56
+ # loaded, or dynamically created
57
+ # 2. When a module/static/singleton method is added when a
58
+ # module/class is loaded, or dynamically created
59
+ class Module
60
+ # module/class instance method trap
61
+ def method_added(id, *args)
62
+ RubyRunInstrumentor__.instrument_it?('i', self, id)
63
+ end
64
+ end
65
+
66
+ class Object
67
+ # class object/object singleton method trap
68
+ def singleton_method_added(id, *args)
69
+ RubyRunInstrumentor__.instrument_it?('s', self, id)
70
+ end
71
+ end
72
+
73
+ # 1. Instrument Thread.new method to provide a begin/rescue clause
74
+ # to catch failure for providing a stack trace
75
+ #
76
+ # 2. Start the monitor timer thread
77
+ instrument_thread_new
78
+ start_thread_monitor
@@ -0,0 +1,49 @@
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
+ # RubyRunBufferMgr__ module is responsible for passing the data #
13
+ # from the inline execution thread to the monitor thread #
14
+ # #
15
+ # Two buffers (primary and secondary) are used and the buffers are #
16
+ # swapped between the inline execution thread and RubyRunMonitor__ #
17
+ # thread periodically as defined by REPORT_TIMER. The inline #
18
+ # execution thread pushes data into the primary buffer, when the #
19
+ # REPORT_TIMER expires, RubyRunMonitor__ thread then takes it over #
20
+ # and gives the inline execution thread the secondary buffer via #
21
+ # a quick swap. The same process keeps repeating as the monitor #
22
+ # timer pops and the primary and secondary keep switched between #
23
+ # the two threads. #
24
+ # #
25
+ #--------------------------------------------------------------------#
26
+ module RubyRunBufferMgr__
27
+
28
+ # Push data into the current buffer
29
+ # Primary or secondary buffer may be used but it is transparent to the caller
30
+ def push_current_buffer(metrics)
31
+ $rubyrun_lock.synchronize {
32
+ ($rubyrun_current_buffer == 1 ? $rubyrun_prime_buffer : $rubyrun_alt_buffer) << metrics
33
+ }
34
+ end
35
+
36
+ # Return the current buffer and swap it with the other one
37
+ # This method is invoked by the consumer of the data in the buffer
38
+ def return_and_switch_buffer()
39
+ $rubyrun_lock.synchronize {
40
+ if ($rubyrun_current_buffer == 1)
41
+ $rubyrun_current_buffer == 2
42
+ $rubyrun_prime_buffer
43
+ else
44
+ $rubyrun_current_buffer == 1
45
+ $rubyrun_alt_buffer
46
+ end
47
+ }
48
+ end
49
+ end
@@ -0,0 +1,196 @@
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/18/08 #
10
+ #-----------------------------------------------------------------#
11
+ # #
12
+ # RubyRunCommander__ is a module which handles the commands #
13
+ # cmd_status, cmd_object_map, cmd_soft_kill and cmd_hard_kill #
14
+ # #
15
+ #-----------------------------------------------------------------#
16
+ module RubyRunCommander__
17
+
18
+ # Use Thread.list to list show thread status, and native code to
19
+ # display the last line # and function of the threads
20
+ def dump_thread_status
21
+ (unsupport_function; return) unless $rubyrun_native
22
+ $rubyrun_thread_status_reporter = RubyRunHTMLWriter.new(@rubyrun_report_folder + '/' + File.basename($0, ".*") + '_' + $$.to_s + '_thread_status.html', nil, shift_age = 10, shift_size = 4096000) unless $rubyrun_thread_status_reporter
23
+ start_time = Time.now
24
+ th_data_hash = RubyRunNative__.get_all_top_stacks
25
+ odd_row ||= true
26
+ table_content = ''
27
+ Thread.list.each {|th|
28
+ thread_id = get_thread_id(th)
29
+ table_content += sprintf("#{odd_row ? THREAD_STATUS_ODD_ROW : THREAD_STATUS_EVEN_ROW}",
30
+ thread_id, th.status, get_top_stack(th_data_hash, thread_id))
31
+ odd_row = !odd_row
32
+ }
33
+ html_content = THREAD_STATUS_HTML.sub(/%START_TIMESTAMP%/,start_time.strftime("%H:%M:%S %m/%d/%Y"))
34
+ html_content.sub!(/%THREAD_STATUS_ROW%/,table_content)
35
+ $rubyrun_thread_status_reporter.info(html_content)
36
+ end
37
+
38
+ # Dump Controller/Actions response time metrics
39
+ # metrics structure
40
+ # metrics[0] Thread ID metrics[1] Timestamp of the request
41
+ # metrics[2] URL metrics[3] Controller name
42
+ # metrics[4] Action name metrics[5] Response time
43
+ # metrics[6] Action time metrics[7] Database IO time
44
+ # metrics[8] View time metrics[9] Uncaptured time
45
+ # metrics[10] Dispatch wait time
46
+ def dump_reports(dump_all_reports = false)
47
+ buffer = return_and_switch_buffer
48
+ buffer.each { |metrics|
49
+ # Last element is 1, representing a request count of 1, used for calculating average response time for this controller/action
50
+ update_perf_metrics(metrics[3], {metrics[4] => [metrics[5],metrics[6],metrics[7],metrics[8],metrics[9],metrics[10],1]})
51
+ }
52
+ @rubyrun_req_count ||= 0
53
+ @rubyrun_req_count += buffer.length
54
+ if $rubyrun_config['OUTPUT'].include?(RUBYRUN_OUTPUT_PERF_SUMMARY) && dump_all_reports
55
+ create_rss_channels if (!$rubyrun_perf_summary_rss && $rubyrun_rails_env)
56
+ add_perf_summary_rss_item(@rubyrun_req_count)
57
+ @rubyrun_req_count = 0
58
+ end
59
+ if $rubyrun_config['OUTPUT'].include?(RUBYRUN_OUTPUT_TXN_LOG)
60
+ create_csv_files unless $rubyrun_txn_log_reporter
61
+ add_txn_log_csv_item(buffer)
62
+ end
63
+ buffer.clear # Clear the buffer so that the main thread will push the data into a blank bucket
64
+ end
65
+
66
+ # The way to do soft/hard kill is to performa a thr.raise on the thread
67
+ # from the thread monitor. Using the begin/rescue created around the block
68
+ # in Thread.new by RubyRunInstrumentor__, the raise will be rescued
69
+ # and $@ is then extracted to a global hash.
70
+ # Softkill only kills non-main threads. Hardkill kills the main thread also
71
+ # but as the last step.
72
+ def kill_threads(monitor_thr)
73
+ (unsupport_function; return) unless $rubyrun_native
74
+ if !$rubyrun_thread_dump_reporter
75
+ $rubyrun_thread_dump_reporter = Logger.new(@rubyrun_report_folder + '/' + File.basename($0, ".*") + '_' + $$.to_s + '_thread_dump.txt', shift_age = 10, shift_size = 4096000)
76
+ $rubyrun_thread_dump_reporter.level = Logger::INFO
77
+ class << $rubyrun_thread_dump_reporter
78
+ include RubyRunUtils__
79
+ def format_message (severity, timestamp, progname, msg)
80
+ "[#{timestamp.strftime("%Y-%m-%d %H:%M:%S")}.#{("%.3f" % timestamp.to_f).split('.')[1]}] #{get_thread_id} #{msg}\n"
81
+ end
82
+ end
83
+ end
84
+ th_data_hash = RubyRunNative__.get_all_top_stacks
85
+ j_th_id = return_joined_thread(th_data_hash)
86
+ Thread.list.each {|th|
87
+ th_id = get_thread_id(th)
88
+ if th.status == 'sleep' && th_id != get_thread_id && th_id != get_thread_id(monitor_thr) &&
89
+ th_id != get_thread_id(Thread.main) && th_id != j_th_id
90
+ $rubyrun_thread_dump_reporter.info "*** Raising exception #{RUBYRUN_KILL_3_STRING} to #{get_thread_id(th)} ***"
91
+ th.raise ThreadError, RUBYRUN_KILL_3_STRING
92
+ end
93
+ }
94
+ sleep 3
95
+ back_trace_all(th_data_hash)
96
+ hard_kill = hard_kill?
97
+ remove_cmd_folder
98
+ Thread.main.raise ThreadError, RUBYRUN_KILL_3_STRING if hard_kill
99
+ end
100
+
101
+ # Show the top 20 Ruby classes which have the largest no. of instances in memory
102
+ # The snapshot is taken after a gc call is made
103
+ def dump_object_map
104
+ start_time = Time.now
105
+ $rubyrun_obj_map_reporter = RubyRunHTMLWriter.new(@rubyrun_report_folder + '/' + File.basename($0, ".*") + '_' + $$.to_s + '_object_map.html', nil, shift_age = 10, shift_size = 4096000) unless $rubyrun_obj_map_reporter
106
+ object_map = Hash.new
107
+ ttl_object = 0
108
+ ObjectSpace.garbage_collect
109
+ ObjectSpace.each_object { |obj|
110
+ ttl_object += 1
111
+ object_map.has_key?(obj.class) ? object_map[obj.class] += 1 : object_map[obj.class] = 1
112
+ }
113
+ results = object_map.sort{|a,b| a[1]<=>b[1]}.reverse!
114
+ table_content = ''
115
+ odd_row ||=true
116
+ 20.times {|i|
117
+ table_content += sprintf("#{odd_row ? OBJ_MAP_ODD_ROW : OBJ_MAP_EVEN_ROW}",
118
+ results[i][0], results[i][1].to_s)
119
+ odd_row = !odd_row
120
+ }
121
+ html_content = OBJ_MAP_HTML.sub(/%START_TIMESTAMP%/,start_time.strftime("%H:%M:%S %m/%d/%Y"))
122
+ html_content.sub!(/%OBJ_MAP_ROW%/,table_content)
123
+ $rubyrun_obj_map_reporter.info(html_content)
124
+ end
125
+
126
+ # metrics hash is a global collection point for all metrics (averaged)
127
+ # for all actions by controller
128
+ # Use serialization before updating this global hash
129
+ # Structure of $rubyrun_metrics_hash:
130
+ # controller_name => {action_name => [response_time, action_time,
131
+ # db_io_time, view_time,
132
+ # uncaptured_time, dispatch_wait_time,
133
+ # request_count]}
134
+ def update_perf_metrics(controller, action_metrics_hash)
135
+ $rubyrun_metrics_hash[controller].merge!(action_metrics_hash) {|action, o_metrics, new_metrics|
136
+ o_metrics.each_index { |x|
137
+ (o_metrics[x] += new_metrics[x]; break) if x == (o_metrics.length-1) # Calculate the total request count for this controller/action
138
+ o_metrics[x] = (o_metrics[x] * o_metrics.last + new_metrics[x])/(o_metrics.last + new_metrics.last).to_f
139
+ }
140
+ o_metrics
141
+ }
142
+ end
143
+
144
+ # If a thread is joined this method returns the joining thread ID
145
+ def return_joined_thread(th_data_hash)
146
+ th_data_hash.each {|th, top_stack|
147
+ if th.to_s.include?(get_thread_id(Thread.main))
148
+ top_stack[0] =~ /\*\*(.+?)\*\*/
149
+ return $1
150
+ end
151
+ }
152
+ end
153
+
154
+ # Remove the cmd_kill-3 folder or file if any
155
+ def remove_cmd_folder
156
+ [RUBYRUN_CMD_SOFT_KILL, RUBYRUN_CMD_HARD_KILL].each { |cmd|
157
+ path = ENV[RUBYRUN_WORKING_DIR] + cmd + '_' + Process.pid.to_s
158
+ next unless File.exist?(path)
159
+ File.directory?(path) ? Dir.delete(path) : File.delete(path)
160
+ }
161
+ end
162
+
163
+ # If exists, indicate to the monitor thread that a thread
164
+ # status report is requested
165
+ def thread_status?
166
+ File.exists?(ENV[RUBYRUN_WORKING_DIR] + RUBYRUN_CMD_STATUS)
167
+ end
168
+
169
+ # If exists, indicate to the monitor thread that a soft kill
170
+ # (kill all threads except the main thread) command is sent
171
+ def soft_kill?
172
+ File.exists?(ENV[RUBYRUN_WORKING_DIR] + RUBYRUN_CMD_SOFT_KILL + '_' + Process.pid.to_s)
173
+ end
174
+
175
+ # If exists, indicate to the monitor thread that a hard kill
176
+ # (kill all threads including the main thread) command is sent
177
+ def hard_kill?
178
+ File.exists?(ENV[RUBYRUN_WORKING_DIR] + RUBYRUN_CMD_HARD_KILL + '_' + Process.pid.to_s)
179
+ end
180
+
181
+ # If exists, indicate to the montior thread that a object map is requested
182
+ def object_map?
183
+ File.exists?(ENV[RUBYRUN_WORKING_DIR] + RUBYRUN_CMD_OBJECT_MAP)
184
+ end
185
+
186
+ # If exists, indicate to the monitor thread to exit
187
+ def exit_monitor?
188
+ File.exists?(ENV[RUBYRUN_WORKING_DIR] + RUBYRUN_CMD_EXIT)
189
+ end
190
+
191
+ # Log if native library can't be loaded or not found
192
+ def unsupport_function
193
+ $rubyrun_logger.info "Native library not available. Function not supported."
194
+ end
195
+
196
+ end
@@ -0,0 +1,35 @@
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: 7/09/08 #
11
+ #---------------------------------------------------------------#
12
+ # #
13
+ # Dynamic Application Discovery lists out the name of a method #
14
+ # as it is being added to the ruby process. #
15
+ # #
16
+ #---------------------------------------------------------------#
17
+ module RubyRunDad__
18
+
19
+ # perform dynamic application discovery if requested by printing
20
+ # out the class and method name of the method being added
21
+ def get_dad(type, klass, id)
22
+ print_method_added(type, klass, id) if $rubyrun_dad
23
+ end
24
+
25
+ private
26
+
27
+ # print the dynamic method added message
28
+ def print_method_added(type, obj, id)
29
+ if type == 'i'
30
+ $rubyrun_logger.info "#{obj.to_s}.#{id.id2name} added as an instance method"
31
+ else
32
+ $rubyrun_logger.info "#{obj.to_s}.#{id.id2name} added as an singleton method"
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,51 @@
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
+ # Provide CONSTANTS for RubyRun modules #
13
+ # #
14
+ #---------------------------------------------------------------#
15
+ module RubyRunGlobals
16
+
17
+ RUBYRUN_PREFIX = 'rubyrunX'
18
+ RUBYRUN_PREFIX_LENGTH = RUBYRUN_PREFIX.length
19
+ RUBYRUN_HIGHLIGHT_THRESHOLD = 1
20
+ RUBYRUN_FIREWALL_HASH = {"Gem" => [], "gem" => [], "FileUtils::Verbose" => [], "FileUtils" => [],
21
+ "Module" => [], "Object" => [], "Time" => [], "Logger" => [], "Thread" => [],
22
+ "*" => ['method_added', 'initialize', 'singleton_method_added', 'send', 'caller']}
23
+ RUBYRUN_WORKING_DIR = 'RUBYRUN_WORKING_DIR'
24
+ RUBYRUN_LOG = '/log'
25
+ RUBYRUN_REPORT = '/report'
26
+ RUBYRUN_SIGNATURE = '/signatures'
27
+ RUBYRUN_INCLUDE_HASH_FILE = '/include_hash_file'
28
+ RUBYRUN_EXCLUDE_HASH_FILE = '/exclude_hash_file'
29
+ RUBYRUN_DIR_HASH_FILE = '/dir_hash_file'
30
+ RUBYRUN_CMD_SOFT_KILL = '/cmd_soft_kill'
31
+ RUBYRUN_CMD_HARD_KILL = '/cmd_hard_kill'
32
+ RUBYRUN_CMD_STATUS = '/cmd_status'
33
+ RUBYRUN_CMD_EXIT = '/cmd_exit'
34
+ RUBYRUN_CMD_OBJECT_MAP = '/cmd_object_map'
35
+ RUBYRUN_MONITOR_TIMER = 10
36
+ RUBYRUN_OUTPUT_PERF_SUMMARY = 'perf_summary'
37
+ RUBYRUN_OUTPUT_TXN_LOG = 'txn_log'
38
+ RUBYRUN_KILL_3_STRING = 'RUBYRUN kill -3'
39
+ RUBYRUN_OPTS_FILE = '/rubyrun_opts.yml'
40
+ RUBYRUN_PROP_DEFAULTS = {"APP_PATHS"=>[], "EXCLUDE_HASH"=>{}, "INCLUDE_HASH"=>{},
41
+ "DEBUG_ARGS"=>false, "DEBUG_OBJ"=>false, "DAD"=>false,
42
+ "REPORT_TIMER"=>60, "REPORT_SHIFT_AGE"=>60,
43
+ "OUTPUT" => ["#{RUBYRUN_OUTPUT_PERF_SUMMARY}","#{RUBYRUN_OUTPUT_TXN_LOG}","#{RUBYRUN_OUTPUT_PERF_SUMMARY}"],
44
+ "RSS_PATH" => nil, "TRACE_HASH"=>{}, "DB_ADAPTER_HASH"=>{}}
45
+ RUBYRUN_ACTIVERECORD = 'ActiveRecord::Base'
46
+ RUBYRUN_VIEW_HASH = {'ActionView::Base' => ['pick_template_extension','render_file']}
47
+ RUBYRUN_THREAD_END_HASH = {'WEBrick::HTTPServer' => ['run'], 'Mongrel::HttpServer' => ['process_client']}
48
+ RUBYRUN_OUTER_DISPATCH_HASH = {'Mongrel::Rails::RailsHandler' => ['process'], 'DispatchServlet' => ['service']}
49
+ RUBYRUN_INNER_DISPATCH_HASH = { 'Dispatcher' => ['dispatch'], 'ActionController::Dispatcher' => ['dispatch']}
50
+
51
+ end