最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

log4j控制日志輸出文件名稱的兩種方式小結(jié)

 更新時(shí)間:2021年12月27日 10:47:42   作者:生活不只*眼前的茍且  
這篇文章主要介紹了log4j控制日志輸出文件名稱的兩種方式小結(jié),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

log4j控制日志輸出文件名稱

1. 第一種方式

在類對(duì)象中用如下方式定義logger變量

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

這樣通過名稱的方式獲取logger,需要在log4j.properties文件中定義一個(gè)名稱為lemmaXml的appender,配置如下:

log4j.logger.lemmaXml=INFO,lemmaXml
log4j.appender.lemmaXml=org.apache.log4j.DailyRollingFileAppender
log4j.appender.lemmaXml.Threshold=DEBUG
log4j.appender.lemmaXml.File=${catalina.home}/logs/lemmaXml.log
log4j.appender.lemmaXml.layout=org.apache.log4j.PatternLayout
log4j.appender.lemmaXml.layout.ConversionPattern=%5p %d{yyyy-MM-dd HH:mm:ss} %m %n

上述配置說明,名稱為lemmaXml的appender,是每天形成一個(gè)日志文件,日志文件的名稱為

${catalina.home}/logs/lemmaXml.log

日志的格式為

%5p %d{yyyy-MM-dd HH:mm:ss} %m %n

2. 第二種方式(這種方式親測(cè)正確)

在類對(duì)象中用如下方式定義logger變量

import org.apache.log4j.Logger;
private static Logger logger = Logger.getLogger(ExportLemmaManagerService.class);

即,通過類的參數(shù)來獲取logger變量,此時(shí)必然也需要在log4j.properties文件有關(guān)于該對(duì)象日志文件的輸出配置,當(dāng)然這里的配置不是針對(duì)每個(gè)類專門配置,而是針對(duì)一個(gè)路徑整體配置,即,你可以配置某個(gè)目錄下的所有類方式的輸出文件的文件名稱,如下

log4j.rootLogger=info,stdout 
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Threshold=DEBUG
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p %d{yyyy-MM-dd HH:mm:ss} %c %m %n
  
log4j.logger.com.soso.baike.service=DEBUG,ServiceLog
log4j.appender.ServiceLog=org.apache.log4j.DailyRollingFileAppender
log4j.appender.ServiceLog.Threshold=DEBUG
log4j.appender.ServiceLog.File=${catalina.home}/logs/service.log
log4j.appender.ServiceLog.MaxBackupIndex=10
log4j.appender.ServiceLog.layout=org.apache.log4j.PatternLayout
log4j.appender.ServiceLog.layout.ConversionPattern=%5p %d{yyyy-MM-dd HH:mm:ss} %c %m %n

上述配置了目錄com.soso.baike.service下的輸出文件方式,上述ExportLemmaManagerService類就是在該包下,所以用該包下的類方式來定義logger的話,輸出的文件就都在service.log文件中,每天生成一個(gè)新的日志文件。

如何隨心所欲地自定義log4j輸出格式

在某種情況下,我們需要在不影響原有代碼的基礎(chǔ)上自定義log4j的輸出格式。

例如這樣的需求,硬性規(guī)定了項(xiàng)目的日志格式為:

日期 日志等級(jí) ClassName:line - [版本號(hào)] [請(qǐng)求ip地址] [項(xiàng)目應(yīng)用名稱] [服務(wù)接口模塊] [模塊方法] [業(yè)務(wù)參數(shù)1] [業(yè)務(wù)參數(shù)2] [業(yè)務(wù)參數(shù)3] 日志詳細(xì)內(nèi)容(必須為json格式)

示例:

2018-05-10 14:04:50,972 INFO ViolationService:51 - [v1.0.0] [192.168.137.47] [merchant-service.cx580.com] [OrderController] [messageList] [null] [] [] {"body":"訂單狀態(tài)消息列表resp:{\"code\":1000,\"msg\":\"成功\"}"}

其中:

  • 版本號(hào)是指當(dāng)前服務(wù)接口實(shí)際的版本信息,例如V1.0.1;
  • 請(qǐng)求ip地址為用戶真實(shí)的請(qǐng)求ip;
  • 項(xiàng)目應(yīng)用名稱為項(xiàng)目的名稱或者標(biāo)識(shí),例如支付服務(wù)定義應(yīng)用名稱為payService;
  • 服務(wù)接口模塊是指請(qǐng)求接口對(duì)應(yīng)的模塊代碼,例如請(qǐng)求訂單接口,則接口模塊為OrderControlller;
  • 模塊方法是指接口對(duì)應(yīng)的請(qǐng)求方法,例如下單接口對(duì)應(yīng)模塊方法為createOrder;
  • 業(yè)務(wù)參數(shù)1可根據(jù)實(shí)際情況寫入相應(yīng)的業(yè)務(wù)數(shù)據(jù),錄入訂單號(hào)orderId,該參數(shù)可為空;
  • 業(yè)務(wù)參數(shù)2同上;
  • 業(yè)務(wù)參數(shù)3同上;
  • 日志詳細(xì)內(nèi)容是指請(qǐng)求接口時(shí)需打印出來的描述信息,例如創(chuàng)建訂單異常時(shí),在異常捕捉方法體中描述異常詳細(xì)信息,日志內(nèi)容需定義到一個(gè)json結(jié)構(gòu)中。

以上是我遇到的場(chǎng)景,這時(shí)在不影響原有項(xiàng)目代碼的基礎(chǔ)上,我們做出日志格式的調(diào)整,使用如下方案:

1.通過log4j的占位替換符%X{}配合MDC格式化日志,使用AOP切面在請(qǐng)求線程開始處填充替換符變量

2.繼承l(wèi)og4j的具體appender類,重寫subAppend方法,修改日志輸出的內(nèi)容格式。

此時(shí)log4j文件如下

log4j.rootCategory=INFO, stdout, file, errorfile
#log4j.category.com.cx=DEBUG
log4j.logger.error=errorfile
 
log4j.appender.stdout=com.test.common.GrayLogConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} %5p %c{1}:%L%X{log_version}%X{log_ip}%X{log_item}%X{log_module}%X{log_method}%X{log_req_params} %m%n
 
log4j.appender.file=com.test.common.GrayLogDailyRollingFileAppender
log4j.appender.file.file=${log.dir}/${spring.application.name}.log
log4j.appender.file.DatePattern='.'yyyy-MM-dd
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} %5p %c{1}:%L%X{log_version}%X{log_ip}%X{log_item}%X{log_module}%X{log_method}%X{log_req_params} %m%n
 
log4j.appender.errorfile=com.test.common.GrayLogDailyRollingFileAppender
log4j.appender.errorfile.file=${log.dir}/${spring.application.name}_error.log
log4j.appender.errorfile.DatePattern='.'yyyy-MM-dd
log4j.appender.errorfile.Threshold = ERROR
log4j.appender.errorfile.layout=org.apache.log4j.PatternLayout
log4j.appender.errorfile.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} %5p %c{1}:%L%X{log_version}%X{log_ip}%X{log_item}%X{log_module}%X{log_method}%X{log_req_params} %m%n

在log4j.properties文件,我們做了兩個(gè)變動(dòng),一個(gè)是添加了%X{value}的變量,另一個(gè)則是將原本的DailyRollingFileAppender修改成了com.test.common.GrayLogConsoleAppender。

處理log4j的變量,對(duì)代碼進(jìn)行controller切面,在一個(gè)http請(qǐng)求java的入口中放入線程變量,該線程變量在當(dāng)次http請(qǐng)求生命周期內(nèi)生效。

切面代碼如下:

@Around("execution(public * com.test.controller..*.*(..))")
    public Object aroundController(ProceedingJoinPoint joinPoint) {
        ServletRequestAttributes attributes =(ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request =attributes.getRequest();
        String execIp = request.getHeader("X-Real-IP");
        if(StringUtils.isBlank(execIp)){
            execIp=request.getRemoteAddr();
        }
        String execClass= joinPoint.getTarget().getClass().getSimpleName();
        String execMethod = joinPoint.getSignature().getName();
        Map<String,String[]> map = request.getParameterMap();
        List<String> paramsList = new ArrayList<>();
        for(Map.Entry<String,String []> m : map.entrySet()){
            String [] value = m.getValue();
            paramsList.add( m.getKey() + "=" + StringUtils.join(value,","));
        }
 
        String execParams = "[" + StringUtils.join(paramsList,"&") + "] [] []";
        MDC.put("log_version"," - [V1.0.0]");
        MDC.put("log_item"," [violation-mini]");
        MDC.put("log_module"," [" + execClass + "]");
        MDC.put("log_method"," [" + execMethod+ "]");
        MDC.put("log_req_params"," " + execParams);
        MDC.put("log_ip"," [" + execIp+ "]");
        Object result= null;
        try {
            result = joinPoint.proceed();
        } catch (Throwable throwable) {
            LOGGER.error("方法異常:",throwable);
        }
        return result;
    }

至此,格式中的MDC變量都已被放入成功。

下一步,將原本的日志內(nèi)容套上json外套。

新建GrayLogConsoleAppender類繼承具體的appender類

代碼如下:

package com.test.common; 
import net.sf.json.JSONObject;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.ConsoleAppender;
import org.apache.log4j.spi.LoggingEvent;
import org.apache.log4j.spi.ThrowableInformation; 
import java.lang.reflect.Field;
 
/**
 * @Author: Lxx
 * @Description:
 * @Date: Created in 17:29 2018/5/30
 */
public class GrayLogConsoleAppender extends ConsoleAppender {
    @Override
    protected void subAppend(LoggingEvent event) {
        try {
            Class<LoggingEvent> clazz = LoggingEvent.class;
            Field filed = clazz.getDeclaredField("throwableInfo");
            filed.setAccessible(true);
            Object exception = filed.get(event);
            JSONObject json = new JSONObject();
            if(exception != null){
                if(exception instanceof ThrowableInformation){
                    ThrowableInformation throwableInformation = (ThrowableInformation) exception;
                    String [] details = throwableInformation.getThrowableStrRep();
                    String error_msg = StringUtils.join(details,"\r\n");
                    json.put("exception",error_msg);
                }
            }
            filed.set(event,null);
            boolean flag = false;
            Field filed1 = clazz.getDeclaredField("message");
            filed1.setAccessible(true);
            Object message = filed1.get(event);
            if (message instanceof String) {
                String msg = (String) message;
                if (message != null) {
                    flag = true;
                }
                json.put("body", msg);
                filed1.set(event, json.toString());
            }
            if(!flag){
                Field filed2 = clazz.getDeclaredField("renderedMessage");
                filed2.setAccessible(true);
                Object message2 = filed2.get(event);
                if (message2 instanceof String) {
                    String msg = (String) message2;
                    json.put("body", msg);
                    filed2.set(event, json.toString());
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        super.subAppend(event);
    }
}

至此,已為日志內(nèi)容套上json外套,并且當(dāng)有異常日志時(shí),將異常的堆棧信息放入json的exception中輸出出來,不打印堆棧信息。

最終結(jié)果:

2018-06-09 00:48:31,849 INFO LogAspect:65 - [V1.0.0] [223.88.53.135] [violation-mini] [TestController] [queryList] [appName=abc&authType=test&avatar=&nickName=&token=asdfasdfadsfasdf&userId=asdfasdfasdfasdf&userType=aaaaa] [] [] {"body":"結(jié)果為:ResponseResult{code='0', msg='null', errormsg='查詢成功', data={}, successFlag=false}"}

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • springCloud中的Sidecar多語言支持詳解

    springCloud中的Sidecar多語言支持詳解

    這篇文章主要介紹了springCloud中的Sidecar多語言支持詳解,Sidecar是將一組緊密結(jié)合的任務(wù)與主應(yīng)用程序共同放在一臺(tái)主機(jī)Host中,但會(huì)將它們部署在各自的進(jìn)程或容器中,需要的朋友可以參考下
    2024-01-01
  • Linux系統(tǒng)卸載重裝JDK的完整流程

    Linux系統(tǒng)卸載重裝JDK的完整流程

    Linux系統(tǒng)有時(shí)候會(huì)默認(rèn)使用OpenJDK版本,需要卸載后重新安裝自己需要的JDK版本,下面這篇文章主要給大家介紹了關(guān)于Linux系統(tǒng)卸載重裝JDK的完整流程,需要的朋友可以參考下
    2024-02-02
  • Java通過JsApi方式實(shí)現(xiàn)微信支付

    Java通過JsApi方式實(shí)現(xiàn)微信支付

    本文講解了Java如何實(shí)現(xiàn)JsApi方式的微信支付,代碼內(nèi)容詳細(xì),文章思路清晰,需要的朋友可以參考下
    2015-07-07
  • spring設(shè)置攔截器代碼實(shí)例

    spring設(shè)置攔截器代碼實(shí)例

    這篇文章主要介紹了spring設(shè)置攔截器代碼實(shí)例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-09-09
  • Java正則表達(dá)式匹配不到結(jié)果的解決

    Java正則表達(dá)式匹配不到結(jié)果的解決

    這篇文章主要介紹了Java正則表達(dá)式匹配不到結(jié)果的解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2021-02-02
  • Java集合ArrayDeque類實(shí)例分析

    Java集合ArrayDeque類實(shí)例分析

    這篇文章主要介紹了Java集合ArrayDeque類實(shí)例分析的相關(guān)資料,需要的朋友可以參考下
    2017-04-04
  • 淺談Java slf4j日志簡(jiǎn)單理解

    淺談Java slf4j日志簡(jiǎn)單理解

    這篇文章主要介紹了淺談Java日志簡(jiǎn)單理解,詳細(xì)的介紹了slf4j的概念和使用,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-07-07
  • idea中g(shù)it提交的代碼如何回退到指定版本

    idea中g(shù)it提交的代碼如何回退到指定版本

    文章詳細(xì)介紹了如何在本地和遠(yuǎn)程倉庫中回退到指定的Git版本,通過步驟說明了如何使用Git命令和右鍵菜單選項(xiàng)來實(shí)現(xiàn)這一操作
    2024-11-11
  • SpringBoot密碼加密的實(shí)現(xiàn)示例

    SpringBoot密碼加密的實(shí)現(xiàn)示例

    本文主要介紹了SpringBoot密碼加密的實(shí)現(xiàn)示例,包括引入依賴、配置加密工具、生成加密密鑰、加密密碼、配置解密,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-08-08
  • java基礎(chǔ)的詳細(xì)了解第五天

    java基礎(chǔ)的詳細(xì)了解第五天

    這篇文章對(duì)Java編程語言的基礎(chǔ)知識(shí)作了一個(gè)較為全面的匯總,在這里給大家分享一下。需要的朋友可以參考,希望能給你帶來幫助
    2021-08-08

最新評(píng)論

东丰县| 和顺县| 永修县| 崇阳县| 密山市| 东丰县| 威远县| 保靖县| 苍南县| 白城市| 嵩明县| 阜城县| 清水县| 江津市| 拉孜县| 遵化市| 开封市| 宁明县| 开原市| 钦州市| 庆元县| 旬阳县| 益阳市| 东莞市| 依安县| 伊春市| 响水县| 云霄县| 新乡市| 都兰县| 永寿县| 崇文区| 娱乐| 额敏县| 武城县| 宣城市| 阜新市| 清原| 友谊县| 交口县| 黄浦区|