267 lines
10 KiB
Plaintext
267 lines
10 KiB
Plaintext
@using System
|
|
@using System.Collections.Generic
|
|
@using System.Globalization
|
|
@using System.Linq
|
|
@using Microsoft.AspNetCore.Diagnostics.Elm
|
|
@using Microsoft.AspNetCore.Diagnostics.Elm.RazorViews
|
|
@using Microsoft.Extensions.RazorViews
|
|
@using Microsoft.Extensions.Logging
|
|
|
|
@functions
|
|
{
|
|
public LogPage(LogPageModel model)
|
|
{
|
|
Model = model;
|
|
}
|
|
|
|
public LogPageModel Model { get; set; }
|
|
|
|
public HelperResult LogRow(LogInfo log, int level)
|
|
{
|
|
return new HelperResult((writer) =>
|
|
{
|
|
if (log.Severity >= Model.Options.MinLevel &&
|
|
(string.IsNullOrEmpty(Model.Options.NamePrefix) || log.Name.StartsWith(Model.Options.NamePrefix, StringComparison.Ordinal)))
|
|
{
|
|
PushWriter(writer);
|
|
WriteLiteral(" <tr class=\"logRow\">\r\n <td>");
|
|
Write(string.Format("{0:MM/dd/yy}", log.Time));
|
|
|
|
WriteLiteral("</td>\r\n <td>");
|
|
Write(string.Format("{0:H:mm:ss}", log.Time));
|
|
|
|
WriteLiteral($"</td>\r\n <td title=\"{log.Name}\">");
|
|
Write(log.Name);
|
|
var severity = log.Severity.ToString().ToLowerInvariant();
|
|
WriteLiteral($"</td>\r\n <td class=\"{severity}\">");
|
|
Write(log.Severity);
|
|
|
|
WriteLiteral($"</td>\r\n <td title=\"{log.Message}\"> \r\n");
|
|
|
|
for (var i = 0; i < level; i++)
|
|
{
|
|
WriteLiteral(" <span class=\"tab\"></span>\r\n");
|
|
}
|
|
|
|
WriteLiteral(" ");
|
|
Write(log.Message);
|
|
|
|
WriteLiteral($"\r\n </td>\r\n <td title=\"{log.Exception}\">");
|
|
|
|
Write(log.Exception);
|
|
|
|
WriteLiteral("</td>\r\n </tr>\r\n");
|
|
PopWriter();
|
|
}
|
|
});
|
|
}
|
|
|
|
public HelperResult Traverse(ScopeNode node, int level, Dictionary<string, int> counts)
|
|
{
|
|
return new HelperResult((writer) => {
|
|
PushWriter(writer);
|
|
|
|
// print start of scope
|
|
Write(LogRow(new LogInfo()
|
|
{
|
|
Name = node.Name,
|
|
Time = node.StartTime,
|
|
Severity = LogLevel.Debug,
|
|
Message = "Beginning " + node.State,
|
|
}, level));
|
|
|
|
var messageIndex = 0;
|
|
var childIndex = 0;
|
|
while (messageIndex < node.Messages.Count && childIndex < node.Children.Count)
|
|
{
|
|
if (node.Messages[messageIndex].Time < node.Children[childIndex].StartTime)
|
|
{
|
|
Write(LogRow(node.Messages[messageIndex], level));
|
|
|
|
counts[node.Messages[messageIndex].Severity.ToString()]++;
|
|
messageIndex++;
|
|
}
|
|
else
|
|
{
|
|
Write(Traverse(node.Children[childIndex], level + 1, counts));
|
|
childIndex++;
|
|
}
|
|
}
|
|
if (messageIndex < node.Messages.Count)
|
|
{
|
|
for (var i = messageIndex; i < node.Messages.Count; i++)
|
|
{
|
|
Write(LogRow(node.Messages[i], level));
|
|
counts[node.Messages[i].Severity.ToString()]++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (var i = childIndex; i < node.Children.Count; i++)
|
|
{
|
|
Write(Traverse(node.Children[i], level + 1, counts));
|
|
}
|
|
}
|
|
// print end of scope
|
|
Write(LogRow(new LogInfo()
|
|
{
|
|
Name = node.Name,
|
|
Time = node.EndTime,
|
|
Severity = LogLevel.Debug,
|
|
Message = string.Format("Completed {0} in {1}ms", node.State, node.EndTime - node.StartTime)
|
|
}, level));
|
|
|
|
PopWriter();
|
|
});
|
|
}
|
|
}
|
|
@{
|
|
Response.ContentType = "text/html; charset=utf-8";
|
|
}
|
|
|
|
<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<meta charset="utf-8" />
|
|
<title>ASP.NET Core Logs</title>
|
|
<script src="//ajax.aspnetcdn.com/ajax/jquery/jquery-2.1.1.min.js"></script>
|
|
<style>
|
|
<%$ include: LogPage.css %>
|
|
<%$ include: Shared.css %>
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<h1>ASP.NET Core Logs</h1>
|
|
<form id="viewOptions" method="get">
|
|
<select name="level">
|
|
@foreach (var severity in Enum.GetValues(typeof(LogLevel)))
|
|
{
|
|
var severityInt = (int)severity;
|
|
if ((int)Model.Options.MinLevel == severityInt)
|
|
{
|
|
<option value="@severityInt" selected="selected">@severity</option>
|
|
}
|
|
else
|
|
{
|
|
<option value="@severityInt">@severity</option>
|
|
}
|
|
}
|
|
</select>
|
|
<input type="text" name="name" value="@Model.Options.NamePrefix" />
|
|
<input type="submit" value="filter" />
|
|
</form>
|
|
<form id="clear" method="post" action="">
|
|
<button type="submit" name="clear" value="1">Clear Logs</button>
|
|
</form>
|
|
|
|
<table id="requestTable">
|
|
<thead id="requestHeader">
|
|
<tr>
|
|
<th class="path">Path</th>
|
|
<th class="method">Method</th>
|
|
<th class="host">Host</th>
|
|
<th class="statusCode">Status Code</th>
|
|
<th class="logs">Logs</th>
|
|
</tr>
|
|
</thead>
|
|
<colgroup>
|
|
<col />
|
|
<col />
|
|
<col />
|
|
<col />
|
|
<col />
|
|
</colgroup>
|
|
@foreach (var activity in Model.Activities.Reverse())
|
|
{
|
|
<tbody>
|
|
<tr class="requestRow">
|
|
@{
|
|
var activityPath = Model.Path.Value + "/" + activity.Id;
|
|
if (activity.HttpInfo != null)
|
|
{
|
|
<td><a href="@activityPath" title="@activity.HttpInfo.Path">@activity.HttpInfo.Path</a></td>
|
|
<td>@activity.HttpInfo.Method</td>
|
|
<td>@activity.HttpInfo.Host</td>
|
|
<td>@activity.HttpInfo.StatusCode</td>
|
|
}
|
|
else if (activity.RepresentsScope)
|
|
{
|
|
<td colspan="4"><a href="@activityPath" title="@activity.Root.State">@activity.Root.State</a></td>
|
|
}
|
|
else
|
|
{
|
|
<td colspan="4"><a href="@activityPath">Non-scope Log</a></td>
|
|
}
|
|
}
|
|
<td class="logTd">
|
|
<table class="logTable">
|
|
<thead class="logHeader">
|
|
<tr class="headerRow">
|
|
<th class="date">Date</th>
|
|
<th class="time">Time</th>
|
|
<th class="name">Name</th>
|
|
<th class="severity">Severity</th>
|
|
<th class="state">State</th>
|
|
<th>Error<span class="collapse">^</span></th>
|
|
</tr>
|
|
</thead>
|
|
@{
|
|
var counts = new Dictionary<string, int>();
|
|
counts["Critical"] = 0;
|
|
counts["Error"] = 0;
|
|
counts["Warning"] = 0;
|
|
counts["Information"] = 0;
|
|
counts["Debug"] = 0;
|
|
}
|
|
<tbody class="logBody">
|
|
@if (!activity.RepresentsScope)
|
|
{
|
|
// message not within a scope
|
|
var logInfo = activity.Root.Messages.FirstOrDefault();
|
|
@LogRow(logInfo, 0)
|
|
counts[logInfo.Severity.ToString()] = 1;
|
|
}
|
|
else
|
|
{
|
|
@Traverse(activity.Root, 0, counts)
|
|
}
|
|
</tbody>
|
|
<tbody class="summary">
|
|
<tr class="logRow">
|
|
<td>@activity.Time.ToString("MM-dd-yyyy HH:mm:ss")</td>
|
|
@foreach (var kvp in counts)
|
|
{
|
|
if (string.Equals("Debug", kvp.Key)) {
|
|
<td>@kvp.Value @kvp.Key<span class="collapse">v</span></td>
|
|
}
|
|
else
|
|
{
|
|
<td>@kvp.Value @kvp.Key</td>
|
|
}
|
|
}
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
}
|
|
</table>
|
|
<script type="text/javascript">
|
|
$(document).ready(function () {
|
|
$(".logBody").hide();
|
|
$(".logTable > thead").hide();
|
|
$(".logTable > thead").click(function () {
|
|
$(this).closest(".logTable").find("tbody").hide();
|
|
$(this).closest(".logTable").find(".summary").show();
|
|
$(this).hide();
|
|
});
|
|
$(".logTable > .summary").click(function () {
|
|
$(this).closest(".logTable").find("tbody").show();
|
|
$(this).closest(".logTable").find("thead").show();
|
|
$(this).hide();
|
|
});
|
|
});
|
|
</script>
|
|
</body>
|
|
</html> |