/** * 记录时间(微秒)和内存使用情况 * @param string $start 开始标签 * @param string $end 结束标签 * @param integer $dec 小数位 * @return mixed */ function G($start, $end = '', $dec = 6) { if ('' == $end) { \think\Debug::remark($start); } else { return 'm' == $dec ? \think\Debug::getRangeMem($start, $end) : \think\Debug::getRangeTime($start, $end, $dec); } }
/** * 记录时间(微秒)和内存使用情况 * @param string $start 开始标签 * @param string $end 结束标签 * @param integer|string $dec 小数位 如果是m 表示统计内存占用 * @return mixed */ function debug($start, $end = '', $dec = 6) { if ('' == $end) { Debug::remark($start); } else { return 'm' == $dec ? Debug::getRangeMem($start, $end) : Debug::getRangeTime($start, $end, $dec); } }
/** * 显示页面Trace信息 * @access private */ private function showTrace() { // 系统默认显示信息 $files = get_included_files(); $info = []; foreach ($files as $key => $file) { $info[] = $file . ' ( ' . number_format(filesize($file) / 1024, 2) . ' KB )'; } $trace = []; Debug::remark('START', NOW_TIME); $base = ['请求信息' => date('Y-m-d H:i:s', $_SERVER['REQUEST_TIME']) . ' ' . $_SERVER['SERVER_PROTOCOL'] . ' ' . $_SERVER['REQUEST_METHOD'] . ' : ' . $_SERVER['PHP_SELF'], '运行时间' => Debug::getUseTime('START', 'END', 6) . 's', '内存开销' => MEMORY_LIMIT_ON ? G('START', 'END', 'm') . 'b' : '不支持', '查询信息' => N('db_query') . ' queries ' . N('db_write') . ' writes ', '文件加载' => count($files), '缓存信息' => N('cache_read') . ' gets ' . N('cache_write') . ' writes ', '配置加载' => count(Config::get())]; // 读取项目定义的Trace文件 $traceFile = MODULE_PATH . 'trace.php'; if (is_file($traceFile)) { $base = array_merge($base, include $traceFile); } $debug = Log::getLog(); $tabs = Config::get('trace_page_tabs'); foreach ($tabs as $name => $title) { switch (strtoupper($name)) { case 'BASE': // 基本信息 $trace[$title] = $base; break; case 'FILE': // 文件信息 $trace[$title] = $info; break; default: // 调试信息 $name = strtoupper($name); if (strpos($name, '|')) { // 多组信息 $array = explode('|', $name); $result = []; foreach ($array as $name) { $result += isset($debug[$name]) ? $debug[$name] : []; } $trace[$title] = $result; } else { $trace[$title] = isset($debug[$name]) ? $debug[$name] : ''; } } } unset($files, $info, $base, $debug); // 调用Trace页面模板 ob_start(); include Config::has('tmpl_trace_file') ? Config::get('tmpl_trace_file') : THINK_PATH . 'tpl/page_trace.tpl'; return ob_get_clean(); }
/** * 数据库调试 记录当前SQL * @access protected * @param boolean $start 调试开始标记 true 开始 false 结束 */ protected function debug($start) { if (!empty($this->config['debug'])) { // 开启数据库调试模式 if ($start) { Debug::remark('queryStartTime', 'time'); } else { $this->modelSql[$this->model] = $this->queryStr; // 记录操作结束时间 Debug::remark('queryEndTime', 'time'); Log::record($this->queryStr . ' [ RunTime:' . Debug::getRangeTime('queryStartTime', 'queryEndTime') . 's ]', 'sql'); } } }
/** * 数据库调试 记录当前SQL * @access protected * @param boolean $start 调试开始标记 true 开始 false 结束 */ protected function debug($start) { if (!empty($this->config['debug'])) { // 开启数据库调试模式 if ($start) { Debug::remark('queryStartTime', 'time'); } else { $this->modelSql[$this->model] = $this->queryStr; // 记录操作结束时间 Debug::remark('queryEndTime', 'time'); $log = $this->queryStr . ' [ RunTime:' . Debug::getRangeTime('queryStartTime', 'queryEndTime') . 's ]'; // SQL性能分析 if (0 === stripos(trim($this->queryStr), 'select')) { $result = $this->getExplain($this->queryStr); Log::record('[ EXPLAIN : ' . var_export($result, true) . ' ]', 'sql'); } Log::record('[ SQL ] ' . $log, 'sql'); } } }
/** * 数据库调试 记录当前SQL及分析性能 * @access protected * @param boolean $start 调试开始标记 true 开始 false 结束 * @return void */ protected function debug($start) { if (!empty($this->config['debug'])) { // 开启数据库调试模式 if ($start) { Debug::remark('queryStartTime', 'time'); } else { // 记录操作结束时间 Debug::remark('queryEndTime', 'time'); $runtime = Debug::getRangeTime('queryStartTime', 'queryEndTime'); $log = $this->queryStr . ' [ RunTime:' . $runtime . 's ]'; $result = []; // SQL性能分析 if ($this->config['sql_explain'] && 0 === stripos(trim($this->queryStr), 'select')) { $result = $this->getExplain($this->queryStr); } // SQL监听 $this->trigger($this->queryStr, $runtime, $result); } } }
/** * 数据库调试 记录当前SQL * @access protected * @param boolean $start 调试开始标记 true 开始 false 结束 */ protected function debug($start) { if (!empty($this->config['debug'])) { // 开启数据库调试模式 if ($start) { Debug::remark('queryStartTime', 'time'); } else { $this->modelSql[$this->model] = $this->queryStr; // 记录操作结束时间 Debug::remark('queryEndTime', 'time'); $log = $this->queryStr . ' [ RunTime:' . Debug::getRangeTime('queryStartTime', 'queryEndTime') . 's ]'; // SQL性能分析 if (0 === stripos(trim($this->queryStr), 'select')) { $pdo = $this->linkID->query("EXPLAIN " . $this->queryStr); $result = $pdo->fetch(PDO::FETCH_ASSOC); if (strpos($result['extra'], 'filesort') || strpos($result['extra'], 'temporary')) { Log::record('SQL:' . $this->queryStr . '[' . $result['extra'] . ']', 'warn'); } $log .= '[ EXPLAIN : ' . var_export($result, true) . ' ]'; } Log::record('[ SQL ] ' . $log, 'sql'); } } }
/** * @covers think\Debug::getMemPeak * @todo Implement testGetMemPeak(). */ public function testGetMemPeak() { $start = "testGetMemPeakStart"; $end = "testGetMemPeakEnd"; \think\Debug::remark($start); $str = ""; for ($i = 0; $i < 100000; $i++) { $str .= "mem"; } $memPeak = \think\Debug::getMemPeak($start, $end); // echo "\r\n" . $memPeak . "\r\n"; $this->assertLessThan(238, explode(" ", $memPeak)[0]); }
/** * 数据库调试 记录当前SQL * @access protected * @param boolean $start 调试开始标记 true 开始 false 结束 */ protected function debug($start) { if ($this->config['debug']) { // 开启数据库调试模式 if ($start) { Debug::remark('queryStartTime', 'time'); } else { $this->modelSql[$this->model] = $this->queryStr; //$this->model = '_think_'; // 记录操作结束时间 Debug::remark('queryEndTime', 'time'); Log::record($this->queryStr . ' [ RunTime:' . Debug::getUseTime('queryStartTime', 'queryEndTime') . 's ]', 'SQL'); } } if (SLOG_ON && $start) { \think\Slog::sql($this->queryStr, $this->_linkID); } }
/** * @covers think\Debug::getMemPeak * @todo Implement testGetMemPeak(). */ public function testGetMemPeak() { $start = "testGetMemPeakStart"; $end = "testGetMemPeakEnd"; Debug::remark($start); $str = ""; for ($i = 0; $i < 100000; $i++) { $str .= "mem"; } $memPeak = Debug::getMemPeak($start, $end); $this->assertLessThan(400, explode(" ", $memPeak)[0]); }
/** * 监听标签的行为 * @param string $tag 标签名称 * @param mixed $params 传入参数 * @param mixed $extra 额外参数 * @param bool $once 只获取一个有效返回值 * @return mixed */ public static function listen($tag, &$params = null, $extra = null, $once = false) { $results = []; if (isset(self::$tags[$tag])) { foreach (self::$tags[$tag] as $name) { if (App::$debug) { Debug::remark('behavior_start', 'time'); } $result = self::exec($name, $tag, $params, $extra); if (!is_null($result) && $once) { return $result; } if (App::$debug) { Debug::remark('behavior_end', 'time'); if ($name instanceof \Closure) { $name = 'Closure'; } elseif (is_object($name)) { $name = get_class($name); } Log::record('[ BEHAVIOR ] Run ' . $name . ' @' . $tag . ' [ RunTime:' . Debug::getRangeTime('behavior_start', 'behavior_end') . 's ]', 'info'); } if (false === $result) { // 如果返回false 则中断行为执行 break; } $results[] = $result; } } return $once ? null : $results; }
/** * 执行某个行为 * @param mixed $class 要执行的行为 * @param string $tag 方法名(标签名) * @param Mixed $params 传人的参数 * @param mixed $extra 额外参数 * @return mixed */ public static function exec($class, $tag = '', &$params = null, $extra = null) { App::$debug && Debug::remark('behavior_start', 'time'); if (is_callable($class)) { $result = call_user_func_array($class, [&$params, $extra]); $class = 'Closure'; } elseif (is_object($class)) { $result = call_user_func_array([$class, $tag], [&$params, $extra]); $class = get_class($class); } else { $obj = new $class(); $result = $tag && is_callable([$obj, $tag]) ? $obj->{$tag}($params, $extra) : $obj->run($params, $extra); } if (App::$debug) { Debug::remark('behavior_end', 'time'); Log::record('[ BEHAVIOR ] Run ' . $class . ' @' . $tag . ' [ RunTime:' . Debug::getRangeTime('behavior_start', 'behavior_end') . 's ]', 'info'); } return $result; }