qqxx6661 / log-record Goto Github PK
View Code? Open in Web Editor NEW使用注解优雅记录系统日志,操作日志,后端埋点等,支持SpEL表达式,自定义上下文,自定义函数,实体类DIFF等其他高阶处理。
License: Apache License 2.0
使用注解优雅记录系统日志,操作日志,后端埋点等,支持SpEL表达式,自定义上下文,自定义函数,实体类DIFF等其他高阶处理。
License: Apache License 2.0
配置了github生效后,依赖仍爆红。Could not find artifact cn.monitor4all:log-record-starter:pom:1.0.0 in central (https://repo1.maven.org/maven2)
LogRecordContext.putVariable其他方法获取不到,是否存在LogRecordContext.putGlobalVariable这种操作呢
作者你好,注解上的SpEL表达式执行顺序总是晚于被注解的整体方法执行的,有一种逻辑就会产生问题。
比如,有个方法是删除数据,参数只有一个ID,这种情况下需要通过id查到这条数据的信息,然后一起记录到日志。
但是现在的结果是,数据先被删除,然后SpEL函数去查数据时数据已经是null了。
看到您有个LogRecordContext的上下文,可以在方法体先查出来,但是这样子的话入侵太严重。
现在入参ID不变,不动入参,不能影响到前端。这种情况怎么处理比较好,后续会优化这种情况吗?
实际业务中,当修改的对象是复杂对象,里面又包含List对像集合,这种情况时支持吗?我自测没通过
如题
在finally里将日志提交到主线程或者线程池是什么意思呢,这样操作的作用是啥呢,有时间麻烦给解答一下,谢谢啦
@OperationLog嵌套线程上下文会被清除,本意是为了重复注解使用,但是有副作用,需要优化。
我看介绍支持RabbitMQ、RocketMQ、SpringCloud Stream。如果想接入其他MQ,有对应的扩展点嘛?
一些简单项目不依赖消息队列和springcloud,能否直接写到数据库
org.springframework.aop.AopInvocationException: Null return value from advice does not match primitive return type for: public abstract boolean cn.monitor4all.logRecord.service.IOperationLogGetService.createLog(cn.monitor4all.logRecord.bean.LogDTO) throws java.lang.Exception
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:229)
at com.sun.proxy.$Proxy259.createLog(Unknown Source)
at cn.monitor4all.logRecord.aop.SystemLogAspect.createLog(SystemLogAspect.java:323)
at cn.monitor4all.logRecord.aop.SystemLogAspect.lambda$doAround$2(SystemLogAspect.java:167)
at java.util.ArrayList.forEach(ArrayList.java:1259)
at cn.monitor4all.logRecord.aop.SystemLogAspect.doAround(SystemLogAspect.java:175)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:634)
at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:624)
at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:72)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:175)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:763)
at com.hiifans.brick.spring.framework.logging.RequestLogInterceptor.invoke(RequestLogInterceptor.java:44)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:763)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:97)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:763)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:708)
at com.hiifans.crm.admin.controller.ReportController$$EnhancerBySpringCGLIB$$773e8852.reportViewLog(<generated>)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:150)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:117)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1071)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:964)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:696)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:779)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:227)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
at org.springframework.web.filter.CorsFilter.doFilterInternal(CorsFilter.java:91)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:177)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:541)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:135)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:360)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:399)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:891)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1784)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191)
at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:750)
使用方式:
@PostMapping("/view-log")
@OperationLog(bizId = "", bizType = "'VIEW'", msg = "'菜单名称:' + #reportViewLogDTO.menuName + ',进入时间:' + #enterTime")
@ApiOperation("浏览日志上报")
public DataResponse<?> reportViewLog(@RequestBody @Valid ReportViewLogDTO reportViewLogDTO) {
LogRecordContext.putVariable("enterTime", LocalDateTimeUtil.formatNormal(LocalDateTime.now()));
return DataResponse.ok();
}
@Slf4j
@Service
public class OperationLogGetServiceImpl implements IOperationLogGetService {
@Async
@Override
public boolean createLog(LogDTO logDTO) throws Exception {
try {
log.error("{}", JSONUtil.toJsonStr(logDTO));
} catch (Exception e) {
}
return true;
}
}
Diff功能支持数据吗?
版本:v1.5.1
application.yml
:
log-record:
# Diff 时忽略新对象中 null 值字段,默认为 false
diff-ignore-new-object-null-value: true
# Diff 格式
diff-msg-format: 【${_fieldName}】:【${_oldValue}】->【${_newValue}】
# Diff 分隔符
diff-msg-separator: ;
UserController
:
@OperationLog(bizId = "#id", bizType = "'user:update'", msg = "'更新用户:' + #_DIFF(#oldObj, #obj)")
public ApiResponse update(@Min(value = 1, message = "参数错误") @PathVariable Long id, @Validated @RequestBody UserUpdateQO obj) {
User user = userService.getById(id);
if (user == null) {
throw new ServiceException("用户不存在");
}
LogRecordContext.putVariable("oldObj", user);
// ……
}
User
:
@LogRecordDiffObject(alias = "用户")
public class User {
@LogRecordDiffField(alias = "用户名")
private String username;
// ……
}
UserUpdateQO
:
@LogRecordDiffObject
public class UserUpdateQO {
@LogRecordDiffField(alias = "用户名")
private String username;
// ……
}
结果:更新用户:?电话?:?18888888887?->?18888888888?;?昵称?:?234?->?23?;?角色?:?2,1671440885033914373?->?2?
我所有的文件编码都是UTF-8
。
我试过给diff-msg-format
的内容前后加单引号也没用。
项目集成log-record通过k8s发布启动后报javassist.NotFoundException: cn.monitor4all.logRecord.function.CustomFunctionObjectDiff异常
但是本地通过idea启动是没问题的,以下是详细的错误日志,希望作者帮忙看一下
DEBUG 2022-12-20 10:50:39:929 main AgentPackagePath : The beacon class location is jar:file:/skywalking-agent/skywalking-agent.jar!/org/apache/skywalking/apm/agent/core/boot/AgentPackagePath.class.
INFO 2022-12-20 10:50:39:932 main SnifferConfigInitializer : Config file found in /skywalking-agent/config/agent.config.
. ____ _ __ _ _
/\ / ' __ _ () __ __ _ \ \ \
( ( )__ | '_ | '| | ' / ` | \ \ \
\/ )| |)| | | | | || (| | ) ) ) )
' || .__|| ||| |_, | / / / /
=========||==============|/=////
:: Spring Boot :: (v2.5.1)
10:51:23.614 [main] INFO [TID:N/A] com.toplion.download.DownloadCenterApplication - The following profiles are active: pre
10:53:03.515 [main] ERROR [TID:N/A] cn.monitor4all.logRecord.function.CustomFunctionRegistrar - cn.monitor4all.logRecord.function.CustomFunctionObjectDiff
javassist.NotFoundException: cn.monitor4all.logRecord.function.CustomFunctionObjectDiff
at javassist.ClassPool.get(ClassPool.java:430)
at cn.monitor4all.logRecord.function.CustomFunctionRegistrar.constructCtClass(CustomFunctionRegistrar.java:118)
at cn.monitor4all.logRecord.function.CustomFunctionRegistrar.proxy2static(CustomFunctionRegistrar.java:104)
at cn.monitor4all.logRecord.function.CustomFunctionRegistrar.lambda$setApplicationContext$4(CustomFunctionRegistrar.java:72)
at java.util.LinkedHashMap$LinkedValues.forEach(LinkedHashMap.java:608)
at cn.monitor4all.logRecord.function.CustomFunctionRegistrar.setApplicationContext(CustomFunctionRegistrar.java:43)
at org.springframework.context.support.ApplicationContextAwareProcessor.invokeAwareInterfaces(ApplicationContextAwareProcessor.java:128)
at org.springframework.context.support.ApplicationContextAwareProcessor.postProcessBeforeInitialization(ApplicationContextAwareProcessor.java:102)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization(AbstractAutowireCapableBeanFactory.java:422)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1778)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:602)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:524)
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:944)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:918)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:583)
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:145)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:754)
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:434)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:338)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1343)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1332)
at com.toplion.download.DownloadCenterApplication.main(DownloadCenterApplication.java:16)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:49)
at org.springframework.boot.loader.Launcher.launch(Launcher.java:108)
at org.springframework.boot.loader.Launcher.launch(Launcher.java:58)
at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:88)
10:53:04.323 [main] ERROR [TID:N/A] org.springframework.boot.SpringApplication - Application run failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'registrar' defined in class path resource [cn/monitor4all/logRecord/configuration/LogRecordConfiguration.class]: Initialization of bean failed; nested exception is java.lang.RuntimeException: javassist.NotFoundException: cn.monitor4all.logRecord.function.CustomFunctionObjectDiff
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:610)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:524)
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:944)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:918)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:583)
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:145)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:754)
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:434)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:338)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1343)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1332)
at com.toplion.download.DownloadCenterApplication.main(DownloadCenterApplication.java:16)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:49)
at org.springframework.boot.loader.Launcher.launch(Launcher.java:108)
at org.springframework.boot.loader.Launcher.launch(Launcher.java:58)
at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:88)
Caused by: java.lang.RuntimeException: javassist.NotFoundException: cn.monitor4all.logRecord.function.CustomFunctionObjectDiff
at cn.monitor4all.logRecord.function.CustomFunctionRegistrar.lambda$setApplicationContext$4(CustomFunctionRegistrar.java:85)
at java.util.LinkedHashMap$LinkedValues.forEach(LinkedHashMap.java:608)
at cn.monitor4all.logRecord.function.CustomFunctionRegistrar.setApplicationContext(CustomFunctionRegistrar.java:43)
at org.springframework.context.support.ApplicationContextAwareProcessor.invokeAwareInterfaces(ApplicationContextAwareProcessor.java:128)
at org.springframework.context.support.ApplicationContextAwareProcessor.postProcessBeforeInitialization(ApplicationContextAwareProcessor.java:102)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization(AbstractAutowireCapableBeanFactory.java:422)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1778)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:602)
... 23 common frames omitted
Caused by: javassist.NotFoundException: cn.monitor4all.logRecord.function.CustomFunctionObjectDiff
at javassist.ClassPool.get(ClassPool.java:430)
at cn.monitor4all.logRecord.function.CustomFunctionRegistrar.constructCtClass(CustomFunctionRegistrar.java:118)
at cn.monitor4all.logRecord.function.CustomFunctionRegistrar.proxy2static(CustomFunctionRegistrar.java:104)
at cn.monitor4all.logRecord.function.CustomFunctionRegistrar.lambda$setApplicationContext$4(CustomFunctionRegistrar.java:72)
... 30 common frames omitted
我再提些建议,你别烦我🥺
我在使用过程中自定义了一个toLogString
函数,作用是传进去对象或集合,输出有@LogRecordDiffField
的属性,而且还和diff-ignore-new-object-null-value
、diff-msg-separator
结合起来使用了。我觉得将参数属性名转为中文是很常见的需求,可以新增类似的公共函数。
我觉得@LogRecordDiffField
注解可以改成@LogRecordField
,然后同时适用于 Diff 和其他功能,就像 MyBatis Plus 的@TableField
或 Hibernate 的@Column
一样。
我很久以前写过一个基于 Hibernate 的注解日志记录,会自动将带有@Column
的属性名转为这个注解的 comment 输出,或者将它的属性名、@column 注解的 comment 属性的值、属性值传到一个集合里后续再使用。
我觉得除了新增类似的公共函数之外,也可以给@OperationLog
加一个属性,为 true 就直接把属性名转成@LogRecordField
的 alias 的值了。
CustomLogFn
:
/**
* 日志自定义函数
*/
@Slf4j
@Component
@LogRecordFunc("custom")
public class CustomLogFn {
private static boolean ignoreNullValues;
private static String diffMsgSeparator;
@Value("${log-record.diff-ignore-new-object-null-value}")
public void setIgnoreNullValues(boolean ignoreNullValues) {
CustomLogFn.ignoreNullValues = ignoreNullValues;
}
@Value("${log-record.diff-msg-separator}")
public void setDiffMsgSeparator(String diffMsgSeparator) {
CustomLogFn.diffMsgSeparator = diffMsgSeparator;
}
@LogRecordFunc("toLogString")
public static String toLogString(Object object) {
List<String> fields = new ArrayList<>();
// 操作多个对象
if (object instanceof Iterable<?>) {
for (Object o : (Iterable<?>) object) {
fields.add(toLogString(o));
}
return StringUtils.join(fields, " | ");
} else {
// 遍历对象的所有字段
for (Field field : object.getClass().getDeclaredFields()) {
// 跳过没有 @LogRecordDiffField 的字段
if (!field.isAnnotationPresent(LogRecordDiffField.class)) {
continue;
}
field.setAccessible(true);
LogRecordDiffField annotation = field.getAnnotation(LogRecordDiffField.class);
// 跳过忽略的字段
if (annotation.ignored()) {
continue;
}
try {
Object value = field.get(object);
// 是否忽略 null 值
if (ignoreNullValues && value == null) {
continue;
}
fields.add(annotation.alias() + ":" + (value != null ? value.toString() : "null"));
} catch (IllegalAccessException e) {
log.error("获取字段值失败", e);
}
}
return StringUtils.join(fields, diffMsgSeparator);
}
}
}
@OperationLog(bizId = "#bizId", bizType = "'user:save'", msg = "'【保存用户】' + #custom_toLogString(#obj)")
// 结果:【保存用户】用户名:test2;昵称:test2;电话:18888888888;角色:3
@OperationLog(bizId = "#ids", bizType = "'user:remove'", msg = "'【删除用户】' + #custom_toLogString(#removedList)")
// 结果:【删除用户】用户名:test1;电话:18888888888;昵称:test1;角色:2 | 用户名:test2;电话:18888888888;昵称:test2;角色:3
您好
在两个对象DIFF时,如果该对象的类有父类,父类的属性并不会参与DIFF。
建议:cn.hutool.core.util.ReflectUtil
当自定义上下文中,设置一个为空字符串的值时,如LogRecordContext.putVariable("insertId", “”);
此时, @OperationLog注解有多个时间,顺序不会按照定义的顺序进行输出
此条请置顶
获取请求ip地址或者request对象,您是怎么传递的
我看图片当中也提到了访问ip
tils.function.CustomFunctionObjectDiff
at javassist.ClassPool.get(ClassPool.java:430)
at com.zeekr.speech.config.utils.function.CustomFunctionRegistrar.constructCtClass(CustomFunctionRegistrar.java:122)
at com.zeekr.speech.config.utils.function.CustomFunctionRegistrar.proxy2static(CustomFunctionRegistrar.java:108)
at com.zeekr.speech.config.utils.function.CustomFunctionRegistrar.lambda$setApplicationContext$4(CustomFunctionRegistrar.java:74)
at java.util.LinkedHashMap$LinkedValues.forEach(LinkedHashMap.java:608)
at com.zeekr.speech.config.utils.function.CustomFunctionRegistrar.setApplicationContext(CustomFunctionRegistrar.java:45)
at org.springframework.context.support.ApplicationContextAwareProcessor.invokeAwareInterfaces(ApplicationContextAwareProcessor.java:123)
at org.springframework.context.support.ApplicationContextAwareProcessor.postProcessBeforeInitialization(ApplicationContextAwareProcessor.java:100)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization(AbstractAutowireCapableBeanFactory.java:415)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1791)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:594)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:516)
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:324)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:322)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:897)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:879)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:551)
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:143)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:755)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:747)
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:402)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:312)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1247)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1236)
at com.zeekr.speech.config.Application.main(Application.java:23)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:49)
at org.springframework.boot.loader.Launcher.launch(Launcher.java:108)
at org.springframework.boot.loader.Launcher.launch(Launcher.java:58)
at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:88)
diff函数内,我看作者大大在msg输出时是直接调用 old/newValue.toString()。请问能否支持通过注解别名优化一下输出。
例子:【列表A】从【[TestDiffJob(jobId=22, jobName=222, dutyList=[TestDiffDuty(dutyId=222, dutyName=222)])]】 改为
【列表A】从【[实体A(编号=22, 名字=222, 列表A=[实体B(编号=222, 名=222)])]】
原输出虽然开发人员能够明白,但对于业务人员的查看并不友好
以上效果虽然可以直接通过覆写toString实现,但不算是一个太好的方案,容易干扰用到toString的相关代码。
大多情况下自定义的函数为了查old的值都会调用spring容器中的方法去获取,在@component注解标记的类中使用LogRecordFunc注解会报空指针,代理类获取不到Annotation,微调后发现非静态方法无法放到StandardEvaluationContext里
有打算添加spel对自定义函数解析的内容吗
testService.testObjectDiff(new TestUser(2, "李四"));
===========================
"diffDTOList":[
{
"diffFieldDTOList":[
{
"fieldName":"id",
"newFieldAlias":"用户工号",
"newValue":2,
"oldFieldAlias":"用户工号",
"oldValue":1
},
{
"fieldName":"name",
"newValue":"李四",
"oldValue":"张三"
}],
"newClassAlias":"用户信息实体",
"newClassName":"cn.monitor4all.logRecord.test.bean.TestUser",
"oldClassAlias":"用户信息实体",
"oldClassName":"cn.monitor4all.logRecord.test.bean.TestUser"
},
{
"diffFieldDTOList":[
{
"fieldName":"id",
"newFieldAlias":"用户工号",
"newValue":2,
"oldFieldAlias":"用户工号",
"oldValue":1
},
{
"fieldName":"name",
"newValue":"李四",
"oldValue":"张三"
}],
"newClassAlias":"用户信息实体",
"newClassName":"cn.monitor4all.logRecord.test.bean.TestUser",
"oldClassAlias":"用户信息实体",
"oldClassName":"cn.monitor4all.logRecord.test.bean.TestUser"
}]
是线程不安全,好像不能在生产环境使用吧?
Simple stop watch, allowing for timing of a number of tasks, exposing total running time and running time for each named task.
Conceals use of [System.nanoTime()](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/System.html#nanoTime()), improving the readability of application code and reducing the likelihood of calculation errors.
Note that this object is not designed to be thread-safe and does not use synchronization.
This class is normally used to verify performance during proof-of-concept work and in development, rather than as part of production applications.
As of Spring Framework 5.2, running time is tracked and reported in nanoseconds.
CustomFunctionObjectDiff 类里第54行
// 对象类名
51 String oldClassName = oldObject.getClass().getName();
52 String newClassName = newObject.getClass().getName();
53 LogRecordDiff oldClassLogRecordDiff = oldObject.getClass().getDeclaredAnnotation(LogRecordDiff.class);
54 LogRecordDiff newClassLogRecordDiff = oldObject.getClass().getDeclaredAnnotation(LogRecordDiff.class);
// 原方法执行异常
catch (Throwable throwable) {
// 方法异常执行后日志切面
try {
if (stopWatch != null) {
stopWatch.stop();
executionTime = stopWatch.getTotalTimeMillis();
}
// 在LogRecordContext中写入执行后信息
LogRecordContext.putVariable(LogRecordContext.CONTEXT_KEY_NAME_ERROR_MSG, throwable.getMessage());
for (OperationLog annotation : annotations) {
if (!annotation.executeBeforeFunc()) {
logDtoMap.put(annotation, resolveExpress(annotation, pjp));
}
}
// 写入异常执行后日志
logDTOList = new ArrayList<>(logDtoMap.values());
logDTOList.forEach(logDTO -> { // 此处的是否有问题??
logDTO.setSuccess(false);
logDTO.setException(throwable.getMessage());
});
} catch (Throwable throwableAfterFuncFailure) {
log.error("OperationLogAspect doAround after function failure, error:", throwableAfterFuncFailure);
}
// 抛出原方法异常
throw throwable;
} finally {
作者你好,使用DIFF的时候需要从业务代码中获取原来的值,这个还有调整的空间吗
目前createLog
方法中LogDTO.exception
获取的仅为e.getMessage()
,而我想获取的是e.printStackTrace()
的内容。
大多项目都会有一个全局异常处理。
GlobalExceptionHandler
:
/**
* 全局异常处理
*/
@Slf4j
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(value = Exception.class)
@ResponseBody
public ApiResponse<String> handlerException(Exception e) {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
e.printStackTrace(pw);
LogRecordContext.putVariable("exception", sw.toString());
// ……
}
上文代码中的LogRecordContext.putVariable("exception", sw.toString());
仅为我的猜想,能否通过这种方式去设置LogDTO.exception
的值(put 中可以特殊点叫 $exception 或者加新方法),不然每个@OperationLog
都要加属性(当然现在还没有可以配置exception
的属性)。
假设可以自定义LogDTO.exception
的值的话,GlobalExceptionHandler.handlerException
的执行顺序也总是在createLog
方法后,@Order
注解无效。或者 LogDTO 可以获取到 Exception 对象也行。
Diff功能支持数组吗?
msg
最终为:“【username】从【xxx】变成了【 】 【xxx】……”。实际上因为 MyBatis 配置的更新策略,是不会更新参数中为 null 的字段(此处即 username)的,但是操作日志中却显示了。@LogRecordDiffField
新增一个属性用于单独配置。@LogRecordDiffIgnoreField
这个注解,可以变成@LogRecordDiffField
的一个属性。关于第 1 点,我现在自己的做法是在implements IOperationLogGetService
的类中判断diffDTOList
是否不为空,如果不为空的话,获取其中 newValue 为 null 的,再去处理 msg。
需要完善单元测试,用于PR做回归测试,保证代码质量
针对业务中的批量操作,比如批量删除、批量新增操作,通过注解的方式记录日志时貌似无法满足业务需求,请问您这种情况有考虑吗?
支持传入用户自定义线程池替换默认日志记录线程池
报错内容如下,原因是因为Date转JSONObject的时候出错,建议进行优化一下默认的_DIFF方法
2023-05-19 11:49:21.555 [http-nio-8080-exec-5] ERROR c.m.logRecord.function.CustomFunctionObjectDiff:124 - objectDiff error
cn.monitor4all.logRecord.exception.LogRecordException: fieldValueEquals error
at cn.monitor4all.logRecord.function.CustomFunctionObjectDiff.fieldValueEquals(CustomFunctionObjectDiff.java:228)
at cn.monitor4all.logRecord.function.CustomFunctionObjectDiff.objectDiff(CustomFunctionObjectDiff.java:115)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.expression.spel.ast.FunctionReference.executeFunctionJLRMethod(FunctionReference.java:121)
at org.springframework.expression.spel.ast.FunctionReference.getValueInternal(FunctionReference.java:80)
at org.springframework.expression.spel.ast.SpelNodeImpl.getTypedValue(SpelNodeImpl.java:117)
at org.springframework.expression.spel.standard.SpelExpression.getValue(SpelExpression.java:308)
at cn.monitor4all.logRecord.aop.SystemLogAspect.resolveExpress(SystemLogAspect.java:259)
at cn.monitor4all.logRecord.aop.SystemLogAspect.doAround(SystemLogAspect.java:118)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:644)
at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:633)
at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:70)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:175)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)
at org.springframework.aop.aspectj.AspectJAfterAdvice.invoke(AspectJAfterAdvice.java:47)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)
at org.springframework.aop.framework.adapter.MethodBeforeAdviceInterceptor.invoke(MethodBeforeAdviceInterceptor.java:56)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)
at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:88)
at org.jeecg.common.aspect.PrintLogAspect.doAround(PrintLogAspect.java:155)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:644)
at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:633)
at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:70)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)
at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:88)
at org.jeecg.common.aspect.DictAspect.doAround(DictAspect.java:56)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:644)
at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:633)
at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:70)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)
at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:88)
at org.jeecg.common.aspect.AutoLogAspect.around(AutoLogAspect.java:57)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:644)
at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:633)
at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:70)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:175)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:95)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:691)
at org.jeecg.modules.sys.controller.SysConfigController$$EnhancerBySpringCGLIB$$d91be327.edit(<generated>)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:190)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:105)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:878)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:792)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1040)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
at org.springframework.web.servlet.FrameworkServlet.doPut(FrameworkServlet.java:920)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:655)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:733)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.jeecg.common.config.mqtoken.TransmitUserTokenFilter.doFilter(TransmitUserTokenFilter.java:26)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.shiro.web.servlet.ProxiedFilterChain.doFilter(ProxiedFilterChain.java:61)
at org.apache.shiro.web.servlet.AdviceFilter.executeChain(AdviceFilter.java:108)
at org.apache.shiro.web.servlet.AdviceFilter.doFilterInternal(AdviceFilter.java:137)
at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:125)
at org.apache.shiro.web.servlet.ProxiedFilterChain.doFilter(ProxiedFilterChain.java:66)
at org.apache.shiro.web.servlet.AdviceFilter.executeChain(AdviceFilter.java:108)
at org.apache.shiro.web.servlet.AdviceFilter.doFilterInternal(AdviceFilter.java:137)
at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:125)
at org.apache.shiro.web.servlet.ProxiedFilterChain.doFilter(ProxiedFilterChain.java:66)
at org.apache.shiro.web.servlet.AbstractShiroFilter.executeChain(AbstractShiroFilter.java:450)
at org.apache.shiro.web.servlet.AbstractShiroFilter$1.call(AbstractShiroFilter.java:365)
at org.apache.shiro.subject.support.SubjectCallable.doCall(SubjectCallable.java:90)
at org.apache.shiro.subject.support.SubjectCallable.call(SubjectCallable.java:83)
at org.apache.shiro.subject.support.DelegatingSubject.execute(DelegatingSubject.java:387)
at org.apache.shiro.web.servlet.AbstractShiroFilter.doFilterInternal(AbstractShiroFilter.java:362)
at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:125)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.CorsFilter.doFilterInternal(CorsFilter.java:92)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at com.alibaba.druid.support.http.WebStatFilter.doFilter(WebStatFilter.java:124)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.boot.actuate.web.trace.servlet.HttpTraceFilter.doFilterInternal(HttpTraceFilter.java:88)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.doFilterInternal(WebMvcMetricsFilter.java:93)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:542)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:143)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:374)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1590)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.ClassCastException: java.util.Date cannot be cast to com.alibaba.fastjson.JSONObject
at cn.monitor4all.logRecord.function.CustomFunctionObjectDiff.fieldValueEquals(CustomFunctionObjectDiff.java:214)
... 150 common frames omitted
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.