使用logback实现http请求日志导入mongodb

spring boot自带logback作为其日志新系统,但是在实际工作中,常常需要对日志进行管理或分析,
如果只是单纯的将日志导入文本文件,则在查询时操作过于繁琐,
如果将其导入mysql等关系型数据库进行存储,又太影响系统性能,同时由于Mysql其结构化的信息存储结构,导致在存储时不够灵活。
因此,在此考虑将springboot系统中产出的日志(logback) 存入mongodb中

1.pom.xml 引入依赖

注意排除掉log4j的依赖

  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-mongodb</artifactId>
    <version>1.5.8.RELEASE</version>
  </dependency>

  <!-- https://mvnrepository.com/artifact/ch.qos.logback/logback-core -->
  <dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-core</artifactId>
    <version>1.2.3</version>
  </dependency>

  <!-- https://mvnrepository.com/artifact/ch.qos.logback/logback-classic -->
  <dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-classic</artifactId>
    <version>1.2.3</version>
  </dependency>
<!-- log4j 记录日志-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j</artifactId>
<version>1.3.8.RELEASE</version>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</exclusion>
</exclusions>
</dependency>

<!--AOP-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
<version>1.5.7.RELEASE</version>
</dependency>

2.创建实体类: logback.MyLog.java

package com.wutongshu.springboot.logback;

import java.io.Serializable;
import java.util.Date;

public class MyLog implements Serializable {
    private String id;
    private String msg;
    private Date time;
    private String threadName;
    private String level;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

    public Date getTime() {
        return time;
    }

    public void setTime(Date time) {
        this.time = time;
    }

    public String getThreadName() {
        return threadName;
    }

    public void setThreadName(String threadName) {
        this.threadName = threadName;
    }

    public String getLevel() {
        return level;
    }

    public void setLevel(String level) {
        this.level = level;
    }
}
View Code

3.添加数据访问接口: LogRepository.java

package com.wutongshu.springboot.logback;

import org.springframework.data.mongodb.repository.MongoRepository;

public interface LogRepository extends MongoRepository<MyLog,String> {
}

4.Appender 类: MongoDBAppender.java

package com.wutongshu.springboot.logback;

import ch.qos.logback.classic.spi.LoggingEvent;
import ch.qos.logback.core.UnsynchronizedAppenderBase;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

import java.util.Date;
@Component
public class MongoDBAppender extends UnsynchronizedAppenderBase<LoggingEvent> implements
        ApplicationContextAware {
    private static LogRepository logRepository;

    @Override
    public void start() {
        super.start();
    }
    @Override
    public void stop() {
        super.stop();
    }
    @Override
    protected void append(LoggingEvent e) {
        MyLog myLog = new MyLog();
        myLog.setLevel(e.getLevel().toString());
        myLog.setMsg(e.getFormattedMessage());
        myLog.setThreadName(e.getThreadName());
        myLog.setTime(new Date(e.getTimeStamp()));
        logRepository.save(myLog);
    }
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) {
        if (applicationContext.getAutowireCapableBeanFactory().getBean(LogRepository.class) != null) {
            logRepository = (LogRepository) applicationContext.getAutowireCapableBeanFactory().getBean(LogRepository.class);
        }
    }
}

5.创建切面类记录日志信息

logger取名为MONGODB
通过getBasicDBObject函数从HttpServletRequest和JoinPoint对象中获取请求信息,并组装成BasicDBObject
getHeadersInfo函数从HttpServletRequest中获取header信息
通过logger.info(),输出BasicDBObject对象的信息到mongodb

package com.wutongshu.springboot.logback;

import com.mongodb.BasicDBObject;
import org.apache.log4j.Logger;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

/**
 * 日志切面类
 */
@Aspect
@Component
@Order(5)
public class WebLogAspect {
    private Logger logger=Logger.getLogger("MONGODB");

    private ThreadLocal<Long> startTime=new ThreadLocal<>();


    @Pointcut("execution(public * com.*.*.web.*.*(..))")
    public void webLog(){

    }

    @Before(value = "webLog()")
    public void doBefore(JoinPoint point){
        startTime.set(System.currentTimeMillis());

        logger.info("WebLogAspect.doBefore............");
        ServletRequestAttributes attributes=
                (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request=attributes.getRequest();
        // 获取要记录的日志内容
        BasicDBObject logInfo = getBasicDBObject(request, point);
        logger.info(logInfo);
    }

    private BasicDBObject getBasicDBObject(HttpServletRequest request, JoinPoint point) {
        // 基本信息
        BasicDBObject r = new BasicDBObject();
        r.append("requestURL", request.getRequestURL().toString());
        r.append("requestURI", request.getRequestURI());
        r.append("queryString", request.getQueryString());
        r.append("remoteAddr", request.getRemoteAddr());
        r.append("remoteHost", request.getRemoteHost());
        r.append("remotePort", request.getRemotePort());
        r.append("localAddr", request.getLocalAddr());
        r.append("localName", request.getLocalName());
        r.append("method", request.getMethod());
        r.append("headers", getHeadersInfo(request));
        r.append("parameters", request.getParameterMap());
        r.append("classMethod", point.getSignature().getDeclaringTypeName() + "." + point.getSignature().getName());
        r.append("args", Arrays.toString(point.getArgs()));
        return r;
    }

    /**
     * 获取头信息
     *
     * @param request
     * @return
     */
    private Map<String, String> getHeadersInfo(HttpServletRequest request) {
        Map<String, String> map = new HashMap<>();
        Enumeration headerNames = request.getHeaderNames();
        while (headerNames.hasMoreElements()) {
            String key = (String) headerNames.nextElement();
            String value = request.getHeader(key);
            map.put(key, value);
        }
        return map;
    }


}
View Code

 6.创建logback.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE xml>

<configuration scan="true" scanPeriod="3600 seconds" debug="false">

  <property name="logDir" value="logs"/>

  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    <encoder>
      <charset>UTF-8</charset>
      <pattern>%d [%thread] %-5level %logger{68} %line - logId[[%X{client}][%X{request_id}]] - %msg%n</pattern>
    </encoder>
  </appender>

  <appender name="RollingFile" class="ch.qos.logback.core.rolling.RollingFileAppender">

    <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
      <level>TRACE</level>
    </filter>

    <!-- 可让每天产生一个日志文件,最多 10 个,自动回滚 -->
    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
      <fileNamePattern>${logDir}/file-%d{yyyy-MM-dd}.log</fileNamePattern>
      <maxHistory>10</maxHistory>
    </rollingPolicy>

    <encoder>
      <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n</pattern>
      <charset>UTF-8</charset>
    </encoder>
  </appender>
  <!--appender类的路径-->
  <appender name="MONGODB" class="com.wutongshu.springboot.logback.MongoDBAppender"/>

  <root level="INFO">
    <appender-ref ref="STDOUT"/>
    <appender-ref ref="RollingFile"/>
    <appender-ref ref="MONGODB"/>
  </root>
</configuration>

7.在application.properties里添加mongodb的uri

启动MongoDB数据库,可看到多了一个名为logs的database

在java的项目结构上也多了个logs的文件夹

原文地址:https://www.cnblogs.com/wutongshu-master/p/10930812.html