Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [Symfony][SF2][Symfony2] Logowanie wyjątków w bazie
Forum PHP.pl > Forum > PHP > Frameworki
Ghost_78
Witam szanowne grono.

Od jakiegoś czasu bawię się z S2 i dzisiaj napotkałem problem, którego nie mogę przeskoczyć.

Tak jak w temacie - staram się zrobić zapis logów 400 i 500 w bazie. Znalazłem kilka tutków w necie jak tworzyć logi w plikach, jak wysyłać mailem ale nie trafiłem na konkretny opisujący zapis w bazie :/.

Mam gdzieś z netu przykład ale nie działa :/.

service.yml
  1. parameters:
  2. logger_database.class: Tools\LogBundle\Logger\DatabaseHandler
  3.  
  4. services:
  5. monolog.processor.request:
  6. class: Tools\LogBundle\Processor\RequestProcessor
  7. arguments: [ '@session' ]
  8. tags:
  9. - { name: monolog.processor, method: processRecord }
  10. - { name: kernel.event_listener, event: kernel.request, method: onKernelRequest}
  11.  
  12. logger_database:
  13. class: %logger_database.class%
  14. calls:
  15. - [ setContainer, [ '@service_container' ] ]
  16.  
  17. tools.backtrace_logger_listener:
  18. class: Tools\LogBundle\EventListener\BacktraceLoggerListener
  19. tags:
  20. - {name: "monolog.logger", channel: "backtrace"}
  21. - {name: "kernel.event_listener", event: "kernel.exception", method: "onKernelException"}
  22. arguments:
  23. - '@logger'


config.yml
  1. monolog:
  2. handlers:
  3. main:
  4. type: service
  5. level: error
  6. id: logger_database
  7. formatter: monolog.processor.request


Request processor.php
  1. namespace Tools\LogBundle\Processor;
  2.  
  3. use Symfony\Component\HttpFoundation\Session\Session;
  4. use Symfony\Bridge\Monolog\Processor\WebProcessor;
  5.  
  6. class RequestProcessor extends WebProcessor
  7. {
  8. private $_session;
  9.  
  10. public function __construct(Session $session)
  11. {
  12. $this->_session = $session;
  13. }
  14.  
  15. public function processRecord(array $record)
  16. {
  17. $record['extra']['serverData'] = "";
  18.  
  19. if( is_array($this->serverData) ) {
  20. foreach ($this->serverData as $key => $value) {
  21.  
  22. if( is_array($value) ) {
  23. $value = print_r($value, true);
  24. }
  25.  
  26. $record['extra']['serverData'] .= $key . ": " . $value . "\n";
  27. }
  28. }
  29.  
  30. foreach ($_SERVER as $key => $value) {
  31.  
  32. if( is_array($value) ) {
  33. $value = print_r($value, true);
  34. }
  35.  
  36. $record['extra']['serverData'] .= $key . ": " . $value . "\n";
  37. }
  38.  
  39. return $record;
  40. }
  41. }


BacktraceLoggerListener.php
  1. namespace Tools\LogBundle\EventListener;
  2.  
  3. use Symfony\Component\HttpKernel\Log\LoggerInterface;
  4. use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
  5.  
  6. class BacktraceLoggerListener
  7. {
  8. private $_logger;
  9.  
  10. public function __construct(LoggerInterface $logger = null)
  11. {
  12. $this->_logger = $logger;
  13. }
  14.  
  15. public function onKernelException(GetResponseForExceptionEvent $event)
  16. {
  17. $this->_logger->addError($event->getException());
  18. }
  19. }


DatabaseHandler.php
  1. <?php
  2. namespace Tools\LogBundle\Logger;
  3.  
  4. use Monolog\Handler\AbstractProcessingHandler;
  5. use Monolog\Logger;
  6.  
  7. /**
  8.  * Stores to database
  9.  *
  10.  */
  11. class DatabaseHandler extends AbstractProcessingHandler
  12. {
  13. protected $_container;
  14.  
  15. /**
  16.   * @param string $stream
  17.   * @param integer $level The minimum logging level at which this handler will be triggered
  18.   * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not
  19.   */
  20. public function __construct($level = Logger::DEBUG, $bubble = true)
  21. {
  22. parent::__construct($level, $bubble);
  23. }
  24.  
  25. /**
  26.   *
  27.   * @param type $container
  28.   */
  29. public function setContainer($container)
  30. {
  31. $this->_container = $container;
  32. }
  33.  
  34. /**
  35.   * {@inheritdoc}
  36.   */
  37. protected function write(array $record)
  38. {
  39. // Ensure the doctrine channel is ignored (unless its greater than a warning error), otherwise you will create an infinite loop, as doctrine like to log.. a lot..
  40. if( 'doctrine' == $record['channel'] ) {
  41.  
  42. if( (int)$record['level'] >= Logger::WARNING ) {
  43. error_log($record['message']);
  44. }
  45.  
  46. return;
  47. }
  48.  
  49. if( (int)$record['level'] >= Logger::WARNING ) {
  50.  
  51. try
  52. {
  53. // Logs are inserted as separate SQL statements, separate to the current transactions that may exist within the entity manager.
  54. $em = $this->_container->get('doctrine')->getEntityManager();
  55. $conn = $em->getConnection();
  56.  
  57. $created = date('Y-m-d H:i:s');
  58.  
  59. $serverData = $record['extra']['serverData'];
  60.  
  61. $stmt = $em->getConnection()->prepare('INSERT INTO system_log(log, level, serverData, modified, created)
  62. VALUES(' . $conn->quote($record['message']) . ', \'' . $record['level'] . '\', ' . $conn->quote($serverData) . ', \'' . $created . '\', \'' . $created . '\');');
  63. $stmt->execute();
  64.  
  65. } catch( \Exception $e ) {
  66.  
  67. // Fallback to just writing to php error logs if something really bad happens
  68. error_log($record['message']);
  69. error_log($e->getMessage());
  70. }
  71. }
  72. }
  73. }
  74.  


Problem w powyższym przykładzie jest taki, że dostaję komunikat:
Catchable Fatal Error: Argument 1 passed to Monolog\Handler\AbstractHandler::setFormatter() must implement interface Monolog\Formatter\FormatterInterface, instance of Tools\LogBundle\Processor\RequestProcessor given,
Wiem co on oznacza ale niestety nie potrafię rozwiązać tego problemu. Nie do konca rozgrysłem jeszcze ten mechanizm (kernel listenery itp) w S2.

Czy zapisuje ktoś z Was logi w ten sposób? Może ma ktoś jakiś ciekawy link do tutka ?
Będę wdzięczny za jakiekolwiek pokierowanie.

Pozdrawiam serdecznie.
misi3kk
Mam taką propozycję, pobierz sobie:
https://github.com/Elao/ErrorNotifierBundle

Ten bundle działa bez problemu i wysyła maile. Na jego podstawie możesz bez większych problemów zrobić zapis do bazy.

1. W service wywal ustawienia do maili, a dodaj przekazywanie EM
2. Odpowiednio przerób Notifier
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.