mirror of
https://gitee.com/fastadminnet/framework.git
synced 2026-07-08 23:52:49 +08:00
重写Log类和驱动 SockectLog纳入Log驱动
This commit is contained in:
12
base.php
12
base.php
@@ -38,7 +38,6 @@ defined('APP_DEBUG') or define('APP_DEBUG', false); // 是否调试模式
|
|||||||
defined('APP_HOOK') or define('APP_HOOK', false); // 是否开启HOOK
|
defined('APP_HOOK') or define('APP_HOOK', false); // 是否开启HOOK
|
||||||
defined('ENV_PREFIX') or define('ENV_PREFIX', 'T_'); // 环境变量的配置前缀
|
defined('ENV_PREFIX') or define('ENV_PREFIX', 'T_'); // 环境变量的配置前缀
|
||||||
defined('IS_API') or define('IS_API', false); // 是否API接口
|
defined('IS_API') or define('IS_API', false); // 是否API接口
|
||||||
defined('SLOG_ON') or define('SLOG_ON', false); // 是否开启socketLog
|
|
||||||
defined('IN_UNIT_TEST') or define('IN_UNIT_TEST', false); // 是否为单元测试
|
defined('IN_UNIT_TEST') or define('IN_UNIT_TEST', false); // 是否为单元测试
|
||||||
|
|
||||||
// 应用模式 默认为普通模式
|
// 应用模式 默认为普通模式
|
||||||
@@ -310,14 +309,13 @@ function S($name, $value = '', $options = null)
|
|||||||
* 添加Trace记录到SocketLog
|
* 添加Trace记录到SocketLog
|
||||||
* @param mixed $log log信息 支持字符串和数组
|
* @param mixed $log log信息 支持字符串和数组
|
||||||
* @param string $level 日志级别
|
* @param string $level 日志级别
|
||||||
* @param string $css 样式
|
|
||||||
* @return void|array
|
* @return void|array
|
||||||
*/
|
*/
|
||||||
function trace($log, $level = 'log', $css = '')
|
function trace($log='[think]', $level = 'log')
|
||||||
{
|
{
|
||||||
if ('trace' == $level) {
|
if('[think]'==$log){
|
||||||
\think\Slog::trace($log, 2, $css);
|
return \think\Log::getLog();
|
||||||
} else {
|
}else{
|
||||||
\think\Slog::record($level, $log, $css);
|
\think\Log::record($log,$level);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -176,19 +176,4 @@ return [
|
|||||||
'slave_no' => '',
|
'slave_no' => '',
|
||||||
],
|
],
|
||||||
|
|
||||||
// +----------------------------------------------------------------------
|
|
||||||
// | SocketLog设置
|
|
||||||
// +----------------------------------------------------------------------
|
|
||||||
|
|
||||||
'slog' => [
|
|
||||||
'host' => 'localhost',
|
|
||||||
//是否显示利于优化的参数,如果允许时间,消耗内存等
|
|
||||||
'optimize' => true,
|
|
||||||
'show_included_files' => true,
|
|
||||||
'error_handler' => true,
|
|
||||||
//日志强制记录到配置的client_id
|
|
||||||
'force_client_id' => '',
|
|
||||||
//限制允许读取日志的client_id
|
|
||||||
'allow_client_ids' => [],
|
|
||||||
],
|
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -43,10 +43,6 @@ class App
|
|||||||
// 缓存初始化
|
// 缓存初始化
|
||||||
Cache::connect($config['cache']);
|
Cache::connect($config['cache']);
|
||||||
|
|
||||||
// 如果启动SocketLog调试, 进行SocketLog配置
|
|
||||||
if (SLOG_ON) {
|
|
||||||
Slog::config($config['slog']);
|
|
||||||
}
|
|
||||||
// 设置系统时区
|
// 设置系统时区
|
||||||
date_default_timezone_set($config['default_timezone']);
|
date_default_timezone_set($config['default_timezone']);
|
||||||
|
|
||||||
@@ -61,8 +57,8 @@ class App
|
|||||||
Lang::load(THINK_PATH . 'lang' . DS . LANG_SET . EXT);
|
Lang::load(THINK_PATH . 'lang' . DS . LANG_SET . EXT);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 启动session API CLI 不开启
|
// 启动session CLI 不开启
|
||||||
if (!IS_CLI && !IS_API && $config['use_session']) {
|
if (!IS_CLI && $config['use_session']) {
|
||||||
Session::init($config['session']);
|
Session::init($config['session']);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1156,16 +1156,11 @@ abstract class Driver
|
|||||||
Debug::remark('queryStartTime', 'time');
|
Debug::remark('queryStartTime', 'time');
|
||||||
} else {
|
} else {
|
||||||
$this->modelSql[$this->model] = $this->queryStr;
|
$this->modelSql[$this->model] = $this->queryStr;
|
||||||
//$this->model = '_think_';
|
|
||||||
// 记录操作结束时间
|
// 记录操作结束时间
|
||||||
Debug::remark('queryEndTime', 'time');
|
Debug::remark('queryEndTime', 'time');
|
||||||
Log::record($this->queryStr . ' [ RunTime:' . Debug::getUseTime('queryStartTime', 'queryEndTime') . 's ]', 'SQL');
|
Log::record($this->queryStr . ' [ RunTime:' . Debug::getRangeTime('queryStartTime', 'queryEndTime') . 's ]', 'sql');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SLOG_ON && $start) {
|
|
||||||
\think\Slog::sql($this->queryStr, $this->_linkID);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -13,9 +13,10 @@ namespace think;
|
|||||||
|
|
||||||
class Debug
|
class Debug
|
||||||
{
|
{
|
||||||
|
// 区间时间信息
|
||||||
protected static $info = [];
|
protected static $info = [];
|
||||||
protected static $mem = [];
|
// 区间内存信息
|
||||||
|
protected static $mem = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 记录时间(微秒)和内存使用情况
|
* 记录时间(微秒)和内存使用情况
|
||||||
@@ -38,9 +39,9 @@ class Debug
|
|||||||
* @param string $start 开始标签
|
* @param string $start 开始标签
|
||||||
* @param string $end 结束标签
|
* @param string $end 结束标签
|
||||||
* @param integer|string $dec 小数位
|
* @param integer|string $dec 小数位
|
||||||
* @return mixed
|
* @return integer
|
||||||
*/
|
*/
|
||||||
public static function getUseTime($start, $end, $dec = 6)
|
public static function getRangeTime($start, $end, $dec = 6)
|
||||||
{
|
{
|
||||||
if (!isset(self::$info[$end])) {
|
if (!isset(self::$info[$end])) {
|
||||||
self::$info[$end] = microtime(true);
|
self::$info[$end] = microtime(true);
|
||||||
@@ -49,13 +50,32 @@ class Debug
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 记录内存使用情况
|
* 统计从开始到统计时的时间(微秒)使用情况
|
||||||
|
* @param integer|string $dec 小数位
|
||||||
|
* @return integer
|
||||||
|
*/
|
||||||
|
public static function getUseTime($dec = 6)
|
||||||
|
{
|
||||||
|
return number_format((microtime(true) - START_TIME), $dec);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取当前访问的吞吐率情况
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public static function getThroughputRate()
|
||||||
|
{
|
||||||
|
return number_format(1 / self::getUseTime(), 2) . 'req/s';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 记录区间的内存使用情况
|
||||||
* @param string $start 开始标签
|
* @param string $start 开始标签
|
||||||
* @param string $end 结束标签
|
* @param string $end 结束标签
|
||||||
* @param integer|string $dec 小数位
|
* @param integer|string $dec 小数位
|
||||||
* @return mixed
|
* @return string
|
||||||
*/
|
*/
|
||||||
public static function getUseMem($start, $end, $dec = 2)
|
public static function getRangeMem($start, $end, $dec = 2)
|
||||||
{
|
{
|
||||||
if (!isset(self::$mem['mem'][$end])) {
|
if (!isset(self::$mem['mem'][$end])) {
|
||||||
self::$mem['mem'][$end] = memory_get_usage();
|
self::$mem['mem'][$end] = memory_get_usage();
|
||||||
@@ -71,7 +91,24 @@ class Debug
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 统计内存峰值情况
|
* 统计从开始到统计时的内存使用情况
|
||||||
|
* @param integer|string $dec 小数位
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public static function getUseMem($dec = 2)
|
||||||
|
{
|
||||||
|
$size = memory_get_usage() - START_MEM;
|
||||||
|
$a = ['B', 'KB', 'MB', 'GB', 'TB'];
|
||||||
|
$pos = 0;
|
||||||
|
while ($size >= 1024) {
|
||||||
|
$size /= 1024;
|
||||||
|
$pos++;
|
||||||
|
}
|
||||||
|
return round($size, $dec) . " " . $a[$pos];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 统计区间的内存峰值情况
|
||||||
* @param string $start 开始标签
|
* @param string $start 开始标签
|
||||||
* @param string $end 结束标签
|
* @param string $end 结束标签
|
||||||
* @param integer|string $dec 小数位
|
* @param integer|string $dec 小数位
|
||||||
@@ -92,6 +129,33 @@ class Debug
|
|||||||
return round($size, $dec) . " " . $a[$pos];
|
return round($size, $dec) . " " . $a[$pos];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取数据库查询信息
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public static function getDbQuery()
|
||||||
|
{
|
||||||
|
return Db::getInstance()->getQueryTimes() . ' queries ' . Db::getInstance()->getExecuteTimes() . ' writes ';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取文件加载信息
|
||||||
|
* @param bool $detail 是否显示详细
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public static function getFile($detail = false)
|
||||||
|
{
|
||||||
|
if ($detail) {
|
||||||
|
$files = get_included_files();
|
||||||
|
$info = [];
|
||||||
|
foreach ($files as $key => $file) {
|
||||||
|
$info[] = $file . ' ( ' . number_format(filesize($file) / 1024, 2) . ' KB )';
|
||||||
|
}
|
||||||
|
return $info;
|
||||||
|
}
|
||||||
|
return count(get_included_files());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 浏览器友好的变量输出
|
* 浏览器友好的变量输出
|
||||||
* @param mixed $var 变量
|
* @param mixed $var 变量
|
||||||
@@ -121,4 +185,5 @@ class Debug
|
|||||||
return $output;
|
return $output;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ class Error
|
|||||||
'code' => $e->getCode(),
|
'code' => $e->getCode(),
|
||||||
];
|
];
|
||||||
// 记录异常日志
|
// 记录异常日志
|
||||||
Log::record($error['message'], 'ERR');
|
Log::record($error['message'], 'error');
|
||||||
// 发送http状态信息
|
// 发送http状态信息
|
||||||
Response::sendHttpStatus(Config::get('exception_http_status'));
|
Response::sendHttpStatus(Config::get('exception_http_status'));
|
||||||
// 输出异常页面
|
// 输出异常页面
|
||||||
@@ -49,14 +49,14 @@ class Error
|
|||||||
$errorStr = "[{$errno}] {$errstr} {$errfile} 第 {$errline} 行.";
|
$errorStr = "[{$errno}] {$errstr} {$errfile} 第 {$errline} 行.";
|
||||||
switch ($errno) {
|
switch ($errno) {
|
||||||
case E_USER_ERROR:
|
case E_USER_ERROR:
|
||||||
Log::record($errorStr, 'ERROR');
|
Log::record($errorStr, 'error');
|
||||||
self::halt($errorStr, $errno);
|
self::halt($errorStr, $errno);
|
||||||
break;
|
break;
|
||||||
case E_STRICT:
|
case E_STRICT:
|
||||||
case E_USER_WARNING:
|
case E_USER_WARNING:
|
||||||
case E_USER_NOTICE:
|
case E_USER_NOTICE:
|
||||||
default:
|
default:
|
||||||
Log::record($errorStr, 'NOTIC');
|
Log::record($errorStr, 'warn');
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -69,9 +69,6 @@ class Error
|
|||||||
{
|
{
|
||||||
// 记录日志
|
// 记录日志
|
||||||
Log::save();
|
Log::save();
|
||||||
if (SLOG_ON) {
|
|
||||||
Slog::sendLog();
|
|
||||||
}
|
|
||||||
if ($e = error_get_last()) {
|
if ($e = error_get_last()) {
|
||||||
switch ($e['type']) {
|
switch ($e['type']) {
|
||||||
case E_ERROR:
|
case E_ERROR:
|
||||||
|
|||||||
@@ -13,10 +13,19 @@ namespace think;
|
|||||||
|
|
||||||
class Log
|
class Log
|
||||||
{
|
{
|
||||||
|
const LOG = 'log';
|
||||||
|
const ERROR = 'error';
|
||||||
|
const INFO = 'info';
|
||||||
|
const SQL = 'sql';
|
||||||
|
const WARN = 'warn';
|
||||||
|
const ALERT = 'alert';
|
||||||
|
|
||||||
// 日志信息
|
// 日志信息
|
||||||
protected static $log = [];
|
protected static $log = [];
|
||||||
protected static $level = ['ERR', 'NOTIC', 'DEBUG', 'SQL', 'INFO'];
|
// 日志类型
|
||||||
protected static $storage = null;
|
protected static $type = ['log', 'error', 'info', 'sql', 'warn', 'alert'];
|
||||||
|
// 日志写入驱动
|
||||||
|
protected static $driver = null;
|
||||||
|
|
||||||
// 日志初始化
|
// 日志初始化
|
||||||
public static function init($config = [])
|
public static function init($config = [])
|
||||||
@@ -24,70 +33,55 @@ class Log
|
|||||||
$type = isset($config['type']) ? $config['type'] : 'File';
|
$type = isset($config['type']) ? $config['type'] : 'File';
|
||||||
$class = '\\think\\log\\driver\\' . ucwords($type);
|
$class = '\\think\\log\\driver\\' . ucwords($type);
|
||||||
unset($config['type']);
|
unset($config['type']);
|
||||||
self::$storage = new $class($config);
|
self::$driver = new $class($config);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 记录日志 并且会过滤未经设置的级别
|
* 获取全部日志信息
|
||||||
* @access public
|
|
||||||
*
|
|
||||||
* @param string $message 日志信息
|
|
||||||
* @param string $level 日志级别
|
|
||||||
*
|
|
||||||
* @internal param bool $record 是否强制记录
|
|
||||||
*/
|
|
||||||
public static function record($message, $level = 'INFO')
|
|
||||||
{
|
|
||||||
self::$log[$level][] = "{$level}: {$message}";
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取内存中的日志信息
|
|
||||||
* @access public
|
|
||||||
* @param string $level 日志级别
|
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
public static function getLog($level = '')
|
public static function getLog()
|
||||||
{
|
{
|
||||||
return $level ? self::$log[$level] : self::$log;
|
return self::$log;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 日志保存
|
* 记录调试信息
|
||||||
* @access public
|
* @param string $msg 调试信息
|
||||||
* @param string $destination 写入目标
|
* @param string $type 信息类型
|
||||||
* @param string $level 保存的日志级别
|
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public static function save($destination = '', $level = '')
|
public static function record($msg, $type = 'log')
|
||||||
{
|
{
|
||||||
$log = self::getLog($level);
|
self::$log[] = ['type' => $type, 'msg' => $msg];
|
||||||
if (empty($log)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
$message = '';
|
|
||||||
if ($level) {
|
|
||||||
$message .= implode("\r\n", $log);
|
|
||||||
self::$log[$level] = [];
|
|
||||||
} else {
|
|
||||||
foreach ($log as $info) {
|
|
||||||
$message .= implode("\r\n", $info) . "\r\n";
|
|
||||||
}
|
|
||||||
self::$log = [];
|
|
||||||
}
|
|
||||||
self::$storage && self::$storage->write($message, $destination);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 日志直接写入
|
* 保存调试信息
|
||||||
* @access public
|
|
||||||
* @param string $log 日志信息
|
|
||||||
* @param string $level 日志级别
|
|
||||||
* @param string $destination 写入目标
|
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public static function write($log, $level = '', $destination = '')
|
public static function save()
|
||||||
{
|
{
|
||||||
self::$storage && self::$storage->write("{$level}: {$log}", $destination);
|
self::$driver && self::$driver->save(self::$log);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 写入调试信息
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public static function write($msg, $type, $destination)
|
||||||
|
{
|
||||||
|
$log[] = ['type' => $type, 'msg' => $msg];
|
||||||
|
self::$driver && self::$driver->save($log);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 静态调用
|
||||||
|
public static function __callStatic($method, $args)
|
||||||
|
{
|
||||||
|
if (in_array($method, self::$type)) {
|
||||||
|
array_push($args, $method);
|
||||||
|
return call_user_func_array('\think\Log::record', $args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,23 +1,25 @@
|
|||||||
<?php
|
<?php
|
||||||
// +----------------------------------------------------------------------
|
// +----------------------------------------------------------------------
|
||||||
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
|
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
|
||||||
// +----------------------------------------------------------------------
|
// +----------------------------------------------------------------------
|
||||||
// | Copyright (c) 2006~2015 http://thinkphp.cn All rights reserved.
|
// | Copyright (c) 2006-2016 http://thinkphp.cn All rights reserved.
|
||||||
// +----------------------------------------------------------------------
|
// +----------------------------------------------------------------------
|
||||||
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
|
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
|
||||||
// +----------------------------------------------------------------------
|
// +----------------------------------------------------------------------
|
||||||
// | Author: liu21st <liu21st@gmail.com>
|
// | Author: liu21st <liu21st@gmail.com>
|
||||||
// +----------------------------------------------------------------------
|
// +----------------------------------------------------------------------
|
||||||
|
|
||||||
namespace think\log\driver;
|
namespace think\log\driver;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 本地化调试输出到文件
|
||||||
|
*/
|
||||||
class File
|
class File
|
||||||
{
|
{
|
||||||
|
|
||||||
protected $config = [
|
protected $config = [
|
||||||
'time_format' => ' c ',
|
'time_format' => ' c ',
|
||||||
'file_size' => 2097152,
|
'file_size' => 2097152,
|
||||||
'path' => '',
|
'path' => LOG_PATH,
|
||||||
];
|
];
|
||||||
|
|
||||||
// 实例化并传入参数
|
// 实例化并传入参数
|
||||||
@@ -29,22 +31,41 @@ class File
|
|||||||
/**
|
/**
|
||||||
* 日志写入接口
|
* 日志写入接口
|
||||||
* @access public
|
* @access public
|
||||||
* @param string $log 日志信息
|
* @param array $log 日志信息
|
||||||
* @param string $destination 写入目标
|
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function write($log, $destination = '')
|
public function save($log = [])
|
||||||
{
|
{
|
||||||
$now = date($this->config['time_format']);
|
$now = date($this->config['time_format']);
|
||||||
if (empty($destination)) {
|
$destination = $this->config['path'] . date('y_m_d') . '.log';
|
||||||
$destination = $this->config['path'] . date('y_m_d') . '.log';
|
|
||||||
}
|
|
||||||
|
|
||||||
//检测日志文件大小,超过配置大小则备份日志文件重新生成
|
//检测日志文件大小,超过配置大小则备份日志文件重新生成
|
||||||
if (is_file($destination) && floor($this->config['file_size']) <= filesize($destination)) {
|
if (is_file($destination) && floor($this->config['file_size']) <= filesize($destination)) {
|
||||||
rename($destination, dirname($destination) . DS . time() . '-' . basename($destination));
|
rename($destination, dirname($destination) . DS . time() . '-' . basename($destination));
|
||||||
}
|
}
|
||||||
|
// 获取基本信息
|
||||||
|
if (isset($_SERVER['HTTP_HOST'])) {
|
||||||
|
$current_uri = $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
|
||||||
|
} else {
|
||||||
|
$current_uri = "cmd:" . implode(' ', $_SERVER['argv']);
|
||||||
|
}
|
||||||
|
$runtime = number_format(microtime(true) - START_TIME, 6);
|
||||||
|
$reqs = number_format(1 / $runtime, 2);
|
||||||
|
$time_str = " [运行时间:{$runtime}s] [吞吐率:{$reqs}req/s]";
|
||||||
|
$memory_use = number_format((memory_get_usage() - START_MEM) / 1024, 2);
|
||||||
|
$memory_str = " [内存消耗:{$memory_use}kb]";
|
||||||
|
$file_load = " [文件加载:" . count(get_included_files()) . "]";
|
||||||
|
|
||||||
error_log("[{$now}] {$_SERVER['SERVER_ADDR']} {$_SERVER['REMOTE_ADDR']} {$_SERVER['REQUEST_URI']}\r\n{$log}\r\n", 3, $destination);
|
array_unshift($log, [
|
||||||
|
'type' => 'log',
|
||||||
|
'msg' => $current_uri . $time_str . $memory_str . $file_load,
|
||||||
|
]);
|
||||||
|
|
||||||
|
$info = '';
|
||||||
|
foreach ($log as $line) {
|
||||||
|
$info .= '[' . $line['type'] . '] ' . $line['msg'] . "\r\n";
|
||||||
|
}
|
||||||
|
error_log("[{$now}] {$_SERVER['SERVER_ADDR']} {$_SERVER['REMOTE_ADDR']} {$_SERVER['REQUEST_URI']}\r\n{$info}\r\n", 3, $destination);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,19 +1,20 @@
|
|||||||
<?php
|
<?php
|
||||||
// +----------------------------------------------------------------------
|
// +----------------------------------------------------------------------
|
||||||
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
|
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
|
||||||
// +----------------------------------------------------------------------
|
// +----------------------------------------------------------------------
|
||||||
// | Copyright (c) 2006~2016 http://thinkphp.cn All rights reserved.
|
// | Copyright (c) 2006-2016 http://thinkphp.cn All rights reserved.
|
||||||
// +----------------------------------------------------------------------
|
// +----------------------------------------------------------------------
|
||||||
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
|
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
|
||||||
// +----------------------------------------------------------------------
|
// +----------------------------------------------------------------------
|
||||||
// | Author: luofei614 <weibo.com/luofei614>
|
// | Author: liu21st <liu21st@gmail.com>
|
||||||
// +----------------------------------------------------------------------
|
// +----------------------------------------------------------------------
|
||||||
|
|
||||||
namespace think\log\driver;
|
namespace think\log\driver;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 调试输出到SAE
|
||||||
|
*/
|
||||||
class Sae
|
class Sae
|
||||||
{
|
{
|
||||||
|
|
||||||
protected $config = [
|
protected $config = [
|
||||||
'log_time_format' => ' c ',
|
'log_time_format' => ' c ',
|
||||||
];
|
];
|
||||||
@@ -27,15 +28,37 @@ class Sae
|
|||||||
/**
|
/**
|
||||||
* 日志写入接口
|
* 日志写入接口
|
||||||
* @access public
|
* @access public
|
||||||
* @param string $log 日志信息
|
* @param array $log 日志信息
|
||||||
* @param string $destination 写入目标
|
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function write($log, $destination = '')
|
public function save($log = [])
|
||||||
{
|
{
|
||||||
static $is_debug = null;
|
static $is_debug = null;
|
||||||
$now = date($this->config['log_time_format']);
|
$now = date($this->config['log_time_format']);
|
||||||
$logstr = "[{$now}] {$_SERVER['SERVER_ADDR']} {$_SERVER['REMOTE_ADDR']} {$_SERVER['REQUEST_URI']}\r\n{$log}\r\n";
|
// 获取基本信息
|
||||||
|
if (isset($_SERVER['HTTP_HOST'])) {
|
||||||
|
$current_uri = $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
|
||||||
|
} else {
|
||||||
|
$current_uri = "cmd:" . implode(' ', $_SERVER['argv']);
|
||||||
|
}
|
||||||
|
$runtime = number_format(microtime(true) - START_TIME, 6);
|
||||||
|
$reqs = number_format(1 / $runtime, 2);
|
||||||
|
$time_str = " [运行时间:{$runtime}s] [吞吐率:{$reqs}req/s]";
|
||||||
|
$memory_use = number_format((memory_get_usage() - START_MEM) / 1024, 2);
|
||||||
|
$memory_str = " [内存消耗:{$memory_use}kb]";
|
||||||
|
$file_load = " [文件加载:" . count(get_included_files()) . "]";
|
||||||
|
|
||||||
|
array_unshift($log, [
|
||||||
|
'type' => 'log',
|
||||||
|
'msg' => $current_uri . $time_str . $memory_str . $file_load,
|
||||||
|
]);
|
||||||
|
|
||||||
|
$info = '';
|
||||||
|
foreach ($log as $line) {
|
||||||
|
$info .= '[' . $line['type'] . '] ' . $line['msg'] . "\r\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
$logstr = "[{$now}] {$_SERVER['SERVER_ADDR']} {$_SERVER['REMOTE_ADDR']} {$_SERVER['REQUEST_URI']}\r\n{$info}\r\n";
|
||||||
if (is_null($is_debug)) {
|
if (is_null($is_debug)) {
|
||||||
preg_replace('@(\w+)\=([^;]*)@e', '$appSettings[\'\\1\']="\\2";', $_SERVER['HTTP_APPCOOKIE']);
|
preg_replace('@(\w+)\=([^;]*)@e', '$appSettings[\'\\1\']="\\2";', $_SERVER['HTTP_APPCOOKIE']);
|
||||||
$is_debug = in_array($_SERVER['HTTP_APPVERSION'], explode(',', $appSettings['debug'])) ? true : false;
|
$is_debug = in_array($_SERVER['HTTP_APPVERSION'], explode(',', $appSettings['debug'])) ? true : false;
|
||||||
@@ -49,4 +72,5 @@ class Sae
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
185
library/think/log/driver/socket.php
Normal file
185
library/think/log/driver/socket.php
Normal file
@@ -0,0 +1,185 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* github: https://github.com/luofei614/SocketLog
|
||||||
|
* @author luofei614<weibo.com/luofei614>
|
||||||
|
*/
|
||||||
|
namespace think\log\driver;
|
||||||
|
|
||||||
|
class Socket
|
||||||
|
{
|
||||||
|
public $port = 1116; //SocketLog 服务的http的端口号
|
||||||
|
|
||||||
|
protected $config = [
|
||||||
|
'enable' => true, //是否记录日志的开关
|
||||||
|
'host' => 'localhost',
|
||||||
|
//是否显示利于优化的参数,如果允许时间,消耗内存等
|
||||||
|
'optimize' => false,
|
||||||
|
'show_included_files' => false,
|
||||||
|
'error_handler' => false,
|
||||||
|
//日志强制记录到配置的client_id
|
||||||
|
'force_client_id' => '',
|
||||||
|
//限制允许读取日志的client_id
|
||||||
|
'allow_client_ids' => [],
|
||||||
|
];
|
||||||
|
|
||||||
|
protected $css = [
|
||||||
|
'sql' => 'color:#009bb4;',
|
||||||
|
'sql_warn' => 'color:#009bb4;font-size:14px;',
|
||||||
|
'error_handler' => 'color:#f4006b;font-size:14px;',
|
||||||
|
'page' => 'color:#40e2ff;background:#171717;',
|
||||||
|
'big' => 'font-size:20px;color:red;',
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 架构函数
|
||||||
|
* @param array $options 缓存参数
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
public function __construct($config = [])
|
||||||
|
{
|
||||||
|
if (!empty($config)) {
|
||||||
|
$this->config = array_merge($this->config, $config);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function save($logs = [])
|
||||||
|
{
|
||||||
|
if (!$this->check()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$runtime = number_format(microtime(true) - START_TIME, 6);
|
||||||
|
$reqs = number_format(1 / $runtime, 2);
|
||||||
|
$time_str = " [运行时间:{$runtime}s][吞吐率:{$reqs}req/s]";
|
||||||
|
$memory_use = number_format((memory_get_usage() - START_MEM) / 1024, 2);
|
||||||
|
$memory_str = " [内存消耗:{$memory_use}kb]";
|
||||||
|
$file_load = " [文件加载:" . count(get_included_files()) . "]";
|
||||||
|
|
||||||
|
if (isset($_SERVER['HTTP_HOST'])) {
|
||||||
|
$current_uri = $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
|
||||||
|
} else {
|
||||||
|
$current_uri = "cmd:" . implode(' ', $_SERVER['argv']);
|
||||||
|
}
|
||||||
|
array_unshift($logs, [
|
||||||
|
'type' => 'group',
|
||||||
|
'msg' => $current_uri . $time_str . $memory_str . $file_load,
|
||||||
|
'css' => $this->css['page'],
|
||||||
|
]);
|
||||||
|
|
||||||
|
$logs[] = [
|
||||||
|
'type' => 'groupCollapsed',
|
||||||
|
'msg' => 'included_files',
|
||||||
|
'css' => '',
|
||||||
|
];
|
||||||
|
$logs[] = [
|
||||||
|
'type' => 'log',
|
||||||
|
'msg' => implode("\n", get_included_files()),
|
||||||
|
'css' => '',
|
||||||
|
];
|
||||||
|
$logs[] = [
|
||||||
|
'type' => 'groupEnd',
|
||||||
|
'msg' => '',
|
||||||
|
'css' => '',
|
||||||
|
];
|
||||||
|
|
||||||
|
$logs[] = [
|
||||||
|
'type' => 'groupEnd',
|
||||||
|
'msg' => '',
|
||||||
|
'css' => '',
|
||||||
|
];
|
||||||
|
|
||||||
|
foreach ($logs as &$log) {
|
||||||
|
if ('sql' == $log['type']) {
|
||||||
|
$log['type'] = 'log';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$tabid = $this->getClientArg('tabid');
|
||||||
|
if (!$client_id = $this->getClientArg('client_id')) {
|
||||||
|
$client_id = '';
|
||||||
|
}
|
||||||
|
if ($force_client_id = $this->config['force_client_id']) {
|
||||||
|
$client_id = $force_client_id;
|
||||||
|
}
|
||||||
|
$logs = [
|
||||||
|
'tabid' => $tabid,
|
||||||
|
'client_id' => $client_id,
|
||||||
|
'logs' => $logs,
|
||||||
|
'force_client_id' => $force_client_id,
|
||||||
|
];
|
||||||
|
$msg = json_encode($logs);
|
||||||
|
$address = '/' . $client_id; //将client_id作为地址, server端通过地址判断将日志发布给谁
|
||||||
|
$this->send($this->config['host'], $msg, $address);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function check()
|
||||||
|
{
|
||||||
|
$tabid = $this->getClientArg('tabid');
|
||||||
|
//是否记录日志的检查
|
||||||
|
if (!$tabid && !$this->config['force_client_id']) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
//用户认证
|
||||||
|
$allow_client_ids = $this->config['allow_client_ids'];
|
||||||
|
if (!empty($allow_client_ids)) {
|
||||||
|
if (!$tabid && in_array($this->config['force_client_id'], $allow_client_ids)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
$client_id = $this->getClientArg('client_id');
|
||||||
|
if (!in_array($client_id, $allow_client_ids)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getClientArg($name)
|
||||||
|
{
|
||||||
|
static $args = [];
|
||||||
|
|
||||||
|
$key = 'HTTP_USER_AGENT';
|
||||||
|
|
||||||
|
if (isset($_SERVER['HTTP_SOCKETLOG'])) {
|
||||||
|
$key = 'HTTP_SOCKETLOG';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isset($_SERVER[$key])) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (empty($args)) {
|
||||||
|
if (!preg_match('/SocketLog\((.*?)\)/', $_SERVER[$key], $match)) {
|
||||||
|
$args = ['tabid' => null];
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
parse_str($match[1], $args);
|
||||||
|
}
|
||||||
|
if (isset($args[$name])) {
|
||||||
|
return $args[$name];
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param null $host - $host of socket server
|
||||||
|
* @param string $message - 发送的消息
|
||||||
|
* @param string $address - 地址
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
protected function send($host, $message = '', $address = '/')
|
||||||
|
{
|
||||||
|
$url = 'http://' . $host . ':' . $this->port . $address;
|
||||||
|
$ch = curl_init();
|
||||||
|
curl_setopt($ch, CURLOPT_URL, $url);
|
||||||
|
curl_setopt($ch, CURLOPT_POST, true);
|
||||||
|
curl_setopt($ch, CURLOPT_POSTFIELDS, $message);
|
||||||
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||||
|
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 1);
|
||||||
|
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
|
||||||
|
$headers = [
|
||||||
|
"Content-Type: application/json;charset=UTF-8",
|
||||||
|
];
|
||||||
|
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); //设置header
|
||||||
|
$txt = curl_exec($ch);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,382 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* github: https://github.com/luofei614/SocketLog
|
|
||||||
* @author luofei614<weibo.com/luofei614>
|
|
||||||
*/
|
|
||||||
namespace think;
|
|
||||||
|
|
||||||
use think\Exception;
|
|
||||||
|
|
||||||
class Slog
|
|
||||||
{
|
|
||||||
public static $start_time = 0;
|
|
||||||
public static $start_memory = 0;
|
|
||||||
public static $port = 1116; //SocketLog 服务的http的端口号
|
|
||||||
public static $log_types = ['log', 'info', 'error', 'warn', 'table', 'group','groupCollapsed','groupEnd','alert'];
|
|
||||||
|
|
||||||
protected static $config = [
|
|
||||||
'enable' => true, //是否记录日志的开关
|
|
||||||
'host' => 'localhost',
|
|
||||||
//是否显示利于优化的参数,如果允许时间,消耗内存等
|
|
||||||
'optimize' => false,
|
|
||||||
'show_included_files' => false,
|
|
||||||
'error_handler' => false,
|
|
||||||
//日志强制记录到配置的client_id
|
|
||||||
'force_client_id' => '',
|
|
||||||
//限制允许读取日志的client_id
|
|
||||||
'allow_client_ids' => [],
|
|
||||||
];
|
|
||||||
|
|
||||||
protected static $logs = [];
|
|
||||||
|
|
||||||
protected static $css = [
|
|
||||||
'sql' => 'color:#009bb4;',
|
|
||||||
'sql_warn' => 'color:#009bb4;font-size:14px;',
|
|
||||||
'error_handler' => 'color:#f4006b;font-size:14px;',
|
|
||||||
'page' => 'color:#40e2ff;background:#171717;',
|
|
||||||
'big' => 'font-size:20px;color:red;',
|
|
||||||
];
|
|
||||||
|
|
||||||
public static function sql($sql, $pdo)
|
|
||||||
{
|
|
||||||
|
|
||||||
if (is_object($pdo)) {
|
|
||||||
if (!self::check()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
$css = self::$css['sql'];
|
|
||||||
if (preg_match('/^SELECT /i', $sql)) {
|
|
||||||
//explain
|
|
||||||
try {
|
|
||||||
$obj = $pdo->query("EXPLAIN " . $sql);
|
|
||||||
if (is_object($obj) && method_exists($obj, 'fetch')) {
|
|
||||||
$arr = $obj->fetch(\PDO::FETCH_ASSOC);
|
|
||||||
self::sqlexplain($arr, $sql, $css);
|
|
||||||
}
|
|
||||||
} catch (Exception $e) {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
self::sqlwhere($sql, $css);
|
|
||||||
self::trace($sql, 2, $css);
|
|
||||||
} else {
|
|
||||||
throw new Exception('SocketLog can not support this database link');
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function trace($msg, $trace_level = 1, $css = '')
|
|
||||||
{
|
|
||||||
if (!self::check()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
self::record('groupCollapsed', $msg, $css);
|
|
||||||
$traces = debug_backtrace(false);
|
|
||||||
$traces = array_reverse($traces);
|
|
||||||
$max = count($traces) - $trace_level;
|
|
||||||
for ($i = 0; $i < $max; $i++) {
|
|
||||||
$trace = $traces[$i];
|
|
||||||
$fun = isset($trace['class']) ? $trace['class'] . '::' . $trace['function'] : $trace['function'];
|
|
||||||
$file = isset($trace['file']) ? $trace['file'] : 'unknown file';
|
|
||||||
$line = isset($trace['line']) ? $trace['line'] : 'unknown line';
|
|
||||||
$trace_msg = '#' . $i . ' ' . $fun . ' called at [' . $file . ':' . $line . ']';
|
|
||||||
if (!empty($trace['args'])) {
|
|
||||||
self::record('groupCollapsed', $trace_msg);
|
|
||||||
self::record('log', $trace['args']);
|
|
||||||
self::record('groupEnd');
|
|
||||||
} else {
|
|
||||||
self::record('log', $trace_msg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
self::record('groupEnd');
|
|
||||||
}
|
|
||||||
|
|
||||||
private static function sqlexplain($arr, &$sql, &$css)
|
|
||||||
{
|
|
||||||
$arr = array_change_key_case($arr, CASE_LOWER);
|
|
||||||
if (false !== strpos($arr['extra'], 'Using filesort')) {
|
|
||||||
$sql .= ' <---################[Using filesort]';
|
|
||||||
$css = self::$css['sql_warn'];
|
|
||||||
}
|
|
||||||
if (false !== strpos($arr['extra'], 'Using temporary')) {
|
|
||||||
$sql .= ' <---################[Using temporary]';
|
|
||||||
$css = self::$css['sql_warn'];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private static function sqlwhere(&$sql, &$css)
|
|
||||||
{
|
|
||||||
//判断sql语句是否有where
|
|
||||||
if (preg_match('/^UPDATE |DELETE /i', $sql) && !preg_match('/WHERE.*(=|>|<|LIKE|IN)/i', $sql)) {
|
|
||||||
$sql .= '<---###########[NO WHERE]';
|
|
||||||
$css = self::$css['sql_warn'];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 接管报错
|
|
||||||
*/
|
|
||||||
public static function registerErrorHandler()
|
|
||||||
{
|
|
||||||
if (!self::check()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
set_error_handler([__CLASS__, 'error_handler']);
|
|
||||||
register_shutdown_function([__CLASS__, 'fatalError']);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function error_handler($errno, $errstr, $errfile, $errline)
|
|
||||||
{
|
|
||||||
switch ($errno) {
|
|
||||||
case E_WARNING:
|
|
||||||
$severity = 'E_WARNING';
|
|
||||||
break;
|
|
||||||
case E_NOTICE:
|
|
||||||
$severity = 'E_NOTICE';
|
|
||||||
break;
|
|
||||||
case E_USER_ERROR:
|
|
||||||
$severity = 'E_USER_ERROR';
|
|
||||||
break;
|
|
||||||
case E_USER_WARNING:
|
|
||||||
$severity = 'E_USER_WARNING';
|
|
||||||
break;
|
|
||||||
case E_USER_NOTICE:
|
|
||||||
$severity = 'E_USER_NOTICE';
|
|
||||||
break;
|
|
||||||
case E_STRICT:
|
|
||||||
$severity = 'E_STRICT';
|
|
||||||
break;
|
|
||||||
case E_RECOVERABLE_ERROR:
|
|
||||||
$severity = 'E_RECOVERABLE_ERROR';
|
|
||||||
break;
|
|
||||||
case E_DEPRECATED:
|
|
||||||
$severity = 'E_DEPRECATED';
|
|
||||||
break;
|
|
||||||
case E_USER_DEPRECATED:
|
|
||||||
$severity = 'E_USER_DEPRECATED';
|
|
||||||
break;
|
|
||||||
case E_ERROR:
|
|
||||||
$severity = 'E_ERR';
|
|
||||||
break;
|
|
||||||
case E_PARSE:
|
|
||||||
$severity = 'E_PARSE';
|
|
||||||
break;
|
|
||||||
case E_CORE_ERROR:
|
|
||||||
$severity = 'E_CORE_ERROR';
|
|
||||||
break;
|
|
||||||
case E_COMPILE_ERROR:
|
|
||||||
$severity = 'E_COMPILE_ERROR';
|
|
||||||
break;
|
|
||||||
case E_USER_ERROR:
|
|
||||||
$severity = 'E_USER_ERROR';
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
$severity = 'E_UNKNOWN_ERROR_' . $errno;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
$msg = "{$severity}: {$errstr} in {$errfile} on line {$errline} -- SocketLog error handler";
|
|
||||||
self::trace($msg, 2, self::$css['error_handler']);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function fatalError()
|
|
||||||
{
|
|
||||||
// 保存日志记录
|
|
||||||
if ($e = error_get_last()) {
|
|
||||||
self::error_handler($e['type'], $e['message'], $e['file'], $e['line']);
|
|
||||||
self::sendLog();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected static function check()
|
|
||||||
{
|
|
||||||
if (!SLOG_ON) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
$tabid = self::getClientArg('tabid');
|
|
||||||
//是否记录日志的检查
|
|
||||||
if (!$tabid && !self::$config['force_client_id']) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
//用户认证
|
|
||||||
$allow_client_ids = self::$config['allow_client_ids'];
|
|
||||||
if (!empty($allow_client_ids)) {
|
|
||||||
if (!$tabid && in_array(self::$config['force_client_id'], $allow_client_ids)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
$client_id = self::getClientArg('client_id');
|
|
||||||
if (!in_array($client_id, $allow_client_ids)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected static function getClientArg($name)
|
|
||||||
{
|
|
||||||
static $args = [];
|
|
||||||
|
|
||||||
$key = 'HTTP_USER_AGENT';
|
|
||||||
|
|
||||||
if (isset($_SERVER['HTTP_SOCKETLOG'])) {
|
|
||||||
$key = 'HTTP_SOCKETLOG';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isset($_SERVER[$key])) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
if (empty($args)) {
|
|
||||||
if (!preg_match('/SocketLog\((.*?)\)/', $_SERVER[$key], $match)) {
|
|
||||||
$args = ['tabid' => null];
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
parse_str($match[1], $args);
|
|
||||||
}
|
|
||||||
if (isset($args[$name])) {
|
|
||||||
return $args[$name];
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
//设置配置
|
|
||||||
public static function config($config)
|
|
||||||
{
|
|
||||||
$config = array_merge(self::$config, $config);
|
|
||||||
self::$config = $config;
|
|
||||||
if (self::check()) {
|
|
||||||
if ($config['optimize']) {
|
|
||||||
self::$start_time = microtime(true);
|
|
||||||
self::$start_memory = memory_get_usage();
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($config['error_handler']) {
|
|
||||||
self::registerErrorHandler();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//获得配置
|
|
||||||
public static function getConfig($name)
|
|
||||||
{
|
|
||||||
return isset(self::$config[$name]) ? self::$config[$name] : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
//记录日志
|
|
||||||
public static function record($type, $msg = '', $css = '')
|
|
||||||
{
|
|
||||||
if (!self::check()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
self::$logs[] = [
|
|
||||||
'type' => $type,
|
|
||||||
'msg' => $msg,
|
|
||||||
'css' => isset(self::$css[$css]) ? self::$css[$css] : $css,
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param null $host - $host of socket server
|
|
||||||
* @param string $message - 发送的消息
|
|
||||||
* @param string $address - 地址
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public static function send($host, $message = '', $address = '/')
|
|
||||||
{
|
|
||||||
$url = 'http://' . $host . ':' . self::$port . $address;
|
|
||||||
$ch = curl_init();
|
|
||||||
curl_setopt($ch, CURLOPT_URL, $url);
|
|
||||||
curl_setopt($ch, CURLOPT_POST, true);
|
|
||||||
curl_setopt($ch, CURLOPT_POSTFIELDS, $message);
|
|
||||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
|
||||||
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 1);
|
|
||||||
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
|
|
||||||
$headers = [
|
|
||||||
"Content-Type: application/json;charset=UTF-8",
|
|
||||||
];
|
|
||||||
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); //设置header
|
|
||||||
$txt = curl_exec($ch);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function sendLog()
|
|
||||||
{
|
|
||||||
if (!self::check()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$time_str = '';
|
|
||||||
$memory_str = '';
|
|
||||||
if (self::$start_time) {
|
|
||||||
$runtime = microtime(true) - self::$start_time;
|
|
||||||
$reqs = number_format(1 / $runtime, 2);
|
|
||||||
$time_str = "[运行时间:{$runtime}s][吞吐率:{$reqs}req/s]";
|
|
||||||
}
|
|
||||||
if (self::$start_memory) {
|
|
||||||
$memory_use = number_format((memory_get_usage() - self::$start_memory) / 1024, 2);
|
|
||||||
$memory_str = "[内存消耗:{$memory_use}kb]";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($_SERVER['HTTP_HOST'])) {
|
|
||||||
$current_uri = $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
|
|
||||||
} else {
|
|
||||||
$current_uri = "cmd:" . implode(' ', $_SERVER['argv']);
|
|
||||||
}
|
|
||||||
array_unshift(self::$logs, [
|
|
||||||
'type' => 'group',
|
|
||||||
'msg' => $current_uri . $time_str . $memory_str,
|
|
||||||
'css' => self::$css['page'],
|
|
||||||
]);
|
|
||||||
|
|
||||||
if (self::$config['show_included_files']) {
|
|
||||||
self::$logs[] = [
|
|
||||||
'type' => 'groupCollapsed',
|
|
||||||
'msg' => 'included_files',
|
|
||||||
'css' => '',
|
|
||||||
];
|
|
||||||
self::$logs[] = [
|
|
||||||
'type' => 'log',
|
|
||||||
'msg' => implode("\n", get_included_files()),
|
|
||||||
'css' => '',
|
|
||||||
];
|
|
||||||
self::$logs[] = [
|
|
||||||
'type' => 'groupEnd',
|
|
||||||
'msg' => '',
|
|
||||||
'css' => '',
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
self::$logs[] = [
|
|
||||||
'type' => 'groupEnd',
|
|
||||||
'msg' => '',
|
|
||||||
'css' => '',
|
|
||||||
];
|
|
||||||
|
|
||||||
$tabid = self::getClientArg('tabid');
|
|
||||||
if (!$client_id = self::getClientArg('client_id')) {
|
|
||||||
$client_id = '';
|
|
||||||
}
|
|
||||||
if ($force_client_id = self::$config['force_client_id']) {
|
|
||||||
$client_id = $force_client_id;
|
|
||||||
}
|
|
||||||
$logs = [
|
|
||||||
'tabid' => $tabid,
|
|
||||||
'client_id' => $client_id,
|
|
||||||
'logs' => self::$logs,
|
|
||||||
'force_client_id' => $force_client_id,
|
|
||||||
];
|
|
||||||
$msg = @json_encode($logs);
|
|
||||||
$address = '/' . $client_id; //将client_id作为地址, server端通过地址判断将日志发布给谁
|
|
||||||
self::send(self::$config['host'], $msg, $address);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function __callStatic($method, $args)
|
|
||||||
{
|
|
||||||
if (in_array($method, self::$log_types)) {
|
|
||||||
array_unshift($args, $method);
|
|
||||||
return call_user_func_array(['\think\Slog', 'record'], $args);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -45,7 +45,6 @@ return [
|
|||||||
'think\template\driver\File' => CORE_PATH . 'template' . DS . 'driver' . DS . 'file' . EXT,
|
'think\template\driver\File' => CORE_PATH . 'template' . DS . 'driver' . DS . 'file' . EXT,
|
||||||
'think\log\driver\File' => CORE_PATH . 'log' . DS . 'driver' . DS . 'file' . EXT,
|
'think\log\driver\File' => CORE_PATH . 'log' . DS . 'driver' . DS . 'file' . EXT,
|
||||||
'think\cache\driver\File' => CORE_PATH . 'cache' . DS . 'driver' . DS . 'file' . EXT,
|
'think\cache\driver\File' => CORE_PATH . 'cache' . DS . 'driver' . DS . 'file' . EXT,
|
||||||
'think\Slog' => CORE_PATH . 'slog'.EXT,
|
|
||||||
],
|
],
|
||||||
|
|
||||||
];
|
];
|
||||||
|
|||||||
Reference in New Issue
Block a user