java 分布式微服务配置统一的日志输出包括logstash

这篇具有很好参考价值的文章主要介绍了java 分布式微服务配置统一的日志输出包括logstash。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

在springcloud分布式微服务中,每个微服务都要配置一个日志输出文件,当微服务多起来的时候,日志输出有变动就要一个一个微服务去修改,这样使工作量增加,变得很麻烦,还有可能出现错误。

对日志文件进行统一的配置处理是个不错的选择。

首先在微服务中有一个基础的模块是存放一些基础的,共用的工具,配置,common模块,所有项目都依赖common模块。

微服务统一日志管理,java,分布式,微服务

 首先在服务中appliction-dev.yml中进行配置:

微服务统一日志管理,java,分布式,微服务

logging:
  path: /yunpan/logs/admin
  config: classpath:logback-spring.xml
# logstash连接配置
  host: 
  port: 
  level:
    root: info

在服务中进行spring_logback.xml配置:

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

<configuration debug="false" packagingData="true">

    <!-- log application level -->
    <springProperty scope="context" name="LOG_LEVEL" source="logging.level.root" />

    <include resource="com/zj/common/logback/commonLogback.xml" />

    <!-- 日志输出级别 -->
    <root level="${LOG_LEVEL}">
        <appender-ref ref="CONSOLE" />
        <appender-ref ref="ALL_LOG" />
        <appender-ref ref="ALL_ERROR" />
        <appender-ref ref="LOGSTASH" />
    </root>

</configuration>

<include resource="指向公共的配置文件路径">

在commonLogback.xml 中这样配置,当然还可以添加其他的配置属性,具体配置可以另行查找。

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

    <include resource="org/springframework/boot/logging/logback/defaults.xml" />
    <!-- <configuration scan="false" scanPeriod="60 seconds" debug="false"> -->
    <!-- log application name -->
    <springProperty scope="context" name="springAppName" source="spring.application.name" />
    <springProperty scope="context" name="logLevel" source="logging.level.root" />
    <!--设置系统日志目录-->
    <springProperty scope="context" name="logPath" source="logging.path"/>
    <!--logstash输入地址-->
    <springProperty scope="context" name="LOG_HOST" source="logging.host"/>
    <springProperty scope="context" name="LOG_PORT" source="logging.port"/>
    <springProperty scope="context" name="env" source="spring.profiles.active" defaultValue="dev"/>
    <property name="FILE_LOG_PATTERN"
              value="%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger[%line] - %msg%n"/>

    <!-- 控制台输出 -->
    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>${FILE_LOG_PATTERN}</pattern>
            <charset>utf8</charset>
        </encoder>
    </appender>

    <!-- 记录项目所有日志 -->
    <appender name="ALL_LOG" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>DEBUG</level>
        </filter>
        <file>${logPath}/${springAppName}.log</file>
        <encoder>
            <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
            <pattern>${FILE_LOG_PATTERN}</pattern>
            <charset>utf8</charset>
        </encoder>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <FileNamePattern>${logPath}/back/${springAppName}.log.%d{yyyy-MM-dd}.%i</FileNamePattern>
            <MaxHistory>30</MaxHistory>
            <!-- 除按日志记录之外,还配置了日志文件不能超过10M,若超过10M,日志文件会以索引0开始,
              命名日志文件,例如honey.log.2017-12-29.0 -->
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>100MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
        </rollingPolicy>
    </appender>

    <!-- 记录项目ERROR级别文件 -->
    <appender name="ALL_ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>ERROR</level>
        </filter>
        <file>${logPath}/${springAppName}-error.log</file>
        <encoder>
            <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
            <pattern>${FILE_LOG_PATTERN}</pattern>
            <charset>utf8</charset>
        </encoder>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <FileNamePattern>${logPath}/back/${springAppName}-error.log.%d{yyyy-MM-dd}.%i</FileNamePattern>
            <MaxHistory>30</MaxHistory>
            <!-- 除按日志记录之外,还配置了日志文件不能超过10M,若超过10M,日志文件会以索引0开始,
               命名日志文件,例如honey-error.logger.logger-2017-12-29.0 -->
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>100MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
        </rollingPolicy>
    </appender>

    <!--配置logstash-->
    <appender name="LOGSTASH" class="net.logstash.logback.appender.LogstashTcpSocketAppender">
        <destination>${LOG_HOST:- }:${LOG_PORT:- }</destination>

        <encoder charset="UTF-8" class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder">
            <providers>
                <timestamp>
                    <timeZone>UTC</timeZone>
                </timestamp>
                <pattern>
                    <pattern> {
                        "env": "${env:-}",
                        "severity": "%level",
                        "service": "${springAppName:-}",
                        "pid": "${PID:-}",
                        "thread": "%thread",
                        "class": "%logger{60}",
                        "rest": "#tryJson{%message}"
                        }
                    </pattern>
                </pattern>
            </providers>
        </encoder>
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>INFO</level>
        </filter>
    </appender>

    <logger name="jdbc.sqltiming" additivity="false" level="DEBUG">
        <appender-ref ref="CONSOLE" />
        <appender-ref ref="ALL_LOG" />
        <appender-ref ref="ALL_ERROR" />
        <appender-ref ref="LOGSTASH" />
    </logger>

    <logger name="com.vanmilk" additivity="false" level="DEBUG">
        <appender-ref ref="CONSOLE" />
        <appender-ref ref="ALL_LOG" />
        <appender-ref ref="ALL_ERROR" />
        <appender-ref ref="LOGSTASH" />
    </logger>

    <!-- 去掉spring打印,实际并没有错, Could not find default TaskScheduler bean异常 -->
    <logger name="org.springframework.scheduling">
        <level value="info" />
    </logger>

</included>

这样在以后添加其他的微服务只需要添加logback-spring.xml就可以了,其他的都会共用commonLogback.xml中的省去了许多工作量。

最好的是能在common模块中再加一个AOP进行全局日志输出管理。文章来源地址https://www.toymoban.com/news/detail-654065.html


import com.alibaba.fastjson.JSON;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * Created by Yuyang Zhang on 2023-03-08
 * <p>
 * 业务耗时日志记录
 */
@Slf4j
@Aspect
public class ControllerLogAop {

    @Pointcut("@annotation(org.springframework.web.bind.annotation.RequestMapping)||" +
            "@annotation(org.springframework.web.bind.annotation.PostMapping)||" +
            "@annotation(org.springframework.web.bind.annotation.DeleteMapping)||" +
            "@annotation(org.springframework.web.bind.annotation.PutMapping)||" +
            "@annotation(org.springframework.web.bind.annotation.GetMapping)")
    public void controllerMethod() {

    }

    @Before("controllerMethod()")
    public void doControllerBefore(final JoinPoint joinPoint) {
        final HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder
                .currentRequestAttributes()).getRequest();
        final String ip = IpUtils.getRemoteAddrIp(request);
        final String errorCode = CommonUtils.getRandomNumberString(8);
        final String params = getParams(joinPoint);
        final String targetName = joinPoint.getTarget().getClass().getName();
        final String methodName = targetName + "." + joinPoint.getSignature().getName();
        final String url = request.getRequestURL() +
                (StringUtils.isNotEmpty(request.getQueryString()) ? "?" + request.getQueryString() : "");
        final StringBuilder message = new StringBuilder();
        final SysAccountToken currentUser = UserContext.getCurrentUser();
        String token = request.getHeader("token") == null ? "UN_KNOW" : request.getHeader("token");
        String appName = request.getHeader("AppName");
        String appVersion = request.getHeader("AppVersion");

        try {
            message.append("\r\n==============Request Start==============")
//                    .append("\r\n请求方法:").append(methodName)
                    .append("\r\n[Requested URL]: ").append(url)
                    .append("\r\n[Requested Params]: ").append(params)
                    .append("\r\n[Requested Method]: ").append(request.getMethod())
                    .append("\r\n[Requested Authorization]: ").append(token);
            if (appName != null && appVersion != null) {
                message.append("\r\n[Requested App Name]: ").append(appName)
                        .append("\r\n[Requested App Version]: ").append(appVersion);
            }
            message.append("\r\n[Requested IP]: ").append(ip)
                    .append("\r\n[Requested By]:").append(currentUser == null ?
                            "anonymous" : currentUser.getFirstName() + " " + currentUser.getLastName() + "[" + currentUser.getId() + "]")
                    .append("\r\n==============Request End==============");
            log.info("Requested Information:{}", message.toString());
        } catch (final Exception e) {
            log.error("异常信息:{}", e.getMessage(), e);
            throw e;
        }
    }

    /**
     * 方法执行拦截,输出请求处理的时间
     *
     * @param joinPoint 切入点
     * @throws Throwable 异常
     */
    @Around("controllerMethod()")
    public Object doControllerAround(final ProceedingJoinPoint joinPoint) throws Throwable {
        final String targetName = joinPoint.getTarget().getClass().getName();
        final String methodName = targetName + "." + joinPoint.getSignature().getName();
        final long start = System.currentTimeMillis();
        final Object object = joinPoint.proceed();
        final long executeTime = System.currentTimeMillis() - start;
        log.info("Polaris Biz [{}] execute time {} ms", methodName, executeTime);
        return object;
    }

    /**
     * 获取请求的参数
     *
     * @param joinPoint 切入点
     * @return 参数JSON ARRAY
     */
    private String getParams(final JoinPoint joinPoint) {
        final Object[] args = joinPoint.getArgs();
        final List<Object> params = new ArrayList<>();
        for (final Object o : args) {
            if (o instanceof ServletRequest) {
                final HttpServletRequest request = (HttpServletRequest) o;
                params.addAll(Arrays.asList(request.getParameterMap().values().toArray()));
                continue;
            }
            if (o instanceof ServletResponse) {
                continue;
            }
            if (o instanceof MultipartFile) {   //过滤文件上传的参数
                continue;
            }
            params.add(o);
        }
        String result = null;
        try {
            result = JSON.toJSONString(params);
        } catch (final Exception e) {
            log.error("controller 参数拦截失败,{}", e.getMessage(), e);
        }
        return result;
    }
}

到了这里,关于java 分布式微服务配置统一的日志输出包括logstash的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Java分布式微服务4——异步服务通讯(RabbitMQ)中间件

    为什么需要异步调用? 故障隔离 :支付服务不负责调用其他三个服务,只负责通知Broker支付成功这个事件,然后就返回结果,后面的服务故障了和前面发布事件的服务无关,前面的服务发布完事件就结束了 吞吐量提升 :Broker将支付成功的事件广播给订阅了这个事件的那些服

    2024年02月13日
    浏览(34)
  • Java分布式微服务1——注册中心(Eureka/Nacos)

    远程调用 向其他服务器请求信息(远程调用) 先在application或者configuration中注册一个Bean方便之后使用(可忽略) 使用restTemplate方法发送请求 getForObject/postForObject/… 1、Eureka注册中心 上面的url是硬编码写死的,很不方便切换,所以使用Eurake注册中心来管理服务提供者的地址 E

    2024年02月14日
    浏览(29)
  • tomcat服务器统一配置错误页面

    问题:访问服务器出错时,可能页面会显示空白或者别的错误页面,这样的显示并不友好,所以我们要统一解决一下这样不友好的页面 解决方法 :将所有异常都抛出,最后抛给tomcat服务器进行统一的处理。 步骤一:编写服务器500错误或者404错误页面;例如:error404.jsp 步骤二

    2024年02月13日
    浏览(33)
  • ELK-日志服务【redis-配置使用】

    目录 环境 【1】redis配置 【2】filebeat配置 【3】对接logstash配置 【4】验证 【5】安全配置:第一种:kibana-nginx访问控制 【6】第二种:在ES-主节点-配置TLS 【7】kibana配置密码 【8】logstash添加用户密码 环境 es-01,kibana 10.0.0.21 es-02 10.0.0.22 es-03 10.0.0.23 filebeat,nginx 10.0.0.25 logstash 10.

    2024年02月16日
    浏览(25)
  • ELK-日志服务【kafka-配置使用】

    kafka-01 10.0.0.21 kafka-02 10.0.0.22 kafka-03 10.0.0.23 【1】安装zk集群、配置 【2】安装kafka集群  

    2024年02月16日
    浏览(30)
  • 微服务组件Feign实战 - 解决日志配置失效

    1. RPC概述 思考: 微服务之间如何方便优雅的实现服务间的远程调用? RPC 全称是 Remote Procedure Call ,即远程过程调用,其对应的是我们的本地调用。RPC 的目的是:让我们调用远程方法像调用本地方法一样。 RPC框架设计架构 2. 什么是Feign Feign是Netflix开发的声明式、模板化的

    2024年02月16日
    浏览(21)
  • 微服务系列文章 之 nginx日志配置指令详解

    日志对于统计排错来说非常有利的。本文总结了nginx日志相关的配置如access_log、log_format、open_log_file_cache、log_not_found、log_subrequest、rewrite_log、error_log。 nginx有一个非常灵活的日志记录模式。每个级别的配置可以有各自独立的访问日志。日志格式通过log_format命令来定义。ngx_

    2024年02月16日
    浏览(36)
  • Microsoft ISA服务器配置及日志分析

    Microsoft ISA 分析器工具,可分析 Microsoft ISA 服务器(或 Forefront 威胁管理网关服务器)的日志并生成安全和流量报告。支持来自 Microsoft ISA 服务器组件的以下日志: 数据包过滤器 ISA 服务器防火墙服务 ISA 服务器网络代理服务 除了Microsoft ISA服务器日志外,还能分析来自各种网

    2024年02月12日
    浏览(25)
  • 服务器集群配置LDAP统一认证高可用集群(配置tsl安全链接)-centos9stream-openldap2.6.2

    因之前集群为centos6,已经很久没升级了,所以这次配置统一用户认证也是伴随系统升级到centos9时一起做的配套升级。新版的openldap配置大致与老版本比较相似,但有些地方配置还是有变化,另外,铺天盖地的帮助文档有相当一部分是直接搬砖过来的,所以参考时容易出错,这

    2024年02月05日
    浏览(29)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包