logback自定义日志格式

logback自定义日志格式logback自定义日志格式1.ClassicConverter继承ClassicConverterpackagecom.demo.conf;importch.qos.logback.classic.pattern.ClassicConverter;importch.qos.logback.classic.spi.ILoggingEvent;importjava.net…

大家好,又见面了,我是你们的朋友全栈君。

logback自定义日志格式

1.ClassicConverter

继承ClassicConverter

package com.demo.conf;
 
import ch.qos.logback.classic.pattern.ClassicConverter;
import ch.qos.logback.classic.spi.ILoggingEvent;
 
import java.net.InetAddress;
import java.net.UnknownHostException;
 
/** * 配置日志中显示IP */
public class IPLogConfig extends ClassicConverter { 
   
    @Override
    public String convert(ILoggingEvent event) { 
   
        try { 
   
            return InetAddress.getLocalHost().getHostAddress();
        } catch (UnknownHostException e) { 
   
            e.printStackTrace();
        }
        return null;
    }
}

然后再logback.xml中配置

<!--配置规则类的位置-->
<conversionRule conversionWord="ip" converterClass="com.demo.conf.IPLogConfig" />
 <appender name="Console" class="ch.qos.logback.core.ConsoleAppender">
        <layout>
            <pattern>%ip -%date{HH:mm:ss} %highlight(%-5level)[%yellow(%thread)]%green(%logger{56}.%method:%L) -%msg%n"</pattern>
        </layout>
    </appender>

2.实现PropertyDefiner

logback提供自定义属性接口PropertyDefiner

实现PropertyDefiner:getPropertyValue()方法

public class GetIpProperty implements PropertyDefiner{ 
   
    @override
    public String getPropertyValue() { 
   
        try { 
   
                InetAddress address = InetAddress.getLocalHost();
                return address.getHostAddress();
 
          } catch (UnknownHostException e) { 
   
              e.printStackTrace();
          }   
               return null;
      }
   	//....
}

然后在logback.xml配置文件中,定义自定义标签define name代表标签,class指向处理的类。在初始化时调用getPropertyValue()

<configuration>
	<define name="ip" class="com.lay.config.log.GetIpProperty"></define>
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    	<encode>
        	<parttern>${ip}-%date{HH:mm:ss} %highlight(%-5level)[%yellow(%thread)]%green(%logger{56}.%method:%L) -%msg%n"</parttern>
        </encode>
    </appender>
</configuration>

3.SLF4JMDC

Logback是在logback-classic模块中实现了SLF4J的MDC功能。

MDC中管理的数据(简称MDC数据)是以单个线程为单位进行访问的,即对MDC数据的操作(如put, get)只对当前线程有效,所以也永远是线程安全的。
在服务端,为每个请求分配一个线程进行处理,所以每个服务端线程处理的请求,都具有唯一的MDC上下文数据。

子线程不会自动继承父线程的MDC数据。所以在创建子线程时,可以先调用MDC的getCopyOfContextMap()方法以返回一个Map<String, String>对象,从而获取父线程的MDC数据,然后再在子线程的开始处,最先调用MDC的setContextMap()方法为子线程设置父线程的MDC数据。从而能够在子线程中访问父线程的MDC数据。

在使用java.util.concurrent.Executors管理线程时,使用同样的方法让子线程继承主线程的MDC数据。

但是,在Web应用中,一个请求可能在不同的阶段被多个线程处理。这时,只是在服务端的处理线程中设置MDC数据,并不能保证请求的某些信息(如用户的认证信息等)总是能够被处理线程访问到。为了在处理一个请求时能够保证某些信息总是可访问,建议使用Servlet Filter,在请求到来时就将信息装入到MDC中,在完成所有的后续处理后,再次通过过滤器时将MDC数据移除。

	public class MyFilter implements Filter { 
   
		public void doFilter(ServletRequest request, ServletResponse response,
			FilterChain chain) throws IOException, ServletException { 
   
			...
			MDC.put(MY_KEY, myValue);
			...
		    try { 
   
			  chain.doFilter(request, response);
			} finally { 
   
			  if (MDC.contains(MY_KEY)) { 
   
				MDC.remove(MY_KEY);
			  }
			}

Logback自带的ch.qos.logback.classic.helpers.MDCInsertingServletFilter能够将HTTP请求的hostname, request URI, user-agent等信息装入MDC,只需在web.xml中设置(建议MDCInsertingServletFilter作为第一个Filter配置,原因请读者思考),后续处理过程就可以直接访问如下请求参数的值:

req.remoteHost
req.xForwardedFor
req.method
req.requestURI
req.requestURL
req.queryString

req.userAgent

源码如下

package com.lay.log.core.filter;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;

/** * @Description: * @Author: lay * @Date: Created in 11:22 2019/3/19 * @Modified By:IntelliJ IDEA */
public class LogFilter implements Filter { 
   
    private static final Logger log = LoggerFactory.getLogger(LogFilter.class);


    @Override
    public void init(FilterConfig filterConfig) { 
   

    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { 
   
        log.info("start log filter");
        this.insertIntoMDC(request);
        log.info("log filter....");
        try { 
   
            chain.doFilter(request, response);
        } finally { 
   
            log.info("log filter....");
            this.clearMDC();
            log.info("end log filter");
        }

    }

    void insertIntoMDC(ServletRequest request) { 
   
        MDC.put("req.remoteHost", request.getRemoteHost());
        if (request instanceof HttpServletRequest) { 
   
            HttpServletRequest httpServletRequest = (HttpServletRequest) request;
            MDC.put("req.requestURI", httpServletRequest.getRequestURI());
            StringBuffer requestURL = httpServletRequest.getRequestURL();
            if (requestURL != null) { 
   
                MDC.put("req.requestURL", requestURL.toString());
            }
            String requestNo = httpServletRequest.getHeader("Request-No");
            if (requestNo != null && !requestNo.equals("")) { 
   
                MDC.put("req.requestNo", requestNo);
            }
            MDC.put("req.method", httpServletRequest.getMethod());
            MDC.put("req.queryString", httpServletRequest.getQueryString());
            MDC.put("req.userAgent", httpServletRequest.getHeader("User-Agent"));
            MDC.put("req.xForwardedFor", httpServletRequest.getHeader("X-Forwarded-For"));
            MDC.put("req.hostIp", getHostIp());
        }
    }

    void clearMDC() { 
   
        MDC.remove("req.remoteHost");
        MDC.remove("req.requestURI");
        MDC.remove("req.queryString");
        MDC.remove("req.requestURL");
        MDC.remove("req.method");
        MDC.remove("req.userAgent");
        MDC.remove("req.xForwardedFor");
        MDC.remove("req.requestNo");
        MDC.remove("req.ho stIp");
    }

    @Override
    public void destroy() { 
   

    }

    public String getHostIp() { 
   
        try { 
   
            InetAddress address = InetAddress.getLocalHost();
            return address.getHostAddress();

        } catch (UnknownHostException e) { 
   
            e.printStackTrace();
        }
        return null;
    }
}

配置

@Component
public class ApplicationConfig { 
   
    @Bean
    public FilterRegistrationBean filterRegistrationBean() { 
   
        FilterRegistrationBean registrationBean = new FilterRegistrationBean();
        Filter actionFilter = new MDCInsertingServletFilter();
        registrationBean.setFilter(actionFilter);
        List<String> urlPatterns = new ArrayList<>();
        urlPatterns.add("/*");
        registrationBean.setUrlPatterns(urlPatterns);
        return registrationBean;
    }
}

使用

<configuration>
    <!-- 彩色日志 -->
    <!-- 彩色日志依赖的渲染类 -->
    <conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter"/>
    <conversionRule conversionWord="wex" converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter"/>
    <conversionRule conversionWord="wEx" converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter"/>
    <!-- 彩色日志格式 -->
    <property name="CONSOLE_LOG_PATTERN" value="${CONSOLE_LOG_PATTERN:-%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(--){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/>/>



    <property name="MDC_LOG_PATTERN" value="IP:%X{req.remoteHost} -url:%X{req.requestURI} -Method:%X{req.method} - QueryString:%X{req.queryString} - device:%X{req.userAgent} -ips:%X{req.xForwardedFor} - %m%n "></property>

    <appender name="Console" class="ch.qos.logback.core.ConsoleAppender">
        <layout>
            <pattern>${MDC_LOG_PATTERN}</pattern>
        </layout>
    </appender>


    <root level="INFO">
        <appender-ref ref="Console"/>
        <!--<appender-ref ref="Sentry"/>-->
    </root>
</configuration>

可以看到 MDC_LOG_PATTERN 中获取了从MDC过滤器中的参数,这样我们就能打印出来了

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/134466.html原文链接:https://javaforall.net

(0)
上一篇 2022年5月2日 下午6:40
下一篇 2022年5月2日 下午6:40


相关推荐

  • cmd net命令详解与图片示意[通俗易懂]

    cmd net命令详解与图片示意[通俗易懂]net命令大全,net命令用法,net网络命令,net命令使用,net命令集,net命令介绍,net常用命令,net命令的使用技巧,net命令如何使用下面对NET命令的不同参数的使用技巧介绍如下:1、NetViewI  作用:显示域列表、计算机列表或指定计算机的共享资源列表。  命令格式:Netview[\computername|/domain[:domainname]]  …

    2022年5月8日
    70
  • hive数据类型转换cast_c语言数据类型的转换

    hive数据类型转换cast_c语言数据类型的转换在《Hive内置数据类型》文章中,我们提到了Hive内置数据类型由基本数据类型和复杂数据类型组成。今天的话题是Hive数据类型之间的转换。同Java语言一样,Hive也包括隐式转换(implicitconversions)和显式转换(explicitlyconversions)。  Hive在需要的时候将会对numeric类型的数据进行隐式转换。比如我们对两个不同数据类型的数字进行比较

    2026年2月7日
    6
  • Vue学习之v-if和v-for指令「建议收藏」

    Vue学习之v-if和v-for指令「建议收藏」Vue学习之v-if和v-for指令

    2022年4月23日
    104
  • idea2019.3.4激活码【2021最新】

    (idea2019.3.4激活码)最近有小伙伴私信我,问我这边有没有免费的intellijIdea的激活码,然后我将全栈君台教程分享给他了。激活成功之后他一直表示感谢,哈哈~IntelliJ2021最新激活注册码,破解教程可免费永久激活,亲测有效,下面是详细链接哦~https://javaforall.net/100143.html…

    2022年3月30日
    54
  • vim编辑器显示行数过多_vim查看指定行

    vim编辑器显示行数过多_vim查看指定行设置ubuntu的vim编辑器显示行数,方法如下:1.打开终端输入:sudovi/etc/vim/vimrc,打开vim的配置文件(使用sudo可忽视vimrc文件的readonly属性);2.在配置文件中,找到最底行,点击键盘a键,打开输入模式;3.输入:setnu,设置显示行数;4.点击键盘esc键,退出输入模式,点击shift+:,输入:wq,保存退出;至此所有用vim打开的…

    2025年7月21日
    7
  • pymssql for linux[通俗易懂]

    pymssql for linux[通俗易懂]linux连接SQLServer,pymssql安装包下载,链接:https://pan.baidu.com/s/1zXyhvatpoaFRpcptmv0reA密码:y3w1安装如下:yuminstallpython-devel-ytarzxfpytz-2018.4.tar.gzcdpytz-2018.4pythonsetup.pyinstallcdta…

    2022年6月19日
    30

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号