Unity應用架構設計(13)——日誌組件的實施

来源:http://www.cnblogs.com/OceanEyes/archive/2017/07/05/log_strategy.html
-Advertisement-
Play Games

對於應用程式而言,日誌是非常重要的功能,通過日誌,我們可以跟蹤應用程式的數據狀態,記錄Crash的日誌可以幫助我們分析應用程式崩潰的原因,我們甚至可以通過日誌來進行性能的監控。總之,日誌的好處很多,特別是對Release之後的線上版本進行異常的跟蹤。 日誌存儲的分類 在平常開發時,我們通常喜歡在De ...


對於應用程式而言,日誌是非常重要的功能,通過日誌,我們可以跟蹤應用程式的數據狀態,記錄Crash的日誌可以幫助我們分析應用程式崩潰的原因,我們甚至可以通過日誌來進行性能的監控。總之,日誌的好處很多,特別是對Release之後的線上版本進行異常的跟蹤。

日誌存儲的分類

在平常開發時,我們通常喜歡在Debug模式下進行調試,通過斷點,可以跟蹤數據的變化。除了調試,另一種直觀的方式是使用控制台輸出,比如Java的system.out.println(),.NET的Console.WriteLine(),Swift的print()等等。在Untiy中,為我們提供了Debug.Log()方式來記錄。

而對於線上的版本,上述兩種調試都不行,那我們怎麼來跟蹤數據呢?

從日誌的存儲分類上來看,可以分為四類:控制台,文件系統,資料庫,第三方平臺

  • 控制台:本地開發時使用,記錄數據和跟蹤執行過程,方便直觀
  • 文件系統:可以是一些用戶行為性的日誌,這些文件可以被用來監控執行時間,進行性能的分析,如果用戶同意,則將這些日誌傳到伺服器上
  • 資料庫:記錄了一些異常日誌,也就是Catch了之後的行為,每次用戶登錄時,傳到伺服器,幫助分析原因
  • 第三方平臺:比如友盟等,當應用閃退時,Crash原因會記錄在友盟中,可以通過DashBoard查看

日誌組件的設計

為了可以更加靈活的跟蹤線上的變化,可以使用第三方的Analysis,也可以自建日誌組件。我偏向於混合使用,所以接下來,談談一個日誌組件的基本設計理念,如下圖所示:

從上圖可以看出,整個入口由工廠LogFactory來創建LogStrategy子類實例,LogStrategy是個抽象的模板類,定義了公共的處理方法,但並不知道怎樣寫日誌(比如是寫入到資料庫呢還是到文件),寫日誌的行為交給子類去完成。

日誌組件的實施

有了日誌組件的設計圖,接下來就是將理念落實到行動,讓我們來實現它吧!

LogFactory是一個簡單工廠,封裝創建LogStrategy對象的代碼。

public class LogFactory
{
    public static LogFactory Instance=new LogFactory();
    private LogFactory(){}
    private readonly Dictionary<string,LogStrategy> _strategies=new Dictionary<string, LogStrategy>()
    {
        {typeof(ConsoleLogStrategy).Name,new ConsoleLogStrategy() },
        {typeof(FileLogStrategy).Name,new FileLogStrategy() },
        {typeof(DatabaseLogStrategy).Name,new DatabaseLogStrategy() }
    }; 
    public LogStrategy Resolve<T>() where T:LogStrategy
    {
        return _strategies[typeof(T).Name];
    }
}
    

LogFactory內部定義了一個字典,Key為LogStrategy子類的類名,Value為具體的LogStrategy對象。通過一個公共介面Resolve<T>來獲取相關對象。

使用字典比switch..case更直觀,也更加容易擴展其他選項。更重要的是,不會對公共介面Resolve<T>進行修改。

LogStrategy是一個抽象類,即模板類。

它定義了一個公共的API,即Log。在方法Log中,定義了一些對內容的公共操作,因為對於日誌來說,不管是記錄在資料庫還是文件系統,都將對內容拼接上設備類型、設備名稱、操作系統、創建時間等基本信息。

同時還定義了一個抽象方法RecordMessage,對於需要寫入的類型(文件系統Or資料庫Or控制台)延遲到子類決定。

public abstract class LogStrategy
{
    private readonly StringBuilder _messageBuilder=new StringBuilder();
    protected IContentWriter Writer { get; set; }

    /// <summary>
    ///     模板方法
    /// </summary>
    protected abstract void RecordMessage(string message);

    protected abstract void SetContentWriter();

    /// <summary>
    ///     公共的API
    /// </summary>
    public void Log(string message,bool verbose=false)
    {
        if (verbose)
        {
            //公共方法
            RecordDateTime();
            RecordDeviceModel();
            RecordDeviceName();
            RecordOperatingSystem();
        }
        //抽象方法,交由子類實現
        RecordMessage(_messageBuilder.AppendLine(string.Format("Message:{0}", message)).ToString());
    }

    private void RecordDateTime()
    {
        _messageBuilder.AppendLine(string.Format("DateTime:{0}", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")));
    }

    private void RecordDeviceModel()
    {
        _messageBuilder.AppendLine(string.Format("Device Model:{0}",SystemInfo.deviceModel));
    }

    private void RecordDeviceName()
    {
        _messageBuilder.AppendLine(string.Format("Device Name:{0}", SystemInfo.deviceName));
    }

    private void RecordOperatingSystem()
    {
        _messageBuilder
            .AppendLine(string.Format("Operating System:{0}", SystemInfo.operatingSystem))
            .AppendLine();
    }

模板方法模式:在一個方法中定義演算法的骨架,而將一些步驟延遲到子類。模板方法使得子類可以在不改變演算法的結構下,重新定義演算法中的某些步驟。

當在控制台Debug時,我們其實不需要設備類型,設備名稱等信息,故公共介面Log提供了一個開關verbose來開啟是否需要詳細信息,預設為false,即關閉狀態。

繼承LogStrategy,創建自定義的日誌策略

比如實現FileLogStrategy,除了override了 RecordMessage方法之外,還需要提供一個實現了IContentWriter介面的類,你可以直接在RecordMessage方法中寫入日誌,但可能有一些公共的操作,比如在非同步線程,批量將10條數據寫到文件或者資料庫中,所以提供一個IContentWriter更加容易擴展。

public class FileLogStrategy:LogStrategy
{
    public FileLogStrategy()
    {
        SetContentWriter();
    }
    protected sealed override void SetContentWriter()
    {
        Writer = new FileContentWriter(); 
    }
    protected override void RecordMessage(string message)
    {
        Writer.Write(message);
    }

}

創建一個BaseContentWriter,提供了公共的寫入方法,比如為了提高性能,文件的IO並不是馬上寫入文件,而是批量Flush。同樣資料庫記錄日誌也是一樣,像Unit Of Work那樣,批量向資料庫寫入數據,提高它的吞吐率。

根據需求使用不同的日誌類

LogFactory.Instance.Resolve<FileLogStrategy>().Log("Welcome");

小結

不同於伺服器端的日誌組件,比如Log4J,只需要將日誌寫在本地文件系統中,客戶端的日誌相對來說複雜點,因為記錄的日誌是發生在用戶的客戶端,所以你必須要想辦法把日誌傳到伺服器,比如一些Crash的異常。既然要把日誌發回來,在應用閃退時,必須能夠持久化到本地,故我們會將日誌寫到文件系統或者資料庫,然後在合適的時候將日誌發送到伺服器進行分析。當然,你也可以使用第三方的服務,比如友盟或者 Unity Analytics 來分析數據。
源代碼托管在Github上,點擊此瞭解


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • Python中字典和集合 映射類型: 表示一個任意對象的集合,且可以通過另一個幾乎是任意鍵值的集合進行索引 與序列不同,映射是無序的,通過鍵進行索引 任何不可變對象都可用作字典的鍵,如字元串、數字、元組等 包含可變對象的列表、字典和元組不能用作鍵 引用不存在的鍵會引發KeyError異常 1)字典 ...
  • 通過添加powershell插件後,使用它強大的windows系統命令,就把發佈好的程式包推送到具體的應用伺服器了。 系統管理-插件管理-powershell 把它安裝,重啟jenkins,然後修改你之前的job,把powershell的推送文件腳本加上 添加一個構建類型,在msbuild下麵添加 ...
  • Jenkins是一個持續集成的環境,它是java開發的,大叔認為它的工作流程是 從源代碼拉一個項目下來到它本地(可以配置定時機制) 恢復相關程式包nuget 編譯程式 發佈程式 現在說一下在配置jenkins里要註意的幾個地方: jenkins的構建工作目錄和job目錄說明 構建目錄:C:\Prog ...
  • 本章內容還在整理上傳中,你可以等全部更新完畢後再查閱也可以先預覽已上傳的內容。。。。。。 7. 應用層的命令模式 在上個章節里我們設計並編碼了領域對象Permission,但是目前Permission並沒有任何行為上的設計。這是因為我們不建議“憑空去製造行為”,而是在領域對象第一個版本的代碼實現之後 ...
  • "DDD理論學習系列——案例及目錄" 1. 引言 A domain event is a full fledged part of the domain model, a representation of something that happened in the domain. Ignore ...
  • 設計模式分類 設計模式是一套被反覆使用、多數人知曉的、經過分類編目的、代碼設計經驗的總結。使用設計模式是為了可重用代碼、讓代碼更容易被他人理解、保證代碼可靠性。主流的設計模式有23種,總體來說可以分為三大類 創建型模式(5) 工廠方法模式(Factory Pattern) 一種場景是希望工廠與產品的 ...
  • 通過使用ps加上msbuild可以方便的編譯你的.net應用程式,並且可以把它發佈到你的磁碟上,部署非常方例! 我們在c盤添加一個hello網站,解決方案名是hello.sln,它的網站是hello.csproj,現在使用這個腳本來生成這個網站和發佈這個網站! 最後生成的網站結果為 這個功能對於自動 ...
  • 靜態頁面:純html頁面 動態頁面:內容存在資料庫中,根據要求顯示,url中以? &顯示不同的參數 偽靜態:僅僅是對靜態頁面的重寫,不能讓動態頁面靜態化。搜索引擎不會認為偽靜態就是HTML文檔。其次,偽靜態可取,但應把重心放在去除冗餘參數、規範URL、儘可能的避免 重覆頁上。 舉例說明: 這是一個動 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...