zoukankan      html  css  js  c++  java
  • WPF 自定义日志记录

    为了便于分析应用程序的运行情况和BUG诊断,一般都会搞个日志输出。
    当初看过一点Log4net,觉得有些麻烦了,就动手写了个简单的。
    本例子已经在 项目中使用过,拿出来分享一下,欢迎各位拍砖,呵呵。
    本日志记录比较轻巧,在config文件里面配置后,把loghelper.cs 文件放到项目中即可使用。日志输出开关有四个:不输出、输出到DebugVIew、每次全新输出到文本、追加输出到文本。
    输出的日志有特定的分隔符,可以放到excel里面,分割为每一列后继续进行筛选等分析。

    本例子运行环境是DoNet 3.5 WPF C#,也可以扩展到别的环境使用.

    效果预览

    配置文件

    当初想过使用ini文件或者xml文件存储配置信息,后来发现config文件用的比较多,而且config文件读取比较方便,索性就集成到Config文件里面。

    在项目里面添加config文件即可。

     1 <?xml version="1.0" encoding="utf-8" ?>
    2 <!-- Author Shi Xiaokang
    3 http://www.cnblogs.com/xiaokang088/
    4 Version 1.00
    5 Date: 2011-1-21-->
    6 <configuration>
    7 <runtime>
    8 <generatePublisherEvidence enabled="false"/>
    9 </runtime>
    10 <appSettings>
    11 <!--
    12 ; 0 - No output
    13 ; 1 - Debugger (Such as DbgView)
    14 ; 2 - File (Overwrite the old file and doesn't close it until application exits)
    15 ; 3 - File (Append the log at the end of file and close it after each log output)
    16 ; 4 - Debugger&File (Append the log at the end of file and close it after each log output)
    17 -->
    18 <add key="logDestination" value="4"/>
    19 <!--log file path. if value is null or string.empty, don't ouput log to file-->
    20 <!--example:%LocalAppData%\log.txt-->
    21 <add key="logPath" value="%LocalAppData%\log.txt"/>
    22 </appSettings>
    23 </configuration>
    logDestination
    • 0         没有任何日志输出
    • 1         可以输出到DebugView
    • 2         每次启动应用程序后,把上次写的日志清除掉,重新写一份日志
    • 3         第一次启动应用程序后,创建日志文件,后面一直累加

    logPath 文本日志的文件位置, 推荐使用 AppData里面的路径,这个是系统默认的应用程序 数据存储路径。

    如果搞别的,也可以,但是要考虑只读、权限等问题,由于客户机环境复杂,所以还是放在AppData 比较省心。

     使用方法

    在需要打印日志的地方调用方法, 大致分为:简单打印、打印变量、打印方法执行结果、打印堆栈信息、打印异常。

    下面只列举了一部分,

     1 // UI|2011/12/20 14:57:39 630 | Test Write Method 
    2 LogHelper.Write("Test Write Method");
    3
    4 bool? testBool = false;
    5 /// UI|2011/12/20 14:57:48 277 | False
    6 LogHelper.Write(testBool);
    7
    8 Double testDouble = 0.2256;
    9 /// UI|2011/12/20 14:57:48 279 | 0.2256
    10 LogHelper.Write(testDouble);
    11
    12 /// UI|2011/12/20 15:01:28 801 | current ID:115001 Name:Jackon
    13 LogHelper.Write("current ID:{0} Name:{1}", 115001, "Jackon");
    14
    15 bool? ret = DoTestIsOK();
    16 /// UI|2011/12/20 15:17:04 732 | Method:DoTestIsOK --> Result:Null
    17 LogHelper.WriteMethod("DoTestIsOK", ret);
    18 int a = 1, b = 3;
    19 int ret = DoTestAdd(a, b);
    20
    21 /// UI|2011/12/20 15:17:05 316 | Method:DoTestAdd --> Result:4 -- Parms:a:1 b:3
    22 LogHelper.WriteMethod("DoTestAdd", ret, "a:{0} b:{1}", a, b);
    23


    原理

    C# 的Trace可以打印到output里面,Realse后,也可以打印到DebugView中。

    这里的实现是丰富了Trace的功能,并且将日志输出为 不同的格式,打印出来后方便分析。

    通过     Trace.Listeners 可以控制输出的目的地。

    话不多说,都在代码里,如下:

      1     #region init
    2 /// <summary>
    3 /// init by configuration
    4 /// </summary>
    5 public static void Init()
    6 {
    7 #region define
    8 string logPathKey = "logPath", logDestinationKey = "logDestination", autoFlushKey = "autoFlush";
    9 string logPath = string.Empty, logDestination = string.Empty;
    10 FileStream stream;
    11 FileMode fileMode;
    12 #endregion
    13
    14 #region get destination
    15 //no destination,return
    16 if (!ConfigurationManager.AppSettings.AllKeys.Contains(logDestinationKey)) return;
    17 logDestination = ConfigurationManager.AppSettings[logDestinationKey].Trim();
    18
    19 int logType = 0;
    20 Int32.TryParse(logDestination, out logType);
    21 //if logType == 0 , don't record log
    22 isLog = (logType != 0);
    23 #endregion
    24
    25
    26
    27
    28
    29
    30 #region switch log type
    31 switch (logType)
    32 {
    33 case 0:
    34 {
    35 //0 - No output
    36 Trace.Listeners.Clear();
    37 return;
    38 }
    39 case 1:
    40 {
    41 //1 - Debugger (Such as DbgView)
    42 //use default listener
    43 return;
    44 }
    45 case 2:
    46 {
    47 //2 - File (Overwrite the old file and doesn't close it until application exits)
    48 Trace.Listeners.Clear();
    49 fileMode = FileMode.Create; break;
    50 }
    51 case 3:
    52 {
    53 //3 - File (Append the log at the end of file and close it after each log output)
    54 Trace.Listeners.Clear();
    55 fileMode = FileMode.Append; break;
    56 }
    57 case 4:
    58 {
    59 //4 - Debugger&File (Append the log at the end of file and close it after each log output)
    60 fileMode = FileMode.Append; break;
    61 }
    62
    63 default: return;
    64 }
    65 #endregion
    66
    67 #region check path
    68 //path is null
    69 logPath = ConfigurationManager.AppSettings[logPathKey].Trim();
    70 if (string.IsNullOrEmpty(logPath)) return;
    71
    72 //path has invalid char
    73 var pathCharArray = logPath.ToCharArray();
    74 if (pathCharArray.Any(o => Path.GetInvalidPathChars().Contains(o)))
    75 return;
    76
    77 //FileName has invalid char
    78 //note : invalid file name chars count is 41,
    79 //invalid path chars count is 36
    80 //and , the top 36 of invalid file name chars are same as invalid path chars
    81 //so,first check path invalid chars,second check filename,only filename
    82 var filenameCharArray = Path.GetFileName(logPath).ToCharArray();
    83 if (filenameCharArray.Any(o => Path.GetInvalidFileNameChars().Contains(o)))
    84 return;
    85
    86 //EnvironmentVariables Path
    87 if (logPath.Contains('%'))
    88 logPath = Environment.ExpandEnvironmentVariables(logPath);
    89
    90 //cheng relative path to absolute path.
    91 if (String.IsNullOrEmpty(Path.GetPathRoot(logPath)))
    92 logPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, logPath);
    93 #endregion
    94
    95 #region file log
    96 //risk:directory readonly;need administrator right to createfile;and so on
    97 //use try-catch
    98 try
    99 {
    100 if (!Directory.Exists(Path.GetDirectoryName(logPath)))
    101 Directory.CreateDirectory(Path.GetDirectoryName(logPath));
    102
    103 stream = File.Open(logPath, fileMode, FileAccess.Write, FileShare.ReadWrite);
    104 TextWriterTraceListener text = new TextWriterTraceListener(stream);
    105 //text.TraceOutputOptions = TraceOptions.DateTime;
    106 Trace.Listeners.Add(text);
    107 }
    108 catch (Exception ex)
    109 {
    110 Trace.Write(ex);
    111 }
    112 #endregion
    113
    114 }
    115 #endregion


    结束,欢迎拍砖。

    代码下载




  • 相关阅读:
    测试爬虫
    流式大数据处理的三种框架:Storm,Spark和Samza
    redo日志
    HTTP协议之chunk编码(分块传输编码
    QWidget 实现 打破布局 或者 当前窗体内的 弹窗 (借助伪造实现)
    How to use kingshard building a MySQL cluster
    转载: Qt 学习之路 2归档
    Python与机器人技术
    Nginx配置正向代理
    使用Chrony配置 NTP
  • 原文地址:https://www.cnblogs.com/xiaokang088/p/2303725.html
Copyright © 2011-2022 走看看