Skip to content

Instantly share code, notes, and snippets.

@rn0
Created September 10, 2012 22:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rn0/3694490 to your computer and use it in GitHub Desktop.
Save rn0/3694490 to your computer and use it in GitHub Desktop.
Elao\ErrorNotifierBundle
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<meta name="robots" content="noindex,nofollow" />
<title>{{ exception.message }} ({{ status_code }})</title>
<style type="text/css">
html {
background: #eee;
}
body {
font: 11px Verdana, Arial, sans-serif;
color: #333;
}
.sf-exceptionreset, .sf-exceptionreset .block, .sf-exceptionreset #message {
margin: auto;
}
img {
border: 0;
}
.clear {
clear: both;
height: 0;
font-size: 0;
line-height: 0;
}
.clear_fix:after {
content: "\0020";
display: block;
height: 0;
clear: both;
visibility: hidden;
}
.clear_fix {
display: inline-block;
}
* html .clear_fix {
height: 1%;
}
.clear_fix {
display: block;
}
.header {
padding: 30px 30px 20px 30px;
}
pre {
white-space: normal;
font-family: Arial, Helvetica, sans-serif;
}
table td {
text-align: left;
}
/*
Copyright (c) 2010, Yahoo! Inc. All rights reserved.
Code licensed under the BSD License:
http://developer.yahoo.com/yui/license.html
version: 3.1.2
build: 56
*/
.sf-exceptionreset html{color:#000;background:#FFF;}.sf-exceptionreset body,.sf-exceptionreset div,.sf-exceptionreset dl,.sf-exceptionreset dt,.sf-exceptionreset dd,.sf-exceptionreset ul,.sf-exceptionreset ol,.sf-exceptionreset li,.sf-exceptionreset h1,.sf-exceptionreset h2,.sf-exceptionreset h3,.sf-exceptionreset h4,.sf-exceptionreset h5,.sf-exceptionreset h6,.sf-exceptionreset pre,.sf-exceptionreset code,.sf-exceptionreset form,.sf-exceptionreset fieldset,.sf-exceptionreset legend,.sf-exceptionreset input,.sf-exceptionreset textarea,.sf-exceptionreset p,.sf-exceptionreset blockquote,.sf-exceptionreset th,.sf-exceptionreset td{margin:0;padding:0;}.sf-exceptionreset .sf-exceptionreset fieldset,.sf-exceptionreset img{border:0;}.sf-exceptionreset address,.sf-exceptionreset caption,.sf-exceptionreset cite,.sf-exceptionreset code,.sf-exceptionreset dfn,.sf-exceptionreset em,.sf-exceptionreset strong,.sf-exceptionreset th,.sf-exceptionreset var{font-style:normal;font-weight:normal;}.sf-exceptionreset li{list-style:none;}.sf-exceptionreset caption,.sf-exceptionreset th{text-align:left;}.sf-exceptionreset h1,.sf-exceptionreset h2,.sf-exceptionreset h3,.sf-exceptionreset h4,.sf-exceptionreset h5,.sf-exceptionreset h6{font-size:100%;font-weight:normal;}.sf-exceptionreset q:before,.sf-exceptionreset q:after{content:'';}.sf-exceptionreset abbr,.sf-exceptionreset acronym{border:0;font-variant:normal;}.sf-exceptionreset sup{vertical-align:text-top;}.sf-exceptionreset sub{vertical-align:text-bottom;}.sf-exceptionreset input,.sf-exceptionreset textarea,.sf-exceptionreset select{font-family:inherit;font-size:inherit;font-weight:inherit;}.sf-exceptionreset input,.sf-exceptionreset textarea,.sf-exceptionreset select{*font-size:100%;}.sf-exceptionreset legend{color:#000;}
.sf-exceptionreset html,
.sf-exceptionreset body {
width: 100%;
min-height: 100%;
_height: 100%;
margin: 0;
padding: 0;
}
.sf-exceptionreset body {
font: 1em "Lucida Sans Unicode", "Lucida Grande", Verdana, Arial, Helvetica, sans-serif;
text-align: left;
background-color: #efefef;
}
.sf-exceptionreset abbr {
border-bottom: 1px dotted #000;
cursor: help;
}
.sf-exceptionreset p {
font-size: 14px;
line-height: 20px;
color: #868686;
padding-bottom: 20px;
}
.sf-exceptionreset strong {
color: #313131;
font-weight: bold;
}
.sf-exceptionreset a {
color: #6c6159;
}
.sf-exceptionreset a img {
border: none;
}
.sf-exceptionreset a:hover {
text-decoration: underline;
}
.sf-exceptionreset em {
font-style: italic;
}
.sf-exceptionreset h2,
.sf-exceptionreset h3 {
font-weight: bold;
}
.sf-exceptionreset h1 {
font-family: Georgia, "Times New Roman", Times, serif;
font-size: 20px;
color: #313131;
word-break: break-all;
}
.sf-exceptionreset li {
padding-bottom: 10px;
}
.sf-exceptionreset .traces {
padding-bottom: 14px;
}
.sf-exceptionreset .traces li {
font-size: 12px;
color: #868686;
padding: 5px 4px;
list-style-type: decimal;
margin-left: 20px;
white-space: break-word;
}
.sf-exceptionreset #logs .traces li.error {
font-style: normal;
color: #AA3333;
background: #f9ecec;
}
.sf-exceptionreset #logs .traces li.warning {
font-style: normal;
background: #ffcc00;
}
/* fix for Opera not liking empty <li> */
.sf-exceptionreset .traces li:after {
content: "\00A0";
}
.sf-exceptionreset .trace {
border: 1px solid #D3D3D3;
padding: 10px;
overflow: auto;
margin: 10px 0 20px;
}
.sf-exceptionreset .block,
.sf-exceptionreset .block_exception {
-moz-border-radius: 16px;
-webkit-border-radius: 16px;
border-radius: 16px;
margin-bottom: 20px;
}
.sf-exceptionreset .block {
background-color: #FFFFFF;
border: 1px solid #dfdfdf;
padding: 40px 50px;
}
.sf-exceptionreset .block_exception div {
color: #313131;
font-size: 10px;
}
.sf-exceptionreset .block_exception_detected .illustration_exception,
.sf-exceptionreset .block_exception_detected .text_exception {
float: left;
}
.sf-exceptionreset .block_exception_detected .illustration_exception {
width: 152px;
}
.sf-exceptionreset .block_exception_detected .text_exception {
width: 670px;
padding: 30px 44px 24px 46px;
position: relative;
}
.sf-exceptionreset .text_exception .open_quote,
.sf-exceptionreset .text_exception .close_quote {
position: absolute;
}
.sf-exceptionreset .open_quote {
top: 0;
left: 0;
}
.sf-exceptionreset .close_quote {
bottom: 0;
right: 50px;
}
.sf-exceptionreset .block_exception p {
font-family: Arial, Helvetica, sans-serif;
}
.sf-exceptionreset .block_exception p a,
.sf-exceptionreset .block_exception p a:hover {
color: #565656;
}
.sf-exceptionreset h2 {
font-size: 16px;
font-family: Arial, Helvetica, sans-serif;
padding-bottom: 16px;
}
.sf-exceptionreset li a {
background: none;
color: #868686;
text-decoration: none;
}
.sf-exceptionreset li a:hover {
background: none;
color: #313131;
text-decoration: underline;
}
.sf-exceptionreset .logs h2 {
float: left;
width: 654px;
}
.sf-exceptionreset .error_count {
float: right;
width: 170px;
text-align: right;
}
.sf-exceptionreset .error_count span {
display: inline-block;
background-color: #aacd4e;
-moz-border-radius: 6px;
-webkit-border-radius: 6px;
border-radius: 6px;
padding: 4px;
color: white;
margin-right: 2px;
font-size: 11px;
font-weight: bold;
}
.sf-exceptionreset .toggle {
vertical-align: middle;
}
.sf-exceptionreset .linked ul,
.sf-exceptionreset .linked li {
display: inline;
}
.sf-exceptionreset #output_content {
color: #000;
font-size: 12px;
}
.sf-exceptionreset ol {
padding: 10px 0;
}
.sf-exceptionreset ol li {
list-style: decimal;
margin-left: 20px;
padding: 2px;
padding-bottom: 20px;
}
.sf-exceptionreset ol ol li {
list-style-position: inside;
margin-left: 0;
white-space: nowrap;
font-size: 12px;
padding-bottom: 0;
}
.sf-exceptionreset li .selected {
background-color: #ffd;
}
</style>
</head>
<body>
<div id="content">
<div class="sf-exceptionreset">
<div class="block_exception">
<div class="block_exception_detected clear_fix">
<div class="text_exception" style="background-color: #F6F6F6; border: 1px solid #DFDFDF; padding: 10px; width: 100%;">
<h1 style="font-size: 14px;">{{ exception.message|nl2br }}</h1>
<div>
<strong>{{ status_code }}</strong> - {{ exception.class|abbr_class }}
</div>
{% set previous_count = exception.allPrevious|length %}
{% if previous_count %}
<div class="linked"><span><strong>{{ previous_count }}</strong> linked Exception{{ previous_count > 1 ? 's' : '' }}:</span>
<ul>
{% for i, previous in exception.allPrevious %}
<li>
{{ previous.class|abbr_class }}
</li>
{% endfor %}
</ul>
</div>
{% endif %}
</div>
</div>
</div>
</div>
{#-- Trace Block --#}
<table style="background: #fff; margin: 0 0 20px 0; width: 100%;">
<tr>
<td>
<h4>Information:</h4>
<strong>Generated at: </strong> {{ "now"|date("d-m-Y H:i:s") }} <br />
<strong>Class name: </strong> {{ exception.class|abbr_class }} <br />
<strong>Message: </strong> {{ exception.message }} <br />
<strong>Uri: </strong> {{ request.uri }} <br />
</td>
</tr>
</table>
{#-- Trace Block --#}
<table style="background: #fff; margin: 0 0 20px 0; width: 100%;">
<tr>
<td>
<div class="block">
<h4>Stack Trace</h4>
{# see TwigBundle:Exception:traces.html.twig #}
<ol class="traces list_exception" id="traces">
{% for i, trace in exception.trace %}
{# see TwigBundle:Exception:trace.html.twig #}
<li>
{% if trace.class is defined %}
at
<strong>
<abbr title="{{ trace.class }}">{{ trace.class }}</abbr>
{{ trace.type ~ trace.function }}
</strong>
{#({{ trace.args|format_args }})#}
{% else %}
{{ trace.function }}()
{% endif %}
{% if trace.file is defined and trace.file and trace.line is defined and trace.line %}
{{ trace.function ? '<br />' : '' }}
in {{ trace.file|format_file(trace.line) }}&nbsp;
<div id="trace_{{ 0 ~ '_' ~ i }}" class="trace">
{{ trace.file|file_excerpt(trace.line) }}
</div>
{% endif %}
</li>
{% endfor %}
</ol>
</div>
</td>
</tr>
</table>
<table>
<tr>
<td style="height: 20px;"></td>
</tr>
</table>
{#-- Request GET Parameters Block --#}
<table style="background: #fff; margin: 0 0 20px 0; width: 100%;">
<tr>
<td>
<h4>Request GET Parameters</h4>
{% if request.query.all|length %}
{% include 'ElaoErrorNotifierBundle::_bag.html.twig' with { 'bag': request.query } only %}
{% else %}
<p>
<em>No GET parameters</em>
</p>
{% endif %}
</td>
</tr>
</table>
<table>
<tr>
<td style="height: 20px;"></td>
</tr>
</table>
{#-- Request POST Parameters Block --#}
<table style="background: #fff; margin: 0 0 20px 0; width: 100%;">
<tr>
<td>
<h4>Request POST Parameters</h4>
{% if request.request.all|length %}
{% include 'ElaoErrorNotifierBundle::_bag.html.twig' with { 'bag': request.query } only %}
{% else %}
<p>
<em>No POST parameters</em>
</p>
{% endif %}
</td>
</tr>
</table>
<table>
<tr>
<td style="height: 20px;"></td>
</tr>
</table>
{#-- Request Attributes Block --#}
<table style="background: #fff; margin: 0 0 20px 0; width: 100%;">
<tr>
<td>
<h4>Request Attributes</h4>
{% if request.attributes.all|length %}
{% include 'ElaoErrorNotifierBundle::_bag.html.twig' with { 'bag': request.query } only %}
{% else %}
<p>
<em>No Request Attributes</em>
</p>
{% endif %}
</td>
</tr>
</table>
<table>
<tr>
<td style="height: 20px;"></td>
</tr>
</table>
{#-- Request Cookies Block --#}
<table style="background: #fff; margin: 0 0 20px 0; width: 100%;">
<tr>
<td>
<h4>Request Cookies</h4>
{% if request.cookies.all|length %}
{% include 'ElaoErrorNotifierBundle::_bag.html.twig' with { 'bag': request.query } only %}
{% else %}
<p>
<em>No Request Cookies</em>
</p>
{% endif %}
</td>
</tr>
</table>
<table>
<tr>
<td style="height: 20px;"></td>
</tr>
</table>
{#-- Request Headers Block --#}
<table style="background: #fff; margin: 0 0 20px 0; width: 100%;">
<tr>
<td>
<h4>Request Headers</h4>
{% include 'ElaoErrorNotifierBundle::_bag.html.twig' with { 'bag': request.headers } only %}
</td>
</tr>
</table>
<table>
<tr>
<td style="height: 20px;"></td>
</tr>
</table>
{#-- Request Server Parameters Block --#}
<table style="background: #fff; margin: 0 0 20px 0; width: 100%;">
<tr>
<td>
<h4>Request Server Parameters </h4>
{% include 'ElaoErrorNotifierBundle::_bag.html.twig' with { 'bag': request.server } only %}
</td>
</tr>
</table>
<table>
<tr>
<td style="height: 20px;"></td>
</tr>
</table>
{#-- Request Session Attributes Block --#}
<table style="background: #fff; margin: 0 0 20px 0; width: 100%;">
<tr>
<td>
<h4>Session Attributes</h4>
{% if request.session.all|length %}
<table>
<tr>
<th>Key</th>
<th>Value</th>
</tr>
{% set attributes = request.session.all %}
{% for key in attributes|keys|sort %}
<tr>
<th>{{ key }}</th>
<td>{{ attributes[key]|yaml_dump }}</td>
</tr>
{% endfor %}
</table>
{% else %}
<p>
<em>No session attributes</em>
</p>
{% endif %}
</td>
</tr>
</table>
<table>
<tr>
<td style="height: 20px;"></td>
</tr>
</table>
</div>
</div>
</body>
</html>
<?php
namespace Elao\ErrorNotifierBundle\Listener;
use \Swift_Mailer;
use Symfony\Component\HttpKernel\Exception\FlattenException;
use Symfony\Component\Templating\EngineInterface;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\Exception\HttpException;
use Symfony\Component\HttpKernel\Log\DebugLoggerInterface;
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
/**
* Notifier
*/
class Notifier
{
/**
* @var Swift_Mailer $mailer
*/
private $mailer;
/**
* @var EngineInterface $templating
*/
private $templating;
private $from;
private $to;
private $handle404;
/**
* __construct
*
* @param Swift_Mailer $mailer mailer
* @param EngineInterface $templating templating
* @param string $from send mail from
* @param string $to send mail to
* @param boolean $handle404 handle 404 error ?
*
* @return void
*/
public function __construct(Swift_Mailer $mailer, EngineInterface $templating, $from, $to, $handle404 = false)
{
$this->mailer = $mailer;
$this->templating = $templating;
$this->from = $from;
$this->to = $to;
$this->handle404 = $handle404;
}
/**
* Handle the event
*
* @param GetResponseForExceptionEvent $event event
*
* @return void
*/
public function onKernelException(GetResponseForExceptionEvent $event)
{
if (HttpKernelInterface::MASTER_REQUEST !== $event->getRequestType()) {
return;
}
$exception = FlattenException::create($event->getException());
if (500 === $exception->getStatusCode() || (404 === $exception->getStatusCode() && true === $this->handle404)) {
$body = $this->templating->render('ElaoErrorNotifierBundle::mail.html.twig', array(
'exception' => $exception,
'request' => $event->getRequest(),
'status_code' => $exception->getStatusCode()
));
$exceptionId = md5($exception->getMessage());
$mail = \Swift_Message::newInstance()
->setSubject(sprintf('[%s] Error %s', $event->getRequest()->headers->get('host'), $exceptionId))
->setFrom($this->from)
->setTo($this->to)
->setContentType('text/html')
->setBody($body);
$this->mailer->send($mail);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment