Merge pull request #5401 from umbraco/v8/feature/logviewer-change-time-period
Added support for changing the dates of the log files
This commit is contained in:
@@ -26,26 +26,26 @@ namespace Umbraco.Core.Logging.Viewer
|
||||
/// A count of number of errors
|
||||
/// By counting Warnings with Exceptions, Errors & Fatal messages
|
||||
/// </summary>
|
||||
int GetNumberOfErrors(DateTimeOffset startDate, DateTimeOffset endDate);
|
||||
int GetNumberOfErrors(LogTimePeriod logTimePeriod);
|
||||
|
||||
/// <summary>
|
||||
/// Returns a number of the different log level entries
|
||||
/// </summary>
|
||||
LogLevelCounts GetLogLevelCounts(DateTimeOffset startDate, DateTimeOffset endDate);
|
||||
LogLevelCounts GetLogLevelCounts(LogTimePeriod logTimePeriod);
|
||||
|
||||
/// <summary>
|
||||
/// Returns a list of all unique message templates and their counts
|
||||
/// </summary>
|
||||
IEnumerable<LogTemplate> GetMessageTemplates(DateTimeOffset startDate, DateTimeOffset endDate);
|
||||
IEnumerable<LogTemplate> GetMessageTemplates(LogTimePeriod logTimePeriod);
|
||||
|
||||
bool CanHandleLargeLogs { get; }
|
||||
|
||||
bool CheckCanOpenLogs(DateTimeOffset startDate, DateTimeOffset endDate);
|
||||
bool CheckCanOpenLogs(LogTimePeriod logTimePeriod);
|
||||
|
||||
/// <summary>
|
||||
/// Returns the collection of logs
|
||||
/// </summary>
|
||||
PagedResult<LogMessage> GetLogs(DateTimeOffset startDate, DateTimeOffset endDate,
|
||||
PagedResult<LogMessage> GetLogs(LogTimePeriod logTimePeriod,
|
||||
int pageNumber = 1,
|
||||
int pageSize = 100,
|
||||
Direction orderDirection = Direction.Descending,
|
||||
|
||||
@@ -26,7 +26,7 @@ namespace Umbraco.Core.Logging.Viewer
|
||||
|
||||
public override bool CanHandleLargeLogs => false;
|
||||
|
||||
public override bool CheckCanOpenLogs(DateTimeOffset startDate, DateTimeOffset endDate)
|
||||
public override bool CheckCanOpenLogs(LogTimePeriod logTimePeriod)
|
||||
{
|
||||
//Log Directory
|
||||
var logDirectory = _logsPath;
|
||||
@@ -36,7 +36,7 @@ namespace Umbraco.Core.Logging.Viewer
|
||||
|
||||
//foreach full day in the range - see if we can find one or more filenames that end with
|
||||
//yyyyMMdd.json - Ends with due to MachineName in filenames - could be 1 or more due to load balancing
|
||||
for (var day = startDate.Date; day.Date <= endDate.Date; day = day.AddDays(1))
|
||||
for (var day = logTimePeriod.StartTime.Date; day.Date <= logTimePeriod.EndTime.Date; day = day.AddDays(1))
|
||||
{
|
||||
//Filename ending to search for (As could be multiple)
|
||||
var filesToFind = GetSearchPattern(day);
|
||||
@@ -57,7 +57,7 @@ namespace Umbraco.Core.Logging.Viewer
|
||||
return $"*{day:yyyyMMdd}*.json";
|
||||
}
|
||||
|
||||
protected override IReadOnlyList<LogEvent> GetLogs(DateTimeOffset startDate, DateTimeOffset endDate, ILogFilter filter, int skip, int take)
|
||||
protected override IReadOnlyList<LogEvent> GetLogs(LogTimePeriod logTimePeriod, ILogFilter filter, int skip, int take)
|
||||
{
|
||||
var logs = new List<LogEvent>();
|
||||
|
||||
@@ -68,7 +68,7 @@ namespace Umbraco.Core.Logging.Viewer
|
||||
|
||||
//foreach full day in the range - see if we can find one or more filenames that end with
|
||||
//yyyyMMdd.json - Ends with due to MachineName in filenames - could be 1 or more due to load balancing
|
||||
for (var day = startDate.Date; day.Date <= endDate.Date; day = day.AddDays(1))
|
||||
for (var day = logTimePeriod.StartTime.Date; day.Date <= logTimePeriod.EndTime.Date; day = day.AddDays(1))
|
||||
{
|
||||
//Filename ending to search for (As could be multiple)
|
||||
var filesToFind = GetSearchPattern(day);
|
||||
|
||||
16
src/Umbraco.Core/Logging/Viewer/LogTimePeriod.cs
Normal file
16
src/Umbraco.Core/Logging/Viewer/LogTimePeriod.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
using System;
|
||||
|
||||
namespace Umbraco.Core.Logging.Viewer
|
||||
{
|
||||
public class LogTimePeriod
|
||||
{
|
||||
public LogTimePeriod(DateTime startTime, DateTime endTime)
|
||||
{
|
||||
StartTime = startTime;
|
||||
EndTime = endTime;
|
||||
}
|
||||
|
||||
public DateTime StartTime { get; }
|
||||
public DateTime EndTime { get; }
|
||||
}
|
||||
}
|
||||
@@ -27,9 +27,9 @@ namespace Umbraco.Core.Logging.Viewer
|
||||
/// <summary>
|
||||
/// Get all logs from your chosen data source back as Serilog LogEvents
|
||||
/// </summary>
|
||||
protected abstract IReadOnlyList<LogEvent> GetLogs(DateTimeOffset startDate, DateTimeOffset endDate, ILogFilter filter, int skip, int take);
|
||||
protected abstract IReadOnlyList<LogEvent> GetLogs(LogTimePeriod logTimePeriod, ILogFilter filter, int skip, int take);
|
||||
|
||||
public abstract bool CheckCanOpenLogs(DateTimeOffset startDate, DateTimeOffset endDate);
|
||||
public abstract bool CheckCanOpenLogs(LogTimePeriod logTimePeriod);
|
||||
|
||||
public virtual IReadOnlyList<SavedLogSearch> GetSavedSearches()
|
||||
{
|
||||
@@ -82,24 +82,24 @@ namespace Umbraco.Core.Logging.Viewer
|
||||
return searches;
|
||||
}
|
||||
|
||||
public int GetNumberOfErrors(DateTimeOffset startDate, DateTimeOffset endDate)
|
||||
public int GetNumberOfErrors(LogTimePeriod logTimePeriod)
|
||||
{
|
||||
var errorCounter = new ErrorCounterFilter();
|
||||
GetLogs(startDate, endDate, errorCounter, 0, int.MaxValue);
|
||||
GetLogs(logTimePeriod, errorCounter, 0, int.MaxValue);
|
||||
return errorCounter.Count;
|
||||
}
|
||||
|
||||
public LogLevelCounts GetLogLevelCounts(DateTimeOffset startDate, DateTimeOffset endDate)
|
||||
public LogLevelCounts GetLogLevelCounts(LogTimePeriod logTimePeriod)
|
||||
{
|
||||
var counter = new CountingFilter();
|
||||
GetLogs(startDate, endDate, counter, 0, int.MaxValue);
|
||||
GetLogs(logTimePeriod, counter, 0, int.MaxValue);
|
||||
return counter.Counts;
|
||||
}
|
||||
|
||||
public IEnumerable<LogTemplate> GetMessageTemplates(DateTimeOffset startDate, DateTimeOffset endDate)
|
||||
public IEnumerable<LogTemplate> GetMessageTemplates(LogTimePeriod logTimePeriod)
|
||||
{
|
||||
var messageTemplates = new MessageTemplateFilter();
|
||||
GetLogs(startDate, endDate, messageTemplates, 0, int.MaxValue);
|
||||
GetLogs(logTimePeriod, messageTemplates, 0, int.MaxValue);
|
||||
|
||||
var templates = messageTemplates.Counts.
|
||||
Select(x => new LogTemplate { MessageTemplate = x.Key, Count = x.Value })
|
||||
@@ -108,14 +108,14 @@ namespace Umbraco.Core.Logging.Viewer
|
||||
return templates;
|
||||
}
|
||||
|
||||
public PagedResult<LogMessage> GetLogs(DateTimeOffset startDate, DateTimeOffset endDate,
|
||||
public PagedResult<LogMessage> GetLogs(LogTimePeriod logTimePeriod,
|
||||
int pageNumber = 1, int pageSize = 100,
|
||||
Direction orderDirection = Direction.Descending,
|
||||
string filterExpression = null,
|
||||
string[] logLevels = null)
|
||||
{
|
||||
var expression = new ExpressionFilter(filterExpression);
|
||||
var filteredLogs = GetLogs(startDate, endDate, expression, 0, int.MaxValue);
|
||||
var filteredLogs = GetLogs(logTimePeriod, expression, 0, int.MaxValue);
|
||||
|
||||
//This is user used the checkbox UI to toggle which log levels they wish to see
|
||||
//If an empty array or null - its implied all levels to be viewed
|
||||
|
||||
@@ -218,6 +218,7 @@
|
||||
<Compile Include="Composing\TypeHelper.cs" />
|
||||
<Compile Include="Composing\TypeLoader.cs" />
|
||||
<Compile Include="IO\MediaPathSchemes\UniqueMediaPathScheme.cs" />
|
||||
<Compile Include="Logging\Viewer\LogTimePeriod.cs" />
|
||||
<Compile Include="Mapping\MapperContext.cs" />
|
||||
<Compile Include="Migrations\Upgrade\Common\DeleteKeysAndIndexes.cs" />
|
||||
<Compile Include="Migrations\Upgrade\V_8_0_0\DataTypes\ContentPickerPreValueMigrator.cs" />
|
||||
|
||||
@@ -23,9 +23,10 @@ namespace Umbraco.Tests.Logging
|
||||
private string _newSearchfilePath;
|
||||
private string _newSearchfileDirPath;
|
||||
|
||||
private DateTimeOffset _startDate = new DateTime(year: 2018, month: 11, day: 12, hour:0, minute:0, second:0);
|
||||
private DateTimeOffset _endDate = new DateTime(year: 2018, month: 11, day: 13, hour: 0, minute: 0, second: 0);
|
||||
|
||||
private LogTimePeriod _logTimePeriod = new LogTimePeriod(
|
||||
new DateTime(year: 2018, month: 11, day: 12, hour:0, minute:0, second:0),
|
||||
new DateTime(year: 2018, month: 11, day: 13, hour: 0, minute: 0, second: 0)
|
||||
);
|
||||
[OneTimeSetUp]
|
||||
public void Setup()
|
||||
{
|
||||
@@ -67,7 +68,7 @@ namespace Umbraco.Tests.Logging
|
||||
[Test]
|
||||
public void Logs_Contain_Correct_Error_Count()
|
||||
{
|
||||
var numberOfErrors = _logViewer.GetNumberOfErrors(startDate: _startDate, endDate: _endDate);
|
||||
var numberOfErrors = _logViewer.GetNumberOfErrors(_logTimePeriod);
|
||||
|
||||
//Our dummy log should contain 2 errors
|
||||
Assert.AreEqual(2, numberOfErrors);
|
||||
@@ -76,8 +77,8 @@ namespace Umbraco.Tests.Logging
|
||||
[Test]
|
||||
public void Logs_Contain_Correct_Log_Level_Counts()
|
||||
{
|
||||
var logCounts = _logViewer.GetLogLevelCounts(startDate: _startDate, endDate: _endDate);
|
||||
|
||||
var logCounts = _logViewer.GetLogLevelCounts(_logTimePeriod);
|
||||
|
||||
Assert.AreEqual(1954, logCounts.Debug);
|
||||
Assert.AreEqual(2, logCounts.Error);
|
||||
Assert.AreEqual(0, logCounts.Fatal);
|
||||
@@ -88,7 +89,7 @@ namespace Umbraco.Tests.Logging
|
||||
[Test]
|
||||
public void Logs_Contains_Correct_Message_Templates()
|
||||
{
|
||||
var templates = _logViewer.GetMessageTemplates(startDate: _startDate, endDate: _endDate);
|
||||
var templates = _logViewer.GetMessageTemplates(_logTimePeriod);
|
||||
|
||||
//Count no of templates
|
||||
Assert.AreEqual(43, templates.Count());
|
||||
@@ -112,7 +113,7 @@ namespace Umbraco.Tests.Logging
|
||||
{
|
||||
//We are just testing a return value (as we know the example file is less than 200MB)
|
||||
//But this test method does not test/check that
|
||||
var canOpenLogs = _logViewer.CheckCanOpenLogs(startDate: _startDate, endDate: _endDate);
|
||||
var canOpenLogs = _logViewer.CheckCanOpenLogs(_logTimePeriod);
|
||||
Assert.IsTrue(canOpenLogs);
|
||||
}
|
||||
|
||||
@@ -120,7 +121,7 @@ namespace Umbraco.Tests.Logging
|
||||
public void Logs_Can_Be_Queried()
|
||||
{
|
||||
//Should get me the most 100 recent log entries & using default overloads for remaining params
|
||||
var allLogs = _logViewer.GetLogs(startDate: _startDate, endDate: _endDate, pageNumber: 1);
|
||||
var allLogs = _logViewer.GetLogs(_logTimePeriod, pageNumber: 1);
|
||||
|
||||
//Check we get 100 results back for a page & total items all good :)
|
||||
Assert.AreEqual(100, allLogs.Items.Count());
|
||||
@@ -138,7 +139,7 @@ namespace Umbraco.Tests.Logging
|
||||
|
||||
|
||||
//Check we call method again with a smaller set of results & in ascending
|
||||
var smallQuery = _logViewer.GetLogs(startDate: _startDate, endDate: _endDate, pageNumber: 1, pageSize: 10, orderDirection: Direction.Ascending);
|
||||
var smallQuery = _logViewer.GetLogs(_logTimePeriod, pageNumber: 1, pageSize: 10, orderDirection: Direction.Ascending);
|
||||
Assert.AreEqual(10, smallQuery.Items.Count());
|
||||
Assert.AreEqual(241, smallQuery.TotalPages);
|
||||
|
||||
@@ -152,17 +153,17 @@ namespace Umbraco.Tests.Logging
|
||||
//Check invalid log levels
|
||||
//Rather than expect 0 items - get all items back & ignore the invalid levels
|
||||
string[] invalidLogLevels = { "Invalid", "NotALevel" };
|
||||
var queryWithInvalidLevels = _logViewer.GetLogs(startDate: _startDate, endDate: _endDate, pageNumber: 1, logLevels: invalidLogLevels);
|
||||
var queryWithInvalidLevels = _logViewer.GetLogs(_logTimePeriod, pageNumber: 1, logLevels: invalidLogLevels);
|
||||
Assert.AreEqual(2410, queryWithInvalidLevels.TotalItems);
|
||||
|
||||
//Check we can call method with an array of logLevel (error & warning)
|
||||
string [] logLevels = { "Warning", "Error" };
|
||||
var queryWithLevels = _logViewer.GetLogs(startDate: _startDate, endDate: _endDate, pageNumber: 1, logLevels: logLevels);
|
||||
var queryWithLevels = _logViewer.GetLogs(_logTimePeriod, pageNumber: 1, logLevels: logLevels);
|
||||
Assert.AreEqual(9, queryWithLevels.TotalItems);
|
||||
|
||||
|
||||
//Query @Level='Warning' BUT we pass in array of LogLevels for Debug & Info (Expect to get 0 results)
|
||||
string[] logLevelMismatch = { "Debug", "Information" };
|
||||
var filterLevelQuery = _logViewer.GetLogs(startDate: _startDate, endDate: _endDate, pageNumber: 1, filterExpression: "@Level='Warning'", logLevels: logLevelMismatch); ;
|
||||
var filterLevelQuery = _logViewer.GetLogs(_logTimePeriod, pageNumber: 1, filterExpression: "@Level='Warning'", logLevels: logLevelMismatch); ;
|
||||
Assert.AreEqual(0, filterLevelQuery.TotalItems);
|
||||
}
|
||||
|
||||
@@ -177,10 +178,10 @@ namespace Umbraco.Tests.Logging
|
||||
[Test]
|
||||
public void Logs_Can_Query_With_Expressions(string queryToVerify, int expectedCount)
|
||||
{
|
||||
var testQuery = _logViewer.GetLogs(startDate: _startDate, endDate: _endDate, pageNumber: 1, filterExpression: queryToVerify);
|
||||
var testQuery = _logViewer.GetLogs(_logTimePeriod, pageNumber: 1, filterExpression: queryToVerify);
|
||||
Assert.AreEqual(expectedCount, testQuery.TotalItems);
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
public void Log_Search_Can_Persist()
|
||||
{
|
||||
|
||||
@@ -96,13 +96,13 @@ Use this directive to generate a pagination.
|
||||
scope.pageNumber = parseInt(scope.pageNumber);
|
||||
}
|
||||
|
||||
scope.pagination = [];
|
||||
let tempPagination = [];
|
||||
|
||||
var i = 0;
|
||||
|
||||
if (scope.totalPages <= 10) {
|
||||
for (i = 0; i < scope.totalPages; i++) {
|
||||
scope.pagination.push({
|
||||
tempPagination.push({
|
||||
val: (i + 1),
|
||||
isActive: scope.pageNumber === (i + 1)
|
||||
});
|
||||
@@ -119,7 +119,7 @@ Use this directive to generate a pagination.
|
||||
start = Math.min(maxIndex, start);
|
||||
|
||||
for (i = start; i < (10 + start) ; i++) {
|
||||
scope.pagination.push({
|
||||
tempPagination.push({
|
||||
val: (i + 1),
|
||||
isActive: scope.pageNumber === (i + 1)
|
||||
});
|
||||
@@ -129,7 +129,7 @@ Use this directive to generate a pagination.
|
||||
if (start > 0) {
|
||||
localizationService.localize("general_first").then(function(value){
|
||||
var firstLabel = value;
|
||||
scope.pagination.unshift({ name: firstLabel, val: 1, isActive: false }, {val: "...",isActive: false});
|
||||
tempPagination.unshift({ name: firstLabel, val: 1, isActive: false }, {val: "...",isActive: false});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -137,9 +137,11 @@ Use this directive to generate a pagination.
|
||||
if (start < maxIndex) {
|
||||
localizationService.localize("general_last").then(function(value){
|
||||
var lastLabel = value;
|
||||
scope.pagination.push({ val: "...", isActive: false }, { name: lastLabel, val: scope.totalPages, isActive: false });
|
||||
tempPagination.push({ val: "...", isActive: false }, { name: lastLabel, val: scope.totalPages, isActive: false });
|
||||
});
|
||||
}
|
||||
|
||||
scope.pagination = tempPagination;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,39 +1,39 @@
|
||||
/**
|
||||
* @ngdoc service
|
||||
* @name umbraco.resources.logViewerResource
|
||||
* @description Retrives Umbraco log items (by default from JSON files on disk)
|
||||
*
|
||||
*
|
||||
**/
|
||||
function logViewerResource($q, $http, umbRequestHelper) {
|
||||
* @ngdoc service
|
||||
* @name umbraco.resources.logViewerResource
|
||||
* @description Retrives Umbraco log items (by default from JSON files on disk)
|
||||
*
|
||||
*
|
||||
**/
|
||||
function logViewerResource($q, $http, umbRequestHelper) {
|
||||
|
||||
//the factory object returned
|
||||
return {
|
||||
|
||||
getNumberOfErrors: function () {
|
||||
getNumberOfErrors: function (startDate, endDate) {
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.get(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"logViewerApiBaseUrl",
|
||||
"GetNumberOfErrors")),
|
||||
"GetNumberOfErrors")+ '?startDate='+startDate+ '&endDate='+ endDate ),
|
||||
'Failed to retrieve number of errors in logs');
|
||||
},
|
||||
|
||||
getLogLevelCounts: function () {
|
||||
getLogLevelCounts: function (startDate, endDate) {
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.get(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"logViewerApiBaseUrl",
|
||||
"GetLogLevelCounts")),
|
||||
"GetLogLevelCounts")+ '?startDate='+startDate+ '&endDate='+ endDate ),
|
||||
'Failed to retrieve log level counts');
|
||||
},
|
||||
|
||||
getMessageTemplates: function () {
|
||||
getMessageTemplates: function (startDate, endDate) {
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.get(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"logViewerApiBaseUrl",
|
||||
"GetMessageTemplates")),
|
||||
"GetMessageTemplates")+ '?startDate='+startDate+ '&endDate='+ endDate ),
|
||||
'Failed to retrieve log templates');
|
||||
},
|
||||
|
||||
@@ -93,12 +93,12 @@
|
||||
'Failed to retrieve common log messages');
|
||||
},
|
||||
|
||||
canViewLogs: function () {
|
||||
canViewLogs: function (startDate, endDate) {
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.get(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"logViewerApiBaseUrl",
|
||||
"GetCanViewLogs")),
|
||||
"GetCanViewLogs") + '?startDate='+startDate+ '&endDate='+ endDate ),
|
||||
'Failed to retrieve state if logs can be viewed');
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,15 @@
|
||||
|
||||
.umb-logviewer__sidebar {
|
||||
flex: 0 0 @sidebarwidth;
|
||||
|
||||
.flatpickr-input {
|
||||
background-color: @white;
|
||||
border: 0;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
font-size: larger;
|
||||
padding-top: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
|
||||
@@ -22,16 +22,32 @@
|
||||
}
|
||||
};
|
||||
|
||||
let querystring = $location.search();
|
||||
if(querystring.startDate){
|
||||
vm.startDate = querystring.startDate;
|
||||
}else{
|
||||
vm.startDate = new Date(Date.now());
|
||||
vm.startDate.setDate(vm.startDate.getDate()-1);
|
||||
vm.startDate = vm.startDate.toIsoDateString();
|
||||
}
|
||||
|
||||
if(querystring.endDate){
|
||||
vm.endDate = querystring.endDate;
|
||||
}else{
|
||||
vm.endDate = new Date(Date.now()).toIsoDateString();
|
||||
}
|
||||
vm.period = [vm.startDate, vm.endDate];
|
||||
|
||||
|
||||
//functions
|
||||
vm.searchLogQuery = searchLogQuery;
|
||||
vm.findMessageTemplate = findMessageTemplate;
|
||||
|
||||
|
||||
function preFlightCheck(){
|
||||
vm.loading = true;
|
||||
|
||||
//Do our pre-flight check (to see if we can view logs)
|
||||
//IE the log file is NOT too big such as 1GB & crash the site
|
||||
logViewerResource.canViewLogs().then(function(result){
|
||||
logViewerResource.canViewLogs(vm.startDate, vm.endDate).then(function(result){
|
||||
vm.loading = false;
|
||||
vm.canLoadLogs = result;
|
||||
|
||||
@@ -46,7 +62,7 @@
|
||||
function init() {
|
||||
|
||||
vm.loading = true;
|
||||
|
||||
|
||||
var savedSearches = logViewerResource.getSavedSearches().then(function (data) {
|
||||
vm.searches = data;
|
||||
},
|
||||
@@ -80,11 +96,11 @@
|
||||
]
|
||||
});
|
||||
|
||||
var numOfErrors = logViewerResource.getNumberOfErrors().then(function (data) {
|
||||
var numOfErrors = logViewerResource.getNumberOfErrors(vm.startDate, vm.endDate).then(function (data) {
|
||||
vm.numberOfErrors = data;
|
||||
});
|
||||
|
||||
var logCounts = logViewerResource.getLogLevelCounts().then(function (data) {
|
||||
var logCounts = logViewerResource.getLogLevelCounts(vm.startDate, vm.endDate).then(function (data) {
|
||||
vm.logTypeData = [];
|
||||
vm.logTypeData.push(data.Information);
|
||||
vm.logTypeData.push(data.Debug);
|
||||
@@ -93,7 +109,7 @@
|
||||
vm.logTypeData.push(data.Fatal);
|
||||
});
|
||||
|
||||
var commonMsgs = logViewerResource.getMessageTemplates().then(function(data){
|
||||
var commonMsgs = logViewerResource.getMessageTemplates(vm.startDate, vm.endDate).then(function(data){
|
||||
vm.commonLogMessages = data;
|
||||
});
|
||||
|
||||
@@ -108,7 +124,7 @@
|
||||
}
|
||||
|
||||
function searchLogQuery(logQuery){
|
||||
$location.path("/settings/logViewer/search").search({lq: logQuery});
|
||||
$location.path("/settings/logViewer/search").search({lq: logQuery, startDate: vm.startDate, endDate: vm.endDate});
|
||||
}
|
||||
|
||||
function findMessageTemplate(template){
|
||||
@@ -116,8 +132,38 @@
|
||||
searchLogQuery(logQuery);
|
||||
}
|
||||
|
||||
preFlightCheck();
|
||||
|
||||
|
||||
|
||||
preFlightCheck();
|
||||
|
||||
/////////////////////
|
||||
|
||||
vm.config = {
|
||||
enableTime: false,
|
||||
dateFormat: "Y-m-d",
|
||||
time_24hr: false,
|
||||
mode: "range",
|
||||
maxDate: "today",
|
||||
conjunction: " to "
|
||||
};
|
||||
|
||||
vm.dateRangeChange = function(selectedDates, dateStr, instance) {
|
||||
|
||||
if(selectedDates.length > 0){
|
||||
vm.startDate = selectedDates[0].toIsoDateString();
|
||||
vm.endDate = selectedDates[selectedDates.length-1].toIsoDateString(); // Take the last date as end
|
||||
|
||||
if(vm.startDate === vm.endDate){
|
||||
vm.period = [vm.startDate];
|
||||
}else{
|
||||
vm.period = [vm.startDate, vm.endDate];
|
||||
}
|
||||
|
||||
preFlightCheck();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
angular.module("umbraco").controller("Umbraco.Editors.LogViewer.OverviewController", LogViewerOverviewController);
|
||||
|
||||
@@ -14,45 +14,45 @@
|
||||
<umb-load-indicator ng-if="vm.loading"></umb-load-indicator>
|
||||
|
||||
<!-- Warning message (if unable to view log files) -->
|
||||
<div ng-show="!vm.loading && !vm.canLoadLogs">
|
||||
<umb-box>
|
||||
<umb-box-header title="Unable to view logs"/>
|
||||
<umb-box-content>
|
||||
<p>Today's log file is too large to be viewed and would cause performance problems.</p>
|
||||
<p>If you need to view the log files, try opening them manually</p>
|
||||
</umb-box-content>
|
||||
</umb-box>
|
||||
</div>
|
||||
|
||||
<div class="umb-logviewer" ng-show="!vm.loading && vm.canLoadLogs">
|
||||
<div class="umb-logviewer" ng-show="!vm.loading">
|
||||
<div class="umb-logviewer__main-content">
|
||||
<!-- Saved Searches -->
|
||||
<umb-box>
|
||||
<umb-box-header title="Saved Searches"></umb-box-header>
|
||||
<umb-box-content>
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
<a ng-click="vm.searchLogQuery()" title="View all Logs" class="btn btn-link">All Logs <i class="icon-search"></i></a>
|
||||
</td>
|
||||
</tr>
|
||||
<!-- Fetch saved searches -->
|
||||
<tr ng-repeat="search in vm.searches">
|
||||
<td>
|
||||
<a ng-click="vm.searchLogQuery(search.query)" title="{{search.name}}" class="btn btn-link">{{search.name}} <i class="icon-search"></i></a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</umb-box-content>
|
||||
</umb-box>
|
||||
<div ng-show="!vm.canLoadLogs">
|
||||
<umb-box>
|
||||
<umb-box-header title="Unable to view logs"/>
|
||||
<umb-box-content>
|
||||
<p>Today's log file is too large to be viewed and would cause performance problems.</p>
|
||||
<p>If you need to view the log files, try opening them manually</p>
|
||||
</umb-box-content>
|
||||
</umb-box>
|
||||
</div>
|
||||
<div ng-show="vm.canLoadLogs">
|
||||
<!-- Saved Searches -->
|
||||
<umb-box>
|
||||
<umb-box-header title="Saved Searches"></umb-box-header>
|
||||
<umb-box-content>
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
<a ng-click="vm.searchLogQuery()" title="View all Logs" class="btn btn-link">All Logs <i class="icon-search"></i></a>
|
||||
</td>
|
||||
</tr>
|
||||
<!-- Fetch saved searches -->
|
||||
<tr ng-repeat="search in vm.searches">
|
||||
<td>
|
||||
<a ng-click="vm.searchLogQuery(search.query)" title="{{search.name}}" class="btn btn-link">{{search.name}} <i class="icon-search"></i></a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</umb-box-content>
|
||||
</umb-box>
|
||||
|
||||
<!-- List of top X common log messages -->
|
||||
<umb-box>
|
||||
<umb-box-header title="Common Log Messages"></umb-box-header>
|
||||
<umb-box-content class="block-form">
|
||||
<em>Total Unique Message types</em>: {{ vm.commonLogMessages.length }}
|
||||
<table class="table table-hover">
|
||||
<tbody>
|
||||
<!-- List of top X common log messages -->
|
||||
<umb-box>
|
||||
<umb-box-header title="Common Log Messages"></umb-box-header>
|
||||
<umb-box-content class="block-form">
|
||||
<em>Total Unique Message types</em>: {{ vm.commonLogMessages.length }}
|
||||
<table class="table table-hover">
|
||||
<tbody>
|
||||
<tr ng-repeat="template in vm.commonLogMessages | limitTo:vm.commonLogMessagesCount" ng-click="vm.findMessageTemplate(template)" style="cursor: pointer;">
|
||||
<td>
|
||||
{{ template.MessageTemplate }}
|
||||
@@ -61,38 +61,54 @@
|
||||
{{ template.Count }}
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<a class="btn btn-primary" ng-if="vm.commonLogMessagesCount < vm.commonLogMessages.length" ng-click="vm.commonLogMessagesCount = vm.commonLogMessagesCount +10">Show More</a>
|
||||
</umb-box-content>
|
||||
</umb-box>
|
||||
</tbody>
|
||||
</table>
|
||||
<a class="btn btn-primary" ng-if="vm.commonLogMessagesCount < vm.commonLogMessages.length" ng-click="vm.commonLogMessagesCount = vm.commonLogMessagesCount +10">Show More</a>
|
||||
</umb-box-content>
|
||||
</umb-box>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="umb-logviewer__sidebar">
|
||||
<!-- No of Errors -->
|
||||
<umb-box ng-click="vm.searchLogQuery('Has(@Exception)')" style="cursor:pointer;">
|
||||
<umb-box-header title="Number of Errors"></umb-box-header>
|
||||
<umb-box-content class="block-form" style="font-size: 40px; font-weight:900; text-align:center; color:#fe6561;">
|
||||
{{ vm.numberOfErrors }}
|
||||
</umb-box-content>
|
||||
</umb-box>
|
||||
|
||||
<!-- Chart of diff log types -->
|
||||
<!-- Time period -->
|
||||
<umb-box>
|
||||
<umb-box-header title="Log Types"></umb-box-header>
|
||||
<umb-box-content class="block-form">
|
||||
<umb-box-header title="Time Period"></umb-box-header>
|
||||
|
||||
<canvas chart-doughnut
|
||||
chart-data="vm.logTypeData"
|
||||
chart-labels="vm.logTypeLabels"
|
||||
chart-colors="vm.logTypeColors"
|
||||
chart-options="vm.chartOptions">
|
||||
</canvas>
|
||||
|
||||
</umb-box-content>
|
||||
<umb-flatpickr
|
||||
class="datepicker"
|
||||
ng-model="vm.period"
|
||||
options="vm.config"
|
||||
on-close="vm.dateRangeChange(selectedDates, dateStr, instance)">
|
||||
</umb-flatpickr>
|
||||
</umb-box>
|
||||
|
||||
<div ng-show=" vm.canLoadLogs">
|
||||
<!-- No of Errors -->
|
||||
<umb-box ng-click="vm.searchLogQuery('Has(@Exception)')" style="cursor:pointer;">
|
||||
<umb-box-header title="Number of Errors"></umb-box-header>
|
||||
<umb-box-content class="block-form" style="font-size: 40px; font-weight:900; text-align:center; color:#fe6561;">
|
||||
{{ vm.numberOfErrors }}
|
||||
</umb-box-content>
|
||||
</umb-box>
|
||||
|
||||
<!-- Chart of diff log types -->
|
||||
<umb-box>
|
||||
<umb-box-header title="Log Types"></umb-box-header>
|
||||
<umb-box-content class="block-form">
|
||||
|
||||
<canvas chart-doughnut
|
||||
chart-data="vm.logTypeData"
|
||||
chart-labels="vm.logTypeLabels"
|
||||
chart-colors="vm.logTypeColors"
|
||||
chart-options="vm.chartOptions">
|
||||
</canvas>
|
||||
|
||||
</umb-box-content>
|
||||
</umb-box>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</umb-editor-container>
|
||||
</umb-editor-view>
|
||||
</div>
|
||||
|
||||
@@ -96,6 +96,14 @@
|
||||
vm.logOptions.filterExpression = querystring.lq;
|
||||
}
|
||||
|
||||
if(querystring.startDate){
|
||||
vm.logOptions.startDate = querystring.startDate;
|
||||
}
|
||||
|
||||
if(querystring.endDate){
|
||||
vm.logOptions.endDate = querystring.endDate;
|
||||
}
|
||||
|
||||
vm.loading = true;
|
||||
|
||||
logViewerResource.getSavedSearches().then(function (data) {
|
||||
@@ -270,7 +278,11 @@
|
||||
submitButtonLabel: "Save Search",
|
||||
disableSubmitButton: true,
|
||||
view: "logviewersearch",
|
||||
query: vm.logOptions.filterExpression,
|
||||
query: {
|
||||
filterExpression: vm.logOptions.filterExpression,
|
||||
startDate: vm.logOptions.startDate,
|
||||
endDate: vm.logOptions.endDate
|
||||
},
|
||||
submit: function (model) {
|
||||
//Resource call with two params (name & query)
|
||||
//API that opens the JSON and adds it to the bottom
|
||||
|
||||
@@ -184,7 +184,7 @@ namespace Umbraco.Web.Editors
|
||||
{
|
||||
"currentUserApiBaseUrl", _urlHelper.GetUmbracoApiServiceBaseUrl<CurrentUserController>(
|
||||
controller => controller.PostChangePassword(null))
|
||||
},
|
||||
},
|
||||
{
|
||||
"entityApiBaseUrl", _urlHelper.GetUmbracoApiServiceBaseUrl<EntityController>(
|
||||
controller => controller.GetById(0, UmbracoEntityTypes.Media))
|
||||
@@ -307,7 +307,7 @@ namespace Umbraco.Web.Editors
|
||||
},
|
||||
{
|
||||
"logViewerApiBaseUrl", _urlHelper.GetUmbracoApiServiceBaseUrl<LogViewerController>(
|
||||
controller => controller.GetNumberOfErrors())
|
||||
controller => controller.GetNumberOfErrors(null, null))
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -22,69 +22,97 @@ namespace Umbraco.Web.Editors
|
||||
_logViewer = logViewer;
|
||||
}
|
||||
|
||||
private bool CanViewLogs()
|
||||
private bool CanViewLogs(LogTimePeriod logTimePeriod)
|
||||
{
|
||||
//Can the interface deal with Large Files
|
||||
if (_logViewer.CanHandleLargeLogs)
|
||||
return true;
|
||||
|
||||
//Interface CheckCanOpenLogs
|
||||
return _logViewer.CheckCanOpenLogs(startDate: DateTime.Now.AddDays(-1), endDate: DateTime.Now);
|
||||
return _logViewer.CheckCanOpenLogs(logTimePeriod);
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public bool GetCanViewLogs()
|
||||
public bool GetCanViewLogs([FromUri] DateTime? startDate = null,[FromUri] DateTime? endDate = null)
|
||||
{
|
||||
return CanViewLogs();
|
||||
var logTimePeriod = GetTimePeriod(startDate, endDate);
|
||||
return CanViewLogs(logTimePeriod);
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public int GetNumberOfErrors()
|
||||
public int GetNumberOfErrors([FromUri] DateTime? startDate = null,[FromUri] DateTime? endDate = null)
|
||||
{
|
||||
var logTimePeriod = GetTimePeriod(startDate, endDate);
|
||||
//We will need to stop the request if trying to do this on a 1GB file
|
||||
if (CanViewLogs() == false)
|
||||
if (CanViewLogs(logTimePeriod) == false)
|
||||
{
|
||||
throw new HttpResponseException(Request.CreateNotificationValidationErrorResponse("Unable to view logs, due to size"));
|
||||
}
|
||||
|
||||
return _logViewer.GetNumberOfErrors(startDate: DateTime.Now.AddDays(-1), endDate: DateTime.Now);
|
||||
return _logViewer.GetNumberOfErrors(logTimePeriod);
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public LogLevelCounts GetLogLevelCounts()
|
||||
public LogLevelCounts GetLogLevelCounts([FromUri] DateTime? startDate = null,[FromUri] DateTime? endDate = null)
|
||||
{
|
||||
var logTimePeriod = GetTimePeriod(startDate, endDate);
|
||||
//We will need to stop the request if trying to do this on a 1GB file
|
||||
if (CanViewLogs() == false)
|
||||
if (CanViewLogs(logTimePeriod) == false)
|
||||
{
|
||||
throw new HttpResponseException(Request.CreateNotificationValidationErrorResponse("Unable to view logs, due to size"));
|
||||
}
|
||||
|
||||
return _logViewer.GetLogLevelCounts(startDate: DateTime.Now.AddDays(-1), endDate: DateTime.Now);
|
||||
return _logViewer.GetLogLevelCounts(logTimePeriod);
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public IEnumerable<LogTemplate> GetMessageTemplates()
|
||||
public IEnumerable<LogTemplate> GetMessageTemplates([FromUri] DateTime? startDate = null,[FromUri] DateTime? endDate = null)
|
||||
{
|
||||
var logTimePeriod = GetTimePeriod(startDate, endDate);
|
||||
//We will need to stop the request if trying to do this on a 1GB file
|
||||
if (CanViewLogs() == false)
|
||||
if (CanViewLogs(logTimePeriod) == false)
|
||||
{
|
||||
throw new HttpResponseException(Request.CreateNotificationValidationErrorResponse("Unable to view logs, due to size"));
|
||||
}
|
||||
|
||||
return _logViewer.GetMessageTemplates(startDate: DateTime.Now.AddDays(-1), endDate: DateTime.Now);
|
||||
return _logViewer.GetMessageTemplates(logTimePeriod);
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public PagedResult<LogMessage> GetLogs(string orderDirection = "Descending", int pageNumber = 1, string filterExpression = null, [FromUri]string[] logLevels = null)
|
||||
public PagedResult<LogMessage> GetLogs(string orderDirection = "Descending", int pageNumber = 1, string filterExpression = null, [FromUri]string[] logLevels = null, [FromUri] DateTime? startDate = null,[FromUri] DateTime? endDate = null)
|
||||
{
|
||||
var logTimePeriod = GetTimePeriod(startDate, endDate);
|
||||
|
||||
//We will need to stop the request if trying to do this on a 1GB file
|
||||
if (CanViewLogs() == false)
|
||||
if (CanViewLogs(logTimePeriod) == false)
|
||||
{
|
||||
throw new HttpResponseException(Request.CreateNotificationValidationErrorResponse("Unable to view logs, due to size"));
|
||||
}
|
||||
|
||||
var direction = orderDirection == "Descending" ? Direction.Descending : Direction.Ascending;
|
||||
return _logViewer.GetLogs(startDate: DateTime.Now.AddDays(-1), endDate: DateTime.Now, filterExpression: filterExpression, pageNumber: pageNumber, orderDirection: direction, logLevels: logLevels);
|
||||
|
||||
|
||||
|
||||
return _logViewer.GetLogs(logTimePeriod, filterExpression: filterExpression, pageNumber: pageNumber, orderDirection: direction, logLevels: logLevels);
|
||||
}
|
||||
|
||||
private static LogTimePeriod GetTimePeriod(DateTime? startDate, DateTime? endDate)
|
||||
{
|
||||
if (startDate == null || endDate == null)
|
||||
{
|
||||
var now = DateTime.Now;
|
||||
if (startDate == null)
|
||||
{
|
||||
startDate = now.AddDays(-1);
|
||||
}
|
||||
|
||||
if (endDate == null)
|
||||
{
|
||||
endDate = now;
|
||||
}
|
||||
}
|
||||
|
||||
return new LogTimePeriod(startDate.Value, endDate.Value);
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
|
||||
Reference in New Issue
Block a user