diff --git a/src/Umbraco.Core/Logging/Viewer/ILogViewer.cs b/src/Umbraco.Core/Logging/Viewer/ILogViewer.cs index 080a9285f2..1b7016307d 100644 --- a/src/Umbraco.Core/Logging/Viewer/ILogViewer.cs +++ b/src/Umbraco.Core/Logging/Viewer/ILogViewer.cs @@ -1,5 +1,4 @@ using System.Collections.Generic; -using Serilog.Events; namespace Umbraco.Core.Logging.Viewer { @@ -17,14 +16,14 @@ namespace Umbraco.Core.Logging.Viewer LogLevelCounts GetLogLevelCounts(); /// - /// Returns the top 5 common log message templates and their counts + /// Returns the top common log message templates and their counts /// - IEnumerable GetCommonLogMessages(); + IEnumerable GetCommonLogMessages(int numberOfResults = 10); /// /// Returns the collection of logs /// - IEnumerable GetLogs(); + IEnumerable GetLogs(); } } diff --git a/src/Umbraco.Core/Logging/Viewer/LogViewer.cs b/src/Umbraco.Core/Logging/Viewer/JsonLogViewer.cs similarity index 55% rename from src/Umbraco.Core/Logging/Viewer/LogViewer.cs rename to src/Umbraco.Core/Logging/Viewer/JsonLogViewer.cs index c72798f3dd..b7d13777c8 100644 --- a/src/Umbraco.Core/Logging/Viewer/LogViewer.cs +++ b/src/Umbraco.Core/Logging/Viewer/JsonLogViewer.cs @@ -7,13 +7,13 @@ using Serilog.Formatting.Compact.Reader; namespace Umbraco.Core.Logging.Viewer { - public class LogViewer : ILogViewer + public class JsonLogViewer : ILogViewer { - private List _logs; + private List _logs = new List(); - public LogViewer() + public JsonLogViewer() { - var filePath = $@"{AppDomain.CurrentDomain.BaseDirectory}\App_Data\Logs\UmbracoTraceLog.DELLBOOK.20180824.json"; + var filePath = $@"{AppDomain.CurrentDomain.BaseDirectory}\App_Data\Logs\UmbracoTraceLog.DELLBOOK.20180828.json"; //Open log file using (var fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) @@ -48,16 +48,37 @@ namespace Umbraco.Core.Logging.Viewer }; } - public IEnumerable GetCommonLogMessages() + public IEnumerable GetCommonLogMessages(int numberOfResults) { - var messages = new List(); - return messages; + var templates = _logs.GroupBy(x => x.MessageTemplate.Text) + .Select(g => new CommonLogMessage { MessageTemplate = g.Key, Count = g.Count() }) + .OrderByDescending(x => x.Count) + .Take(numberOfResults); + return templates; } - public IEnumerable GetLogs() + public IEnumerable GetLogs() { - throw new NotImplementedException(); + var messages = new List(); + var logs = _logs.Take(20); + + foreach(var log in logs) + { + var logItem = new LogMessage + { + Level = log.Level, + Properties = log.Properties, + Timestamp = log.Timestamp, + MessageTemplateText = log.MessageTemplate.Text, //Not necesarily worried about token position just the message text itself + RenderedMessage = log.RenderMessage(), //Not returning LogEvent itself from Serilog (as we don't get the rendered txt log back) + Exception = log.Exception + }; + + messages.Add(logItem); + } + + return messages; } } } diff --git a/src/Umbraco.Core/Logging/Viewer/LogMessage.cs b/src/Umbraco.Core/Logging/Viewer/LogMessage.cs new file mode 100644 index 0000000000..86d136be43 --- /dev/null +++ b/src/Umbraco.Core/Logging/Viewer/LogMessage.cs @@ -0,0 +1,42 @@ +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; +using Serilog.Events; +using System; +using System.Collections.Generic; + +namespace Umbraco.Core.Logging.Viewer +{ + public class LogMessage + { + /// + /// The time at which the logevent occurred. + /// + public DateTimeOffset Timestamp { get; set; } + + /// + /// The level of the event. + /// + [JsonConverter(typeof(StringEnumConverter))] + public LogEventLevel Level { get; set; } + + /// + /// The message template describing the logevent. + /// + public string MessageTemplateText { get; set; } + + /// + /// The message template filled with the logevent properties. + /// + public string RenderedMessage { get; set; } + + /// + /// Properties associated with the logevent, including those presented in Serilog.Events.LogEvent.MessageTemplate. + /// + public IReadOnlyDictionary Properties { get; set; } + + /// + /// An exception associated with the logevent, or null. + /// + public Exception Exception { get; set; } + } +} diff --git a/src/Umbraco.Core/Logging/Viewer/LogViewerComponent.cs b/src/Umbraco.Core/Logging/Viewer/LogViewerComponent.cs new file mode 100644 index 0000000000..5c22ae9282 --- /dev/null +++ b/src/Umbraco.Core/Logging/Viewer/LogViewerComponent.cs @@ -0,0 +1,14 @@ +using Umbraco.Core.Components; +using Umbraco.Core.Composing; + +namespace Umbraco.Core.Logging.Viewer +{ + [RuntimeLevel(MinLevel = RuntimeLevel.Run)] + public class LogViewerComponent : UmbracoComponentBase, IUmbracoCoreComponent + { + public override void Compose(Composition composition) + { + composition.Container.RegisterSingleton(); + } + } +} diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index 9ffb0161d9..42b893aea2 100644 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -337,7 +337,9 @@ - + + + diff --git a/src/Umbraco.Web/Editors/LogsController.cs b/src/Umbraco.Web/Editors/LogsController.cs index 96add77d66..a649dffde0 100644 --- a/src/Umbraco.Web/Editors/LogsController.cs +++ b/src/Umbraco.Web/Editors/LogsController.cs @@ -1,20 +1,21 @@ -using System.Web.Mvc; +using System.Collections.Generic; +using System.Web.Mvc; using Umbraco.Core.Logging.Viewer; using Umbraco.Web.Mvc; namespace Umbraco.Web.Editors { /// - /// Backoffice controller supporting the dashboard for language administration. + /// Backoffice controller supporting the dashboard for viewing logs with some simple graphs & filtering /// [PluginController("UmbracoApi")] public class LogsController : UmbracoAuthorizedJsonController { - private LogViewer _logViewer; + private ILogViewer _logViewer; - public LogsController() + public LogsController(ILogViewer logViewer) { - _logViewer = new LogViewer(); + _logViewer = logViewer; } [HttpGet] @@ -22,11 +23,24 @@ namespace Umbraco.Web.Editors { return _logViewer.GetNumberOfErrors(); } - + [HttpGet] public LogLevelCounts GetLogLevelCounts() { return _logViewer.GetLogLevelCounts(); } + + [HttpGet] + public IEnumerable GetCommonLogMessages() + { + return _logViewer.GetCommonLogMessages(); + } + + [HttpGet] + public IEnumerable GetLogs() + { + return _logViewer.GetLogs(); + } + } }