標籤:
摘要
昨天吃飯的時候,突然想起來一個好玩的事,如果能有個頁面可以即時的監控網站或者其他類型的程式的日誌,其實也不錯。當然,網上也有很多成熟的類似的監控系統。就想著如果通過.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
[Asp.net]SignalR實現即時日誌監控