• log4j2或者logback配置模版实现灵活输出服务名


    介绍

    在我们使用log4j2或者logback打印日志时,输出的内容中通常是一定要加上服务名的。以log4j2为例:

    
    <Console name="Console" target="SYSTEM_OUT">
        
        <PatternLayout pattern="server-case %d{yyyy-MM-dd HH:mm:ss} %5p %c{1}:%L - %m%n"/>
    Console>
    
    • 1
    • 2
    • 3
    • 4
    • 5

    服务名为server-case,输出的内容为

    server-case 2023-09-15 17:44:38  INFO ServerCaseApplication:648 - No active profile set, falling back to default profiles: default
    server-case 2023-09-15 17:44:39  INFO TomcatWebServer:108 - Tomcat initialized with port(s): 7081 (http)
    server-case 2023-09-15 17:44:39  INFO Http11NioProtocol:173 - Initializing ProtocolHandler ["http-nio-7081"]
    server-case 2023-09-15 17:44:39  INFO StandardService:173 - Starting service [Tomcat]
    ...
    
    • 1
    • 2
    • 3
    • 4
    • 5

    一般而言都是这么配置就可以完整日志的打印了。但事实却不是,会存在这样一种情况,有的业务是需要去操作合作方他们那边的数据的,包括查询和更新。比如物流网、售票业务、挂号业务、等等。这些数据合作方会提供接口来调用。而在乙方这边,会有一个专门的服务来直连这些接口,其他的服务如果需要合作方的数据或者更新了,就会通过微服务调用这个专门对接数据的服务。

    当开发的项目时间长了后,就会有不同的合作方,而这些不同的合作方会部署到同一套环境中,就比如说注册中心,用的是同一个,而为了保护这个直连接口的服务,防止某一个服务宕机后,会影响其他的合作方,就会把这个服务按照合作方不同,部署成多个不同的实例。

    比如说合作方A B C,那么这个服务的实例就会有ADataService、BDataService、CDataService

    这就有个问题,因为都是用的是一套代码,那怎么才能实现在同一套代码上能部署成不同的实例呢?其实可以从jenkins上修改,

    先把spring.application.name配置的值,使用占位符设置,比如#spring.application.name#,然后在jenkins部署的使用,执行脚本,按照不同的合作方,来替换掉#spring.application.name#,这样就实现了可以有不同的示例名了

    但上述的日志打印服务名还没有解决呢?我们就来解决这个问题

    问题

    有的人可能会想到直接设置一个对象实现EnvironmentAware接口中的setEnvironment(Environment environment),来获取environment来获取spring.application.name

    但这样有问题,设置的这个对象是要在spring上下文中进行加载后才能获得environment,所以在这个对象加载之前的日志输出还是拿不到environment

    @Component
    public class Test implements EnvironmentAware {
       
        
        private Environment environment;
        
        @Override
        public void setEnvironment(final Environment environment) {
       
            this.environment = environment;
            System.setProperty("applicationName", Objects.requireNonNull(environment.getProperty("spring.application.name")));
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    
    <Console name="Console" target="SYSTEM_OUT">
        
        <PatternLayout pattern="${sys:applicationName} %d{yyyy-MM-dd HH:mm:ss} %5p %c{1}:%L - %m%n"/>
    Console>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    ${sys:applicationName} 2023-09-18 10:18:34  INFO ServerCaseApplication:55 - Starting ServerCaseApplication on lukuan with PID 21472 (D:\idea_work_my\gitee\cook-frame\server\server-case\target\classes started by lukuan in D:\idea_work_my\gitee\cook-frame)
    ${sys:applicationName} 2023-09-18 10:18:34  INFO ServerCaseApplication:648 - No active profile set, falling back to default profiles: default
    ${sys:applicationName} 2023-09-18 10:18:34  INFO TomcatWebServer:108 - Tomcat initialized with port(s): 7081 (http)
    ${sys:applicationName} 2023-09-18 10:18:34  INFO Http11NioProtocol:173 - Initializing ProtocolHandler ["http-nio-7081"]
    ${sys:applicationName} 2023-09-18 10:18:34  INFO StandardService:173 - Starting service [Tomcat]
    ${sys:applicationName} 2023-09-18 10:18:34  INFO StandardEngine:173 - Starting Servlet engine: [Apache Tomcat/9.0.46]
    ${sys:applicationName} 2023-09-18 10:18:34  INFO [/]:173 - Initializing Spring embedded WebApplicationContext
    ${sys:applicationName} 2023-09-18 10:18:34  INFO ServletWebServerApplicationContext:285 - Root WebApplicationContext: initialization completed in 795 ms
     _ _   |_  _ _|_. ___ _ |    _ 
    | | |\/|_)(_| | |_\  |_)||_|_\ 
         /               |         
                            3.5.1 
    service-case 2023-09-18 10:18:35  INFO ThreadPoolTaskExecutor:181 - Initializing ExecutorService 'applicationTaskExecutor'
    service-case 2023-09-18 10:18:35  INFO PropertySourcedRequestMappingHandlerMapping:69 - Mapped URL path [/v2/api-docs] onto method [springfox.documentation.swagger2.web.Swagger2Controller#getDocumentation(String, HttpServletRequest)]
    service-case 2023-09-18 10:18:35  INFO Http11NioProtocol:173 - Starting ProtocolHandler ["http-nio-7081"]
    service-case 2023-09-18 10:18:35  INFO TomcatWebServer:220 - Tomcat started on port(s): 7081 (http) with context path ''
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    可以看到比较靠前的日志输出中的applicationName变量是没有被替换成真正的服务名的。

    那怎么办呢?

    分析

    所以我们要从SpringBoot的启动过程入手

    SpringApplication#run(String… args)
    public ConfigurableApplicationContext run(String... args) {
       
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        ConfigurableApplicationContext context = null;
        configureHeadlessProperty()
    • 1
    • 2
    • 3
    • 4
    • 5
  • 相关阅读:
    提升用户体验,给你的模态弹窗加个小细节
    当网络隔离成了必须,跨网文件传输该如何实现?
    想成为优秀的HR,从哪些方面努力?
    Python案例分析|使用Python图像处理库Pillow处理图像文件
    【云原生】Java设计模式8,校验、审批流程改善神器,责任链模式
    【数组】最多能完成排序的块 数学
    mysql的锁分类:表锁和行锁和页面锁
    计算机毕业设计ssm企业员工培训管理系统2q63c系统+程序+源码+lw+远程部署
    对于机器学习的回答
    【技术】SQL动态排序?
  • 原文地址:https://blog.csdn.net/guntun8987/article/details/132979150