【Activiti系列学习】--10.Activiti6.0日志记录配置与MDC

本文涉及到的内容:

  • 日志组件的关系及MDC
  • 配置历史记录级别(HistoryLevel
  • 配置基于db的事件日志(Event logging

 1.日志组件的关系及MDC

 

  • 日志门面中,slf4j和commons-logging都是不能直接打印日志的,需要依赖日志实现把日志记录下来

  • 优选关系:Logback > Log4j > Java util logging

  • slf4j和Logback组合的时候默认不需要桥接方式

其中,Log4j既是门面又是实现;一般的组合是slf4j+logback;slf4j-log4j12实现slf4j+log4j; sf4j-jdk14的桥接方式能够实现slf4j+Java util logging

Jcl-over-slf4j排除掉commons-logging的历史实现,当需要commons-logging时,只需要引入jcl-over-slf4j即可;log4j-over-slf4j排除掉Log4j的历史实现

 

MDC(映射诊断上下文)的作用?

MDC打印输出一些上下文信息(如当前登录的用户、当前操作的订单,存储到线程的变量里面);MDC默认是没有开启的,需要手动设置;activiti做的比较保守,只有在流程执行过程中出现异常的时候才会记录MDC的信息。

2.配置历史记录级别

3.配置基于DB的事件日志

实现过程:

Activiti开启mdc的日志记录

在MDC的记录过程的上下文数据都是基于运行过程的,所以需要有一个可以执行的流程来完成这个事,若采用helloword的程序是在方法中执行,不合适,并且junit单元测试中不支持输入。

1.新建测试类ConfigMDCTest.java (复制MyUnitTest中的代码)

public class ConfigMDCTest {
    private static final Logger LOGGER = LoggerFactory.getLogger(ConfigMDCTest.class);
        @Rule
    public ActivitiRule activitiRule = new ActivitiRule();//activitiRule将整个流程引擎的启动和创建过程都构建好了


    @Test
    @Deployment(resources = {"com/syc/activiti/my-process.bpmn20.xml"})
    public void test() {
       ProcessInstance processInstance = activitiRule.getRuntimeService().startProcessInstanceByKey("my-process");//activiti提供的将单元测试文件部署到流程引擎中
       assertNotNull(processInstance);


       Task task = activitiRule.getTaskService().createTaskQuery().singleResult();
       assertEquals("Activiti is awesome!", task.getName());
       activitiRule.getTaskService().complete(task.getId());//添加该代码,让流程执行下去
    }
}

尝试运行时编译报错,显示表已经存在。原因是activiti.cfg.xml文件中数据库更新的值必须写成true

<property name="databaseSchemaUpdate" value="true"/>

修改数据库配置为h2数据库

<beanid="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneInMemProcessEngineConfiguration">
<property name="jdbcUrl" value="jdbc:h2:mem:activiti;DB_CLOSE_DELAY=1000;MVCC=TRUE"/>
<property name="jdbcDriver" value="org.h2.Driver"/>
<property name="jdbcUsername" value="sa"/>
<property name="jdbcPassword" value=""/>
</bean>

2.修改logback.xml的以下内容

(添加mdc的属性,并且控制台输出中将std改为mdc)

<configuration debug="false"scan="true"scanPeriod="30seconds">
<!--定义日志文件的存储地址勿在LogBack的配置中使用相对路径-->
property name="log.dir" value="target/logs"/>
    <property name="encoding" value="UTF-8"/>
    <property name="plain" value="%msg%n"/>
    <property name="std" value="%d{HH:mm:ss.SSS}[%thread][%-5level]%msg %X{user} %logger{10}.%M:%L%n "/>
    <property name="mdc" value="%d{HH:mm:ss.SSS}[%thread][%-5level]%msg ProcessDefinitonId=%X{mdcProcessDefinitionID}
executionId=%X{mdcExecutionId} mdcProcessInstanceID=%X{mdcProcessInstanceID} mdcBusinessKey=%X{mdcBusinessKey} %longger{10}.%M:%L%n" />
    <property name="normal" value="%d{yyyy-MM-dd:HH:mm:ss.SSS}[%thread][%-5level] %logger{10}.%M:%L %msg%n"/>
    <!--控制台输出-->
    <appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>${mdc}</pattern>
            <charset>${encoding}</charset>
        </encoder>
    </appender>

3.在ConfigMDCTest中打开mdc

在test()方法的首行中加入打开mdc的代码,此时运行测试程序不会有mdc日志(因此mdc只在程序错误时打印输出)

LogMDC.setMDCEnabled(true);

4.新建一个MDCErrorDelegate的类(只是用于测试,用于制造异常)

public class MDCErrorDelegate implements JavaDelegate {
    private static final Logger LOGGER = LoggerFactory.getLogger(MDCErrorDelegate.class);

    @Override
    public void execute(DelegateExecution execution) {
        LOGGER.info("run MDCErrorDelegate");
        throw new RuntimeException("only test!");

    }
}

5.将my-process.bpmn20.xml中的userTask改为serviceTask

<!--<userTask id="someTask" name="Activiti is awesome!" />-->
<serviceTask id="someTask" activiti:class="com.syc.activiti.delegate.MDCErrorDelegate"/>

测试能够输出ProcessDefinitionId的信息

(只有当出错时才能打印出日志,因此并不实用,下面通过拦截器进行改进,把每一个流程信息都打印出来)

6 .使用拦截器,把每一个流程信息都打印出来

编写拦截器的代码:

public class MDCCommandInvoker extends DebugCommandInvoker {
    private static final Logger LOGGER = LoggerFactory.getLogger(MDCCommandInvoker.class);

    @Override
    public void executeOperation(Runnable runnable) {
        boolean mdcEnabled = LogMDC.isMDCEnabled();//首先获取mdc的状态是否生效
        LogMDC.setMDCEnabled(true);
        if (runnable instanceof AbstractOperation) {
            AbstractOperation operation = (AbstractOperation) runnable;
            if (operation.getExecution() != null) {
                LogMDC.putMDCExecution(operation.getExecution());//将可执行对象放到上下文中
            }
        }
        super.executeOperation(runnable);//执行正常的业务操作
        LogMDC.clear();//上下文信息清空
        if(!mdcEnabled){//若进来时候mdc就是不生效的,就要还原不生效的状态
            LogMDC.setMDCEnabled(false);
        }
    }
}

7.复制一个新的activiti_mdc.cfg.xml

配置beans里面的属性commandInvoker为我们自定义的MDCCommandInvoker

<bean id="processEngineConfiguration"
      class="org.activiti.engine.impl.cfg.StandaloneInMemProcessEngineConfiguration">
    <property name="commandInvoker" ref="commandInvoker"/>
</bean>

<bean id="commandInvoker" class="com.syc.activiti.iterator.MDCCommandInvoker"/>

8.复制一个新的my-process_mdcerror.bpmn20.xml

恢复原来的my-process.bpmn20.xml

9.在ConfigMDCTest中修改配置文件为“activiti_mdc.cfg.xml”

@Rule
public ActivitiRule activitiRule = new ActivitiRule("activiti_mdc.cfg.xml");

最后测试运行应该是能把每一个流程id、执行id等流程相关信息打印输出

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值