Click here to Skip to main content
15,885,852 members
Articles / Web Development / ASP.NET

Log Reporting Dashboard for ASP.NET MVC

Rate me:
Please Sign up or sign in to vote.
4.94/5 (60 votes)
23 Aug 2010CPOL12 min read 174.4K   5.6K   193  
Log reporting dashboard for Log4Net, NLog, ELMAH, and ASP.NET Health Monitoring.
using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel.Syndication;
using System.Web;
using System.Web.Mvc;

using MvcLoggingDemo.Helpers;
using MvcLoggingDemo.Models.Repository;
using MvcLoggingDemo.Models;
using MvcLoggingDemo.ViewModels;

using MvcLoggingDemo.Models.Google.Visualization;
using MvcLoggingDemo.Services.Paging;
using MvcLoggingDemo.Services.RSS;

namespace MySampleApp.Controllers
{
    [Authorize]
    public class LoggingController : Controller
    {
        private readonly ILogReportingFacade loggingRepository;

        public LoggingController()
        {
            loggingRepository = new LogReportingFacade();
        }

        public LoggingController(ILogReportingFacade repository)
        {
            loggingRepository = repository;
        }

        /// <summary>
        /// Returns the Index view
        /// </summary>
        /// <param name="Period">Text representation of the date time period. eg: Today, Yesterday, Last Week etc.</param>
        /// <param name="LoggerProviderName">Elmah, Log4Net, NLog, Health Monitoring etc</param>
        /// <param name="LogLevel">Debug, Info, Warning, Error, Fatal</param>
        /// <param name="page">The current page index (0 based)</param>
        /// <param name="PageSize">The number of records per page</param>
        /// <returns></returns>
        public ActionResult Index(string Period, string LoggerProviderName, string LogLevel, int? page, int? PageSize)
        {            
            // Set up our default values
            string defaultPeriod = Session["Period"] == null ? "Today" : Session["Period"].ToString();
            string defaultLogType = Session["LoggerProviderName"] == null ? "All" : Session["LoggerProviderName"].ToString();
            string defaultLogLevel = Session["LogLevel"] == null ? "Error" : Session["LogLevel"].ToString();

            // Set up our view model
            LoggingIndexModel model = new LoggingIndexModel();

            model.Period = (Period == null) ? defaultPeriod : Period;
            model.LoggerProviderName = (LoggerProviderName == null) ? defaultLogType : LoggerProviderName;
            model.LogLevel = (LogLevel == null) ? defaultLogLevel : LogLevel;
            model.CurrentPageIndex = page.HasValue ? page.Value - 1 : 0;
            model.PageSize = PageSize.HasValue ? PageSize.Value : 20;

            TimePeriod timePeriod = TimePeriodHelper.GetUtcTimePeriod(model.Period);            

            // Grab the data from the database
            model.LogEvents = loggingRepository.GetByDateRangeAndType(model.CurrentPageIndex, model.PageSize, timePeriod.Start, timePeriod.End, model.LoggerProviderName, model.LogLevel);

            // Put this into the ViewModel so our Pager can get at these values
            ViewData["Period"] = model.Period;
            ViewData["LoggerProviderName"] = model.LoggerProviderName;
            ViewData["LogLevel"] = model.LogLevel;
            ViewData["PageSize"] = model.PageSize;

            // Put the info into the Session so that when we browse away from the page and come back that the last settings are rememberd and used.
            Session["Period"] = model.Period;
            Session["LoggerProviderName"] = model.LoggerProviderName;
            Session["LogLevel"] = model.LogLevel;

            return View(model);
        }

        //
        // GET: /Logging/Details/5

        public ActionResult Details(string loggerProviderName, string id)
        {
            LogEvent logEvent = loggingRepository.GetById(loggerProviderName, id);

            return View(logEvent);
        }   

        // string Period, string LoggerProviderName, string LogLevel, int? page, int? PageSize
        public ActionResult Search()
        {
            return View();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="Period"></param>
        /// <param name="LoggerProviderName"></param>
        /// <param name="LogLevel"></param>
        /// <returns></returns>
        public JsonResult ChartData(string Period, string LoggerProviderName, string LogLevel)
        {                        
            if (Period == "Today" || Period == "Yesterday")
            {
                return ChartDataByHour(Period, LoggerProviderName, LogLevel);
            }
            else
            {
                return ChartDataByDay(Period, LoggerProviderName, LogLevel);
            }
        }        

        /// <summary>
        /// 
        /// </summary>
        /// <param name="Period"></param>
        /// <param name="LoggerProviderName"></param>
        /// <param name="logLevel"></param>
        /// <returns></returns>
        public JsonResult ChartDataByHour(string Period, string LoggerProviderName, string logLevel)
        {
            Func<LogEvent, Object> groupByClause = c => c.LogDate.ToLocalTime().Hour;

            return ChartDataByTimePeriod(Period, LoggerProviderName, logLevel, "", groupByClause);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="Period"></param>
        /// <param name="LoggerProviderName"></param>
        /// <param name="logLevel"></param>
        /// <returns></returns>
        public JsonResult ChartDataByDay(string Period, string LoggerProviderName, string logLevel)
        {
            Func<LogEvent, Object> groupByClause = c => c.LogDate.ToLocalTime().Date;

            return ChartDataByTimePeriod(Period, LoggerProviderName, logLevel, "dd/MM/yyyy", groupByClause);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="Period"></param>
        /// <param name="LoggerProviderName"></param>
        /// <param name="logLevel"></param>
        /// <param name="keyFormatString"></param>
        /// <param name="groupByClause"></param>
        /// <returns></returns>
        public JsonResult ChartDataByTimePeriod(string Period, string LoggerProviderName, string logLevel, string keyFormatString, Func<LogEvent, Object> groupByClause)
        {
            TimePeriod timePeriod = TimePeriodHelper.GetUtcTimePeriod(Period);

            // Grab ALL entries for the chart (DO NOT PAGE REPORTING DATA!!!)
            IPagedList<LogEvent> chartEntries = loggingRepository.GetByDateRangeAndType(0, Int32.MaxValue, timePeriod.Start, timePeriod.End, LoggerProviderName, logLevel);

            var groupedByDate = chartEntries.GroupBy(groupByClause).OrderBy(y => y.Key);

            var groupedByDateAndThenName = groupedByDate.Select(group => new { Key = group.Key, NestedGroup = group.ToLookup(result => result.LoggerProviderName, result => result.Id) });

            var LoggerNames = (from logEvent in chartEntries
                               select new { Name = logEvent.LoggerProviderName }
                               ).Distinct().OrderBy(item => item.Name);

            ChartData chartData = new ChartData();

            // Add columns
            chartData.AddColumn(new ChartColumn("0", "Period", "string"));
            int columnIndex = 1;
            foreach (var name in LoggerNames)
            {
                chartData.AddColumn(new ChartColumn(columnIndex.ToString(), name.Name.ToString(), "number"));
                columnIndex++;
            }

            // add row data
            foreach (var myDate in groupedByDateAndThenName)
            {
                ChartRow row = new ChartRow();

                string dateString = (myDate.Key is DateTime) ? ((DateTime)myDate.Key).ToString(keyFormatString) : myDate.Key.ToString();
                row.AddCellItem(new ChartCellItem(dateString, ""));

                foreach (var name in LoggerNames)
                {
                    bool valueFound = false;
                    foreach (var myLogger in myDate.NestedGroup)
                    {
                        if (myLogger.Key == name.Name.ToString())
                        {
                            row.AddCellItem(new ChartCellItem(myLogger.Count(), ""));
                            valueFound = true;
                        }
                    }
                    if (!valueFound) row.AddCellItem(new ChartCellItem(0, ""));
                }

                chartData.AddRow(row);
            }

            return Json(chartData, "text/x-json", System.Text.Encoding.UTF8, JsonRequestBehavior.AllowGet);
        }

        /// <summary>
        /// Gets the chart
        /// </summary>
        /// <param name="Period"></param>
        /// <param name="LoggerProviderName"></param>
        /// <param name="LogLevel"></param>
        /// <returns></returns>
        public ActionResult Chart(string Period, string LoggerProviderName, string LogLevel)
        {            
            string defaultPeriod = Session["Period"] == null ? "Today" : Session["Period"].ToString();
            string defaultLoggerProviderName = Session["LoggerProviderName"] == null ? "All" : Session["LoggerProviderName"].ToString();
            string defaultLogLevel = Session["LogLevel"] == null ? "Error" : Session["LogLevel"].ToString();

            LoggingIndexModel model = new LoggingIndexModel();

            model.Period = (Period == null) ? defaultPeriod : Period;
            model.LoggerProviderName = (LoggerProviderName == null) ? defaultLoggerProviderName : LoggerProviderName;
            model.LogLevel = (LogLevel == null) ? defaultLogLevel : LogLevel;

            return View(model);
        }       

        //
        // GET: /Logging/Manage
 
        public ActionResult Manage()
        {
            LoggingManageModel model = new LoggingManageModel();

            return View(model);
        }

        //
        // POST: /Logging/Manage/

        [HttpPost]
        public ActionResult Manage(LoggingManageModel model)
        {
            try
            {
                string[] logLevels = new string[] { "Warn" };
                loggingRepository.ClearLog(model.LogSourceName, model.StartDate, model.EndDate, logLevels);

                ViewData["Message"] = "The log has been cleared";

                return View(model);
            }
            catch
            {
                return View();
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="Period"></param>
        /// <param name="LoggerProviderName"></param>
        /// <param name="LogLevel"></param>
        /// <returns></returns>
        public FeedResult RssFeed(string Period, string LoggerProviderName, string LogLevel)
        {
            string defaultPeriod = Session["Period"] == null ? "This Week" : Session["Period"].ToString();
            string defaultLoggerProviderName = Session["LoggerProviderName"] == null ? "All" : Session["LoggerProviderName"].ToString();
            string defaultLogLevel = Session["LogLevel"] == null ? "Error" : Session["LogLevel"].ToString();

            Period = (Period == null) ? defaultPeriod : Period;
            LoggerProviderName = (LoggerProviderName == null) ? defaultLoggerProviderName : LoggerProviderName;
            LogLevel = (LogLevel == null) ? defaultLogLevel : LogLevel;

            TimePeriod timePeriod = TimePeriodHelper.GetUtcTimePeriod(Period);

            // Grab ALL entries for the feed (DO NOT PAGE feed DATA!!!)
            IPagedList<LogEvent> chartEntries = loggingRepository.GetByDateRangeAndType(0, Int32.MaxValue, timePeriod.Start, timePeriod.End, LoggerProviderName, LogLevel);

            var postItems = chartEntries.Select(p => new SyndicationItem(string.Format("{0} - {1} - {2}", p.LogDate, p.Level, p.LoggerProviderName), p.Message, new Uri(Url.AbsoluteAction("Details", new { LoggerProviderName = p.LoggerProviderName, Id = p.Id }))));

            Uri feedAlternateLink = Url.ActionFull("Index", "Logging");

            var feed = new SyndicationFeed("MVC Logging Demo -> Log Reporting", string.Format("Log Provider: {0}, Log Level : {1}, From {2} to {3} ({4})", LoggerProviderName, LogLevel, timePeriod.Start.ToShortDateString(), timePeriod.End.ToShortDateString(), Period), feedAlternateLink, postItems)
            {                
                Language = "en-US"
            };

            return new FeedResult(new Rss20FeedFormatter(feed));
        }
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior) Simbient
Australia Australia
Darren Weir is a senior .NET developer working for Simbient in North Sydney, Australia.

My blog is located at dotnetdarren.wordpress.com

Comments and Discussions