• 一个比较好用的日志记录系统


    首先声明,没有按照AOP的方法来做,现在还是显示调用的。

    using System;
    using System.IO;
    using System.Collections;
    using System.Runtime.InteropServices;

    using ICSharpCode.SharpZipLib.Zip;
    using ICSharpCode.SharpZipLib.Zip.Compression;
    using ICSharpCode.SharpZipLib.Zip.Compression.Streams;
    using ICSharpCode.SharpZipLib.BZip2;
    using ICSharpCode.SharpZipLib.Checksums;

    namespace Genersoft.Focus
    {
     [StructLayoutAttribute(LayoutKind.Sequential, CharSet=CharSet.Auto)]
     public struct LogFileHeader
     {
      [MarshalAs(UnmanagedType.ByValTStr, SizeConst=19)]public string HeaderSignature;//FocusTools.LogFile,前面是0x12
      public int EntryListNumber;
     }

     [StructLayoutAttribute(LayoutKind.Sequential, CharSet=CharSet.Auto)]
     public struct LogFileEntryList
     {
      [MarshalAs(UnmanagedType.ByValTStr, SizeConst=9)]public string CreateDate;//8位,20031201格式
      [MarshalAs(UnmanagedType.ByValTStr, SizeConst=10)]public string CreateTime;//9位,140324111格式
      [MarshalAs(UnmanagedType.ByValTStr, SizeConst=1024)]public string AdditionalInformation;//调用着传递来的日志信息  
      public int AdditionalInformationType;//
      public int EntryNumber;//Entry的个数
     }

     [StructLayoutAttribute(LayoutKind.Sequential, CharSet=CharSet.Auto)]
     public struct LogFileEntry
     {
      [MarshalAs(UnmanagedType.ByValTStr, SizeConst=1024)]public string FileName;//calling的文件名
      [MarshalAs(UnmanagedType.ByValTStr, SizeConst=1024)]public string MethodName;//calling的方法名
      public int FileLineNumber;//calling的行号位置
     }

     public enum LogType
     {
      Info,Warning,Error,Exception,Database
     }

     public class Log
     {  
      private static LogFileHeader lfh;
      private static LogFileEntryList lfel;
      private static LogFileEntry[] lfe;
      private static System.Text.StringBuilder sb = null;
      private static Log instance = null;
      private const string LogFileName = @"c:\focus.log";

      private Log()
      {
       lfh = new LogFileHeader();
       lfh.HeaderSignature = "FocusTools.LogFile";
       sb = new System.Text.StringBuilder();
       lfel = new LogFileEntryList();
      }

      public static Log Instance
      {
       get{if(null == instance)instance = new Log();return instance;}
      }

      public void Write(string s,LogType t)
      {
       System.DateTime dt = System.DateTime.Now;
       lfel = new LogFileEntryList();
       lfel.AdditionalInformation = s;
       lfel.CreateDate = String.Format("{0:d4}{1:d2}{2:d2}",dt.Year,dt.Month,dt.Day);
       lfel.CreateTime = String.Format("{0:d2}{1:d2}{2:d2}{3:d3}",dt.Hour,dt.Minute,dt.Second,dt.Millisecond);

       //查找当前进程内所有线程的调用堆栈信息,怎么做?
       System.Diagnostics.StackTrace st = new System.Diagnostics.StackTrace(true);
       lfel.EntryNumber = st.FrameCount-1;   
       lfel.AdditionalInformationType = Convert.ToInt32(t);
       
       lfe = new LogFileEntry[st.FrameCount-1];
       for(int i=st.FrameCount-1;i>0;i--)//最后一个是Write这个方法本身,所以就不写入了。
       {
        lfe[st.FrameCount-1-i] = new LogFileEntry();
        lfe[st.FrameCount-1-i].FileName = st.GetFrame(i).GetFileName();
        lfe[st.FrameCount-1-i].MethodName = st.GetFrame(i).GetMethod().Name;
        lfe[st.FrameCount-1-i].FileLineNumber = st.GetFrame(i).GetFileLineNumber();
       }

       Flush();
      }

      private void Flush()
      {
       int entryListNum = 0;

       FileStream fs = new FileStream(LogFileName,FileMode.OpenOrCreate,FileAccess.ReadWrite); 
       BinaryWriter bw = new BinaryWriter(fs);
       BinaryReader br = new BinaryReader(fs);
       int size,size2;

       try
       { 
        bw.Write(lfh.HeaderSignature);
        br.BaseStream.Seek(19,SeekOrigin.Begin);
        try
        {
         entryListNum = br.ReadInt32()+1;
        }
        catch
        {
         entryListNum = 1;
        }
        bw.BaseStream.Seek(19,SeekOrigin.Begin);
        bw.Write(entryListNum);
        
        bw.BaseStream.Seek(0,SeekOrigin.End);

        size = Marshal.SizeOf(lfel);
        size2 = Marshal.SizeOf(lfe[0]);

        byte[] input = new byte[size+size2*lfel.EntryNumber];

        IntPtr p = Marshal.AllocHGlobal(size);
        Marshal.StructureToPtr(lfel,p,true);
        byte[] bEntryList = new byte[size];
        Marshal.Copy(p,bEntryList,0,size);
        //bw.Write(bEntryList);
        Marshal.FreeHGlobal(p);
        bEntryList.CopyTo(input,0);

        for(int i=0;i<lfel.EntryNumber;i++)
        {
         IntPtr p2 = Marshal.AllocHGlobal(size2);
         Marshal.StructureToPtr(lfe[i],p2,true);
         byte[] bEntry = new byte[size2];
         Marshal.Copy(p2,bEntry,0,size2);
         // bw.Write(bEntry);
         Marshal.FreeHGlobal(p2);
         bEntry.CopyTo(input,bEntryList.Length+i*size2);
        }

    //    System.Diagnostics.Trace.WriteLine(System.Text.Encoding.Default.GetString(input));
        
        Deflater def = new Deflater(Deflater.BEST_COMPRESSION);
        if(def.IsNeedingInput)def.SetInput(input);
        def.Finish();
    //    System.Diagnostics.Trace.WriteLine(System.Text.Encoding.Default.GetString(input));
        byte[] dbuf = new byte[input.Length];
        int dsize = 0;
        dsize = def.Deflate(dbuf);

        bw.Write(dsize);//压缩后的大小
        bw.Write(input.Length);//压缩前的大小
        bw.Write(dbuf,0,dsize);    
       }
       catch(Exception ex)
       {
        throw ex;
       }
       finally
       {
        if(null != br)br.Close();
        if(null != bw)bw.Close();
        if(null != fs)fs.Close();
       }
      }
     }

     public class LogFileEventArgs
     {
      public LogFileEventArgs(int curvalue,int maxvalue)
      {
       this.curValue = curvalue;
       this.maxValue = maxvalue;
      }

      private int curValue = 0;
      private int maxValue = 0;

      public int CurValue{get{return curValue;}set{curValue = value;}}
      public int MaxValue{get{return maxValue;}set{maxValue = value;}}
     }

     public delegate void LogFileEventHandler(object sender, LogFileEventArgs e);
    }

    一共有两点需要注意:
    1、堆栈信息是从StackTrace中读出来的。发布assembly的时候,要把同版本号的pdb文件也要复制上。否则,line和column信息无法读出来。
    2、对于structure的处理,采用了一点IntPtr的方法。

  • 相关阅读:
    中国石油大学天梯赛真题模拟第三场
    中国石油大学天梯赛真题模拟第一场
    PTA 水果忍者
    演练3-1:留言管理系统的制作
    知识点4-1:哪些应该放在动作方法中?
    Week5(10月11日):国庆后补课的复杂心情
    知识点3-5:使用强类型模板
    Week5(10月10日):国庆之后,让我们整装期待元旦吧
    知识点3-6:HTML辅助方法
    知识点3-4:给视图传递数据
  • 原文地址:https://www.cnblogs.com/juqiang/p/10108.html
Copyright © 2020-2023  润新知