动态调整(springMVC+slf4j)log等级(DEBUG/INFO/WARN/ERROR)

 

1、logback.xml

<pre name="code" class="html"><?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <!-- APP NAME -->
    <property name="APP_NAME" value="template" />
    <!-- 日志ROOT DIR -->
    <property name="LOG_ROOT_DIR" value="Logs/${APP_NAME}"/>
    <!--  格式化输出。
       %d/date{HH:mm:ss.SSS}:输出日志的打印日志,模式语法与java.text.SimpleDateFormat 兼容
       %-5p/le/level:级别从左显示5个字符宽度
       %t/thread	输出产生日志的线程名。
       %logger{36} 表示logger名字最长36个字符 为0表示只输入logger最右边点符号之后的字符串
       %F java源文件名 *.java
       %L 行
       %m/msg/message:日志内容
       %n:换行符 -->
    <property name="ENCODER_PATTERN" value="%d{[yyyy-MM-dd HH:mm:ss]}[%level][%logger{1}:%L] %msg%n" />
    <property name="ENCODING" value="UTF-8"/>

    <contextName>${APP_NAME}</contextName>
    <jmxConfigurator />

    <contextListener class="ch.qos.logback.classic.jul.LevelChangePropagator">
        <resetJUL>true</resetJUL>
    </contextListener>

    <!-- 输出到控制台 -->
    <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
        <encoder charset="${ENCODING}">
            <pattern>${ENCODER_PATTERN}</pattern>
        </encoder>
    </appender>

    <!-- appender 是<configuration>的子节点,是负责写日志的组件。有两个必要属性name和class。name指定appender名称,class指定appender的全限定名 -->
    <appender name="TEMPLATE_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"><!-- 滚动记录文件,先将日志记录到指定文件,当符合某个条件时,将日志记录到其他文件 -->
        <file>${LOG_ROOT_DIR}/template.log</file>
        <encoding>${ENCODING}</encoding>

        <append>true</append> <!--true:日志被追加到文件结尾,false:清空现存文件,默认是true-->
        <encoder> <!-- 对记录事件进行格式化 -->
            <pattern>${ENCODER_PATTERN}</pattern>
        </encoder>
        <!--
        过滤器,执行一个过滤器会有返回个枚举值,即DENY,NEUTRAL,ACCEPT其中之一。
        返回DENY,日志将立即被抛弃不再经过其他过滤器;
        返回NEUTRAL,有序列表里的下个过滤器过接着处理日志;
        返回ACCEPT,日志会被立即处理,不再经过剩余过滤器。
        -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>ERROR</level>
            <onMatch>ACCEPT</onMatch>       <!--用于配置符合过滤条件的操作-->
            <onMismatch>DENY</onMismatch>   <!--用于配置不符合过滤条件的操作-->
        </filter>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${LOG_ROOT_DIR}/template_%d{yyyy-MM-dd}.log.gz</fileNamePattern><!-- 压缩后的文件名设置 -->
        </rollingPolicy>
        <!--日志文件最大的大小-->
        <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
            <MaxFileSize>10MB</MaxFileSize>
        </triggeringPolicy>
    </appender>

    <!--日志异步到数据库 -->
    <appender name="DB" class="ch.qos.logback.classic.db.DBAppender">
        <!--日志异步到数据库 -->
        <connectionSource class="ch.qos.logback.core.db.DriverManagerConnectionSource">
            <!--连接池 -->
            <dataSource class="com.mchange.v2.c3p0.ComboPooledDataSource">
                <driverClass>com.mysql.jdbc.Driver</driverClass>
                <url>jdbc:mysql://127.0.0.1:3306/databaseName</url>
                <user>root</user>
                <password>root</password>
            </dataSource>
        </connectionSource>
    </appender>

    <!-- 邮件发送相关 -->
    <property name="smtpHost" value="smtp.exmail.qq.com"/>
    <property name="username" value="xx@xx.com"/>
    <property name="smtpPort" value="25"/>
    <property name="password" value="xx"/>
    <property name="SSL" value="false"/>
    <property name="email_to" value="xx@xx.com"/>
    <property name="email_from" value="xx@xx.com"/>
    <property name="email_subject" value="【Error:${APP_NAME}】%logger{20}:%L"/>

    <appender name="EMAIL" class="ch.qos.logback.classic.net.SMTPAppender">
        <smtpHost>${smtpHost}</smtpHost>
        <smtpPort>${smtpPort}</smtpPort>
        <username>${username}</username>
        <password>${password}</password>
        <SSL>${SSL}</SSL>
        <asynchronousSending>false</asynchronousSending>
        <to>${email_to}</to>
        <from>${email_from}</from>
        <subject>${email_subject}</subject>
        <layout class="ch.qos.logback.classic.html.HTMLLayout">
            <pattern>%d{[yyyy-MM-dd HH:mm:ss]}[%level][%logger:%L] %msg</pattern>
        </layout>
        <filter class="ch.qos.logback.core.filter.EvaluatorFilter">
            <level>ERROR</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>NEUTRAL</onMismatch>
        </filter>
    </appender>
    <!-- 邮件发送相关 -->

    <root level="DEBUG">
        <appender-ref ref="TEMPLATE_FILE"/>
        <appender-ref ref="console"/>
        <!--<appender-ref ref="DB"/>
        <appender-ref ref="EMAIL"/>-->
    </root>

    <!-- 配置独立包 -->
    <logger name="com.alibaba.dubbo" level="WARN">
        <appender-ref ref="ERROR_FILE"/>
        <appender-ref ref="console"/>
    </logger>
</configuration>

2、Controller

import com.saohuobang.payment.service.JMXConfigService;
import javax.annotation.Resource;
import javax.management.InstanceAlreadyExistsException;
import javax.management.MBeanRegistrationException;
import javax.management.MalformedObjectNameException;
import javax.management.NotCompliantMBeanException;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

/**
 * 作者 yaohua.liu
 * 日期 2015-11-24 11:32
 * 说明 日志等级动态控制接口
 */
@RequestMapping(value = "/log")
@Controller
public class JMXConfigController extends BackdoorController{

    @Resource
    private JMXConfigService JMXConfigService;

    @RequestMapping(value = "/startJMXConfig.api")
    @ResponseBody
    public Object startJMXConfig(@RequestParam(required = false) String port) throws MalformedObjectNameException, NotCompliantMBeanException, InstanceAlreadyExistsException, MBeanRegistrationException {
        String result = JMXConfigService.startJMXConfig(port);
        return result;
    }

    @RequestMapping(value = "/stopJMXConfig.api")
    @ResponseBody
    public Object stopJMXConfig() throws Exception {
        String result = JMXConfigService.stopJMXConfig();
        return result;
    }
}

3、Service

import javax.management.InstanceAlreadyExistsException;
import javax.management.MBeanRegistrationException;
import javax.management.MalformedObjectNameException;
import javax.management.NotCompliantMBeanException;

/**
 * 作者 yaohua.liu
 * 日期 2015-11-25 13:50
 * 说明 ...
 */

public interface JMXConfigService {

    public String startJMXConfig(String port) throws MalformedObjectNameException, NotCompliantMBeanException, InstanceAlreadyExistsException, MBeanRegistrationException;
    public String stopJMXConfig() throws Exception;
}

4、impl实现

import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.jmx.JMXConfigurator;
import com.google.common.base.Strings;
import com.saohuobang.payment.service.JMXConfigService;
import com.sun.jdmk.comm.HtmlAdaptorServer;
import javax.management.InstanceAlreadyExistsException;
import javax.management.MBeanRegistrationException;
import javax.management.MBeanServer;
import javax.management.MBeanServerFactory;
import javax.management.MalformedObjectNameException;
import javax.management.NotCompliantMBeanException;
import javax.management.ObjectName;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

/**
 * 作者 yaohua.liu
 * 日期 2015-11-25 14:23
 * 说明 ...
 */
@Service
public class JMXConfigServiceImpl implements JMXConfigService {

    private Logger logger = LoggerFactory.getLogger(JMXConfigService.class);

    public final String DOMAIN_NAME = "logback_jmx";
    public final String RELOAD_CONFIG_NAME = "reloadConfig";
    public final String CONNECTOR_NAME = "htmlConnector";
    private MBeanServer mBeanServer;
    private JMXConfigurator reloadConfig;
    private HtmlAdaptorServer connector;
    public LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory();
    private int defaultPort = 10110;

    @Override
    public String startJMXConfig(String portStr) throws MalformedObjectNameException, NotCompliantMBeanException, InstanceAlreadyExistsException, MBeanRegistrationException {
        mBeanServer = MBeanServerFactory.createMBeanServer(DOMAIN_NAME);

        int port = 0;
        try {
            if (Strings.isNullOrEmpty(portStr)) {
                port = defaultPort;
            } else {
                port = Integer.parseInt(portStr);
            }
        } catch (Exception e) {
            logger.error("格式化JMX端口:{}失败,使用默认端口:{}", portStr, defaultPort);
            port = defaultPort;
        }
        // 注册服务
        ObjectName on = new ObjectName(DOMAIN_NAME + ":name=" + RELOAD_CONFIG_NAME);
        reloadConfig = new JMXConfigurator(loggerContext, mBeanServer, on);
        mBeanServer.registerMBean(reloadConfig, new ObjectName(DOMAIN_NAME + ":name=" + RELOAD_CONFIG_NAME));
        // 注册连接
        connector = new HtmlAdaptorServer();
        connector.setPort(port);
        mBeanServer.registerMBean(connector, new ObjectName(DOMAIN_NAME + ":name=" + CONNECTOR_NAME));

        connector.start();

        return DOMAIN_NAME + ":" + port;
    }

    @Override
    public String stopJMXConfig() throws Exception {
        if (connector != null && connector.isActive()) {
            connector.stop();
        }

        mBeanServer = null;
        reloadConfig = null;
        connector = null;

        return "stop success!";
    }
}


5、访问:http://127.0.0.1:10001/log/startJMXConfig.api

返回:logback_jmx:10110,说明开通的端口为10110

页可以在请求时指定端口:http://127.0.0.1:10001/log/startJMXConfig.api?port=101010

6、打开地址:http://127.0.0.1:10110/

7、点击name=reloadConfig,跳转到:http://127.0.0.1:10110/ViewObjectRes//logback_jmx%3Aname%3DreloadConfig,滚动条拉到最下面,显示及操作如下:

 

本文已同步更新到公众号,沟通交流请关注公众号。

 

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值