Log.php 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. <?php
  2. declare(strict_types=1);
  3. /**
  4. * MINZ - Copyright 2011 Marien Fressinaud
  5. * Sous licence AGPL3 <http://www.gnu.org/licenses/>
  6. */
  7. /**
  8. * The Minz_Log class is used to log errors and warnings
  9. */
  10. class Minz_Log {
  11. /**
  12. * Enregistre un message dans un fichier de log spécifique
  13. * Message non loggué si
  14. * - environment = SILENT
  15. * - level = LOG_WARNING et environment = PRODUCTION
  16. * - level = LOG_NOTICE et environment = PRODUCTION
  17. * @param string $information message d'erreur / information à enregistrer
  18. * @param int $level niveau d'erreur https://php.net/function.syslog
  19. * @param string $file_name fichier de log
  20. * @throws Minz_PermissionDeniedException
  21. */
  22. public static function record(string $information, int $level, ?string $file_name = null): void {
  23. $env = getenv('FRESHRSS_ENV');
  24. if ($env == '') {
  25. try {
  26. $conf = Minz_Configuration::get('system');
  27. $env = $conf->environment;
  28. } catch (Minz_ConfigurationException $e) {
  29. $env = 'production';
  30. }
  31. }
  32. if (! ($env === 'silent' || ($env === 'production' && ($level >= LOG_NOTICE)))) {
  33. $username = Minz_User::name() ?? Minz_User::INTERNAL_USER;
  34. if ($file_name == null) {
  35. $file_name = join_path(USERS_PATH, $username, LOG_FILENAME);
  36. }
  37. switch ($level) {
  38. case LOG_ERR:
  39. $level_label = 'error';
  40. break;
  41. case LOG_WARNING:
  42. $level_label = 'warning';
  43. break;
  44. case LOG_NOTICE:
  45. $level_label = 'notice';
  46. break;
  47. case LOG_DEBUG:
  48. $level_label = 'debug';
  49. break;
  50. default:
  51. $level = LOG_INFO;
  52. $level_label = 'info';
  53. }
  54. $log = '[' . date('r') . '] [' . $level_label . '] --- ' . str_replace(["\r", "\n"], ' ', $information) . "\n";
  55. if (defined('COPY_LOG_TO_SYSLOG') && COPY_LOG_TO_SYSLOG) {
  56. syslog($level, '[' . $username . '] ' . trim($log));
  57. }
  58. self::ensureMaxLogSize($file_name);
  59. if (file_put_contents($file_name, $log, FILE_APPEND | LOCK_EX) === false) {
  60. throw new Minz_PermissionDeniedException($file_name, Minz_Exception::ERROR);
  61. }
  62. }
  63. }
  64. /**
  65. * Make sure we do not waste a huge amount of disk space with old log messages.
  66. *
  67. * This method can be called multiple times for one script execution, but its result will not change unless
  68. * you call clearstatcache() in between. We won’t do do that for performance reasons.
  69. *
  70. * @throws Minz_PermissionDeniedException
  71. */
  72. protected static function ensureMaxLogSize(string $file_name): void {
  73. $maxSize = defined('MAX_LOG_SIZE') ? MAX_LOG_SIZE : 1048576;
  74. if ($maxSize > 0 && @filesize($file_name) > $maxSize) {
  75. $fp = fopen($file_name, 'c+');
  76. if (is_resource($fp) && flock($fp, LOCK_EX)) {
  77. fseek($fp, -(int)($maxSize / 2), SEEK_END);
  78. $content = fread($fp, $maxSize);
  79. rewind($fp);
  80. ftruncate($fp, 0);
  81. fwrite($fp, $content ?: '');
  82. fwrite($fp, sprintf("[%s] [notice] --- Log rotate.\n", date('r')));
  83. fflush($fp);
  84. flock($fp, LOCK_UN);
  85. } else {
  86. throw new Minz_PermissionDeniedException($file_name, Minz_Exception::ERROR);
  87. }
  88. fclose($fp);
  89. }
  90. }
  91. /**
  92. * Some helpers to Minz_Log::record() method
  93. * Parameters are the same of those of the record() method.
  94. * @throws Minz_PermissionDeniedException
  95. */
  96. public static function debug(string $msg, ?string $file_name = null): void {
  97. self::record($msg, LOG_DEBUG, $file_name);
  98. }
  99. /** @throws Minz_PermissionDeniedException */
  100. public static function notice(string $msg, ?string $file_name = null): void {
  101. self::record($msg, LOG_NOTICE, $file_name);
  102. }
  103. /** @throws Minz_PermissionDeniedException */
  104. public static function warning(string $msg, ?string $file_name = null): void {
  105. self::record($msg, LOG_WARNING, $file_name);
  106. }
  107. /** @throws Minz_PermissionDeniedException */
  108. public static function error(string $msg, ?string $file_name = null): void {
  109. self::record($msg, LOG_ERR, $file_name);
  110. }
  111. }