BufferHandler.php 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. <?php
  2. /*
  3. * This file is part of the Monolog package.
  4. *
  5. * (c) Jordi Boggiano <j.boggiano@seld.be>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace Monolog\Handler;
  11. use Monolog\Logger;
  12. /**
  13. * Buffers all records until closing the handler and then pass them as batch.
  14. *
  15. * This is useful for a MailHandler to send only one mail per request instead of
  16. * sending one per log message.
  17. *
  18. * @author Christophe Coevoet <stof@notk.org>
  19. */
  20. class BufferHandler extends AbstractHandler
  21. {
  22. protected $handler;
  23. protected $bufferSize = 0;
  24. protected $bufferLimit;
  25. protected $flushOnOverflow;
  26. protected $buffer = array();
  27. protected $initialized = false;
  28. /**
  29. * @param HandlerInterface $handler Handler.
  30. * @param int $bufferLimit How many entries should be buffered at most, beyond that the oldest items are removed from the buffer.
  31. * @param int $level The minimum logging level at which this handler will be triggered
  32. * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not
  33. * @param Boolean $flushOnOverflow If true, the buffer is flushed when the max size has been reached, by default oldest entries are discarded
  34. */
  35. public function __construct(HandlerInterface $handler, $bufferLimit = 0, $level = Logger::DEBUG, $bubble = true, $flushOnOverflow = false)
  36. {
  37. parent::__construct($level, $bubble);
  38. $this->handler = $handler;
  39. $this->bufferLimit = (int) $bufferLimit;
  40. $this->flushOnOverflow = $flushOnOverflow;
  41. }
  42. /**
  43. * {@inheritdoc}
  44. */
  45. public function handle(array $record)
  46. {
  47. if ($record['level'] < $this->level) {
  48. return false;
  49. }
  50. if (!$this->initialized) {
  51. // __destructor() doesn't get called on Fatal errors
  52. register_shutdown_function(array($this, 'close'));
  53. $this->initialized = true;
  54. }
  55. if ($this->bufferLimit > 0 && $this->bufferSize === $this->bufferLimit) {
  56. if ($this->flushOnOverflow) {
  57. $this->flush();
  58. } else {
  59. array_shift($this->buffer);
  60. $this->bufferSize--;
  61. }
  62. }
  63. if ($this->processors) {
  64. foreach ($this->processors as $processor) {
  65. $record = call_user_func($processor, $record);
  66. }
  67. }
  68. $this->buffer[] = $record;
  69. $this->bufferSize++;
  70. return false === $this->bubble;
  71. }
  72. public function flush()
  73. {
  74. if ($this->bufferSize === 0) {
  75. return;
  76. }
  77. $this->handler->handleBatch($this->buffer);
  78. $this->clear();
  79. }
  80. public function __destruct()
  81. {
  82. // suppress the parent behavior since we already have register_shutdown_function()
  83. // to call close(), and the reference contained there will prevent this from being
  84. // GC'd until the end of the request
  85. }
  86. /**
  87. * {@inheritdoc}
  88. */
  89. public function close()
  90. {
  91. $this->flush();
  92. }
  93. /**
  94. * Clears the buffer without flushing any messages down to the wrapped handler.
  95. */
  96. public function clear()
  97. {
  98. $this->bufferSize = 0;
  99. $this->buffer = array();
  100. }
  101. }