Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 久久国产精品久久久,久久精品国产精品亚洲红杏,亚洲国产网站

          整合營銷服務商

          電腦端+手機端+微信端=數(shù)據(jù)同步管理

          免費咨詢熱線:

          C#中編寫系統(tǒng)操作日志的實踐

          C#中編寫系統(tǒng)操作日志的實踐

          統(tǒng)操作日志在軟件開發(fā)和運維過程中起著至關重要的作用。通過記錄系統(tǒng)在運行時的關鍵操作和事件,操作日志能幫助開發(fā)者監(jiān)控系統(tǒng)狀態(tài)、診斷問題、追蹤錯誤,并為系統(tǒng)的安全性和穩(wěn)定性提供保障。在C#中,我們可以利用多種方法來編寫系統(tǒng)操作日志,本文將詳細介紹這一過程,并提供實用的示例代碼。

          一、系統(tǒng)操作日志的重要性

          系統(tǒng)操作日志記錄了軟件或系統(tǒng)在運行時的各種活動,包括但不限于用戶登錄、數(shù)據(jù)修改、異常發(fā)生等關鍵事件。這些日志對于后續(xù)的故障排查、系統(tǒng)優(yōu)化、安全審計等方面都具有極高的價值。通過查看和分析日志,開發(fā)人員可以快速定位并解決問題,從而提高系統(tǒng)的可靠性和性能。

          二、在C#中編寫系統(tǒng)操作日志

          在C#中,我們可以使用內置的System.Diagnostics命名空間中的TraceDebug類來記錄日志,也可以使用第三方的日志庫,如NLog、log4net等。以下是一個使用Trace類的基本示例:

          1. 引入命名空間:首先,你需要在代碼文件的頂部引入System.Diagnostics命名空間。
          using System.Diagnostics;
          1. 配置監(jiān)聽器:在應用程序的配置文件(如App.config或Web.config)中,你可以配置Trace類的監(jiān)聽器,以決定將日志信息輸出到哪里,比如文件、控制臺或Windows事件查看器等。

          2. 編寫日志:在你的代碼中,你可以使用Trace.WriteLine方法來記錄日志。

          Trace.WriteLine("This is a trace message.");
          1. 條件編譯:你還可以使用條件編譯指令來確保僅在調試期間記錄日志。
          #if DEBUG
          Trace.WriteLine("Debug message.");
          #endif
          1. 使用第三方庫:對于更復雜的日志需求,如日志級別控制、日志文件分割、異步記錄等,你可能需要使用像NLog或log4net這樣的第三方庫。這些庫提供了更豐富的功能和更靈活的配置選項。

          三、示例代碼

          以下是一個簡單的示例,展示了如何在C#中使用Trace類記錄系統(tǒng)操作日志:

          using System;
          using System.Diagnostics;

          namespace LoggingExample
          {
          class Program
          {
          static void Main(string[] args)
          {
          // 配置Trace監(jiān)聽器(通常在配置文件中完成)
          Trace.Listeners.Add(new TextWriterTraceListener("log.txt"));
          Trace.AutoFlush=true;

          // 記錄操作日志
          Trace.WriteLine("System started at " + DateTime.Now);

          // 模擬一些系統(tǒng)操作
          PerformSomeOperation();

          // 記錄操作完成日志
          Trace.WriteLine("Operation completed successfully.");
          }

          static void PerformSomeOperation()
          {
          Trace.WriteLine("Performing some operation...");
          // 執(zhí)行具體操作的代碼...
          }
          }
          }

          在這個示例中,我們創(chuàng)建了一個TextWriterTraceListener來將日志信息寫入名為"log.txt"的文件中。然后,在程序的關鍵點,我們使用Trace.WriteLine方法來記錄日志。

          四、日志編寫的最佳實踐

          1. 清晰性:確保日志信息清晰明了,能夠準確反映系統(tǒng)狀態(tài)和操作結果。
          2. 簡潔性:避免在日志中記錄過多冗余信息,保持日志的簡潔性。
          3. 可維護性:使用一致的日志格式和命名規(guī)范,便于后續(xù)日志的分析和維護。
          4. 安全性:確保日志文件的訪問權限得到適當控制,防止敏感信息泄露。
          5. 性能考慮:對于高性能要求的應用,需要選擇合適的日志級別和異步日志記錄方式,以減少對系統(tǒng)性能的影響。


          Python 項目中,使用打印語句和堆棧跟蹤很容易跟蹤代碼進度和調試。但是,日志記錄提供了使用時間戳、文件名、代碼行數(shù)等進行跟蹤和調試的附加功能,區(qū)分不同類型的打印語句,甚至可以選擇將打印語句保存到日志文件或其他位置,而不是只能在控制臺或命令行上查看。

          本文將介紹日志記錄的組件,如何在文件中執(zhí)行日志記錄,以及如何使用配置以可重用和可擴展的方式跨多個文件執(zhí)行日志記錄。

          目錄

          • 日志記錄的組件:文件、級別、格式
          • 文件中的基本日志記錄
          • 日志記錄的高級組件:記錄器、處理程序、過濾器、格式化程序
          • 帶有配置文件的高級日志記錄
          • 常見問題:日志配置覆蓋、繼承

          日志記錄的組件

          在深入研究代碼實現(xiàn)之前,一些組件對于有效使用日志記錄是不可或缺的。

          日志文件——在哪里記錄?

          建議將日志保存到日志文件中,而不是在控制臺或命令行上查看它們,因為一旦控制臺或終端關閉,信息就會消失。我們可以指定要存儲日志的項目的相對路徑。

          您還可以定義保存模式。默認情況下,日志以追加模式保存,但可以更改為寫入模式以覆蓋以前的日志。

          日志級別——何時記錄?

          根據(jù)所跟蹤事件的任務和嚴重性,有 5 種日志記錄級別。按照嚴重程度遞增的順序,

          • DEBUG:記錄詳細信息,用于診斷問題,即故障調查
          • INFO:記錄詳細信息,在程序正常運行時使用,即狀態(tài)監(jiān)控
          • WARN:記錄未來的意外事件或潛在問題,當代碼盡管發(fā)生意外事件仍能按預期工作時使用
          • ERROR:記錄嚴重問題,當代碼無法執(zhí)行某些功能時使用
          • CRITICAL:記錄嚴重錯誤,在代碼無法繼續(xù)運行時使用

          有疑問時,我總是INFO在正常操作時使用水平儀,WARN或者ERROR在遇到小問題和主要問題時使用水平儀。

          默認情況下,日志級別為WARN,表示低于該級別的日志級別,即DEBUGINFO,除非更改默認日志級別,否則不會記錄。

          日志格式——記錄什么?

          可以設置日志格式,并將此格式應用于所有日志條目——這意味著您不必手動將相同的格式標準化到每個日志調用!默認情況下,日志條目遵循格式levelname:name:message,例如,DEBUG:root:This is a log entry但可以自定義以包含更多信息,

          • asctime:日志時間,具有默認格式%Y-%m-%d %H:%M:%S,%f,但可以按照 Python 日期時間模塊格式代碼進行更改
          • levelname:日志級別,即DEBUG,,INFO
          • name:記錄器的名稱,默認為root
          • filename: 包含日志調用的文件名,即file.py
          • module:文件名的名稱部分,即file
          • funcName:包含日志調用的函數(shù)名稱,即function_name
          • lineno: 發(fā)出日志調用的文件的行號
          • message: 日志信息,如This is a log entry
          • 更多格式屬性可以在這里找到

          要指定格式,我們使用"%(component)s"約定,例如"%(levelname)s". 例如,默認格式表示為"%(levelname)s:%(name)s:%(message)s". 這將在下一節(jié)中詳細說明。

          文件中的基本日志記錄

          在了解了日志記錄組件之后,我們準備記錄一些信息!日志記錄可以這樣完成,

          import logging
          logging.basicConfig(
              filename="output.log",
              filemode="w",
              level=logging.DEBUG,
              format="%(asctime)s:%(levelname)s:%(message)s",
              datefmt="%Y-%m-%d %I:%M:%S%p",
          )
          
          logging.debug("Log with debug-level severity")
          logging.info("Log with info-level severity")
          logging.warning("Log with warning-level severity")
          logging.error("Log with error-level severity")
          logging.critical("Log with error-level severity")
          
          try:
              raise Exception("Throw exception")
          except Exception as e:
              logging.error("Exception occurred", exc_info=True)

          在上面的例子中,我們使用basicConfig來指定日志配置,

          • filename: 日志文件,項目的相對路徑
          • filemode:保存模式,"a"追加(默認),"w"寫入
          • level: 日志級別,DEBUG表示每一項與級別相同或更嚴重的項目都DEBUG將被記錄
          • format: 日志格式
          • datefmt:asctime日志格式的日期格式
          • encoding: 指定編碼,僅適用于 Python 3.9 版本

          指定配置后,我們可以在代碼中插入日志調用等logging.info()來執(zhí)行日志記錄。默認情況下,只會記錄日志消息,但我們也可以設置exc_info=True捕獲堆棧跟蹤,如第 19 行所示。

          話雖如此,使用basicConfig實現(xiàn)日志記錄需要在不同的文件中定義配置,這會導致重復的代碼。在下一節(jié)中,我們將使用配置文件以可重用和可擴展的方式實現(xiàn)日志記錄。

          日志記錄的高級組件

          對于日志的高級用法,我們可以在配置文件中定義日志配置,使其可重復用于跨多個 Python 文件進行日志記錄。如果以這種方式實現(xiàn)日志記錄,則可以完成更多項目和自定義,并且它建立在上一節(jié)中的基本組件之上。

          記錄器

          記錄器公開應用程序代碼直接使用的接口

          記錄器對應name于日志條目中的屬性。默認情況下root選擇記錄器,其設置(例如保存路徑、保存模式、格式等)由處理程序處理(下一節(jié))。

          使用模塊級記錄器是一個很好的約定,這樣模塊名稱而不是root將顯示為name日志條目的屬性。

          如果存在需要多個設置的情況,可以定義并使用自定義記錄器來代替root記錄器。

          模塊級記錄器和自定義記錄器可以這樣實現(xiàn),

          import logging
          logging.basicConfig(...)
          
          logger=logging.getLogger(__name__)
          
          logger=logging.getLogger("custom_logger")
          
          logger.info("Log with info-level severity")

          請注意,日志調用現(xiàn)在使用logger.info()而不是logging.info()!

          處理程序

          處理程序將日志記錄發(fā)送到適當?shù)哪康牡兀愃朴谌罩疚募?/span>

          處理程序指定如何保存日志。在前面的部分中,我們僅將日志保存到日志文件中,但還有更多處理日志的方法。這可以通過使用已經(jīng)為您實現(xiàn)的相關處理程序類來完成。常見的處理程序類包括,

          • StreamHandler: 將消息發(fā)送到流,即控制臺
          • FileHandler: 發(fā)送消息到磁盤文件
          • RotatingFileHandler:支持最大日志文件大小和日志文件輪換的 FileHandler
          • 可以在logging官方文檔:https://docs.python.org/3/howto/logging.html#useful-handlers,找到更多處理程序類型。

          模塊化:處理程序以模塊化方式實現(xiàn),因此可以定義處理程序名稱并在不同的記錄器(root或自定義記錄器)之間重用。

          多對一:一個記錄器可以由多個處理程序組成,例如,如果我們希望日志同時出現(xiàn)在控制臺上,StreamHandler使用FileHandler.

          過濾器

          過濾器根據(jù)嚴重性確定輸出哪些日志記錄(類似于日志級別)

          過濾器設置日志嚴重級別并記錄指定嚴重級別及以上的所有內容。過濾器與處理程序一起在字段下定義level

          如果需要更多自定義,例如僅過濾一個特定的嚴重級別,則必須編寫一個 Python 類,并且此過濾器將與處理程序一起定義,但現(xiàn)在位于 field 下filters

          模塊化:過濾器以模塊化的方式實現(xiàn),這樣過濾器名稱可以在不同的處理程序中定義和重用。

          多對一:一個處理程序可以由多個過濾器組成。

          格式化程序

          Formatters 指定日志記錄的格式(類似于日志格式)

          格式化程序設置日志條目的格式。格式化程序與處理程序一起定義,在字段下formatter

          模塊化:格式化程序以模塊化方式實現(xiàn),這樣格式化程序名稱可以在不同的處理程序中定義和重用。

          一對一:每個處理程序只能有一種日志格式。

          每個處理程序都有一個唯一的文件過濾器格式設置

          由于過濾器和格式化程序是與處理程序一起定義的,因此每個處理程序都有一個唯一的文件過濾器格式設置。如果需要另一個文件(StreamHandlerFileHandler)、過濾器(DEBUGWARN級別)或格式,則應定義單獨的處理程序。

          帶有配置文件的高級日志記錄

          我們現(xiàn)在將使用配置文件實現(xiàn)日志記錄——它比使用basicConfig. 可以在.conf文件或字典中定義配置.py.yml文件

          字典配置可以這樣定義,

          import logging.config
          
          
          class LevelOnlyFilter:
              def __init__(self, level):
                  self.level=level
          
              def filter(self, record):
                  return record.levelno==self.level
          
          
          LOGGING_CONFIG={
              "version": 1,
              "loggers": {
                  "": {  # root logger
                      "level": "DEBUG",
                      "propagate": False,
                      "handlers": ["stream_handler", "file_handler"],
                  },
                  "custom_logger": {
                      "level": "DEBUG",
                      "propagate": False,
                      "handlers": ["stream_handler"],
                  },
              },
              "handlers": {
                  "stream_handler": {
                      "class": "logging.StreamHandler",
                      "stream": "ext://sys.stdout",
                      "level": "DEBUG",
                      "filters": ["only_warning"],
                      "formatter": "default_formatter",
                  },
                  "file_handler": {
                      "class": "logging.FileHandler",
                      "filename": "output.log",
                      "mode": "w",
                      "level": "DEBUG",
                      "formatter": "default_formatter",
                  },
              },
              "filters": {
                  "only_warning": {
                      "()": LevelOnlyFilter,
                      "level": logging.WARN,
                  },
              },
              "formatters": {
                  "default_formatter": {
                      "format": "%(asctime)s-%(levelname)s-%(name)s::%(module)s|%(lineno)s:: %(message)s",
                  },
              },
          }
          
          logging.config.dictConfig(LOGGING_CONFIG)
          logger=logging.getLogger(__name__)

          我們可以觀察到字典配置被分成幾個部分

          • version(第 13 行):將版本號表示為整數(shù)
          • loggers((第 14-25 行):定義根和自定義記錄器,由一個或多個處理程序組成
          • handlers(第 26-41 行):定義記錄器中使用的自定義處理程序,包括特定的文件過濾器格式設置
          • filters(第 42-47 行):定義在處理程序中使用的自定義過濾器
          • formatters(第 48-53 行):定義在處理程序中使用的自定義格式化程序

          具有.conf文件的等效實現(xiàn)可以是這樣的,

          [loggers]
          keys=root,customLogger
          
          [handlers]
          keys=streamHandler,fileHandler
          
          [formatters]
          keys=defaultFormatter
          
          [logger_root]
          level=DEBUG
          propagate=0
          handlers=streamHandler,fileHandler
          
          [logger_customLogger]
          level=DEBUG
          propagate=0
          handlers=streamHandler
          qualname=customLogger
          
          [handler_streamHandler]
          class=StreamHandler
          args=(sys.stdout,)
          level=DEBUG
          formatter=defaultFormatter
          
          [handler_fileHandler]
          class=FileHandler
          args=("output.log", "w")
          level=DEBUG
          formatter=defaultFormatter
          
          [formatter_defaultFormatter]
          format=%(asctime)s:%(levelname)s:%(name)s:%(module)s:%(funcName)s:%(lineno)s:%(message)s

          要使用中定義的配置初始化記錄器logging.conf

          import logging.config 
          logging.config .fileConfig("logging.conf") 
          logger=logging.getLogger(__name__)

          比較dictConfigfileConfig,字典實現(xiàn)是首選,因為它更新并且能夠支持更多功能,例如使用自定義過濾器。

          比較logging.configlogging.basicConfig,使用配置文件可以減少重復代碼的數(shù)量,并將配置抽象到單獨的字典或配置文件中,這是跨多個文件執(zhí)行日志記錄的首選方式。

          常見問題

          在本節(jié)中,我將討論使用配置文件實現(xiàn)日志記錄的一些常見問題和注意事項。

          日志配置覆蓋

          有幾種方式可以發(fā)生日志配置覆蓋。

          №1:同時使用logging.basicConfiglogging.config

          如果不同的文件使用不同的方法來實例化記錄器,并且在這些文件之間進行了一些導入,使得日志配置中存在沖突,則logging.config實現(xiàn)優(yōu)先logging.basicConfig并被覆蓋。

          №2:在記錄器級別與處理程序級別定義的日志級別

          如果您在字典和logging.conf文件中注意到,日志級別被定義了兩次,一次在記錄器定義中,另一次在處理程序定義中。較高的嚴重級別優(yōu)先,其次是記錄器級別優(yōu)先于處理程序級別。

          為了使這項工作對您有利,我們可以將記錄器級別設置為最低嚴重性,DEBUG并使用處理程序級別來控制級別。如果一個級別應該跨多個處理程序標準化,請隨意在記錄器定義中定義級別。

          繼承

          在繼承期間,日志將被傳遞給記錄器及其高級(祖先)記錄器,從而導致日志條目重復。默認情況下,所有自定義記錄器都從root記錄器繼承。

          為了防止繼承導致重復日志,我們可以在配置中定義記錄器時指定propagate字段。False

          希望您對日志記錄的組件以及如何使用配置文件以可重用和可擴展的方式實現(xiàn)它有更多的了解!與普通的打印語句相比,日志記錄有助于開發(fā)人員更好地控制和理解代碼庫,并且在調試大型項目中的代碼時特別有用。

          感謝您的閱讀!如果您喜歡這篇文章,請隨時分享

          文轉載自微信公眾號“前端先鋒”(jingchengyideng)。

          每個前端都會用 JavaScript 控制臺打開日志或調試。但是 console 對象比 console.log() 有更多的東西。

          計算屬性名稱

          ES6 的計算屬性名稱特別有用,因為它們可以通過在變量周圍添加一對大括號來幫你識別的變量。

          const x=1, y=2, z=3; 
           
          console.log({x, y, z}); // {x: 1, y: 2, z: 3} 

          console.trace()

          console.trac() 與 console.log() 完全相同,但它也會輸出整個棧跟蹤,能讓你確切地知道到底發(fā)生了什么。

          const outer=()=> { 
            const inner=()=> console.trace('Hello'); 
            inner(); 
          }; 
           
          outer(); 
          /* 
            Hello 
            inner @ VM207:3 
            outer @ VM207:5 
            (anonymous) @ VM228:1 
          */ 

          console.group()

          console.group() 可以把日志分組為可折疊的結構,當有多個日志時特別有用。

          console.group('Outer');           // 創(chuàng)建一個名為 'Outer' 的組 
          console.log('Hello');             // 在 'Outer' 組中輸出日志 
          console.groupCollapsed('Inner');  // 創(chuàng)建一個名為 'Inner' 的組,折疊狀態(tài) 
          console.log('Hellooooo');         // 在 'Inner' 組中輸出日志 
          console.groupEnd();               // 結束當前組, 'Inner' 
          console.groupEnd();               // 結束當前組, 'Outer' 
          console.log('Hi');                // 在組外輸出日志 

          日志級別

          除了 console.log() 之外,還有其他一些日志記錄級別,例如 [console.debug()](https://developer.mozilla.org/en-US/docs/Web/API/Console /debug)、 console.info()、 console.warn()和 console.error()。

          console.debug('Debug message'); 
          console.info('Useful information'); 
          console.warn('This is a warning'); 
          console.error('Something went wrong!'); 

          console.assert()

          console.assert() 提供了一種簡便的方法,僅在斷言失敗時將某些內容記錄為錯誤(例如當?shù)谝粋€參數(shù)為 false 時),否則完全跳過日志。

          const value=10; 
           
          console.assert(value===10, 'Value is not 10!'); // 不輸出日志 
          console.assert(value===20, 'Value is not 20!'); // 輸出日志:"Value is not 20!" 

          console.count()

          可以用 console.count() 來統(tǒng)計一段代碼執(zhí)行了多少次。

          Array.from({ length: 4 }).forEach( 
            ()=> console.count('items')  // 名為 items 的計數(shù)器 
          ); 
          /* 
            items: 1 
            items: 2 
            items: 3 
            items: 4 
          */ 
          console.countReset('items');  // 重置計數(shù)器 

          console.time()

          console.time() 提供了一種快速檢查代碼性能的方法,但是由于精度較低,不可用于真正的基準測試。

          console.time('slow comp');     
          console.timeLog('slow comp');  
          console.timeEnd('slow comp');  

          CSS

          最后一個,還可以在 console.log() 中用 %c 字符串替換表達式將 CSS 應用于日志的各個部分。


          主站蜘蛛池模板: 香蕉久久AⅤ一区二区三区| 久久蜜桃精品一区二区三区| 色欲AV蜜臀一区二区三区| 亚洲电影一区二区三区| 国产成人av一区二区三区在线| 精品人妻少妇一区二区| 国产成人精品无码一区二区老年人| 日本亚洲成高清一区二区三区| 在线视频国产一区| 无码少妇一区二区浪潮免费| 无码少妇精品一区二区免费动态| 中文字幕日韩一区二区三区不| 日本一区二区三区不卡视频中文字幕| 波多野结衣一区二区| 亚洲电影国产一区| 亚洲AV无一区二区三区久久| 国产精品亚洲综合一区| 精品国产一区二区三区AV性色| 日韩一区二区三区不卡视频| 亚洲欧洲专线一区| 成人区精品一区二区不卡亚洲 | 中字幕一区二区三区乱码| 国产精品区一区二区三在线播放 | 亚洲AV噜噜一区二区三区| 亚洲国产精品综合一区在线| 色偷偷一区二区无码视频| 91精品国产一区| 一区二区传媒有限公司| 亚洲综合激情五月色一区| 无码精品不卡一区二区三区| 亚洲日韩国产一区二区三区在线| 国产精品合集一区二区三区 | 黑人一区二区三区中文字幕| 波多野结衣在线观看一区二区三区 | 韩国资源视频一区二区三区| 国产一国产一区秋霞在线观看| 国产一区二区视频免费| 三上悠亚国产精品一区| 国产激情无码一区二区app| 97久久精品一区二区三区 | 无码人妻AV免费一区二区三区|