function daggerExceptionHandler($exception) { $errormsg = $exception->getMessage(); $errno = $exception->getCode(); $sendmsg = (empty($_SERVER['REQUEST_URI']) ? empty($_SERVER['SCRIPT_FILENAME']) ? '' : '(' . $_SERVER['SCRIPT_FILENAME'] . ')' : '(' . $_SERVER['REQUEST_URI'] . ')') . $errormsg; //记录到监控中心 switch (get_class($exception)) { case 'BaseModelDBException': BaseModelLog::sendLog($errno, $sendmsg, '', BaseModelLog::ERROR_MODEL_ID_DB); break; case 'BaseModelMCException': BaseModelLog::sendLog($errno, $sendmsg, '', BaseModelLog::ERROR_MODEL_ID_MC); break; case 'BaseModelHTTPException': BaseModelLog::sendLog($errno, $sendmsg, '', BaseModelLog::ERROR_MODEL_ID_HTTP); break; case 'BaseModelS3Exception': BaseModelLog::sendLog($errno, $sendmsg, '', BaseModelLog::ERROR_MODEL_ID_S3); break; default: BaseModelLog::sendLog($errno, $sendmsg, '', BaseModelLog::ERROR_MODEL_ID_DEFAULT); break; } defined('DAGGER_DEBUG') && BaseModelCommon::debug('[errro code] ' . $errno . ' [errro msg] ' . $errormsg . ' [详细说明]:https://github.com/wxkingstar/dagger/wiki/' . $errno, 'dagger_error'); if (!defined('DAGGER_DEBUG') || defined('DAGGER_ENV') && DAGGER_ENV === 'product') { BaseModelMessage::showError('抱歉让您看到这个页面'); } else { if (defined('QUEUE') || isset($_SERVER['HTTP_X_REQUESTED_WITH'])) { BaseModelMessage::showError($errormsg, BaseModelException::$data, $errno); } else { $trace = $exception->getTrace(); $tracemsg = array(); $pos = 0; foreach ($trace as $k => $error) { if (strpos($error['function'], "smarty_function_") === 0) { $errormsg = 'smarty插件:' . substr($error['function'], 16) . $errormsg; $pos = false; defined('DAGGER_DEBUG') && BaseModelCommon::debug($errormsg, 'dagger_error'); } if (!isset($error['line']) && $pos === 0) { $pos = $k; } if (!empty($error['function'])) { $fun = ''; if (!empty($error['class'])) { $fun .= $error['class'] . $error['type']; } $fun .= $error['function'] . '('; if (!empty($error['args'])) { $mark = ''; foreach ($error['args'] as $arg) { //由于smarty和call_user方法会出现超大对象或数组传入,导致报错页面崩溃,所以直接跳过参数解析输出 if (stripos($error['function'], 'smarty') === 0 || stripos($error['function'], 'call_user') === 0) { continue; } $fun .= $mark; if (is_array($arg)) { $fun .= var_export($arg, true); } else { if (is_bool($arg)) { $fun .= $arg ? 'true' : 'false'; } else { if (is_int($arg) || is_float($arg)) { $fun .= $arg; } else { if (is_null($arg)) { $fun .= 'NULL'; } else { $fun .= '\'' . BaseModelException::daggerHtmlspecialchars(BaseModelException::daggerClear($arg)) . '\''; } } } } $mark = ', '; } } $fun .= ')'; $error['function'] = $fun; } $tracemsg[] = array('file' => isset($error['file']) ? str_replace(array(DAGGER_PATH_ROOT, '\\'), array('', '/'), $error['file']) : '', 'line' => isset($error['line']) ? $error['line'] : '', 'function' => $error['function']); } $throwPhpCode = file($exception->getFile()); $tracemsg = array_merge(array(array('file' => str_replace(array(DAGGER_PATH_ROOT, '\\'), array('', '/'), $exception->getFile()), 'line' => $exception->getLine(), 'function' => $throwPhpCode[$exception->getLine() - 1])), $tracemsg); defined('DAGGER_DEBUG') && BaseModelCommon::debug(array_merge(array(array('File', 'Line', 'Function')), $tracemsg), 'dagger_error_trace'); if ($pos > 0) { $errorFileCode = array_slice(file($tracemsg[$pos]['file']), $tracemsg[$pos]['line'] > 6 ? $tracemsg[$pos]['line'] - 7 : 0, 13); $tracemsg[$pos]['function'] = '<pre class="brush: php; toolbar : false; highlight: ' . $tracemsg[$pos]['line'] . '; first-line: ' . ($tracemsg[$pos]['line'] > 6 ? $tracemsg[$pos]['line'] - 6 : 1) . '">' . implode('', $errorFileCode) . '</pre>'; } $traceTable = ''; if (is_array($tracemsg) && !empty($tracemsg)) { $traceTable .= '<table cellpadding="5" cellspacing="1" width="100%" class="table">'; $traceTable .= '<tr class="bg2"><th width="249px">File</th><th width="44px">Line</th><th width="629px">Function</th></tr>'; foreach ($tracemsg as $k => $msg) { $traceTable .= '<tr class="' . ($pos > 0 && $k == $pos ? 'bg3' : 'bg1') . '">'; $traceTable .= '<td>' . $msg['file'] . '</td>'; $traceTable .= '<td>' . $msg['line'] . '</td>'; $traceTable .= '<td>' . $msg['function'] . '</td>'; $traceTable .= '</tr>'; } $traceTable .= '</table>'; } BaseModelDebug::showTrace($errno, $errormsg, $traceTable); } } }
<?php /** * dagger项目初始化 */ session_start(); ob_start(); //用户配置 require DAGGER_PATH_ROOT . 'config/SysInitConfig.php'; //系统配置 require DAGGER_PATH_ROOT . 'libs/DaggerSysInitConfig.php'; //__autoload函数 require DAGGER_PATH_LIBS . 'basics.php'; //载入数据存储配置 require DAGGER_PATH_CONFIG . 'DBConfig.php'; if (1 === DAGGER_XHPROF && defined('DAGGER_ALARM_XHPROF_API')) { xhprof_enable(XHPROF_FLAGS_CPU + XHPROF_FLAGS_MEMORY); define('DAGGER_XHPROF_ID', uniqid()); } //静态URL解析规则 BaseModelRouter::route(); $class = BaseModelCommon::getFormatName($_GET[DAGGER_CONTROLLER], 'class'); $class .= 'Controller'; $controller = new $class($_GET[DAGGER_CONTROLLER], $_GET[DAGGER_ACTION]); $controller->runCommand(); if (defined('DAGGER_XHPROF') && 1 === DAGGER_XHPROF) { echo '<br /><a href="' . BaseModelDebug::getXhprofUrl() . '" target="_blank" >xhprof</a>'; }
/** * 调试信息打印 * @param mixed $value 需要打印的调试信息 * @param string $type 需要打印的调试信息的类型,默认为:DEBUG * @param bool/int $verbose 是否缩略输出,默认为false,但可以制定缩略长度 * @param string $encoding 指定传入编码 * @return void */ public static function debug($value, $type = 'DEBUG', $verbose = false, $encoding = 'UTF-8') { if (defined('DAGGER_DEBUG') && defined('DAGGER_ENV') && DAGGER_ENV !== 'product') { BaseModelDebug::debug($value, $type, $verbose, $encoding); } if (1 === DAGGER_ONLINE_DEBUG) { self::$onlineDebugData[$type] = $value; } }
/** * 在firephp中捕获fatal异常,用以display_error * 不开的情况下调试网站 */ function daggerShutDown() { if (!defined('QUEUE')) { // 超时报警 $runtime = floatval(BaseModelCommon::getRunTime()); $timeout = DAGGER_TIMEOUT; if ($runtime > $timeout) { $statInfo = BaseModelCommon::getStatInfo(); BaseModelLog::sendLog(90106, "[run:{$runtime}s]" . "[db:({$statInfo['db']['count']}次{$statInfo['db']['time']}ms)]" . "[mc:({$statInfo['mc']['count']}次{$statInfo['mc']['time']}ms)]" . "[request:({$statInfo['request']['count']}次{$statInfo['request']['time']}ms)]" . "[redis:({$statInfo['redis']['count']}次{$statInfo['redis']['time']}ms)]", '', BaseModelLog::ERROR_MODEL_ID_PHP); 1 === DAGGER_DEBUG && BaseModelCommon::debug("当前脚本运行[{$runtime}],大于{$timeout}秒", 'timeout_error'); } } //xhprof if (defined('DAGGER_XHPROF_ID')) { BaseModelCommon::debug(BaseModelDebug::getXhprofUrl(), 'xhprof_url'); } // all_info的debug信息 if (1 === DAGGER_DEBUG) { $statInfo = BaseModelCommon::getStatInfo(); BaseModelCommon::debug(array(array('资源', '次数', '消耗时间(ms)'), array('sql', $statInfo['db']['count'] . ' 次', $statInfo['db']['time'] . ' ms'), array('request', $statInfo['request']['count'] . ' 次', $statInfo['request']['time'] . ' ms'), array('mc', $statInfo['mc']['count'] . ' 次', $statInfo['mc']['time'] . ' ms'), array('redis', $statInfo['redis']['count'] . ' 次', $statInfo['redis']['time'] . ' ms'), array('总运行时间', '', BaseModelCommon::getRunTime())), 'all_info'); empty(BaseModelCommon::$debugTypeFilter) || BaseModelCommon::debug('部分debug信息被隐藏,规则:' . BaseModelCommon::$debugTypeFilter, 'filter_info'); BaseModelCommon::debug(DAGGER_VERSION, 'dagger_version'); } if (!defined('QUEUE')) { // 在线调试 if (1 === DAGGER_ONLINE_DEBUG) { BaseModelCommon::sendOnlineDebug(); } ob_end_flush(); } $error = error_get_last(); if (empty($error) || !(E_ERROR & $error['type'])) { // This error code is not included in error_reporting defined('QUEUE_CTL') && QueueTaskCtl::end(0, ''); return false; } formatErrorInfo($error['type'], $error['message'], $error['file'], $error['line']); defined('QUEUE_CTL') && QueueTaskCtl::end(1, $error['message']); return true; }
/** * 输出json/xml/html格式的消息。该函数参数很多,还读取$_REQUSET的format、fileds参数,很凶残呐 * @param int $code 错误号, 0表示没有错误发生 * @param string $msg 结果描述 * @param array $data 数据,可以是一维数组,也可以是二维数组, 仅在输出json/xml数据时有用 * @param string $url 将要跳转的页面,仅在输出html页面时使用 * @param int $t 跳转等待时间,仅在输出html页面时使用 * @param array $otherData 消息的补充字段, 仅在输出json/xml数据时有用 * @param string $ie 输入数据的编码,默认为gbk * @param string $oe 输出数据的编码,默认为utf8 */ protected static function message($code, $msg, $data, $url, $t, $otherData = array(), $ie = '', $oe = 'UTF-8') { $format = empty($_REQUEST['format']) ? '' : strtolower($_REQUEST['format']); if (isset($_GET['oe']) && in_array(strtoupper($_GET['oe']), array('GBK', 'UTF-8'), true)) { $oe = $_GET['oe']; } $oe = $format === 'json' ? 'UTF-8' : $oe; // 标准的json只支持utf8中文 $code = intval($code); // 转码 if (!empty($ie) && strcasecmp($ie, $oe) !== 0) { $msg = BaseModelCommon::convertEncoding($msg, $oe, $ie); $data = BaseModelCommon::convertEncoding($data, $oe, $ie); $otherData = BaseModelCommon::convertEncoding($otherData, $oe, $ie); } /* 支持get参数fields字段筛选结果,用于节约带宽 //如果传入了fields字段,返回结果只显示指定字段,fields内容使用半角逗号隔开 // 传fileds参数 && 返回的data是数组 && data不为空 && (data的第一维存在字符串key,对该key进行筛选 || (存在数字0的键,并且0的值为数组,则对下一维数组进行逐个筛选a)) if (!empty($_GET['fields']) && is_array($data) && !empty($data) && (!isset($data['0']) || (!empty($data['0']) && is_array($data['0'])))) { $data = self::_checkFields($data); } */ // 依据不同格式选择性输出 switch ($format) { case 'xml': header("Content-Type: text/xml; charset=" . strtoupper($oe)); $outArr = array(); if (!is_array($msg)) { $outArr['status']['code'] = $code; $outArr['status']['msg'] = $msg; if (is_array($otherData)) { foreach ($otherData as $k => $v) { if (!in_array($k, array('status', 'data'), true)) { $outArr[$k] = $v; } } } $outArr['data'] = $data; } else { $outArr = $msg; } $xml = new BaseModelXML(); $xml->setSerializerOption(XML_SERIALIZER_OPTION_ENCODING, $oe); echo $xml->encode($outArr); break; case 'json': $outArr = array(); if (!is_array($msg)) { $outArr['status']['code'] = $code; $outArr['status']['msg'] = $msg; if (is_array($otherData)) { foreach ($otherData as $k => $v) { if (!in_array($k, array('status', 'data'), true)) { $outArr[$k] = $v; } } } $outArr['data'] = $data; } else { $outArr = $msg; } $json = json_encode($outArr); $callback = isset($_GET['callback']) ? $_GET['callback'] : ''; if (preg_match("/^[a-zA-Z][a-zA-Z0-9_\\.]+\$/", $callback)) { if (isset($_SERVER['REQUEST_METHOD']) && strtoupper($_SERVER['REQUEST_METHOD']) === 'POST') { //POST header("Content-Type: text/html"); $refer = isset($_SERVER['HTTP_REFERER']) ? parse_url($_SERVER['HTTP_REFERER']) : array(); if (!empty($refer) && substr($refer['host'], -9, 9) == 'weibo.com') { $result = '<script>document.domain="weibo.com";'; } else { $result = '<script>document.domain="sina.com.cn";'; } $result .= "parent.{$callback}({$json});</script>"; echo $result; } else { if (isset($_SERVER['HTTP_USER_AGENT']) && stripos($_SERVER['HTTP_USER_AGENT'], 'MSIE')) { header('Content-Type: text/javascript; charset=UTF-8'); } else { header('Content-Type: application/javascript; charset=UTF-8'); } echo "{$callback}({$json});"; } } elseif ($callback) { header('Content-Type: text/html; charset=UTF-8'); echo 'callback参数包含非法字符!'; } else { if (isset($_SERVER['HTTP_USER_AGENT']) && stripos($_SERVER['HTTP_USER_AGENT'], 'MSIE')) { header('Content-Type: text/plain; charset=UTF-8'); } else { header('Content-Type: application/json; charset=UTF-8'); } echo $json; } break; default: if (defined('QUEUE') || defined('EXTERN')) { BaseModelDebug::queueOut($code, $msg, $oe); return; } try { $tpl = new BaseView(); $tpl->assign('msg', $msg); $tpl->assign('url', $url); $tpl->assign('t', $t); if ($code == '0') { $tpl->display('message/message.html'); } else { $tpl->display('message/error.html'); } } catch (Exception $e) { // 默认模板 $html = <<<OUT <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-type" content="text/html; charset=utf-8" /> <title>提示信息</title> <meta name="keywords" content="提示信息" /> <style type="text/css"> <!-- /* 初始化CSS */ html, body, ul, li, ol, dl, dd, dt, p, h1, h2, h3, h4, h5, h6, form, fieldset, legend,img{margin:0;padding:0;} fieldset,img{border:none;} address,caption,cite,code,dfn,th,var{font-style:normal;font-weight:normal;} ul,ol{list-style:none;} select,input{vertical-align:middle;} select,input,textarea{font-size:12px;margin:0;} table{border-collapse:collapse;} body{background:#fff;color:#333;padding:5px 0;font:12px/20px "SimSun","宋体","Arial Narrow";} .clearfix:after{content:".";display:block;height:0;visibility:hidden;clear:both;} .clearfix{zoom:1;} .clearit{clear:both;height:0;font-size:0;overflow:hidden;} a{color:#009;text-decoration:none;} a:visited{color:#800080;} a:hover, a:active, a:focus{color:#f00;text-decoration:underline;} a.linkRed:link,a.linkRed:visited{color:#f00!important;}/* 红色 */ a.linkRed:hover{color:#c00!important;} a.linkRed01:link,a.linkRed01:visited{color:red!important} a.linkRed01:hover{color:red!important} .alert{margin:150px auto;width:390px;height:201px;padding:75px 30px 0;background:url(http://i1.sinaimg.cn/dy/deco/2012/0426/pic_m_01.png) no-repeat 0 0;color:#482400;font-size:14px;line-height:38px;text-align:center;} .error{margin:150px auto;width:390px;height:201px;padding:75px 30px 0;background:url(http://i1.sinaimg.cn/dy/deco/2012/0426/pic_m_02.png) no-repeat 0 0;color:#482400;font-size:14px;line-height:38px;text-align:center;} --> </style> </head> <body> OUT; $html .= "<div class=\"" . ($code == '0' ? 'alert' : 'error') . "\">"; $html .= $msg; $html .= empty($url) ? '' : "<div>{$t}秒钟后跳转下一页面</div><div><a href=\"{$url}\">点击直接跳转</a></div>"; $html .= "</div></body></html>"; print $html; } break; } exit; }