00001 <?php
00002
00003
00004
00005
00006
00007
00008 class WidgetDebugBlock implements IWidget {
00009 public static function output() {
00010 $w = new WidgetDebugBlock();
00011 return $w->render();
00012 }
00013
00014 public function render($policy = self::NONE) {
00015 $out = '';
00016 if (Config::has_feature(Config::TESTMODE)) {
00017 $out .= html::h('Debug Block', 2);
00018 if (!Config::has_feature(Config::DISABLE_CACHE)) {
00019 $out .= html::warning('Cache is enabled!');
00020 }
00021 $out .= $this->render_properties();
00022
00023 $sections = array(
00024 'Slow and Failed Queries' => $this->render_db_queries(true),
00025 'Templates' => $this->render_templates(),
00026 'DB Queries' => $this->render_db_queries(),
00027 );
00028
00029 EventSource::Instance()->invoke_event('debugblock', 'sections', $sections);
00030
00031 foreach($sections as $heading => $content) {
00032 if ($content) {
00033 $out .= html::h(String::escape($heading), 3);
00034 $out .= $content;
00035 }
00036 }
00037 }
00038
00039 return html::div($out, 'debugblock');
00040 }
00041
00042 protected function render_properties() {
00043 $endtime = microtime(true);
00044 $modules = Load::get_loaded_modules();
00045 $count_queries = count(DB::$query_log);
00046 $debugs = array(
00047 'Memory' => String::number(memory_get_usage()/1024, 2) . ' KB',
00048 'Memory Peak' => String::number(memory_get_peak_usage()/1024, 2) . ' KB',
00049 'Execution time' => $this->duration($endtime - APP_START_MICROTIME),
00050 'DB-Queries execution time' => $this->duration(DB::$queries_total_time),
00051 'DB-Queries' => $count_queries,
00052 'DB-Queries average time' => $this->duration(DB::$queries_total_time / max($count_queries, 1)),
00053 'DB connect time' => $this->duration(DB::$db_connect_time),
00054 'PHP-Version' => phpversion(),
00055 'Generated' => GyroDate::local_date(time()),
00056 'Modules' => (count($modules) > 0) ? implode(', ', $modules) : '-'
00057 );
00058
00059
00060 EventSource::Instance()->invoke_event('debugblock', 'properties', $debugs);
00061
00062
00063 $li = array();
00064 foreach($debugs as $key => $value) {
00065 $li[] = html::b($key . ':') . ' ' . $value;
00066 }
00067 return html::li($li);
00068 }
00069
00070 protected function render_db_queries($only_problems = false) {
00071 $out = '';
00072
00073 if (count(DB::$query_log)) {
00074 $table = '';
00075 $c = 0;
00076 foreach(DB::$query_log as $query) {
00077 $is_problem = !$query['success'] || ($query['seconds'] > Config::get_value(Config::DB_SLOW_QUERY_THRESHOLD));
00078 if (!$only_problems || $is_problem) {
00079 $table .= $this->render_db_query_times($query);
00080 $table .= $this->render_db_query_message($query);
00081 $table .= $this->render_db_query_explain($query);
00082 }
00083 }
00084 if ($table) {
00085 $out .= html::tag('table', $table, array('summary' => 'List of all issued DB queries'));
00086 }
00087 }
00088 return $out;
00089 }
00090
00091 protected function render_db_query_times($query) {
00092 $is_slow = ($query['seconds'] > Config::get_value(Config::DB_SLOW_QUERY_THRESHOLD));
00093 $cls = $query['success'] ? 'query ok' : 'query error';
00094
00095 $query_time = array(
00096 $this->msec($query['seconds']),
00097 $this->sec($query['seconds']),
00098 );
00099 if ($is_slow) {
00100 $cls .= ' slow';
00101 $query_time[] = 'Slow!';
00102 }
00103
00104 return html::tr(
00105 array(
00106 html::td(html::b(implode('<br />', $query_time))),
00107 html::td(String::escape($query['query'])),
00108 ),
00109 array('class' => $cls)
00110 );
00111 }
00112
00113 protected function render_db_query_message($query) {
00114 $ret = '';
00115 if ($query['message']) {
00116 $ret .= html::tr(
00117 html::td(String::escape($query['message']), array('colspan' => 2)),
00118 array('class' => 'query message')
00119 );
00120 }
00121 return $ret;
00122 }
00123
00124 protected function render_db_query_explain($query) {
00125 $ret = '';
00126 $is_slow = ($query['seconds'] > Config::get_value(Config::DB_SLOW_QUERY_THRESHOLD));
00127 if ($is_slow) {
00128 $sql = $query['query'];
00129 $result = DB::explain($query['query'], $query['connection']);
00130 if ($result) {
00131 $ret .= html::tr(
00132 html::td($this->render_db_query_explain_result($result), array('colspan' => 2)),
00133 array('class' => 'query explain')
00134 );
00135 }
00136 }
00137 return $ret;
00138 }
00139
00140 protected function render_db_query_explain_result(IDBResultSet $result) {
00141 $rows = array();
00142 $head = false;
00143 while($row = $result->fetch()) {
00144 if ($head === false) {
00145 $head = array();
00146 foreach(array_keys($row) as $h) {
00147 $head[] = html::td(String::escape($h), array(), true);
00148 }
00149 }
00150
00151 $tr = array();
00152 foreach($row as $col => $value) {
00153 $tr[] = html::td(String::escape($value));
00154 }
00155 $rows[] = $tr;
00156 }
00157 $table = html::table($rows, $head, 'Explain Result', array('class' => 'full'));
00158 return $table;
00159 }
00160
00161 protected function render_templates() {
00162 $out = '';
00163
00164 if (count(TemplatePathResolver::$resolved_paths)) {
00165 $table = '';
00166 foreach(TemplatePathResolver::$resolved_paths as $resource => $file) {
00167 $cls = 'template';
00168 $table .= html::tr(
00169 array(
00170 html::td(String::escape($resource)),
00171 html::td(String::escape($file)),
00172 ),
00173 array('class' => $cls)
00174 );
00175 }
00176 $out .= html::tag('table', $table, array('summary' => 'Mapping of template ressources to files'));
00177 }
00178 return $out;
00179 }
00180
00181 protected function render_translations() {
00182 $out = '';
00183
00184 if (count(Translator::Instance()->groups)) {
00185 $out .= html::h('Translations', 3);
00186
00187 $li = array();
00188 foreach(Translator::Instance()->groups as $key => $group) {
00189 if (count($group)) {
00190 $li[] = String::escape($key);
00191 }
00192 }
00193 $out .= html::li($li, 'translations');
00194 }
00195 return $out;
00196 }
00197
00198 protected function sec($sec) {
00199 return String::number($sec, 4) . ' sec';
00200 }
00201
00202 protected function msec($sec) {
00203 return String::number($sec * 1000, 2) . ' msec';
00204 }
00205
00206 protected function duration($sec) {
00207 return $this->msec($sec) . ' - ' . $this->sec($sec);
00208 }
00209 }