Builder

web application developer blog

Symfony ile üretim ortamından ekran görüntülü ve dataylı hata raporlarını email yoluyla almak

Üretim ortamında hata olmaz. Olursa da haberimiz olmaz. Çünkü hata mesajlarını ekranda göstermek tehlikelidir. Zaten son kullanıcı hata mesajını görse de size raporlamaz. Raporlasa da o rapor bizim bir işimize yaramaz.

“Aynı hatayı tekrar oluşturup, problemin sebini anlamaya çalışıyoruz” denir, ürüne değer kaybettirilir. Biraz daha tecrübeli geliştiriciler, hemen log dosyasını tarar ama o kadar veri içinden gerçek hatayı bulup çıkarmak da ayrı bir ustalık işi.

Peki ne yapmamız gerekli?

Öncelikle, bir geliştirici, son kullanıcıdan, bir hata ile karşılaştığında ne ister ve bu isteği otomatik olarak nasıl gerçekleştiririz sorusunu cevaplamamız lazım.

  • İyi bir hata raporunda ekran görüntüsü olmalı,
  • hatanın oluştuğu dosya, dosyanın satır numarası hatta işlev (function) ve aldığı parametreler, bu işlevi hangi işlev çağırdı gibi sorularında yanıtı olmalı.

Burada en kolayı ikincisi. Eğer sunucu ile veri alışverişini AJAX ile yapıyorsak birincisi de kolay.

  1. ilk olarak uygulamamıza html2canvas kütüphanesini eklemeliyiz:
    <script src="/assets/js/html2canvas/html2canvas.min.js"></script>
  2. Ana javascript fonksiyonumuza JQuery AJAX istekleri ile hata almamız durumunu yakalamalıyız.
    $(document).bind('ajaxError',function(event,jqXHR, ajaxSettings, thrownError){
                    switch (jqXHR.status){
                        case 500:
                            var responseTime = new Date();
                            html2canvas(document.body, {
                                onrendered: function(canvas) {
                                    $.ajax({
                                        url: REPORTING_URL,
                                        type: 'POST',
                                        data:{image:canvas.toDataURL("image/png"),"time":parseInt(responseTime.timestamp / 1000)},
                                        success:function(response){
                                            $.infoBox(lastMsg);
                                        }
                                    });
                                }
                            });
                            break;
                    }
                });
  3. Symfony tarafında oluşan hataları yakalamamız gerekiyor. Bunun için bir servis yazmamız gerkli. Yakaladığımız hatayı $_SESSION içine kaydedeceğiz. Ekran görüntüsü geldiğinde, ikisini birlikte gönderebilmek için
    namespace YourNameSpace\YourBundle\Controller;
    use Symfony\Bundle\FrameworkBundle\Templating\EngineInterface;
    use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
    
    class MyExceptionListener {
        protected $templating;
        protected $kernel;
        public function __construct(EngineInterface $templating, $kernel)
        {
            $this->templating = $templating;
            $this->kernel = $kernel;
        }
        public function onKernelException(GetResponseForExceptionEvent $event)
        {
    
            $exception = $event->getException();
            $_SESSION["last_error_message"]=$exception->xdebug_message;
        }
    }
  4. Servis tanımlamalarını services.yml içinde yapıyoruz:
    services:
        kernel.listener.selphiu_exception_listener:
            class: YourNameSpace\YourBundleBundle\Controller\MyExceptionListener
            arguments: [@templating, @kernel]
            tags:
                - { name: kernel.event_listener, event: kernel.exception, method: onKernelException }
  5. Hata raporunun gönderileceği email adresini parameters.yml içine ekliyoruz
    parameters:
        error_reporting_email_address: '[email protected]'
        mailer_transport: smtp
        mailer_host: mail.domain.com
        mailer_user: [email protected]
        mailer_password: PASSWORD
        mailer_port: 587

     

  6. İkinci adımda REPORTING_URL ile belirttiğimiz  adresi dinleyen bir Action yazmamız gerekiyor. Bu action, ekran görüntüsü ile $_SESSION içindeki hata raporunu paketleyip email yoluyla bize gönderecek. Bunu yaparken error_report.html.twig isminde bir twig template’inizin zaten var olduğunu varsayıyorum
    namespace YourNameSpace\YourBundle\Controller;
    use Monolog\Handler\StreamHandler;
    use Monolog\Logger;
    use Symfony\Component\HttpFoundation\Request;
    use Symfony\Component\HttpFoundation\Session\Session;
    use Symfony\Component\Validator\Constraints\DateTime;
    
    class ErrorReportingController extends AuthBaseController{
        public function reportAction(Request $request){
            $imageDataURL = $request->get("image");
            $parts = explode(",",$imageDataURL);
            $data = $parts[1];
            $data = base64_decode($data);
            $time = $request->get("time");
            $messageText = $_SESSION["last_error_message"];
            $reportingAddress = $this->container->getParameter("error_reporting_email_address");        
            $attachment = \Swift_Attachment::newInstance()
                ->setFilename('snapshot.png')
                ->setContentType('image/png')
                ->setBody($data)
            ;
            $message = \Swift_Message::newInstance()
                ->setSubject("[Project-Error] Report")
                ->setFrom(array($this->container->getParameter('mailer_user')=>"Project Reporter"))
                ->setTo($reportingAddress)
                ->setContentType("text/html")
                ->setBody($this->renderView('YourBundle:EMail:error_report.html.twig',
                    array(
                        'message' => $messageText,
                    )
                )
                )->attach($attachment)
            ;
            $this->get('mailer')->send($message);
            $response = new Response(json_encode(array("status"=>"OK","result"=>array())));
            $response->headers->set("Content-Type","application/json");
            return $response; 
         } 
    }

 

Bir cevap yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir