zoukankan      html  css  js  c++  java
  • Spring Boot log4j实现把日志存入mongodb

    准备工作

      1.自定义appender的实现

      log4j提供的输出器实现自Appender接口,要自定义appender输出到MongoDB,只需要继承AppenderSkeleton类,并实现几个方法即可完成。

      在pom.xml中引入下面依赖:

    <dependency>
        <groupId>org.mongodb</groupId>
        <artifactId>mongodb-driver</artifactId>
        <version>3.2.2</version>
    </dependency>

      实现MongoAppender

    /**
     * 自定义appender
     */
    public class MongoAppender extends AppenderSkeleton{
    
        private MongoClient mongoClient;
        private MongoDatabase mongoDatabase;
        private MongoCollection<BasicDBObject> logsCollection;
    
        /**
         * mongodb链接url
         */
        private String connectionUrl;
    
        /**
         * 记录日志的数据库
         */
        private String databaseName;
    
        /**
         * 记录日志的集合
         */
        private String collectionName;
    
        /**
         * 根据log4j.properties中的配置创建mongodb连接
         * LoggingEvent提供getMessage()函数来获取日志消息
         * 往配置的记录日志的collection中插入日志消息
         * @param loggingEvent
         */
        @Override
        protected void append(LoggingEvent loggingEvent) {
            if(mongoDatabase == null){
                MongoClientURI connectionString = new MongoClientURI(connectionUrl);
                mongoClient = new MongoClient(connectionString);
                mongoDatabase = mongoClient.getDatabase(databaseName);
                logsCollection = mongoDatabase.getCollection(collectionName, BasicDBObject.class);
            }
            logsCollection.insertOne((BasicDBObject) loggingEvent.getMessage());
        }
    
        @Override
        public void close() {
            if(mongoClient != null){
                mongoClient.close();
            }
        }
    
        @Override
        public boolean requiresLayout() {
            return false;
        }
    }

      配置log4j.properties

    log4j.logger.mongodb=INFO, mongodb
    # mongodb输出
    log4j.appender.mongodb=com.ysl.appender.MongoAppender
    log4j.appender.mongodb.connectionUrl=mongodb://localhost:27017
    log4j.appender.mongodb.databaseName=logs
    log4j.appender.mongodb.collectionName=logs_request

      使用mongodb logger

    • logger取名为mongodb的
    • 通过getBasicDBObject函数从HttpServletRequest和JoinPoint对象中获取请求信息,并组装成BasicDBObject
      • getHeadersInfo函数从HttpServletRequest中获取header信息
    • 通过logger.info(),输出BasicDBObject对象的信息到mongodb
    @Aspect
    @Order(1)
    @Component
    public class WebLogAspect {
    
        private Logger logger = Logger.getLogger("mongodb");
    
        @Pointcut("execution(public * com.didispace.web..*.*(..))")
        public void webLog(){}
    
        @Before("webLog()")
        public void doBefore(JoinPoint joinPoint) throws Throwable {
            // 获取HttpServletRequest
            ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            HttpServletRequest request = attributes.getRequest();
            // 获取要记录的日志内容
            BasicDBObject logInfo = getBasicDBObject(request, joinPoint);
            logger.info(logInfo);
        }
    
    
        private BasicDBObject getBasicDBObject(HttpServletRequest request, JoinPoint joinPoint) {
            // 基本信息
            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", joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName());
            r.append("args", Arrays.toString(joinPoint.getArgs()));
            return r;
        }
    
        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;
        }
    
    }

      

      

  • 相关阅读:
    C#面向过程之类型转换、算术运算符、关系运算符、逻辑运算符、if-else语句、switch-case、循环结构(while、for)、三元表达式
    C#面向过程之编译原理、变量、运算符
    VS快捷键整理
    简单聊聊mybatis插件(附源码)
    高性能页面加载技术(流水线加载)BigPipe的C#简单实现(附源码)
    聊聊js运算符 ‘与(&&)’和‘ 或(||)’
    从内部剖析C# 集合之--Dictionary
    从内部剖析C# 集合之---- HashTable
    字符串查找和函数操作题目解析
    常用排序算法实现
  • 原文地址:https://www.cnblogs.com/senlinyang/p/8676874.html
Copyright © 2011-2022 走看看