题外篇

曾经有段时间,在公司维护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年。
  • 针对本框架,提出您的改进方案,方案要求可行、有简要的技术实现。

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

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

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

技术联系

reborn_zhang@hotmail.com

http://zc22.cnblogs.com/

一个日志框架的开源,有些不错的创意。相关推荐

  1. 动手造轮子:写一个日志框架

    动手造轮子:写一个日志框架 Intro 日志框架有很多,比如 log4net / nlog / serilog / microsoft.extensions.logging 等,如何在切换日志框架的时 ...

  2. 手把手教你从零写一个日志框架

    点击上方 "编程技术圈"关注, 星标或置顶一起成长 后台回复"大礼包"有惊喜礼包! 每日英文 Sometimes you have to accept the ...

  3. 基于微信 xlog 开源 日志框架

    XLogHelper 项目地址:JiangHaiYang01/XLogHelper 简介: 基于微信 xlog 开源 日志框架 更多:作者   提 Bug 标签: 基于微信 XLog 的日志框架&am ...

  4. SpringBoot_日志-日志框架分类和选择

    SpringBoot与日志,说这个日志之前呢,我们先说一个小小的故事,来给大家介绍一下日志的起源,与日志框架的关系,如果说对这一块比较清楚了,那你就可以跳过我这个精彩的故事了,假设现在有一个开发人员, ...

  5. 可能是全网最全的 Java 日志框架适配、冲突解决方案

    作者:空无 juejin.cn/post/6945220055399399455 前言 你是否遇到过配置了日志,但打印不出来的情况? 你是否遇到过配置了logback,启动时却提示log4j错误的情况 ...

  6. 可能是全网最全,JAVA日志框架适配、冲突解决方案,可以早点下班了!

    点击上方"Java基基",选择"设为星标" 做积极的人,而不是积极废人! 每天 14:00 更新文章,每天掉亿点点头发... 源码精品专栏 原创 | Java ...

  7. Java日志框架日志门面介绍

    文章目录 一.日志 二.常见日志框架 历史 各大框架介绍 JUL Log4j(1999-2015) Logback(2006-?) Log4j2 Logback与Log4j2对比 三.日志门面 什么是 ...

  8. 一文详解 C++ 日志框架

    作者: 一去.二三里 个人微信号: iwaleon 微信公众号: 高效程序员 日志框架 日志框架 - 一个经过专门设计的实用程序,用于规范应用程序的日志记录过程. 日志框架可以自己编写(需要一定的能力 ...

  9. Java日志框架SLF4J和log4j以及logback的联系和区别

    1.SLF4J(Simple logging Facade for Java) 意思为简单日志门面,它是把不同的日志系统的实现进行了具体的抽象化,只提供了统一的日志使用接口,使用时只需要按照其提供的接 ...

  10. Java各类日志门面(slf4j,commons-logging)和日志框架(log4j,logback)联系和区别

    日志门面 1.Apache通用日志接口(commons-logging.jar) Apache Commons包中的一个,包含了日志功能,必须使用的jar包.这个包本身包含了一个Simple Logg ...

最新文章

  1. 三,ES6中需要注意的特性(重要)
  2. leetcode第二题java_LeetCode第二题,Java实现
  3. 近期活动盘点: Call for Code编程马拉松邀请赛
  4. html5 form表单,html5 教程
  5. (0045) iOS 开发之MBProgressHUD 源码学习
  6. python中matrix函数_使用python解线性矩阵方程(numpy中的matrix类)
  7. java cpu监控,java系统监控CPU 磁盘
  8. 微信小程序入门(一)
  9. kaggle比赛数据_表格数据二进制分类:来自5个Kaggle比赛的所有技巧和窍门
  10. 桥接模式(Bridge)解析例子
  11. [C++] C/C++ 取整函数ceil(),floor()
  12. SSH安全审计Tool - ssh-audit
  13. office visio 替代_5款替代微软Visio的开源免费软件
  14. 向数据库中存取图片(BITMAP)
  15. 地学计算方法/地统计学(第四章变异函数理论模型)
  16. Buried Town 《死亡日记》 安卓 1.4.3版 破解 + 部分内购 版
  17. MyBatis源码简单分析
  18. 关于“上海电信IPTV系统开机广告不能关闭“问题的看法
  19. 程序员中年危机的真正原因是不懂营销
  20. AXI总线信号含义说明

热门文章

  1. 阿里巴巴CTO程立:双11的再进化
  2. 1.45亿元!甲骨文中标中国邮政储蓄银行数据库项目
  3. 阿里达摩院赵昆:获评“中国客户服务领袖”
  4. 多云时代-着眼布局开源技术之多云数据管理
  5. Linux基金会宣布行业进一步支持Akraino Edge Stack
  6. 【图像融合】基于matlab泊松彩色图像融合【含Matlab源码 1830期】
  7. 【TWVRP】基于matlab遗传算法求解带时间窗的外卖配送车辆路径规划问题【含Matlab源码 1416期】
  8. 【故障分析】基于matlab GUI鼠笼式异步电机转子断条故障诊断【含Matlab源码 1089期】
  9. 【气动学】基于matlab GUI改进的遗传算法和高斯烟羽模型模拟气体扩散【含Matlab源码 1060期】
  10. 【路径规划】基于matlab模拟退火算法求解多车型路径规划问题【含Matlab源码 913期】