分批次,分目录文件记录不同的业务记录的日志,然后日志按照不同的业务在不同的目录下供大数据平台捞日志处理数据
使用的是开源的一个JHipster框架,也是基于Springcloud开源的,整合的功能比较多.但是自己只是知道的寥寥无几..
spring在使用的使用,也是通过切面的方式将日志功能切入到整体架构中:
package com.trs.idap.aop.logging;
import io.github.jhipster.config.JHipsterConstants;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.env.Environment;
import java.util.Arrays;
/**
* Aspect for logging execution of service and repository Spring components.
*
* By default, it only runs with the "dev" profile.
*/
@Aspect
public class LoggingAspect {
private final Logger log = LoggerFactory.getLogger(this.getClass());
private final Environment env;
public LoggingAspect(Environment env) {
this.env = env;
}
/**
* Pointcut that matches all repositories, services and Web REST endpoints.
*/
@Pointcut("within(@org.springframework.stereotype.Repository *)" +
" || within(@org.springframework.stereotype.Service *)" +
" || within(@org.springframework.web.bind.annotation.RestController *)")
public void springBeanPointcut() {
// Method is empty as this is just a Pointcut, the implementations are in the advices.
}
/**
* Pointcut that matches all Spring beans in the application's main packages.
*/
@Pointcut("within(com.trs.idap.repository..*)"+
" || within(com.trs.idap.service..*)"+
" || within(com.trs.idap.web.rest..*)")
public void applicationPackagePointcut() {
// Method is empty as this is just a Pointcut, the implementations are in the advices.
}
/**
* Advice that logs methods throwing exceptions.
*
* @param joinPoint join point for advice
* @param e exception
*/
@AfterThrowing(pointcut = "applicationPackagePointcut() && springBeanPointcut()", throwing = "e")
public void logAfterThrowing(JoinPoint joinPoint, Throwable e) {
if (env.acceptsProfiles(JHipsterConstants.SPRING_PROFILE_DEVELOPMENT)) {
log.error("Exception in {}.{}() with cause = \'{}\' and exception = \'{}\'", joinPoint.getSignature().getDeclaringTypeName(),
joinPoint.getSignature().getName(), e.getCause() != null? e.getCause() : "NULL", e.getMessage(), e);
} else {
log.error("Exception in {}.{}() with cause = {}", joinPoint.getSignature().getDeclaringTypeName(),
joinPoint.getSignature().getName(), e.getCause() != null? e.getCause() : "NULL");
}
}
/**
* Advice that logs when a method is entered and exited.
*
* @param joinPoint join point for advice
* @return result
* @throws Throwable throws IllegalArgumentException
*/
@Around("applicationPackagePointcut() && springBeanPointcut()")
public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {
if (log.isDebugEnabled()) {
log.debug("Enter: {}.{}() with argument[s] = {}", joinPoint.getSignature().getDeclaringTypeName(),
joinPoint.getSignature().getName(), Arrays.toString(joinPoint.getArgs()));
}
try {
Object result = joinPoint.proceed();
if (log.isDebugEnabled()) {
log.debug("Exit: {}.{}() with result = {}", joinPoint.getSignature().getDeclaringTypeName(),
joinPoint.getSignature().getName(), result);
}
return result;
} catch (IllegalArgumentException e) {
log.error("Illegal argument: {} in {}.{}()", Arrays.toString(joinPoint.getArgs()),
joinPoint.getSignature().getDeclaringTypeName(), joinPoint.getSignature().getName());
throw e;
}
}
}
springBeanPointcut
applicationPackagePointcut
两个主要的切面;
我们一般使用的还是根据package来进行切入;
当我们需要增加时,只需要增加package的目录即可;
然后整合logback-spring.xml中的属性:
当configuration标签的scan设置为true时,只需要在下面添加一个appender,给予其相应属性,即可....
<!-- The FILE and ASYNC appenders are here as examples for a production configuration -->
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>logFile.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<maxFileSize>500MB</maxFileSize>
<maxHistory>90</maxHistory>
<totalSizeCap>20GB</totalSizeCap>
</rollingPolicy>
<encoder>
<charset>utf-8</charset>
<Pattern>%d %-5level [%thread] %logger{0}: %msg%n</Pattern>
</encoder>
</appender>
<!-- 4GZM综合时间与大小的滚动策略,先按分钟滚动,文件大于100mb时再按大小滚动 -->
<appender name="4GZM" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/tranruns4G/4gzhenma</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${log.path}/tranruns4G/4gzhenma%d{yyyyMMddHHmm}.log</fileNamePattern>
<!-- <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>100MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>-->
<!-- 保存前30天的日志文件 -->
<!-- <maxHistory>30</maxHistory>-->
</rollingPolicy>
<encoder>
<pattern>%date{yyyy-MM-dd HH:mm:ss.SSS} %-5level %logger{36} - %msg%n</pattern>
<!-- 此处设置字符集 -->
<charset>UTF-8</charset>
<immediateFlush>true</immediateFlush>
</encoder>
</appender>
启用日志
<!--启用4g帧码的日志等级:INFO/OFF-->
<logger name="4GZM" level="INFO" additivity="false">
<appender-ref ref="4GZM"/>
</logger>
异步使用,异步加载日志,提高性能
<appender name="ASYNC" class="ch.qos.logback.classic.AsyncAppender">
<queueSize>512</queueSize>
<appender-ref ref="FILE"/>
<appender-ref ref="4GZM"/>
<appender-ref ref="ERR4GDATA"/>
</appender>
然后在项目中使用的时候,(注意此时的类,需要在前面定义的packagepointcut的切面类下) 声明一个全局变量,下面就是可以根据自己的业务到指定的地方记录日志了...
private final Logger zm4gLog = LoggerFactory.getLogger("4GZM");
就是简单的zm4gLog.info()
然后,日志就会根据你在logback-spring中配置的策略,生成指定的日志文件.....66666
此时有一个属性是
immediateFlush此属性默认是false,是有8k数据量的缓存,而我们在使用的时候,不想使用它的缓存,而做一个及时的flush,所以,就添加了该属性;
其实日志框架有很多很多好玩的东西,只怪自己太菜.......
补充:
后续还增加了对整个日志级别的控制....
可以定义整体控制台或者是写入日志的日志级别;debug,info等级别;
只需要在configuration标签下,添加<springProperty>属性标签,获得配置文件中的日志级别;然后root标签下,给level赋值就是需要的日志级别;即可;
application.yml文件给的配置文件就是:
<configuration scan="true">
<include resource="org/springframework/boot/logging/logback/base.xml"/>
<springProperty scope="context" name="log.path" source="log.path"/>
<springProperty scope="context" name="log.level" source="log.level"/>
<root level="${log.level}">
<appender-ref ref="CONSOLE"/>
<appender-ref ref="FILE"/>
</root>