aspnetcore/src/Microsoft.AspNetCore.Diagno.../Views/LogPage.cshtml

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>