You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

263 lines
6.0 KiB

3 years ago
  1. <?php
  2. declare(strict_types=1);
  3. /**
  4. * @copyright 2020 Christoph Wurst <christoph@winzerhof-wurst.at>
  5. *
  6. * @author Christoph Wurst <christoph@winzerhof-wurst.at>
  7. *
  8. * @license GNU AGPL version 3 or any later version
  9. *
  10. * This program is free software: you can redistribute it and/or modify
  11. * it under the terms of the GNU Affero General Public License as
  12. * published by the Free Software Foundation, either version 3 of the
  13. * License, or (at your option) any later version.
  14. *
  15. * This program is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. * GNU Affero General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU Affero General Public License
  21. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  22. *
  23. */
  24. namespace OC\Log;
  25. use OCP\ILogger;
  26. use Psr\Log\InvalidArgumentException;
  27. use Psr\Log\LoggerInterface;
  28. use Throwable;
  29. use function array_key_exists;
  30. use function array_merge;
  31. final class PsrLoggerAdapter implements LoggerInterface {
  32. /** @var ILogger */
  33. private $logger;
  34. public function __construct(ILogger $logger) {
  35. $this->logger = $logger;
  36. }
  37. private function containsThrowable(array $context): bool {
  38. return array_key_exists('exception', $context) && $context['exception'] instanceof Throwable;
  39. }
  40. /**
  41. * System is unusable.
  42. *
  43. * @param string $message
  44. * @param array $context
  45. *
  46. * @return void
  47. */
  48. public function emergency($message, array $context = []): void {
  49. if ($this->containsThrowable($context)) {
  50. $this->logger->logException($context['exception'], array_merge(
  51. [
  52. 'message' => $message,
  53. 'level' => ILogger::FATAL,
  54. ],
  55. $context
  56. ));
  57. } else {
  58. $this->logger->emergency($message, $context);
  59. }
  60. }
  61. /**
  62. * Action must be taken immediately.
  63. *
  64. * Example: Entire website down, database unavailable, etc. This should
  65. * trigger the SMS alerts and wake you up.
  66. *
  67. * @param string $message
  68. * @param array $context
  69. *
  70. * @return void
  71. */
  72. public function alert($message, array $context = []) {
  73. if ($this->containsThrowable($context)) {
  74. $this->logger->logException($context['exception'], array_merge(
  75. [
  76. 'message' => $message,
  77. 'level' => ILogger::ERROR,
  78. ],
  79. $context
  80. ));
  81. } else {
  82. $this->logger->alert($message, $context);
  83. }
  84. }
  85. /**
  86. * Critical conditions.
  87. *
  88. * Example: Application component unavailable, unexpected exception.
  89. *
  90. * @param string $message
  91. * @param array $context
  92. *
  93. * @return void
  94. */
  95. public function critical($message, array $context = []) {
  96. if ($this->containsThrowable($context)) {
  97. $this->logger->logException($context['exception'], array_merge(
  98. [
  99. 'message' => $message,
  100. 'level' => ILogger::ERROR,
  101. ],
  102. $context
  103. ));
  104. } else {
  105. $this->logger->critical($message, $context);
  106. }
  107. }
  108. /**
  109. * Runtime errors that do not require immediate action but should typically
  110. * be logged and monitored.
  111. *
  112. * @param string $message
  113. * @param array $context
  114. *
  115. * @return void
  116. */
  117. public function error($message, array $context = []) {
  118. if ($this->containsThrowable($context)) {
  119. $this->logger->logException($context['exception'], array_merge(
  120. [
  121. 'message' => $message,
  122. 'level' => ILogger::ERROR,
  123. ],
  124. $context
  125. ));
  126. } else {
  127. $this->logger->error($message, $context);
  128. }
  129. }
  130. /**
  131. * Exceptional occurrences that are not errors.
  132. *
  133. * Example: Use of deprecated APIs, poor use of an API, undesirable things
  134. * that are not necessarily wrong.
  135. *
  136. * @param string $message
  137. * @param array $context
  138. *
  139. * @return void
  140. */
  141. public function warning($message, array $context = []) {
  142. if ($this->containsThrowable($context)) {
  143. $this->logger->logException($context['exception'], array_merge(
  144. [
  145. 'message' => $message,
  146. 'level' => ILogger::WARN,
  147. ],
  148. $context
  149. ));
  150. } else {
  151. $this->logger->warning($message, $context);
  152. }
  153. }
  154. /**
  155. * Normal but significant events.
  156. *
  157. * @param string $message
  158. * @param array $context
  159. *
  160. * @return void
  161. */
  162. public function notice($message, array $context = []) {
  163. if ($this->containsThrowable($context)) {
  164. $this->logger->logException($context['exception'], array_merge(
  165. [
  166. 'message' => $message,
  167. 'level' => ILogger::INFO,
  168. ],
  169. $context
  170. ));
  171. } else {
  172. $this->logger->notice($message, $context);
  173. }
  174. }
  175. /**
  176. * Interesting events.
  177. *
  178. * Example: User logs in, SQL logs.
  179. *
  180. * @param string $message
  181. * @param array $context
  182. *
  183. * @return void
  184. */
  185. public function info($message, array $context = []) {
  186. if ($this->containsThrowable($context)) {
  187. $this->logger->logException($context['exception'], array_merge(
  188. [
  189. 'message' => $message,
  190. 'level' => ILogger::INFO,
  191. ],
  192. $context
  193. ));
  194. } else {
  195. $this->logger->info($message, $context);
  196. }
  197. }
  198. /**
  199. * Detailed debug information.
  200. *
  201. * @param string $message
  202. * @param array $context
  203. *
  204. * @return void
  205. */
  206. public function debug($message, array $context = []) {
  207. if ($this->containsThrowable($context)) {
  208. $this->logger->logException($context['exception'], array_merge(
  209. [
  210. 'message' => $message,
  211. 'level' => ILogger::DEBUG,
  212. ],
  213. $context
  214. ));
  215. } else {
  216. $this->logger->debug($message, $context);
  217. }
  218. }
  219. /**
  220. * Logs with an arbitrary level.
  221. *
  222. * @param mixed $level
  223. * @param string $message
  224. * @param array $context
  225. *
  226. * @return void
  227. *
  228. * @throws InvalidArgumentException
  229. */
  230. public function log($level, $message, array $context = []) {
  231. if (!is_int($level) || $level < ILogger::DEBUG || $level > ILogger::FATAL) {
  232. throw new InvalidArgumentException('Nextcloud allows only integer log levels');
  233. }
  234. if ($this->containsThrowable($context)) {
  235. $this->logger->logException($context['exception'], array_merge(
  236. [
  237. 'message' => $message,
  238. 'level' => $level,
  239. ],
  240. $context
  241. ));
  242. } else {
  243. $this->logger->log($level, $message, $context);
  244. }
  245. }
  246. }