讲到log4j,现在国外基本是没有开发者用这个框架了,原因大致有几点,1、功能太少;2、效率低下;3、线程锁bug等等等各种莫名其妙的bug一直都没解决。

其实最重要的是log4j的作者自己也放弃了log4j,该作者现在在维护logback项目(现在主流的日志记录框架,彻底推翻了log4j的架构重写了,功能很强大),所以log4j以后基本不会再用了。

讲到这里,还是要研究一下要怎么实现的日志记录框架,那么要写个日志记录框架,得要熟悉日志记录系统的整体设计思路。于是自己构思了一晚上,花了一上午时间写了一个简单的日志记录系统(就是logGuide0.1.1),姑且称为一个简单框架吧。

由于后面又继续对logGuide进行开发更新,所以现在的版本有这些:

如果有兴趣研究这一块的话,源码在这里:

logGuide 0.1.1比较简陋就不在提供了。

老核心源码(logGuide 0.2.1):http://download.csdn.net/detail/eguid_1/9491573

最新logGuide 0.3.2.jar包(非源码)下载:http://download.csdn.net/detail/eguid_1/9532267

最新logGuide 0.3.2(源码)下载:http://download.csdn.net/detail/eguid_1/9532617

新核心日志记录(logGuide 0.3.1)大致分为5层结构:

1、写入区        ---> 传入消息,传入消息后交由分发器进行分发

2、分发器        ---> 分发消息,缓冲消息数据(消息分为普通日志和异常错误日志),调用缓冲区缓冲消息日志

3、缓冲区        ---> 缓冲消息日志,把所有消息缓冲到一个双缓冲队列中,交由缓冲分发器进行消息分发处理

4、缓冲分发器 ---> 由一个后台保护线程调用持久层写出日志

5、持久层        ---> 写出消息日志,缓冲区通过持久层实现写出日志,配置文件中配置可以实现文件和数据库同时写出

当前最新版本:

logGuide 0.3.2版本

1、增加独立数据库缓存核心

2、优化数据库写入效率

3、优化文件写入逻辑



logGuide 0.3.1版本(重大更新版本)

1、源代码推翻重写

2、优化代码结构,结构更加清晰,各功能模块分工更加明确

3、优化NIO+BQ缓冲核心,占用资源更少,速度更快,实测 最高50822/每秒
日志文件写出速度

4、增加数据库持久化功能,可通过配置文件配置

5、消息格式可配置



logGuide 0.2.1版本

1、支持配置文件方式指定两种日志记录文件(infoPath=log.log,errorPath=error.log)在项目文件中的路径(注意:目前支持项目文件中的路径,其他路径会出现异常)

2、支持读写顺序日志记录(先读后写)和读写同时两种方式记录(通过配置文件中的auto='false/true'来指定哪种方式,默认先读后写)

3、优化代码结构,可读性更好





logGuide 0.1.1版本

1、实现第三方动态日志记录

2、采用双缓冲队列,更好的多线程并发条件下的日志写入,安全与效率并重

3、采用NIO文件底层操作,更快的读写效率

4、采用读写同时日志记录(并发,写入为单独线程操作),提高组件运行效率

logGuide 0.2.1文件写出核心代码:

<span style="font-size:18px;">private static FileChannel infoChannel = null;
private static FileChannel errorChannel = null; private static BlockingQueue<Object> bq = null;
private static ByteBuffer buffer = null;
private static int index = 0;// 用于控制是否开启自动写入
static {
Properties pro = new Properties();
File infoFile = null;
File errorFile = null;
try {
InputStream is = FileBuffer.class.getClassLoader()
.getResourceAsStream("logConf.properties");
pro.load(is);
} catch (Exception e) {
e.printStackTrace();
}
String infoFilePath = pro.getProperty("infoPath");
String errorFilePath = pro.getProperty("errorPath");
String status = pro.getProperty("auto");
if (status != null && status.equals("true")) {
index = 0;
} else {
index = 1;
}
String path = FileBuffer.class.getClassLoader().getResource("/")
.getPath();
if (infoFilePath != null) {
infoFile = new File(path + infoFilePath);
try {
createFile(infoFile);
} catch (IOException e) {
e.printStackTrace();
}
}
if (errorFilePath != null) {
errorFile = new File(path + errorFilePath);
try {
createFile(errorFile);
} catch (IOException e) {
e.printStackTrace();
}
}
bq = new LinkedBlockingQueue<Object>();
buffer = ByteBuffer.allocate(1024);
try {
infoChannel = new RandomAccessFile(infoFile, "rw").getChannel();
errorChannel = new RandomAccessFile(errorFile, "rw").getChannel();
} catch (Exception e) {
e.printStackTrace();
}
// 如果index=0则自动更新
if (index == 0) {
AutoWrite();
}
} /**
* 把消息存放进缓冲队列
*
* @param msg
* @param name
* @throws Exception
*/
public static void addMsgToFile(StringBuilder msg, String name){ Map<String, Object> map = null;
map = new HashMap<String, Object>();
if (msg != null) {
map.put("fileName", name);
map.put("msg", msg);
}
bq.offer(map);
OneWrite();
}
/**
* index为1时为1次消息1次写入
*/
private static void OneWrite()
{ if (index == 1) {
try {
writen();
} catch (Exception e) {
System.out.println("日志写入失败"+e.getMessage());
}
}
}
/**
* 开启自动写入
*/
private static void AutoWrite() {
Thread t = new Thread() {
public void run() {
while (true) {
try {
writen();
} catch (Exception e) {
e.printStackTrace();
}
}
}
};
//开启写入线程
t.start();
} /**
* 将缓冲队列中的文件写入到对应的文件中
*
* @throws Exception
*/ private static void writen() throws Exception { if (bq.peek() != null) {
Map map = (Map) bq.poll();
String name = (String) map.get("fileName");
StringBuilder msg = (StringBuilder) map.get("msg");
if (name != null && name.equals("info")) {
wirteInfo(msg);
} else if (name != null && name.equals("error")) {
writeError(msg);
}
} else {
Thread.sleep(200);
}
} /**
* 写入普通消息
*
* @param msg
*/
private static void wirteInfo(StringBuilder msg) {
bufferWrite(buffer, infoChannel, msg);
} // 写入错误消息
private static void writeError(StringBuilder msg) {
bufferWrite(buffer, errorChannel, msg);
} /**
* 使用NIO将消息缓冲进buffer,通过buffer写出到到指定通道
*
* @param buffer
* @param fc
* @param msg
*/
private static void bufferWrite(ByteBuffer b, FileChannel fc,
StringBuilder msg) {
b.clear();
msg.append("\r\n");
b.put(msg.toString().getBytes());
try {
b.flip();
fc.write(b, fc.size());
} catch (IOException e) {
e.printStackTrace();
}
} /**
* 是否存在文件,如果不存在则创建
*
* @param file
* @throws IOException
*/
private static void createFile(File file) throws IOException {
if (!file.exists()) {
try {
file.createNewFile();
} catch (IOException e) {
e.printStackTrace();
throw e;
}
}
}</span>

扔掉log4j、log4j2,自己动手实现一个多功能日志记录框架,包含文件,数据库日志写入,实测5W+/秒日志文件写入,2W+/秒数据库日志写入,虽然它现在还没有logback那么强大的更多相关文章

  1. (网页)Java日志记录框架Logback配置详解(企业级应用解决方案)(转)

    转自CSDN: 前言 Logback是现在比较流行的一个日志记录框架,它的配置比较简单学习成本相对较低,所以刚刚接触该框架的朋友不要畏惧,多花点耐心很快就能灵活应用了.本篇博文不会具体介绍Logbac ...

  2. 在android中配置 slf4j + log4j 日志记录框架

    需求: 在项目开发中,需要记录 操作日志 .起初自己写了个简单的日志记录文本写入到文本的方法,后来随着项目的膨胀,需要考虑更多的操作,开始考虑性能问题. 实现: 考虑使用 slf4j + log4j ...

  3. SLF4J - 一个允许你统一日志记录API的抽象层

    一.什么是SLF4J 我们在做Java开发时,如果需要记录日志,有很多日志API可供选择,如: java.util.logging Apache log4j logback SLF4J又是个什么东东呢 ...

  4. Serilog 是 ASP.NET Core 的一个插件,可以简化日志记录

    [翻译] ASP.NET Core 利用 Docker.ElasticSearch.Kibana 来记录日志 原文: Logging with ElasticSearch, Kibana, ASP.N ...

  5. 一个小时搭建一个全栈 Web 应用框架

    把想法变为现实的能力是空想家与实干家的区别.不管你是在一家跨国公司工作,还是正在为自己的创业公司而努力,那些有能力将创意转化为真正产品的人,都具有宝贵的技能并拥有明显的实力.如果你能在不到一个小时的时 ...

  6. logback log4j log4j2 性能实测

    logback log4j log4j2 性能实测 转载: https://blog.souche.com/logback-log4j-log4j2shi-ce/ 日志已经成为系统开发中不可或缺的一部 ...

  7. Log4j,Log4j2,logback,slf4j日志学习

    日志学习笔记 Log4j Log4j是Apache的一个开放源代码项目,通过使用Log4j,我们可以控制日志信息输送的目的地是控制台.文件.数据库等:我们也可以控制每一条日志的输出格式:通过定义每一条 ...

  8. Log4j,Log4j2,logback,slf4j日志学习(转)

    日志学习笔记Log4jLog4j是Apache的一个开放源代码项目,通过使用Log4j,我们可以控制日志信息输送的目的地是控制台.文件.数据库等:我们也可以控制每一条日志的输出格式:通过定义每一条日志 ...

  9. 常见java日志系统的搭配详解:关于slf4j log4j log4j2 logback jul jcl commons-logging jdk-logging

    先看一张图: 是不是有点晕, 晕就对了.这个仅仅是 slf4j 的情况,实际上, 我们不仅要接触到 slf4j ,有时候还会接触其他的日志系统.且看下文分解. 1 直接使用各个日志系统 1.1 直接使 ...

随机推荐

  1. 修改nagios密码和遇到的问题

    htpasswd -c /usr/local/nagios/etc/htpasswd.users nagiosadmin 密码 密码 service httpd restart 由于本屌丢掉一个s使/ ...

  2. C语言之函数和字符串

    二.函数: 2.1.函数的执行: 1.当我们每次进入一个函数的时候,原函数的栈底进行一个备份,之后将当前函数的栈底和栈顶指针分作同一个. 2.此时我们就可以说产生了一个新栈,产生新栈之后会在新栈中申请 ...

  3. 使用 Python 实现命令行词典(一)

    最近经常在服务器上开发,经常会遇到不认识的单词,然而 linux 下实在没有什么好用的词典,索性自己写一个好了. 词典 API 首先,Google 了一下可用的词典的 API,发现金山的 iciba ...

  4. 用java实现大文件分割、排序、合并

    import java.io.BufferedReader;   import java.io.BufferedWriter;   import java.io.FileNotFoundExcepti ...

  5. python之基础中的基础(三)

    1.类,类就像是负责特定项目的主管,交给主管干这件事情,主管可以让手下的人分别去完成自己该干的活,最后综合起来把结果交给主管传递出去,即完成任务. class Dog(): ""& ...

  6. POJ1006: 中国剩余定理的完美演绎(非原创)

    问题描述 人自出生起就有体力,情感和智力三个生理周期,分别为23,28和33天.一个周期内有一天为峰值,在这一天,人在对应的方面(体力,情感或智力)表现最好.通常这三个周期的峰值不会是同一天.现在给出 ...

  7. 运用三角不等式加速Kmeans聚类算法

    运用三角不等式加速Kmeans聚类算法 引言:最近在刷<数据挖掘导论>,第九章, 9.5.1小节有提到,可以用三角不等式,减少不必要的距离计算,从而达到加速聚类算法的目的.这在超大数据量的 ...

  8. zoj 1013 Great Equipment DP

    题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=13 很经典的一个DP的题目 定义dp[i][num1][num2]表示 ...

  9. angular4 JavaScript内存溢出问题 (FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory)

    最近在写基于angular4的项目的时候,在build --prod的时候,突然措手不及的蹦出个报错,大致错误如下: 70% building modules 1345/1345 modules 0 ...

  10. 大数的加法运算,杭电oj-1002

    原题地址:http://acm.hdu.edu.cn/showproblem.php?pid=1002   [Problem Description] I have a very simple pro ...