Log.php 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372
  1. <?php
  2. // +----------------------------------------------------------------------
  3. // | ThinkPHP [ WE CAN DO IT JUST THINK ]
  4. // +----------------------------------------------------------------------
  5. // | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
  6. // +----------------------------------------------------------------------
  7. // | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
  8. // +----------------------------------------------------------------------
  9. // | Author: liu21st <liu21st@gmail.com>
  10. // +----------------------------------------------------------------------
  11. namespace think;
  12. use think\exception\ClassNotFoundException;
  13. class Log implements LoggerInterface
  14. {
  15. const EMERGENCY = 'emergency';
  16. const ALERT = 'alert';
  17. const CRITICAL = 'critical';
  18. const ERROR = 'error';
  19. const WARNING = 'warning';
  20. const NOTICE = 'notice';
  21. const INFO = 'info';
  22. const DEBUG = 'debug';
  23. const SQL = 'sql';
  24. /**
  25. * 日志信息
  26. * @var array
  27. */
  28. protected $log = [];
  29. /**
  30. * 配置参数
  31. * @var array
  32. */
  33. protected $config = [];
  34. /**
  35. * 日志写入驱动
  36. * @var object
  37. */
  38. protected $driver;
  39. /**
  40. * 日志授权key
  41. * @var string
  42. */
  43. protected $key;
  44. /**
  45. * 应用对象
  46. * @var App
  47. */
  48. protected $app;
  49. public function __construct(App $app)
  50. {
  51. $this->app = $app;
  52. }
  53. /**
  54. * 日志初始化
  55. * @access public
  56. * @param array $config
  57. * @return $this
  58. */
  59. public function init($config = [])
  60. {
  61. $type = isset($config['type']) ? $config['type'] : 'File';
  62. $class = false !== strpos($type, '\\') ? $type : '\\think\\log\\driver\\' . ucwords($type);
  63. $this->config = $config;
  64. unset($config['type']);
  65. if (class_exists($class)) {
  66. $this->driver = new $class($config);
  67. } else {
  68. throw new ClassNotFoundException('class not exists:' . $class, $class);
  69. }
  70. // 记录初始化信息
  71. $this->app->isDebug() && $this->record('[ LOG ] INIT ' . $type);
  72. return $this;
  73. }
  74. /**
  75. * 获取日志信息
  76. * @access public
  77. * @param string $type 信息类型
  78. * @return array
  79. */
  80. public function getLog($type = '')
  81. {
  82. return $type ? $this->log[$type] : $this->log;
  83. }
  84. /**
  85. * 记录日志信息
  86. * @access public
  87. * @param mixed $msg 日志信息
  88. * @param string $type 日志级别
  89. * @param array $context 替换内容
  90. * @return $this
  91. */
  92. public function record($msg, $type = 'info', array $context = [])
  93. {
  94. if (is_string($msg)) {
  95. $replace = [];
  96. foreach ($context as $key => $val) {
  97. $replace['{' . $key . '}'] = $val;
  98. }
  99. $msg = strtr($msg, $replace);
  100. }
  101. $this->log[$type][] = $msg;
  102. if (PHP_SAPI == 'cli') {
  103. // 命令行日志实时写入
  104. $this->save();
  105. }
  106. return $this;
  107. }
  108. /**
  109. * 清空日志信息
  110. * @access public
  111. * @return $this
  112. */
  113. public function clear()
  114. {
  115. $this->log = [];
  116. return $this;
  117. }
  118. /**
  119. * 当前日志记录的授权key
  120. * @access public
  121. * @param string $key 授权key
  122. * @return $this
  123. */
  124. public function key($key)
  125. {
  126. $this->key = $key;
  127. return $this;
  128. }
  129. /**
  130. * 检查日志写入权限
  131. * @access public
  132. * @param array $config 当前日志配置参数
  133. * @return bool
  134. */
  135. public function check($config)
  136. {
  137. if ($this->key && !empty($config['allow_key']) && !in_array($this->key, $config['allow_key'])) {
  138. return false;
  139. }
  140. return true;
  141. }
  142. /**
  143. * 保存调试信息
  144. * @access public
  145. * @return bool
  146. */
  147. public function save()
  148. {
  149. if (!empty($this->log)) {
  150. if (is_null($this->driver)) {
  151. $this->init($this->app['config']->pull('log'));
  152. }
  153. if (!$this->check($this->config)) {
  154. // 检测日志写入权限
  155. return false;
  156. }
  157. if (empty($this->config['level'])) {
  158. // 获取全部日志
  159. $log = $this->log;
  160. if (!$this->app->isDebug() && isset($log['debug'])) {
  161. unset($log['debug']);
  162. }
  163. } else {
  164. // 记录允许级别
  165. $log = [];
  166. foreach ($this->config['level'] as $level) {
  167. if (isset($this->log[$level])) {
  168. $log[$level] = $this->log[$level];
  169. }
  170. }
  171. }
  172. $result = $this->driver->save($log);
  173. if ($result) {
  174. $this->log = [];
  175. }
  176. return $result;
  177. }
  178. return true;
  179. }
  180. /**
  181. * 实时写入日志信息 并支持行为
  182. * @access public
  183. * @param mixed $msg 调试信息
  184. * @param string $type 日志级别
  185. * @param bool $force 是否强制写入
  186. * @return bool
  187. */
  188. public function write($msg, $type = 'info', $force = false)
  189. {
  190. // 封装日志信息
  191. $log = $this->log;
  192. if (true === $force || empty($this->config['level'])) {
  193. $log[$type][] = $msg;
  194. } elseif (in_array($type, $this->config['level'])) {
  195. $log[$type][] = $msg;
  196. } else {
  197. return false;
  198. }
  199. // 监听log_write
  200. $this->app['hook']->listen('log_write', $log);
  201. if (is_null($this->driver)) {
  202. $this->init($this->app['config']->pull('log'));
  203. }
  204. // 写入日志
  205. $result = $this->driver->save($log);
  206. if ($result) {
  207. $this->log = [];
  208. }
  209. return $result;
  210. }
  211. /**
  212. * 记录日志信息
  213. * @access public
  214. * @param string $level 日志级别
  215. * @param mixed $message 日志信息
  216. * @param array $context 替换内容
  217. * @return void
  218. */
  219. public function log($level, $message, array $context = [])
  220. {
  221. $this->record($message, $level, $context);
  222. }
  223. /**
  224. * 记录emergency信息
  225. * @access public
  226. * @param mixed $message 日志信息
  227. * @param array $context 替换内容
  228. * @return void
  229. */
  230. public function emergency($message, array $context = [])
  231. {
  232. $this->log(__FUNCTION__, $message, $context);
  233. }
  234. /**
  235. * 记录警报信息
  236. * @access public
  237. * @param mixed $message 日志信息
  238. * @param array $context 替换内容
  239. * @return void
  240. */
  241. public function alert($message, array $context = [])
  242. {
  243. $this->log(__FUNCTION__, $message, $context);
  244. }
  245. /**
  246. * 记录紧急情况
  247. * @access public
  248. * @param mixed $message 日志信息
  249. * @param array $context 替换内容
  250. * @return void
  251. */
  252. public function critical($message, array $context = [])
  253. {
  254. $this->log(__FUNCTION__, $message, $context);
  255. }
  256. /**
  257. * 记录错误信息
  258. * @access public
  259. * @param mixed $message 日志信息
  260. * @param array $context 替换内容
  261. * @return void
  262. */
  263. public function error($message, array $context = [])
  264. {
  265. $this->log(__FUNCTION__, $message, $context);
  266. }
  267. /**
  268. * 记录warning信息
  269. * @access public
  270. * @param mixed $message 日志信息
  271. * @param array $context 替换内容
  272. * @return void
  273. */
  274. public function warning($message, array $context = [])
  275. {
  276. $this->log(__FUNCTION__, $message, $context);
  277. }
  278. /**
  279. * 记录notice信息
  280. * @access public
  281. * @param mixed $message 日志信息
  282. * @param array $context 替换内容
  283. * @return void
  284. */
  285. public function notice($message, array $context = [])
  286. {
  287. $this->log(__FUNCTION__, $message, $context);
  288. }
  289. /**
  290. * 记录一般信息
  291. * @access public
  292. * @param mixed $message 日志信息
  293. * @param array $context 替换内容
  294. * @return void
  295. */
  296. public function info($message, array $context = [])
  297. {
  298. $this->log(__FUNCTION__, $message, $context);
  299. }
  300. /**
  301. * 记录调试信息
  302. * @access public
  303. * @param mixed $message 日志信息
  304. * @param array $context 替换内容
  305. * @return void
  306. */
  307. public function debug($message, array $context = [])
  308. {
  309. $this->log(__FUNCTION__, $message, $context);
  310. }
  311. /**
  312. * 记录sql信息
  313. * @access public
  314. * @param mixed $message 日志信息
  315. * @param array $context 替换内容
  316. * @return void
  317. */
  318. public function sql($message, array $context = [])
  319. {
  320. $this->log(__FUNCTION__, $message, $context);
  321. }
  322. }