Java打log日志

原创 2016年08月31日 17:37:42

最近写Java工程,需要在客户端打上log,以便进行出错追踪。刚开始试了一些log4j之类的包,想着功能强大点儿。但是由于配置、版本不兼容、傻叉Windows等一系列问题,最终放弃,干脆直接采用Java自带的log好了。

关于Java内置Logger的介绍,比较好的有这篇,可以学习一下其基本用法。

但是如果按照那篇博客的“(六)如何使用JDK内置logger ”写一个LogUtil的话,在我的需求下会出现问题。

由于我需要开启多线程,当一个线程出问题之后,另一个线程会出重新开一个log文件写日志,比如原来是xxx.log,会同时出现一个xxx.log.lck,如果那个线程出了问题,新的线程写日志就会写xxx.log.1,同时会出现xxx.log.1.lck,如果再出问题,会继续有xxx.log.2和xxx.log.2.lck以此类推。

从文件的名字来看,在写日志文件xxx.log的时候,xxx.log.lck应该是锁住了这个日志,只有当资源释放后其他的线程才能写这个日志,否则就只能新开日志,写到xxx.log.1中,依次类推。显然这不是我想要的,我想要所有的线程都写到一个log文件中去,不要分开。

功夫不负有心人,经过查找,Writing-logs-single-file-Multiple给出了答案:

Got the error with my code.
Was instantiating a new instance of fileHandler every time getLogger is called. This creates a new file since previous file is locked with other handler.
Changed initialization of Logger to a different method and implemented Singleton on the CustomLogger.

所以说是因为每次写log之前生成的logger创建了不同的fileHandler。只要都使用同一个handler就ok了。

解决了问题之后,感觉还有一些不太满意的地方,想调整一下日志的记录格式,自定义一发。然后在这里找到了答案。

下面是代码:

package com.allinone.client.util;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.logging.Formatter;
import java.util.logging.Handler;
import java.util.logging.LogRecord;

/**
 * 自定义日志格式
 *
 * Created by pos on 2016/8/31.
 */
class MyLogFormatter extends Formatter {

    // Create a DateFormat to format the logger timestamp.
    private static final DateFormat df = new SimpleDateFormat("yyyy/MM/dd hh:mm:ss.SSS");

    public String format(LogRecord record) {
        StringBuilder builder = new StringBuilder(1000);
        builder.append(df.format(new Date(record.getMillis()))).append(" - ");
        builder.append("[").append(record.getSourceClassName()).append(".");
        builder.append(record.getSourceMethodName()).append("] - \n");
        builder.append("\t[").append(record.getLevel()).append("] - ");
        builder.append(formatMessage(record));
        builder.append("\n\n");
        return builder.toString();
    }

    public String getHead(Handler h) {
        return super.getHead(h);
    }

    public String getTail(Handler h) {
        return super.getTail(h);
    }
}
package com.allinone.client.util;

import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.logging.*;

/**
 * 默认将log文件输出到C:\Logs\AIOClient\xxxx年\x月\xxxx-xx-xx.log
 * 路径不存在的话会自动创建
 * 可通过修改getLogFilePath修改生成的log路径
 *
 * Created by pos on 2016/8/30.
 */
public class LogUtil {

    private static Calendar now = Calendar.getInstance();

    private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

    private static final int year = now.get(Calendar.YEAR);

    private static final int month = now.get(Calendar.MONTH) + 1;

    private static final String LOG_FOLDER_NAME = "AIOClient";

    private static final String LOG_FILE_SUFFIX = ".log";

    private static Logger logger = Logger.getLogger("MyLogger");

    //使用唯一的fileHandler,保证当天的所有日志写在同一个文件里
    private static FileHandler fileHandler = getFileHandler();

    private static MyLogFormatter myLogFormatter = new MyLogFormatter();

    private synchronized static String getLogFilePath() {
        StringBuffer logFilePath = new StringBuffer();
//        logFilePath.append(System.getProperty("user.home"));
        logFilePath.append("C:\\Logs");
        logFilePath.append(File.separatorChar);
        logFilePath.append(LOG_FOLDER_NAME);
        logFilePath.append(File.separatorChar);
        logFilePath.append(year);
        logFilePath.append(File.separatorChar);
        logFilePath.append(month);

        File dir = new File(logFilePath.toString());
        if (!dir.exists()) {
            dir.mkdirs();
        }

        logFilePath.append(File.separatorChar);
        logFilePath.append(sdf.format(new Date()));
        logFilePath.append(LOG_FILE_SUFFIX);

//        System.out.println(logFilePath.toString());
        return logFilePath.toString();
    }

    private static FileHandler getFileHandler() {
        FileHandler fileHandler = null;
        boolean APPEND_MODE = true;
        try {
            //文件日志内容标记为可追加
            fileHandler = new FileHandler(getLogFilePath(), APPEND_MODE);
            return fileHandler;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    public synchronized static Logger setLoggerHanlder() {
        return setLoggerHanlder(Level.ALL);
    }

    //    SEVERE > WARNING > INFO > CONFIG > FINE > FINER > FINESET
    public synchronized static Logger setLoggerHanlder(Level level) {

        try {
            //以文本的形式输出
//            fileHandler.setFormatter(new SimpleFormatter());
            fileHandler.setFormatter(myLogFormatter);

            logger.addHandler(fileHandler);
            logger.setLevel(level);
        } catch (SecurityException e) {
            logger.severe(populateExceptionStackTrace(e));
        }
        return logger;
    }

    private synchronized static String populateExceptionStackTrace(Exception e) {
        StringBuilder sb = new StringBuilder();
        sb.append(e.toString()).append("\n");
        for (StackTraceElement elem : e.getStackTrace()) {
            sb.append("\tat ").append(elem).append("\n");
        }
        return sb.toString();
    }

    public static void main(String [] args) {
        Logger logger = LogUtil.setLoggerHanlder(Level.INFO);
        logger.info("Hello, world!");
        logger.severe("What are you doing?");
        logger.warning("Warning !");
//
//        for(Handler h : logger.getHandlers()) {
//            h.close();   //must call h.close or a .LCK file will remain.
//        }
    }
}

效果:
会在C盘下按照年月生成不同的文件夹。以日为单位,每天一个log文件。比如这次的运行结果是生成C:\Logs\AIOClient\2016\8\2016-08-31.log,内容如下:

2016/08/31 05:35:24.077 - [com.allinone.client.util.LogUtil.main] - 
    [INFO] - Hello, world!

2016/08/31 05:35:24.160 - [com.allinone.client.util.LogUtil.main] - 
    [SEVERE] - What are you doing?

2016/08/31 05:35:24.162 - [com.allinone.client.util.LogUtil.main] - 
    [WARNING] - Warning !
版权声明:本文为博主原创文章,未经博主允许不得转载。

Java中的日志——Java.util.logging、log4j、commons-logging

Java中给项目程序添加log主要有三种方式,一使用JDK中的java.util.logging包,一种是log4j,一种是commons-logging。其中log4j和commons-loggin...
  • luoweifu
  • luoweifu
  • 2015年06月14日 22:07
  • 19899

java中log日志的使用(完全版)

 Commons_logging包 Apache通用日志包他为Log4JLogger;NoOpLog;LogKitLogger;Jdk14Logger;AvalonLogger提供了一共通用的接口进行...
  • yuyongpeng
  • yuyongpeng
  • 2007年09月09日 11:25
  • 51176

java中log的应用

log4j的简单应用 备忘#OFF、FATAL、ERROR、WARN、INFO、DEBUG、ALL log4j.rootLogger=warn,stdout,err,war log4j.append...
  • dlf123321
  • dlf123321
  • 2014年08月19日 09:31
  • 1626

Java 中使用log函数的方法

今天用存储过程向数据库插入了500W的数据,耗时N久,于是就想知道二分查找1000万的效率,但忘了怎么计算..... Java 的Math.log(double a) 函数是以e(2.71828....
  • f1024042400
  • f1024042400
  • 2016年11月25日 15:07
  • 7957

记录一个java.util.logging.Logger 使用中关于时间格式的问题

前几天用到了一次java.util.logging.Logger类,该类可以打印相关日志信息并将日志信息写入日志文件。初学该类的时候,代码是从网上拷贝的,具体内容如下: p package c...
  • wanglha
  • wanglha
  • 2016年06月22日 13:15
  • 2078

java log

package com.android.filemanager; import android.util.Log; import java.util.Calendar; public c...
  • zhaoweixing1989
  • zhaoweixing1989
  • 2011年08月09日 23:17
  • 621

JAVA log组件

Log4j2配置文件详解 目录[-] 1 系列目录2 默认配置3 第一个配置例子4 复杂一点的配置4.1 Appender之Syslog配置4.2 Syslog及Syslog-ng相关...
  • huangrunqing
  • huangrunqing
  • 2016年08月25日 15:30
  • 830

java log jar

  • 2012年06月18日 00:53
  • 52KB
  • 下载

Java Logger(java日志)

目录1. 简介2. 安装3. log4j基本概念3.1. Logger3.2. Appender3.2.1. 使用ConsoleAppender3.2.2. 使用FileAppender3.2.3. ...
  • carefree31441
  • carefree31441
  • 2009年10月16日 10:29
  • 56703

Java 提高(4)----- 异常 Logger

异常 Logger推荐博客 http://blog.csdn.net/hguisu/article/details/6155636异常分类 所有的异常有Throwable(直接继承了Object)继...
  • chenqianleo
  • chenqianleo
  • 2017年08月31日 10:43
  • 385
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Java打log日志
举报原因:
原因补充:

(最多只允许输入30个字)