zoukankan      html  css  js  c++  java
  • 一个日志框架的开源,有些不错的创意。

    题外篇

    曾经有段时间,在公司维护IBM ds8000系统,就是服务器。当时的工作就是分析系统的日志,查看是否有运行错误。虽然有一些脚本分析工具,但是一旦发生了问题,还是靠人力,任何工具都没有用。

    当时,如果发现了问题,首先就是把最近的打包日志下载到公司的ftp,然后打开一个pad,找问题发生的时间的所有相关日志,帖在一起。

    如果没有经验,就会把所有模块的日志都帖在一起,慢慢看,那简直就是sb了。有经验的工程师,就会先分析有可能出现问题的模块,然后解压日志再合并查看。

    当时觉得这样的工作非常的无聊,但是又没有好的思路。现在,总算给我找到解决方法了。

    前言

    本框架参考了 Microsoft.Enterprise.lib, log4net,同时集成了一些比较先进的日志思想和技术,能够方便程序开发以及后期的维护。

    与此技术相关的讨论区在:

    http://groups.google.com/group/pixysoft

    优势与特点

    1. 伪XML技术(Pesudo XML):使用伪xml结构记录日志,实现了日志的结构化存储。同时对.net的xml操作部分全部重写,使io性能接近文件流的处理,既摒弃了xml结构化带来的性能问题,又不丧失xml的结构化存储、查询的特性。
    2. 并行日志技术(Parallel Logging):采用了AOP技术,能够对某一类的入口、出口、异常进行全方位跟踪,并且记录输入参数、传出参数;实现代码运行与日志记录的平行(我称其为 Parallel Logging, 并行日志技术)。使用此技术,在项目开发中能够得心应手。
    3. 异常报告技术(Exception Report):当发生异常的时候,能够查询程序调用的堆栈,并且收集此调用过程中相关的其他日志,进行日志合并,更加方便系统debug。
    4. 日志查询技术(Log Searching):支持时间段查询、日志主键查询、日志级别查询;支持跨文件查询;支持不同模块日志合并查询,查询性能接近文件流操作。

    日志片段展示

    以下是一个正常的日志记录:

    代码
    <log level="info" time="2009-11-28 23:33:06:906" id="7cb203b2-b9c9-4818-aa59-4efd8ccec464">
    hello
    </log>

    以下是关于异常的日志记录,能够捕获所有调用的堆栈:

    代码
    <log level="fatal" time="2009-11-28 23:36:39:437" id="339b4e11-a2f2-48c5-b6e3-f15754b36310">
    <message>
    hello
    </message>
    <frame class="Pixysoft.OpenSource.Logs.TestDriven.Hello" method="Helloworld" dll="Pixysoft.OpenSource.Logs.TestDriven.dll" file="E:\xxxx\xxxx\develop\Pixysoft.OpenSource.Logs\Pixysoft.OpenSource.Logs.TestDriven\testcase.cs" line="50" column="13" id="339b4e11-a2f2-48c5-b6e3-f15754b36310"/>
    <frame class="System.Runtime.Remoting.Messaging.Message" method="Dispatch" dll="mscorlib.dll" file="" line="0" column="0" id="339b4e11-a2f2-48c5-b6e3-f15754b36310"/>
    <frame class="System.Runtime.Remoting.Messaging.StackBuilderSink" method="SyncProcessMessage" dll="mscorlib.dll" file="" line="0" column="0" id="339b4e11-a2f2-48c5-b6e3-f15754b36310"/>
    </log>

    一段并行日志记录:

    代码
    <log level="info" time="2009-11-27 23:59:17:843" id="6651d0f8-cc6d-498a-a3ba-2431dedfb844">
    Pixysoft.Framework.Logs.dll::Pixysoft.Framework.Logs._testdriven.Hello.Helloworld(String para1, Hello para2, String[] paras3)
    ::para1 = null;
    ::para2 = null;
    ::paras3 = System.String[].Count = 0;

    </log>

    演示代码

    代码
    using System;
    using System.Collections.Generic;
    using System.Text;

    namespace Pixysoft.OpenSource.Logs.TestDriven
    {
        
    public class testcase
        {
            
    /// <summary>
            
    /// summary:
            
    /// 测试写入日志
            
    /// 
            
    /// output: 
            
    /// 在debug目录下面出现helloworld的目录,里面有helloworld.log的日志
            
    /// </summary>
            public void test001()
            {
                
    for (int i = 0; i < 1000; i++)
                {
                    Console.WriteLine(Logger.Instances[
    "helloworld"].Info("hello"));
                }
            }


            
    /// <summary>
            
    /// summary:
            
    /// 测试aop日志+Exception的记录
            
    /// 
            
    /// output:
            
    /// 1. Hello.Nick可以显示,但是Helloworld不能显示。
            
    /// 2. 所有调用过程全部记录在debug/helloworld-aop目录的helloworld-aop.log里面
            
    /// 3. Exception的所有调用堆栈信息都被记录
            
    /// </summary>
            public void test002()
            {
                Console.WriteLine(
    new Hello().Nick());

                
    try
                {
                    Console.WriteLine(
    new Hello().Helloworld("1"new Hello(), "2""3"));
                }
                
    catch (Exception ex)
                {
                }
            }


            
    /// <summary>
            
    /// summary:
            
    /// 测试注册
            
    /// 
            
    /// output:
            
    /// 在debug/log目录下,出现.log文件,记录了当前模块的注册信息
            
    /// </summary>
            public void test003()
            {
                Logger.Instances[
    "hello"].Register();
            }


            
    /// <summary>
            
    /// summary:
            
    /// 测试日志的查询
            
    /// 
            
    /// output:
            
    /// 正确显示日志HELLOWORLD的查询结果
            
    /// </summary>
            public void test004()
            {
                ILogCommand command 
    = Logger.Instance["HELLOWORLD"].CreateCommand();

                command.Range.From 
    = DateTime.Parse("2009-11-27 23:58:27");

                
    //command.Range.To = DateTime.Now.AddDays(10);

                command.Level 
    = LogLevel.ALL;

                command.CrossFiles 
    = false;

                ILogDocument docs 
    = command.ExecuteReader();

                
    //command.SerializeReader();

                Console.WriteLine(docs.Serialize());

                
    foreach (ILogRecord record in docs.Records)
                {
                    Console.WriteLine(record.Id);
                    Console.WriteLine(record.Date);
                    Console.WriteLine(record.Level);
                    Console.WriteLine(record.Text);
                    Console.WriteLine(record.Ip);

                    
    foreach (ILogFrame frame in record.Frames)
                    {
                        Console.WriteLine(frame.Dll);
                        Console.WriteLine(frame.Class);
                        Console.WriteLine(frame.File);
                        Console.WriteLine(frame.Path);
                        Console.WriteLine(frame.Line);
                        Console.WriteLine(frame.Column);
                    }
                }
            }


            
    /// <summary>
            
    /// summary:
            
    /// 测试根据id获取日志的信息
            
    /// 
            
    /// output:
            
    /// 成功获取日志helloworld信息
            
    /// </summary>
            public void test005()
            {
                ILogRecord record 
    = Logger.Instances["helloworld"].GetRecord("7cb203b2-b9c9-4818-aa59-4efd8ccec464"false);

                Console.WriteLine(record.Text);
            }


            
    /// <summary>
            
    /// summary:
            
    /// 测试生成报告
            
    /// 
            
    /// output:
            
    /// 获取日志id对应的日志的报告
            
    /// </summary>
            public void test006()
            {
                ILogReport report 
    = Logger.Instances["helloworld"].GetReport("7cb203b2-b9c9-4818-aa59-4efd8ccec464"20);

                Console.WriteLine(
    "report record id = " + report.Id);
                Console.WriteLine(
    "report record timespan = " + report.TimeSpan);
                Console.WriteLine(
    "report record timefrom = " + report.TimeFrom);
                Console.WriteLine(
    "report record timeto = " + report.TimeTo);
                Console.WriteLine(
    "report record createdate = " + report.CreateDate);
                Console.WriteLine(
    "report document.record.count = " + report.Document.Records.Count);
                Console.WriteLine(
    "report framedocument.count = " + report.FrameDocuments.Length);
            }

        }

        [Logger(
    "helloworld-aop")]
        
    class Hello : ContextBoundObject
        {
            
    public string Helloworld(string para1, Hello para2, params string[] paras3)
            {
                
    throw new Exception("hello");
            }

            
    public string Nick()
            {
                
    return "1";
            }

        }
    }

    测试代码下载

    http://www.boxcn.net/shared/r34b6299p9

    核心技术说明

    日志系统最关键的就是效率,xml虽然实现了结构化的存储,但是性能非常的差。

    考虑到日志的特性:增量追加+不修改,我就使用了伪xml技术去提高xml的存储、读取性能。

    • xml的存储直接使用了File.Open(xxx,Mode.Append),因此性能 == 文件流的操作
    • xml的读取使用xmlreader,因此又~=文件流的操作

    开源说明

    编译后的代码可以随意使用,没有任何的使用限制。

    为了保证源码质量,如果希望加入开发小组,获取源码,符合以下2点的即可:

    • 在博客园、csdn的博龄大于1年。
    • 针对本框架,提出您的改进方案,方案要求可行、有简要的技术实现。 

    请在以下讨论区提交您的改进方案。

    我们根据您的需求,提供svn进行源码下载,维护。

    技术联系

    reborn_zhang@hotmail.com

    http://zc22.cnblogs.com/

  • 相关阅读:
    解决MySQL报错The server time zone value 'Öйú±ê׼ʱ¼ä' is unrecognized or represents .....
    不安装Oracle客户端,用plsql连接远程Oracle数据库(绝对解决你的问题)
    Java中的String,StringBuilder,StringBuffer三者的区别
    字符串截取的常用方法
    java 项目 导入成功后jsp页面报错处理方法
    PL/SQL Developer安装详解(32位客户端免安装版)
    oracle 11g如何完全卸载
    Struts2下载文件点取消出现的异常解决
    Web框架们
    Django【进阶篇 】
  • 原文地址:https://www.cnblogs.com/zc22/p/1612847.html
Copyright © 2011-2022 走看看