zoukankan      html  css  js  c++  java
  • 使用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的文件夹

  • 相关阅读:
    大型门户网站架构设计的可伸缩性(转载)
    geodatabase的类型(翻译)
    在Windows Server 2008上部署SVN代码管理总结
    可以有效改进项目管理技能的十个过程(转载)
    GTD和知识管理
    查询Oracle版本号
    微软产品组里的十一类人(转载)
    在Win7中创建、部署WebService时遇到的访问被拒绝错误解决方法
    小议地理编码(转载)
    在Win7中将我的电脑快捷方式放入任务栏
  • 原文地址:https://www.cnblogs.com/wutongshu-master/p/10930812.html
Copyright © 2011-2022 走看看