封装log4j支持记录到testng

一、初始方案

自动化中需要把日志通过testng的Reporter.log来记录日志在报告中展示。开始是新增了一个日志类:

ReporterLog.class

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.testng.Reporter;

public class ReporterLogger {
    private Logger LOGGER;

    public ReporterLogger(Class<?> clazz){
        LOGGER= LoggerFactory.getLogger(clazz);
    }

    public void  info(String message){
        //使用slf4j打印到控制台或者文件
        LOGGER.info(message);
        //记录到Reporter
        Reporter.log(message);
    }

}

 

这样会有2个问题:

1、LOGGER.info(message);这句话打印出来的类名、方法名、行号等不是调用ReporterLogger方法info的类,二是ReporterLogger类。

2、Reporter.log记录的日志,没有时间、类名、方法名、行号。

 

第一个问题测试:

import com.sqe.sas.test.service.ReporterLogger;

public class LogTest {
    private static final ReporterLogger LOGGER = new ReporterLogger(LogTest.class);

    public static void main(String[] args) {
        LOGGER.info("processing。。。。");
    }

}

打印结果:

[main][2019-01-29 18:28:14] [INFO] [LogTest.info:25] processing。。。。

类名打印的是对的,但是方法名和行号打印的都是ReporterLogger中的

 

 

二、改进方案:

第一个问题:

使用log4j的log方法

import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.testng.Reporter;

public class ReporterLogger {
    private Logger LOGGER; //使用org.apache.log4j.Logger 而不是org.slf4j.Logger;
    static final String FQCN = ReporterLogger.class.getName();  // log4j把传递进来的callerFQCN在堆栈中一一比较,相等后,再往上一层即认为是用户的调用类

    public ReporterLogger(Class<?> clazz){
        LOGGER= Logger.getLogger(clazz); // 这里也要改
    }


    public void  info(String message){
        //使用slf4j打印到控制台或者文件
        LOGGER.log(FQCN, Level.INFO,message,null);
        //记录到Reporter
        Reporter.log(message);
    }

}

 

再次测试,打印结果如下:

 [main][2019-01-30 10:44:23] [INFO] [LogTest.main:7] processing。。。。

已经可以了打印正确的方法名和行号了

 

第二个问题:

在打印的字符串前加上时间、类名、方法名、行号

 

import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.testng.Reporter;

import java.text.SimpleDateFormat;
import java.util.Date;

public class ReporterLogger {
    private Logger LOGGER; //使用org.apache.log4j.Logger 而不是org.slf4j.Logger;
    static final String FQCN = ReporterLogger.class.getName();  // og4j把传递进来的callerFQCN在堆栈中一一比较,相等后,再往上一层即认为是用户的调用类

    public ReporterLogger(Class<?> clazz){
        LOGGER= Logger.getLogger(clazz); // 这里也要改
    }


    public void  info(String message){
        //使用slf4j打印到控制台或者文件
        LOGGER.log(FQCN, Level.INFO,message,null);
        message = getLogTag()+message;
        //记录到Reporter
        Reporter.log(message);
    }
    //根据堆栈信息,拿到调用类的名称、方法名、行号
    public String getLogTag(){
        String logTag = "";
        Long timeStamp = System.currentTimeMillis();
        String dateString = timestampToDate(timeStamp);
        StackTraceElement stack[] = (new Throwable()).getStackTrace();
        for(int i=0;i<stack.length;i++) {
            StackTraceElement s = stack[i];
            if(s.getClassName().equals(LOGGER.getName())){
                logTag= "["+dateString+"]"+"["+classNameDeal(s.getClassName())+":"+s.getMethodName()+":"+s.getLineNumber()+"]";
            }
        }
        return logTag;
    }

    //时间戳转date字符串
    public static String timestampToDate(Long timestamp){
        if(timestamp.toString().length() <13){
            timestamp = Long.valueOf(timestamp.toString().substring(0,10)+"000");
        }
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
        Date date = new Date(timestamp);
        String dateStr = sdf.format(date);
        return dateStr;
    }

    //去掉包名,只保留类名
    private String classNameDeal(String allName){
        String[] className = allName.split("\\.");
        return className[className.length-1];
    }
}

 

posted @ 2019-01-30 10:57  弘文馆校书  阅读(1210)  评论(0编辑  收藏  举报