Logger.php 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432
  1. <?php
  2. namespace PhpLife\Frame;
  3. use PhpLife\Config\Sentry;
  4. /**
  5. * 简单日志记录
  6. */
  7. class Logger
  8. {
  9. private static $logPath = '/data/wwwlogs/';
  10. private static $logLevel = LOG_ERR;
  11. private static $maps = array(
  12. LOG_DEBUG => 'debug',
  13. LOG_INFO => 'info',
  14. LOG_NOTICE => 'notice',
  15. LOG_WARNING => 'warning',
  16. LOG_ERR => 'err',
  17. LOG_CRIT => 'crit',
  18. LOG_ALERT => 'alert',
  19. LOG_EMERG => 'emerg'
  20. );
  21. /**
  22. * 获取单例
  23. *
  24. * @return Logger
  25. */
  26. public static function getInstance()
  27. {
  28. static $instance = null;
  29. if (is_null($instance)) {
  30. $instance = new Logger();
  31. }
  32. return $instance;
  33. }
  34. /**
  35. * 设置日志记录错误等级
  36. *
  37. * @param int $level
  38. * @return Logger
  39. */
  40. public static function setLogLevel($level = LOG_DEBUG)
  41. {
  42. self::$logLevel = intval($level);
  43. return self::getInstance();
  44. }
  45. /**
  46. * 设置日志记录路径
  47. *
  48. * @param
  49. * $path
  50. * @return Logger
  51. */
  52. public static function setLogPath($path)
  53. {
  54. $path = trim($path);
  55. if (!empty($path) and is_writable($path)) {
  56. self::$logPath = $path;
  57. }
  58. return self::getInstance();
  59. }
  60. public static function debug($message = '', $filename = null)
  61. {
  62. return self::log($message, $filename, LOG_DEBUG);
  63. }
  64. public static function info($message = '', $filename = null)
  65. {
  66. return self::log($message, $filename, LOG_INFO);
  67. }
  68. public static function notice($message = '', $filename = null)
  69. {
  70. return self::log($message, $filename, LOG_NOTICE);
  71. }
  72. public static function warning($message = '', $filename = null)
  73. {
  74. return self::log($message, $filename, LOG_WARNING);
  75. }
  76. public static function error($message = '', $filename = null)
  77. {
  78. return self::log($message, $filename, LOG_ERR);
  79. }
  80. public static function crit($message = '', $filename = null)
  81. {
  82. return self::log($message, $filename, LOG_CRIT);
  83. }
  84. public static function alert($message = '', $filename = null)
  85. {
  86. return self::log($message, $filename, LOG_ALERT);
  87. }
  88. public static function emerg($message = '', $filename = null)
  89. {
  90. return self::log($message, $filename, LOG_EMERG);
  91. }
  92. public static function log($message = '', $filename = null, $logType = LOG_DEBUG)
  93. {
  94. // 达不到错误记录级别的不与记录,主要是线上环境忽略debug信息
  95. if ($logType > self::getLogLevel()) {
  96. return false;
  97. }
  98. self::file($message, $filename, $logType);
  99. return true;
  100. }
  101. /**
  102. * 自定义记录日志
  103. *
  104. * @param null $email
  105. * @param string $message
  106. * @param string $filename
  107. * @return bool
  108. */
  109. public static function setLog($email = NULL, $message = "", $filename = "")
  110. {
  111. $msg=$message;
  112. if (empty($message) || empty($filename))
  113. return false;
  114. $filename = self::getLogPath($filename);
  115. $message = "[" . date('Y-m-d H:i:s') . "]" . "-[IP:" . self::getClientIp() . "]" . "-[http://" . self::getServerIp() . $_SERVER['REQUEST_URI'] . "]" . ($email ? "-[EMAIL:$email]" : "") . "-[操作:$message]" . "\n";
  116. require_once dirname(__DIR__) . '/Library/Raven/Autoloader.php';
  117. \Raven_Autoloader::register();
  118. // $opinion = [
  119. // 'tags' => [
  120. // 'php_version' => phpversion(),
  121. // 'environment' => Request::getMode()
  122. // ]
  123. // ];
  124. $client = new \Raven_Client(Sentry::getData('url'));
  125. $error_handler = new \Raven_ErrorHandler($client);
  126. $error_handler->registerExceptionHandler();
  127. $error_handler->registerErrorHandler();
  128. $error_handler->registerShutdownFunction();
  129. $client->user_context(array(
  130. 'email' => $email,
  131. // 'log_type'=>$filename
  132. ));
  133. $client->captureMessage($msg);
  134. return error_log($message, 3, $filename);
  135. }
  136. /**
  137. * 自定义记录日志
  138. *
  139. * @param string $message
  140. * @param string $filename
  141. * @return bool
  142. */
  143. public static function logApi($message = "", $filename = "")
  144. {
  145. if (empty($message) || empty($filename))
  146. return false;
  147. $filename = self::getLogPath($filename);
  148. $message = "[" . date('Y-m-d H:i:s') . "]" . "-[IP:" . self::getClientIp() . "]" . "-[http://" . self::getServerIp() . $_SERVER['REQUEST_URI'] . "]" . '[post:' . http_build_query($_POST) . ']' . '[get:' . http_build_query($_GET) . ']' . "-[msg:$message]" . "\n";
  149. return error_log($message, 3, $filename);
  150. }
  151. /**
  152. * 记录大数据的日志
  153. *
  154. * @param
  155. * $message
  156. * @param
  157. * $filename
  158. * @return bool
  159. */
  160. public static function bigLog($data)
  161. {
  162. if (empty($data))
  163. return false;
  164. $filename = self::getBigdataLogPath();
  165. $message = json_encode($data) . "\r\n";
  166. return error_log($message, 3, $filename);
  167. }
  168. /**
  169. * 记录简单的日志内容
  170. *
  171. * @param
  172. * $message
  173. * @param
  174. * $filename
  175. * @return bool
  176. */
  177. public static function singleLog($data, $filename)
  178. {
  179. if (is_array($data)) {
  180. $msg = http_build_query($data);
  181. } else {
  182. $msg = $data;
  183. }
  184. $filename = self::getLogPath($filename);
  185. $message = "[" . date('Y-m-d H:i:s') . "][" . $_SERVER['REQUEST_URI'] . "]-[IP:" . self::getClientIp() . "][data:" . $msg . "]\r\n";
  186. return error_log($message, 3, $filename);
  187. }
  188. /**
  189. * 使用文件记录推送日志
  190. *
  191. * @param string $message
  192. * @param string $filename
  193. * @param int $logType
  194. * @return bool
  195. */
  196. private static function file($message = '', $filename = null, $logType = LOG_INFO)
  197. {
  198. if (!$filename) {
  199. $logType = intval($logType);
  200. $filename = self::$maps[$logType];
  201. }
  202. $filename = self::getLogPath($filename);
  203. $message = self::formatFields($message);
  204. return error_log($message, 3, $filename);
  205. }
  206. /**
  207. * 格式日志记录
  208. *
  209. * @param string $message
  210. * @return string
  211. */
  212. private static function formatFields($message)
  213. {
  214. if ($message instanceof \Exception) {
  215. $trace = $message->getTrace();
  216. $trace = $trace[1];
  217. $trace = ' ;trace => ' . json_encode($trace);
  218. $message = $message->getCode() . ' => ' . $message->getMessage() . $trace;
  219. } elseif ($message) {
  220. $message = (is_string($message) || is_numeric($message)) ? $message : json_encode($message);
  221. } else {
  222. $message = ' - ';
  223. }
  224. if (empty($_SERVER['argv'])) {
  225. $cli = "curl 'http://" . self::getServerIp() . $_SERVER['REQUEST_URI'] . "'";
  226. // 解析头信息
  227. $headers = self::getHeaders();
  228. if ($headers) {
  229. foreach ($headers as $k => $v) {
  230. $cli .= " -H '$k:$v'";
  231. }
  232. }
  233. if ($_POST) {
  234. $cli .= " -d '" . http_build_query($_POST) . "'";
  235. }
  236. if ($_COOKIE) {
  237. $cookie = array();
  238. foreach ($_COOKIE as $k => $v) {
  239. $cookie[] = $k . '=' . $v;
  240. }
  241. $cookie = implode(';', $cookie);
  242. $cli .= " -b '" . $cookie . "'";
  243. }
  244. } else {
  245. $cli = 'php ' . $_SERVER['PWD'] . DIRECTORY_SEPARATOR . implode(" ", $_SERVER['argv']);
  246. }
  247. $data = array();
  248. $data['time'] = date('Y-m-d H:i:s');
  249. $data['message'] = trim($message);
  250. $data['client_ip'] = self::getClientIp();
  251. $data['cli'] = $cli;
  252. $string = '[' . implode("] [", $data) . ']' . "\n";
  253. return $string;
  254. }
  255. /**
  256. * 获取错误等级
  257. *
  258. * @return int
  259. */
  260. private static function getLogLevel()
  261. {
  262. return self::$logLevel;
  263. }
  264. /**
  265. * 获取日志路径,如果不存在或者不可写则使用tmp路径
  266. *
  267. * @param
  268. * $filename
  269. * @return string
  270. */
  271. private static function getLogPath($filename)
  272. {
  273. static $path = '';
  274. if (!$path) {
  275. if ((!file_exists(self::$logPath))) {
  276. mkdir(self::$logPath, 0777, true);
  277. }
  278. $path = is_writable(self::$logPath) ? self::$logPath : sys_get_temp_dir();
  279. $path = rtrim($path, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . date('Ym') . DIRECTORY_SEPARATOR . date('d') . DIRECTORY_SEPARATOR;
  280. if (!is_writable($path)) {
  281. if (!file_exists($path)) {
  282. mkdir($path, 0777, true);
  283. }
  284. }
  285. }
  286. $filename = strtolower(strtr($filename, array(
  287. ' ' => '',
  288. DIRECTORY_SEPARATOR => ''
  289. )));
  290. $filename = $path . $filename . '.log';
  291. return $filename;
  292. }
  293. /**
  294. * 获取日志路径,如果不存在或者不可写则使用tmp路径
  295. *
  296. * @param
  297. * $filename
  298. * @return string
  299. */
  300. private static function getBigdataLogPath()
  301. {
  302. $path = '/www/privdata/api.makeup.meitu.com/bigdata/' . date('Ymd') . DIRECTORY_SEPARATOR;
  303. if ((!file_exists($path))) {
  304. mkdir($path, 0777, true);
  305. }
  306. $filename = date("H") . '_' . self::getServerIp();
  307. $filename = $path . $filename . '.log';
  308. return $filename;
  309. }
  310. /**
  311. * 获取HTTP_HOST
  312. *
  313. * @return mixed
  314. */
  315. private static function getHost()
  316. {
  317. static $host;
  318. if (!$host) {
  319. if (isset($_SERVER['HTTP_HOST']) && $_SERVER['HTTP_HOST']) {
  320. $host = $_SERVER['HTTP_HOST'];
  321. } else {
  322. $host = 'script';
  323. }
  324. }
  325. return $host;
  326. }
  327. /**
  328. * 获取客户端Ip
  329. *
  330. * @return string|int
  331. */
  332. private static function getClientIp()
  333. {
  334. static $ip;
  335. if ($ip) {
  336. return $ip;
  337. }
  338. if (isset($_SERVER["HTTP_X_FORWARDED_FOR"])) {
  339. $ip = $_SERVER["HTTP_X_FORWARDED_FOR"];
  340. } elseif (isset($_SERVER["HTTP_CLIENT_IP"])) {
  341. $ip = $_SERVER["HTTP_CLIENT_IP"];
  342. } elseif (isset($_SERVER["HTTP_CLIENTIP"])) {
  343. $ip = $_SERVER["HTTP_CLIENTIP"];
  344. } elseif (isset($_SERVER["HTTP_X_REAL_IP"])) {
  345. $ip = $_SERVER["HTTP_X_REAL_IP"];
  346. } elseif (isset($_SERVER["REMOTE_ADDR"])) {
  347. $ip = $_SERVER["REMOTE_ADDR"];
  348. } else {
  349. $ip = '127.0.0.1';
  350. }
  351. $pos = strpos($ip, '|');
  352. if ($pos) {
  353. $ip = substr($ip, 0, $pos);
  354. }
  355. $ip = trim($ip);
  356. return $ip;
  357. }
  358. /**
  359. * 获取服务器IP
  360. *
  361. * @return string
  362. */
  363. private static function getServerIp()
  364. {
  365. static $ip;
  366. if ($ip) {
  367. return $ip;
  368. }
  369. if (isset($_SERVER['SERVER_ADDR'])) {
  370. $ip = $_SERVER['SERVER_ADDR'];
  371. } else {
  372. $cmd = "/sbin/ifconfig|grep 'inet addr'|awk '{print $2}'|awk -F':' '{print $2}'|awk '$1 !~ /127.0.0.1/{print}'|tail -n 1";
  373. $handle = popen($cmd, 'r');
  374. $ip = trim(fread($handle, 1024));
  375. pclose($handle);
  376. }
  377. return $ip;
  378. }
  379. /**
  380. * 获取Header信息
  381. *
  382. * @return mixed
  383. */
  384. private static function getHeaders()
  385. {
  386. return array();
  387. static $headers = array();
  388. if ($headers) {
  389. return $headers;
  390. }
  391. foreach ($_SERVER as $key => $value) {
  392. if (substr($key, 0, 5) != 'HTTP_') {
  393. continue;
  394. }
  395. $header = str_replace(' ', '-', ucwords(str_replace('_', ' ', strtolower(substr($key, 5)))));
  396. $headers[$header] = $value;
  397. }
  398. return $headers;
  399. }
  400. }