Logback在springboot应用中的common工程共通配置和日志名变量等问题解决方案

Logback在springboot应用中的common工程共通配置和日志名变量等问题解决方案

Logback是Java项目中最常见的日志框架了,不过随着云技术的相关诞生,很多日志已经不用再手动配置生成了。例如常见的K8S容器中就有日志,或者普通的应用日志利用ELK EFK之类的放到ES里面去,本地几乎不留什么日志,那么我为何要写这篇尴尬的文章呢?

因为在这个过程中,有些有趣的和值得记录的事情发生,所以想记录下来与君共勉。如果有幸读到这篇文章的你,刚好遇到需要自己配置Logback,场景和问题与我一样,那或许能帮你少走些弯路也不错。

场景

需求:通过Web接口来查看和下载应用日志日志。

问题:因为我这个项目结构的关系,想在应用本身中生成一个默认的日志文件,用来通过Web接口下载,所以容器的输出流格式的日志没办法获取历史的,总不能把K8S的接口给出来啊,就只能保留应用日志了。自己做日志持久,还不如就用现成的Logback,于是就想把配置的部分当成默认值,直接放到common工程去,就省得开发人员还要改子工程的代码了…然而理想很丰满,现实很骨感…读到这里的你,是不是也觉得so easy?那就来吧,看看我遇见的坑↓

这两天我遇到的坑

  1. logback的共通配置文件放到resource,却读不到?
  2. 如何把logback生成的日志文件配置成和工程名一致呢?
  3. 配置好了logback启动后,为什么会出现多余的日志文件呢?明明没有只有自己的配置,这个是怎么的多出来的(xxxxxxxxx_IS_UNDEFINED)?
  4. logback的filenamepattern只能写静态的日志名,即便是支持变量,也只有日期,数量之类的,不能动态的读取工程名(我就想把日志名动态设置成和项目名一样,为什么就这么费劲,这个需求难道之前没人做过)?
  5. 本地启动明明没啥问题,部署到k8s上就找不到配置文件,连控制台都打印不出日志,什么情况啊?

小坑还有…但都不重要了,就挑这几个大坑说吧。

logback的共通配置文件放到resource,却读不到?

说实话,这个问题其实是我自己对于logback的配置想当然了,所以范的一个典型不看文档而发生错误的例子。如果能仔细看看文件,也不会发生了。

一上来我就认为,不就是logback嘛,我从别的项目里面copy过来一个logback.xml改改,然后丢到common工程,这样就行了吧~~结果,打脸打的啪啪的。日志是有了,但是多了一堆没用的日志,而且还全是一个名,根本分不清是哪个工程的(因为只是测试看看效果,文件名就起的很随意,结果等到要解决第3个问题时,困扰了好长时间,这个容后文详解)
为了让大家看的不那么蒙圈,我先讲一下我的项目结构:
A框架工程
|---- a-comm 框架工程的common包

B项目工程 pom依赖A框架工程
|---- b-comm 业务工程的common包
|-----b-order 业务工程的order子工程

下面看我最初的logback配置文件,大家一定很熟悉了。
a-comm/src/main/resources/logback.xml

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <include resource="org/springframework/boot/logging/logback/base.xml" />

  <!-- 定义日志文件的存储地址 如果变量没定义就是用:后的默认值 只有scope=context的才能在代码中访问到-->
  <property name="LOG_HOME" value="${BOOT_LOGHOME:-logs}" scope="context"/>
  <!-- 日志名称 -->
  <property name="LOG_NAME" value="testlog" scope="context"/>

  <!-- 开发环境 -->
  <springProfile name="dev">
    <!-- 注意这里一定要放到springProfile里, 否则在本机执行的时候还是会去创建相应的文件,但不会输出内容,定义在里面也不会影响ref引用 -->
    <!-- 按照每天生成日志文件 -->
    <appender name="FILE"
      class="ch.qos.logback.core.rolling.RollingFileAppender">
      <rollingPolicy
        class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
        <!--日志文件输出的文件名 -->
        <FileNamePattern>${LOG_HOME}/${LOG_NAME}_%d{yyyy-MM-dd}.%i.log
        </FileNamePattern>
        <!--日志文件保留天数 -->
        <maxHistory>15</maxHistory>
        <!--日志文件最大的大小 -->
        <MaxFileSize>10MB</MaxFileSize>
        <!--日志文件的上限大小,到了阀值就会删除旧的日志 -->
        <totalSizeCap>10GB</totalSizeCap>
      </rollingPolicy>
      <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
        <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
        <charset>UTF-8</charset>
      </encoder>
    </appender>

    <!-- 文件输出 -->
    <appender name="asyncFileAppender" class="ch.qos.logback.classic.AsyncAppender">
      <!-- 不丢失日志.默认的,如果队列的80%已满,则会丢弃TRACT、DEBUG、INFO级别的日志 -->
      <discardingThreshold>0</discardingThreshold>
      <!-- 更改默认的队列的深度,该值会影响性能.默认值为256 -->
      <queueSize>2048</queueSize>
      <includeCallerData>true</includeCallerData>
      <!-- 添加附加的appender,最多只能添加一个 -->
      <appender-ref ref="FILE" />
    </appender>

    <root level="INFO">
      <appender-ref ref="console" />
      <appender-ref ref="asyncFileAppender" />
    </root>
  </springProfile>
</configuration>

这根本不是我想要的效果,那就继续改吧。那就把logback.xml改成include节点,在项目的common工程中引用,这样总行了吧,logback-comm.xml的配置不影响子工程,虽然子工程多个一个共同的配置文件,但也无伤大雅,而且这样还有利于子工程拓展自己的logback配置,一举两得。于是乎改成了这样:

a-comm/src/main/resources/logback-comm.xml

<?xml version="1.0" encoding="UTF-8"?>
<included>
  <include resource="org/springframework/boot/logging/logback/defaults.xml" />
  <include resource="org/springframework/boot/logging/logback/console-appender.xml" />
  
  <!-- 定义日志文件的存储地址 如果变量没定义就是用:后的默认值 只有scope=context的才能在代码中访问到 -表示当前目录 -->
  <property name="LOG_HOME" value="${BOOT_LOGHOME:-logs}" scope="context" />
   <!-- 日志名称 -->
  <property name="LOG_NAME" value="testlog" scope="context"/>
  
  <!-- 将状态信息监听器设置为无操作监听器 不显示logback本身的这些类似 15:40:01,795 |-INFO in ch.qos.logback.xxxxx的相关日志 -->
<!--   <statusListener class="ch.qos.logback.core.status.NopStatusListener" /> -->
  
  <!-- 按照每天生成日志文件 -->
  <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
      <!--日志文件输出的文件名 -->
      <FileNamePattern>${LOG_HOME}/${LOG_NAME}_%d{yyyy-MM-dd}.%i.log
      </FileNamePattern>
      <!--日志文件保留天数 -->
      <maxHistory>7</maxHistory>
      <!--日志文件最大的大小 -->
      <MaxFileSize>20MB</MaxFileSize>
      <!--日志文件的上限大小,到了阀值就会删除旧的日志 -->
      <totalSizeCap>1GB</totalSizeCap>
    </rollingPolicy>
    <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
      <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
      <charset>UTF-8</charset>
    </encoder>
  </appender>
  <!-- 注意这里一定要放到springProfile里, 否则在本机执行的时候还是会去创建相应的文件,但不会输出内容,定义在里面也不会影响ref引用 -->
  <root level="INFO">
      <appender-ref ref="CONSOLE" />
      <appender-ref ref="FILE" />
  </root>
</included>

就是这里 我想当然的认为这样写可以,都在资源目录里面,应该能找的到吧?启动,呵呵,打脸…
b-comm/src/main/resources/logback.xml

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <include resource="a/a-comm/logback-comm.xml"/>
</configuration>

然后仔细翻了一下logback的配置文档,解决了,应该写成完整的包名,把xml放到包名所在的目录里面去,所以共通xml的路径应该是这样:
a-comm/src/main/java/com/a/comm/logging/logback-comm.xml
而业务comm工程的引用格式应该=完整包名+文件名
com/a/a-comm/logging/logback-comm.xml

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <include resource="com/a/comm/logging/logback-comm.xml"/>
</configuration>

启动~OK!第一个问题就搞定了。

如何把logback生成的日志文件配置成和工程名一致呢?

这个比较容易,logback提供了springProperty节点,可以用来接spring的配置文件中的环境变量值。于是把
<property name="LOG_NAME" value="testlog" scope="context"/>
配置替换成
<springProperty scope="context" name="LOG_NAME" source="spring.application.name" />
就ok啦!所以文件又变成这样
a-comm/src/main/resources/logback-comm.xml

<?xml version="1.0" encoding="UTF-8"?>
<included>
  <include resource="org/springframework/boot/logging/logback/defaults.xml" />
  <include resource="org/springframework/boot/logging/logback/console-appender.xml" />
  <springProperty scope="context" name="LOG_NAME" source="spring.application.name" />
  
  <!-- 定义日志文件的存储地址 如果变量没定义就是用:后的默认值 只有scope=context的才能在代码中访问到 -表示当前目录 -->
  <property name="LOG_HOME" value="${BOOT_LOGHOME:-logs}" scope="context" />
  ....
</included>

b-order/src/main/resources/application.yml

spring:
  application:
    name: b-order

ok,启动看看~结果生成了这么两个日志文件

_IS_UNDEFINED.0.log
b-order.0.log

so,我们要的b-order.0.log日志有了,但是这个_IS_UNDEFINED.0.log是什么鬼????作为一个患有完美强迫症的程序员,绝不允许这种莫名其妙的东西出现!!!

配置好了logback启动后,为什么会出现多余的日志文件呢?明明没有只有自己的配置,这个是怎么的多出来的(_IS_UNDEFINED)?

造成这个问题的原因有几种,首先你要确定是否真的在你的工程中只有你的logback生效了,因为有可能在其他依赖工程的jar中,同样存在着logback的配置。

但我的这个工程我很熟悉,就是这一个生效的配置,为什么会多出了这么一个_IS_UNDEFINED的日志文件呢?看起来好像不是配置的问题了,应该是和logback的默认值有关吧?logback.xml配过无数个了,那为什么以前那么多项目,怎么没出现过这个问题呢,奇怪啊?沿着这个思路Debug跟踪了一下。这个问题最后发现是因为logback在spring启动时配置了2次。划重点!!!
日志文件生成:

一次是Spring Cloud的配置加载的,一次是Spring Boot配置加载的。

这回真相大白了!而这个_IS_UNDEFINED正是由于Spring Cloud的配置读取到了我们的a-comm/src/main/java/com/a/comm/logging/logback-comm.xml配置文件中<springProperty scope="context" name="LOG_NAME" source="spring.application.name" />作为日志名变量,但工程的cloud配置文件bootstrap*.yml中并没有指定对应的名称,因为我们只在springboot的配置文件b-order/src/main/resources/application.yml中声明了spring.application.name,cloud的那个没有获取到,所以就变成_IS_UNDEFINED了!

所以你的工程如果只用了spirngboot,那么不会有这个问题的。可如果你的项目中用了springboot+springcloud,还在common配置了logback的话,就会有这个问题了!

既然找到的问题的原因,那么改正就有思路了,把日志名配置成cloud和boot都能获取到的变量不就行啦??思路是没问题了,但现实就是这么残酷,当初放在comm就是为了减少子工程的配置,如果按上面这个方案,那就只能在各个子工程单独增加logback的配置,那不就偏离了初衷了嘛??挠头…挠头…难道就这么个简单的问题,我就想在comm中配置logback,并指定日志名和工程名一样,难道就不行??我不相信!!!然后不信邪的我就开始各种Google和百度,结果…没有!真没有!或许是我没找到吧?但这么大的世界,就只有我一个有这么奇葩的想法吗?不会吧?反复质疑查询了很多遍,就是没找到相关的东西。放弃!靠人不如靠己,有这搜索的功夫,我自己都写出来了,那就自己写吧!我自己写一个总可以了吧?

logback的filenamepattern只能写静态的日志名,即便是支持变量,也只有日期,数量之类的,不能动态的读取工程名(我就想把日志名动态设置成和项目名一样,为什么就这么费劲,这个需求难道之前没人做过)?

于是就开启了我折腾日志文件名的艰辛历程~
首先需要一个属性定义器~这个东西就是logback实现自定义属性而创造的。于是就有了如下代码

/**
 * 日志名称获取器
 */
public class LoggingPropertyDefinerBase extends PropertyDefinerBase {
    private Logger logger = LoggerFactory.getLogger(LoggingPropertyDefinerBase.class);
    private ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();

    /**
     * 获取默认的日志名称 ${spring.application.name}
     * 
     * @return
     */
    private String getLogName() {
        String logName = "";

        // 因为此处logback初始化的太早了 spring还没有加载 所以没有读取的环境变量 只能自己读取了
        Resource[] resources = null;
        try {
            // 加载当前classpath中所有的application*.yml
            resources = resolver.getResources("classpath:application*.yml");
        } catch (IOException e) {
			logger.error("exception in LoggingPropertyDefinerBase.getLogName.getResources with {}", e)
        }
        if (resources != null && resources.length > 0) {
            for (Resource res : resources) {
                // 把yml读取成map
                Map<String, Object> info = YmlUtil.yml2Map(res);
                // 读取application名
                String appName = ConverterUtil.toString(info.get("spring.application.name"));
                // 如果找到了就直接返回
                if (ConverterUtil.isNotEmpty(appName)) {
                    logName += (appName);
                    break;
                }
            }
        }
        return logName;
    }

    @Override
    public String getPropertyValue() {
        return getLogName();
    }
}

有了这个属性定义器,咱们就可以给logback加自定义的属性啦~~~下面改造一下,加一个默认值
a-comm/src/main/java/com/a/comm/logging/logback-comm.xml

  <define name="defLogName" class="com.a.comm.logging.LoggingPropertyDefinerBase"/>
  <!-- 读取spring.application.name中的属性来生成日志文件名 所以需要要求日志的配置要配置在项目的application.yml中 不要放到bootstrap.yml中 否则会出现两个日志文件 -->
  <springProperty scope="context" name="LOG_NAME" source="spring.application.name"  defaultValue="${defLogName}"/>

ok了,启动试试!如期的,cloud和boot的两次加载都获取到了application.yml中的配置(还是会走两次,但两次文件名一致,所以cloud和boot的日志会写到同一个文件里),这样就只剩一个b-order.0.log啦!好,就这样吧~~









------------------------------------------你以为这样就结束了么?和我一样的天真-------------------------------------

本地启动明明没啥问题,部署到k8s上就找不到配置文件,连控制台都打印不出日志,什么情况啊?

开发环境一点问题没有,一部署到测试环境就凉凉,先是一点日志都不打,容器日志一片空白,以至于K8S认为进程没有启动成功,一个劲的LOOP重启。于是版本回滚,开始查找问题。

为什么会什么日志都没有了呢?肯定是刚刚加的东西导致的,那么什么东西找不到了才会不显示日志呢?连正常的输出流都不打印,更别说文件了。所以,那应该是找不到
a-comm/src/main/java/com/a/comm/logging/logback-comm.xml的问题了,但我本地好使啊?做了这么多年开发,自以为是,想当然的觉得我本地环境和测试一样,应该没啥问题,直接上吧,所以就连试都没试,结果,唉…不说了,就这么个logback,打了我多少回脸了,脸都打肿了,我还是老老实实的查吧。于是,本地dockerfile编译,启动,进入容器,哇塞,好神奇!真的不好使呀~~和测试环境一样呢什么情况啊?

于是反着查,先查docker的镜像,是不是缺少了我的a-comm包?答:否
那是不是a-comm包里面没有logback-comm.xml啊?答:是

哎?原来是logback-comm.xml没有打包到jar里面啊?奇怪啊,明明是xml资源文件啊,为什么不打包呢?查了一下maven配置,发现了,原来logback-comm.xml的路径被我从src/main/resources移动到a-comm/src/main/java/com/a/comm/logging/logback-comm.xml去了,所以打包时候被忽略掉了。因为最开始放到resource了,后来改就忘了…maven默认的打包只打包java目录的class文件的,所以缺少了xml的配置,那就加上吧!于是在a-comm/pom.xml中增加了配置

  <build>
    <resources>
        <resource>
            <directory>src/main/resources</directory>
            <includes>
                <include>**/*.properties</include>
                <include>**/*.xml</include>
            </includes>
            <filtering>true</filtering>
        </resource>
        <resource>
            <directory>src/main/java</directory>
            <includes>
                <include>**/*.properties</include>
                <include>**/*.xml</include>
            </includes>
            <filtering>true</filtering>
        </resource>
    </resources>
    ...
  </build>

好,重新打包,这回试试吧。稳重点这回,先我本地的docker里面试一下~~哈哈,正常启动啦,配置的日志生成啦~啦~~啦~~~啪啪啪啪啪,博主的脸被抽的血痕累累~~
刚刚解决的日志名的问题,咋又回来啦?还记不记得上文我们发现cloud和boot初始化了两次logback的事情?对,它又出现了!就是这个undefined!

_IS_UNDEFINED.0.log
b-order.0.log

我自己写的动态获取springboot的配置文件都不好使的嘛?这么神奇吗?于是,继续查吧~
本来想着LoggingPropertyDefinerBase里面也没几行代码,肯定是cloud加载的时候找不到application.yml了。不过我用的可以spring自己的classloader啊PathMatchingResourcePatternResolver!官方的加载器能加载不出资源文件?不可能吧?打个log试试!
于是代码就改成了这样:

		.......
        if (resources != null && resources.length > 0) {
        	......
        } else {
        	logger.debug("not found resources with resolver.getResources(\"classpath:application*.yml\");")
        }

ok,运行一下试试~唉?不对啊,为什么没显示?我的日志呢?输出流,文件里面都没有。我新加的这条logger.debug的日志哪去了?????这么神奇吗?哦,应该是在logback初始化的阶段,logback还没有初始化完成,我用LoggerFactory.getLogger(LoggingPropertyDefinerBase.class);获取的日志对象还没有创建出来,所以这样写打不出来日志的,要是能打出来日志才奇怪呢!!!在想明白了这点后,那么问题来了,那在logback初始化阶段,logback自己是用什么打印出来的日志呢?于是去logback源码找,终于找到了,logback自己用StatusPrinter或者StatusManager来打印的日志,好吧,把这东西挪到自己的代码里面来,于是类变成了这样:

/**
 * 日志名称获取器
 */
public class LoggingPropertyDefinerBase extends PropertyDefinerBase {
    private ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();

    /**
     * 获取默认的日志名称 ${spring.application.name}
     * 
     * @return
     */
    private String getLogName() {
        String logName = "";

        List<Status> statusList = Lists.newArrayList();

        // 因为此处logback初始化的太早了 spring还没有加载 所以没有读取的环境变量 只能自己读取了
        Resource[] resources = null;
        try {
            // 加载当前classpath中所有的application*.yml
            resources = resolver.getResources("classpath:application*.yml");
        } catch (IOException e) {
            ErrorStatus es = new ErrorStatus("exception in LoggingPropertyDefinerBase.getLogName() PathMatchingResourcePatternResolver.getResources", this, e);
            statusList.add(es);
        }
        if (resources != null && resources.length > 0) {
            for (Resource res : resources) {
                // 把yml读取成map
                Map<String, Object> info = YmlUtil.yml2Map(res);
                // 读取application名
                String appName = ConverterUtil.toString(info.get("spring.application.name"));
                // 如果找到了就直接返回
                if (ConverterUtil.isNotEmpty(appName)) {
                    logName += (appName);
                    break;
                }
            }
        }
        // 打印status日志
        InfoStatus is = new InfoStatus("LoggingPropertyDefinerBase gender default log name = " + logName, this);
        statusList.add(is);
        if (statusList.size() > 0) {
            StatusPrinter.print(statusList);
        }
        return logName;
    }

    @Override
    public String getPropertyValue() {
        return getLogName();
    }
}

运行!于是,终于如愿以偿的看见了日志,的确是没有找到application.yml。那就更奇怪了啊,为什么我本地能找到呢?于是开始打断点一点点调试获取配置文件的过程~~经过几番努力,终于发现了问题。原来spring的classloader的路径,受到了一个系统变量的影响,这个变量的名字叫做loader.path,所有java运行时资源都在这里。而我的docker里面因为做了springboot包的瘦身,lib的内容被分离出去了,所以在jar包用命令运行时,覆盖了loader.path参数
java -jar b-order-lastest.jar -Dloader.path=/env/app-lib
所以导致在docker启动了jar包后,就找不到application.yml配置文件了。因为配置文件抽出后,放在了和jar包同级目录的config目录下
/usr/local/app/config/application.yml
/usr/local/app/b-order.jar
而ClassLoader读取的目录是/env/app-lib,当然就找不到配置文件了~~
好吧,事实往往超出你的想象~你以为神奇的诡异BUG,只是一厢情愿罢了,最终还是会发现原来是自己没有写对代码~现实是残酷的~你懂得的越多,就越会发现自己的无知~

那就分开处理吧,开发环境的走PathMatchingResourcePatternResolver,测试和生产这种用了docker的,就走ResourceUtils,于是就有了如下代码:

package com.wisea.cloud.monitor.logging;
/**
 * 日志名称获取器
 * <p/>
 * 日志中如果发现有初始化2次logback 是因为在bootstrap.yml中配置的关系 如果只在application.yml中配置就会只走一次
 * spring cloud 初始化一次
 * spring boot 初始化一次
 */
public class LoggingPropertyDefinerBase extends PropertyDefinerBase {
    private ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();

    /**
     * 获取默认的日志名称 ${spring.application.name}
     * 
     * @return
     */
    private String getLogName() {
        String logName = "";
        List<Status> statusList = Lists.newArrayList();

        // 因为此处logback初始化的太早了 spring还没有加载 所以没有读取的环境变量 只能自己读取了
        List<Resource> resList = Lists.newArrayList();
        try {

            // ResourcePatternResolver读取的是java加载目录 是loader.path
            // 加载当前classpath中所有的application*.yml
            // 一般此处能读到的是开发环境
            Resource[] resArray = resolver.getResources("classpath:application*.yml");
            resList.addAll(Lists.newArrayList(resArray));

            // 如果java加载目录没找到就从运行时目录找
            // 一般此处能读到的 都是jar包和配置分离的测试环境或生产环境
            if (ConverterUtil.isEmpty(resList)) {
                List<File> confList = getDirctoryFiles(ResourceUtils.getFile("/"), ResourceUtils.getFile("config"));
                for (File c : confList) {
                    if (!c.exists()) {
                        continue;
                    }

                    resList.add(new PathResource(c.getAbsolutePath()));
                }
            }
            for (Resource res : resList) {
                // 把yml读取成map
                Map<String, Object> info = YmlUtil.yml2Map(res);
                // 读取application名
                String appName = ConverterUtil.toString(info.get("spring.application.name"));
                // 如果找到了就直接返回
                if (ConverterUtil.isNotEmpty(appName)) {
                    logName += (appName);
                    InfoStatus is = new InfoStatus("find spring.application.name in " + res.getFile().getAbsolutePath(), this);
                    statusList.add(is);
                    break;
                }
            }

        } catch (Exception e) {
            ErrorStatus es = new ErrorStatus("exception in LoggingPropertyDefinerBase.getLogName() PathMatchingResourcePatternResolver.getResources", this, e);
            statusList.add(es);
        }

        // 打印status日志
        InfoStatus is = new InfoStatus("LoggingPropertyDefinerBase gender default log name = " + logName, this);
        statusList.add(is);
        if (statusList.size() > 0) {
            StatusPrinter.print(statusList);
        }
        // 如果没有获取到就用ip地址
        if (ConverterUtil.isEmpty(logName)) {
            List<Inet4Address> localAddresses = Lists.newArrayList();
            try {
                localAddresses = NetworkUtils.getLocalIp4Address();
                if (ConverterUtil.isNotEmpty(localAddresses)) {
                    logName = localAddresses.get(0).getHostAddress();
                }
            } catch (Exception e) {
                ErrorStatus es = new ErrorStatus("exception in LoggingPropertyDefinerBase.getLogName() NetworkUtils.getLocalIp4Address", this, e);
                statusList.add(es);
            }
        }
        return logName;
    }

    /**
     * 查找配置文件
     * 
     * @param filter
     * @param files
     * @return
     */
    private List<File> getDirctoryFiles(File... files) {
        List<File> res = Lists.newArrayList();
        for (File f : files) {
            res.addAll(Lists.newArrayList(f.listFiles((l) -> {
                String n = l.getName();
                return n.startsWith("application") && n.endsWith("yml");
            })));
        }
        return res;
    }

    @Override
    public String getPropertyValue() {
        return getLogName();
    }
}

好了,写到这里就真的结束了。写下这个废话连篇的文章,只是想勉励自己和那些掉到坑里的同志们:

你可以不相信自己,但你要相信机器。在没有绝对的硬件错误情况下,通常出错的都是自己。

  • 6
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值