Skip to content

Instantly share code, notes, and snippets.

@nickalbrecht
Last active August 16, 2017 01:17
Show Gist options
  • Save nickalbrecht/8f0c8f8cf82906049eb1e266f81e6f59 to your computer and use it in GitHub Desktop.
Save nickalbrecht/8f0c8f8cf82906049eb1e266f81e6f59 to your computer and use it in GitHub Desktop.
StackExchange.Exceptional - Custom Error List
Sample of some files I whipped up to try and demonstrate how to provide a
custom RazorPage to list errors recorded in StackExchange's Exceptional
public class ErrorsController : Controller
{
//The stock handler. Still needed to get the default CSS and JS used for Exceptional
public async Task Exceptions() => await StackExchange.Exceptional.ExceptionalMiddleware.HandleRequestAsync(HttpContext);
}
@{
bool InlineCSS = false;
bool IncludeJS = true;
var store = Settings.Current.DefaultStore;
}
<!DOCTYPE html>
<html>
<head>
<title>@ViewBag.PageTitle</title>
@if (InlineCSS)
{
<style>
@Resources.BundleCss.Content
</style>
}
else
{
<link rel="stylesheet" type="text/css" href="/errors/exceptions/@(KnownRoutes.Css)" integrity="[email protected](Resources.BundleCss.Sha512)" crossorigin="anonymous" />
}
@foreach (var css in Settings.Current.Render.CSSIncludes)
{
<link rel="stylesheet" type="text/css" href="@css" />
}
<script>var baseUrl = "";</script>
@if(false)
{
<script>
var Exception = ""; //error.WriteDetailedJson
</script>
}
@if (IncludeJS)
{
<script src="/errors/exceptions/@(KnownRoutes.Js)[email protected]" integrity="[email protected](@Resources.BundleJs.Sha512)" crossorigin="anonymous"></script>
}
@foreach (var js in Settings.Current.Render.JSIncludes)
{
<script src="@js"></script>
}
</head>
<body>
<div class="wrapper">
<header class="@(store.InFailureMode ? "failure": null)">Exceptions Log: @(Settings.Current.ApplicationName ?? "[Application Name]")</header>
<main>
@RenderBody()
</main>
<div class="bottom"></div>
</div>
<footer>
<div class="version-info">Exceptional X.X.X.X <br />@store.Name</div>
<div class="server-time">Server time is @DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssZ")</div>
</footer>
</body>
</html>
@using StackExchange.Exceptional
@using StackExchange.Exceptional.Internal
@inject Microsoft.Extensions.Options.IOptions<Settings> settings
@inject Microsoft.AspNetCore.Hosting.IHostingEnvironment hostingEnvironment
@inject Microsoft.Extensions.Logging.ILoggerFactory loggerFactory
@page "exceptional"
@{
var store = Settings.Current.DefaultStore;
var errors = (await store.GetAllAsync()).OrderByDescending(e => e.LastLogDate ?? e.CreationDate).ToList();
ViewBag.PageTitle = "Error Log";
Layout = "_Layout";
}
@if (store.InFailureMode)
{
<div class="failure-mode">
<svg viewBox="0 0 1792 1792"><path d="M1024 1375v-190q0-14-9.5-23.5t-22.5-9.5h-192q-13 0-22.5 9.5t-9.5 23.5v190q0 14 9.5 23.5t22.5 9.5h192q13 0 22.5-9.5t9.5-23.5zm-2-374l18-459q0-12-10-19-13-11-24-11h-220q-11 0-24 11-10 7-10 21l17 457q0 10 10 16.5t24 6.5h185q14 0 23.5-6.5t10.5-16.5zm-14-934l768 1408q35 63-2 126-17 29-46.5 46t-63.5 17h-1536q-34 0-63.5-17t-46.5-46q-37-63-2-126l768-1408q17-31 47-49t65-18 65 18 47 49z" /></svg>
Error log is in failure mode, @store.WriteQueue.Count queued to log.
@if (store.LastRetryException != null)
{
<div>Last Logging Exception: @store.LastRetryException.Message <a href="#" class="js-show-details">view details</a></div>
<pre class="stack dark details">
<code>
@Utils.StackTrace.HtmlPrettify(store.LastRetryException.Message + "\n" + store.LastRetryException.StackTrace)
</code>
</pre>
}
</div>
}
@if (errors.Count == 0)
{
<div>
<h1>No errors yet, yay!</h1>
<div>There are no active errors in the log.</div>
</div>
}
else
{
var last = errors.FirstOrDefault();
<h1>
<span class="js-error-count">@errors.Count Error@(errors.Count > 1 ? "s" : null)</span>
<span class="sub">(last: @last.CreationDate.ToRelativeTime())</span>
</h1>
<table class="js-error-list hover alt-rows error-list">
<thead>
<tr>
<th></th>
<th>Type</th>
<th>Error</th>
<th>Url</th>
<th>Remote IP</th>
<th>Time</th>
<th>Site</th>
<th>Server</th>
</tr>
</thead>
<tbody>
@foreach (var error in errors)
{
<tr data-id="" class="error @(error.IsProtected ? "js-protected": null)">
<td>
<a href="#" class="js-delete-link" title="Delete this error"><svg class='icon x' viewBox='0 0 1792 1792'><path d='M1490 1322q0 40-28 68l-136 136q-28 28-68 28t-68-28l-294-294-294 294q-28 28-68 28t-68-28l-136-136q-28-28-28-68t28-68l294-294-294-294q-28-28-28-68t28-68l136-136q28-28 68-28t68 28l294 294 294-294q28-28 68-28t68 28l136 136q28 28 28 68t-28 68l-294 294 294 294q28 28 28 68z' /></svg></a>
@if (!error.IsProtected)
{
<a href="#" class="js-protect-link" title="Protect this error"><svg class='icon lock' viewBox='0 0 1792 1792'><path d='M640 768h512v-192q0-106-75-181t-181-75-181 75-75 181v192zm832 96v576q0 40-28 68t-68 28h-960q-40 0-68-28t-28-68v-576q0-40 28-68t68-28h32v-192q0-184 132-316t316-132 316 132 132 316v192h32q40 0 68 28t28 68z' /></svg></a>
}
else
{
<span title="This error is protected"><svg class='icon lock' viewBox='0 0 1792 1792'><path d='M640 768h512v-192q0-106-75-181t-181-75-181 75-75 181v192zm832 96v576q0 40-28 68t-68 28h-960q-40 0-68-28t-28-68v-576q0-40 28-68t68-28h32v-192q0-184 132-316t316-132 316 132 132 316v192h32q40 0 68 28t28 68z' /></svg></span>
}
</td>
<td title="@error.Type">@error.Type.ToShortTypeName()</td>
<td class="wrap">
<a href="/errors/exceptions/@(KnownRoutes.Info)?guid=@(error.GUID)">@error.Message</a> @if (error.DuplicateCount > 1) { <span class="duplicate-count" title="number of similar errors occurring close to this error">(@error.DuplicateCount)</span>}
</td>
<td>@if (error.Url.HasValue()) { <span title="@(error.Host)@(error.Url))">@error.Url.TruncateWithEllipsis(40)</span> }</td>
<td>@error.IPAddress</td>
<td title="@((error.LastLogDate ?? error.CreationDate).ToUniversalTime().ToString("u"))">@((error.LastLogDate ?? error.CreationDate).ToRelativeTime())</td>
<td>@error.Host</td>
<td>@error.MachineName</td>
</tr>
}
</tbody>
</table>
}
@if(errors.Any(x=>x.IsProtected))
{
<div class="page-actions">
<a class="js-clear-all" href="#">Clear all non-protected errors</a>
</div>
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment