[Asp.net]SignalR實現實時日志監控


摘要

昨天吃飯的時候,突然想起來一個好玩的事,如果能有個頁面可以實時的監控網站或者其他類型的程序的日志,其實也不錯。當然,網上也有很多成熟的類似的監控系統。就想着如果通過.net該如何實現?所以就在想,通過系統內部將消息推送到前端,.net中可以通過pull或者push的方式,pull通常的做法就是ajax方式不停的請求一個接口,這種方式,不太理想。然后就在想如何通過服務端想客戶端推送消息。之前看到過SignalR方面的文章可以實現push的功能,signalr也是第一次接觸,在這個網站http://www.asp.net/signalr看了一些文章。就自己動手做了這樣的日志監控的demo。

一個簡單的例子

先上一段代碼,如下:

該類是一個監控日志文件是否變化的一個單例類。其中維護一個日志隊列。

    public class FileSystemWatcherSingle
    {
        public FileSystemWatcher wather;
        private static FileSystemWatcherSingle _instance;
        private static readonly object _objLock = new object();
        public Queue<Log> MyQueue;
        private string _watherFolderPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Log");
        private FileSystemWatcherSingle()
        {
            if (MyQueue == null)
            {
                MyQueue = new Queue<Log>();
            }
            if (wather == null)
            {
                wather = new FileSystemWatcher();
                if (!Directory.Exists(_watherFolderPath))
                {
                    Directory.CreateDirectory(_watherFolderPath);
                }
                wather.Path = _watherFolderPath;
                wather.EnableRaisingEvents = true;
            }
        }

        public static FileSystemWatcherSingle CreateInstance()
        {
            if (_instance == null)
            {
                lock (_objLock)
                {
                    if (_instance == null)
                    {
                        _instance = new FileSystemWatcherSingle();
                    }
                }
            }
            return _instance;
        }
    }

寫日志的操作

在寫入文件之前,將當前的日志加入到日志隊列里面。

using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Web;

namespace Wolfy.LogMonitor.Models
{
    public class LogHelper
    {
        public static void WriteLog(Log log)
        {
            string dir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Log");
            if (!Directory.Exists(dir))
            {
                Directory.CreateDirectory(dir);
            }
            string _watherFilePath = Path.Combine(dir, DateTime.Now.ToString("yyyy-MM-dd") + ".log");
            if (!File.Exists(_watherFilePath))
            {
                File.Create(_watherFilePath);
            }
            FileSystemWatcherSingle wather = FileSystemWatcherSingle.CreateInstance();
            wather.MyQueue.Enqueue(log);
            File.AppendAllText(_watherFilePath, string.Format("{0} {1}\r\n{2}", log.Type.ToString(), log.Dt, log.Content));            
        }
    }
}

LogHub類

需要安裝SignalR,在安裝完成時,有個Readme文件,根據里面的提示,需要添加StartUp類,添加對應的owin程序集。

using Microsoft.Owin;
using Owin;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Wolfy.LogMonitor.App_Start;
[assembly: OwinStartup(typeof(Startup))]
namespace Wolfy.LogMonitor.App_Start
{
    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            app.MapSignalR();
        }
    }
}

LogHub繼承Hub類,並在這里想所有客戶端推送消息。並在這里面面為文件監控類FileSystemWatcher注冊創建和Change事件。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Microsoft.AspNet.SignalR;
using Microsoft.AspNet.SignalR.Hubs;
using System.Timers;
using Newtonsoft.Json;

namespace Wolfy.LogMonitor.Models
{
    [HubName("logHub")]
    public class LogHub : Hub
    {
        private FileSystemWatcherSingle fileWather;
        public void Send(string name, string message)
        {
            // Call the addNewMessageToPage method to update clients.
            Clients.All.addNewMessageToPage(name, message);
        }

        public LogHub()
        {
            fileWather = FileSystemWatcherSingle.CreateInstance();
            fileWather.wather.Changed += wather_Changed;
            fileWather.wather.Created += wather_Created;
        }

        void wather_Created(object sender, System.IO.FileSystemEventArgs e)
        {
            this.Send("system", "創建文件:" + e.Name);
        }

        void wather_Changed(object sender, System.IO.FileSystemEventArgs e)
        {
            while (fileWather.MyQueue != null && fileWather.MyQueue.Count > 0)
            {
                Log log = fileWather.MyQueue.Dequeue();
                if (log != null)
                {
                    this.Send(log.Type.ToString(), JsonConvert.SerializeObject(log));
                }
            }
        }
    }
}

前端

home:log展示的頁面。根據日志類型為該條日志顯示不同的顏色。

@{
    ViewBag.Title = "Home";
}

<div id="container">
</div>

<script>
    $(function () {
        // Reference the auto-generated proxy for the hub.
        var log = $.connection.logHub;
        console.log(log);
        // Create a function that the hub can call back to display messages.
        log.client.addNewMessageToPage = function (name, message) {
            console.log(name);
            console.log(message);
            // Add the message to the page.
            if (name === "Info") {                
                $('#container').append('<p style="color:green;">' + message + '</p>');
            } else {
                $('#container').append('<p style="color:red;">' + message + '</p>');
            }
        };
        // Start the connection.
        $.connection.hub.start().done();
    });

</script>

LogController

Test頁面是一個測試頁面,通過不停的刷新寫入隨機類型的日志。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Wolfy.LogMonitor.Models;

namespace Wolfy.LogMonitor.Controllers
{
    public class LogController : Controller
    {
        // GET: Log
        public ActionResult Home()
        {
            return View();
        }
        public ActionResult Test()
        {
            LogType[] logtypes = { LogType.Info, LogType.Error };
            Random r = new Random();
            int index = r.Next(0, 2);
            LogHelper.WriteLog(new Log { Content = "這是一次日志", Dt = DateTime.Now, Type = logtypes[index] });
            return View();
        }
    }
}

好了,到現在基本上大功告成。測試一下。

通過不停的刷新test頁面,你會發現home頁面上會相應的動態展示這次操作的日志。

總結

昨天突然有這個想法,今天就折騰了一上午,將這個想法用代碼實現了一下。這里沒有signalr的相關介紹,感興趣的話,可以看下面的參考資料中的內容。

參考資料

http://www.asp.net/signalr


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM