mirror of https://github.com/longtai-cn/hippo4j
commit
fad5985f6c
@ -1,43 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package cn.hippo4j.config.service.biz.impl;
|
||||
|
||||
import cn.hippo4j.config.mapper.LogRecordMapper;
|
||||
import cn.hippo4j.tools.logrecord.model.LogRecordInfo;
|
||||
import cn.hippo4j.tools.logrecord.service.LogRecordService;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* 操作日志保存数据库.
|
||||
*
|
||||
* @author chen.ma
|
||||
* @date 2021/10/24 20:57
|
||||
*/
|
||||
@Service
|
||||
@AllArgsConstructor
|
||||
public class LogRecordServiceImpl implements LogRecordService {
|
||||
|
||||
private final LogRecordMapper logRecordMapper;
|
||||
|
||||
@Override
|
||||
public void record(LogRecordInfo logRecordInfo) {
|
||||
logRecordMapper.insert(logRecordInfo);
|
||||
}
|
||||
|
||||
}
|
@ -1,42 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package cn.hippo4j.config.service.handler;
|
||||
|
||||
import cn.hippo4j.common.toolkit.StringUtil;
|
||||
import cn.hippo4j.common.toolkit.UserContext;
|
||||
import cn.hippo4j.tools.logrecord.model.Operator;
|
||||
import cn.hippo4j.tools.logrecord.service.OperatorGetService;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* Custom operator get service.
|
||||
*
|
||||
* @author chen.ma
|
||||
* @date 2021/11/28 17:57
|
||||
*/
|
||||
@Component
|
||||
public class CustomOperatorGetServiceImpl implements OperatorGetService {
|
||||
|
||||
@Override
|
||||
public Operator getUser() {
|
||||
String userName = UserContext.getUserName();
|
||||
userName = StringUtil.isEmpty(userName) ? "-" : userName;
|
||||
return new Operator(userName);
|
||||
}
|
||||
|
||||
}
|
@ -1,56 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package cn.hippo4j.config.service.handler;
|
||||
|
||||
import cn.hippo4j.config.model.biz.tenant.TenantRespDTO;
|
||||
import cn.hippo4j.config.service.biz.TenantService;
|
||||
import cn.hippo4j.tools.logrecord.service.ParseFunction;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* 查找原租户名称.
|
||||
*
|
||||
* @author chen.ma
|
||||
* @date 2021/10/24 22:07
|
||||
*/
|
||||
@Component
|
||||
@AllArgsConstructor
|
||||
public class TenantIdFunctionServiceImpl implements ParseFunction {
|
||||
|
||||
private final TenantService tenantService;
|
||||
|
||||
@Override
|
||||
public boolean executeBefore() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String functionName() {
|
||||
return "TENANT";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String apply(String tenantId) {
|
||||
TenantRespDTO tenant = tenantService.getTenantById(tenantId);
|
||||
return Optional.ofNullable(tenant).map(TenantRespDTO::getTenantName).orElse("");
|
||||
}
|
||||
|
||||
}
|
@ -1,55 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>cn.hippo4j</groupId>
|
||||
<artifactId>hippo4j-tool</artifactId>
|
||||
<version>${revision}</version>
|
||||
</parent>
|
||||
<artifactId>log-record-tool</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<name>log-record-tool</name>
|
||||
|
||||
<properties>
|
||||
<maven.deploy.skip>true</maven.deploy.skip>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.aspectj</groupId>
|
||||
<artifactId>aspectjweaver</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>transmittable-thread-local</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.hibernate.validator</groupId>
|
||||
<artifactId>hibernate-validator</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
@ -1,29 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package cn.hippo4j.tools.logrecord.annotation;
|
||||
|
||||
/**
|
||||
* Log field, used to mark entity properties that need to be compared.
|
||||
*
|
||||
* @author chen.ma
|
||||
* @date 2021/10/23 21:29
|
||||
*/
|
||||
public @interface LogField {
|
||||
|
||||
String name();
|
||||
}
|
@ -1,98 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package cn.hippo4j.tools.logrecord.annotation;
|
||||
|
||||
import cn.hippo4j.tools.logrecord.enums.LogRecordTypeEnum;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* 日志记录注解.
|
||||
*
|
||||
* @author chen.ma
|
||||
* @date 2021/10/23 21:29
|
||||
*/
|
||||
@Documented
|
||||
@Target({ElementType.METHOD})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface LogRecord {
|
||||
|
||||
/**
|
||||
* 业务前缀
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
String prefix() default "";
|
||||
|
||||
/**
|
||||
* 操作日志文本模版
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
String success();
|
||||
|
||||
/**
|
||||
* 操作日志失败的文本
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
String fail() default "";
|
||||
|
||||
/**
|
||||
* 操作人
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
String operator() default "";
|
||||
|
||||
/**
|
||||
* 业务码
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
String bizNo();
|
||||
|
||||
/**
|
||||
* 日志详情
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
String detail() default "";
|
||||
|
||||
/**
|
||||
* 日志种类
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
String category();
|
||||
|
||||
/**
|
||||
* 记录类型
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
LogRecordTypeEnum recordType() default LogRecordTypeEnum.COMPLETE;
|
||||
|
||||
/**
|
||||
* 记录日志条件
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
String condition() default "";
|
||||
|
||||
}
|
@ -1,224 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package cn.hippo4j.tools.logrecord.aop;
|
||||
|
||||
import cn.hippo4j.tools.logrecord.annotation.LogRecord;
|
||||
import cn.hippo4j.tools.logrecord.context.LogRecordContext;
|
||||
import cn.hippo4j.tools.logrecord.model.LogRecordInfo;
|
||||
import cn.hippo4j.tools.logrecord.model.LogRecordOps;
|
||||
import cn.hippo4j.tools.logrecord.model.MethodExecuteResult;
|
||||
import cn.hippo4j.tools.logrecord.parse.LogRecordOperationSource;
|
||||
import cn.hippo4j.tools.logrecord.parse.LogRecordValueParser;
|
||||
import cn.hippo4j.tools.logrecord.service.LogRecordService;
|
||||
import cn.hippo4j.tools.logrecord.service.OperatorGetService;
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.aspectj.lang.ProceedingJoinPoint;
|
||||
import org.aspectj.lang.annotation.Around;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.aspectj.lang.reflect.MethodSignature;
|
||||
import org.springframework.aop.framework.AopProxyUtils;
|
||||
import org.springframework.core.env.ConfigurableEnvironment;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* 日志记录切面.
|
||||
*
|
||||
* @author chen.ma
|
||||
* @date 2021/10/23 22:00
|
||||
*/
|
||||
@Slf4j
|
||||
@Aspect
|
||||
@Component
|
||||
@AllArgsConstructor
|
||||
public class LogRecordAspect {
|
||||
|
||||
private final LogRecordService bizLogService;
|
||||
|
||||
private final LogRecordValueParser logRecordValueParser;
|
||||
|
||||
private final OperatorGetService operatorGetService;
|
||||
|
||||
private final LogRecordOperationSource logRecordOperationSource;
|
||||
|
||||
private final ConfigurableEnvironment environment;
|
||||
|
||||
@Around("@annotation(logRecord)")
|
||||
public Object logRecord(ProceedingJoinPoint joinPoint, LogRecord logRecord) throws Throwable {
|
||||
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
|
||||
Method method = methodSignature.getMethod();
|
||||
Object target = joinPoint.getTarget();
|
||||
Class<?> targetClass = AopProxyUtils.ultimateTargetClass(target);
|
||||
Object[] args = joinPoint.getArgs();
|
||||
|
||||
LogRecordContext.putEmptySpan();
|
||||
|
||||
Object result = null;
|
||||
Collection<LogRecordOps> operations = Lists.newArrayList();
|
||||
Map<String, String> functionNameAndReturnMap = Maps.newHashMap();
|
||||
MethodExecuteResult methodExecuteResult = new MethodExecuteResult(true);
|
||||
|
||||
try {
|
||||
operations = logRecordOperationSource.computeLogRecordOperations(method, targetClass);
|
||||
List<String> spElTemplates = getBeforeExecuteFunctionTemplate(operations);
|
||||
functionNameAndReturnMap = logRecordValueParser.processBeforeExecuteFunctionTemplate(spElTemplates, targetClass, method, args);
|
||||
|
||||
} catch (Exception ex) {
|
||||
log.error("Log record parse before function exception.", ex);
|
||||
}
|
||||
|
||||
try {
|
||||
result = joinPoint.proceed();
|
||||
} catch (Exception ex) {
|
||||
methodExecuteResult = new MethodExecuteResult(false, ex, ex.getMessage());
|
||||
}
|
||||
|
||||
try {
|
||||
if (!CollectionUtils.isEmpty(operations)) {
|
||||
recordExecute(result, method, args, operations, targetClass,
|
||||
methodExecuteResult.isSuccess(), methodExecuteResult.getErrorMsg(), functionNameAndReturnMap);
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
log.error("Log record parse exception.", ex);
|
||||
} finally {
|
||||
LogRecordContext.clear();
|
||||
}
|
||||
|
||||
if (methodExecuteResult.getThrowable() != null) {
|
||||
throw methodExecuteResult.getThrowable();
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
private List<String> getBeforeExecuteFunctionTemplate(Collection<LogRecordOps> operations) {
|
||||
List<String> spElTemplates = new ArrayList();
|
||||
for (LogRecordOps operation : operations) {
|
||||
// 执行之前的函数
|
||||
List<String> templates = getSpElTemplates(operation, operation.getSuccessLogTemplate());
|
||||
if (!CollectionUtils.isEmpty(templates)) {
|
||||
spElTemplates.addAll(templates);
|
||||
}
|
||||
}
|
||||
|
||||
return spElTemplates;
|
||||
}
|
||||
|
||||
private List<String> getSpElTemplates(LogRecordOps operation, String action) {
|
||||
List<String> spElTemplates = Lists.newArrayList(operation.getBizKey(), operation.getBizNo(), action, operation.getDetail());
|
||||
|
||||
if (!StringUtils.isEmpty(operation.getCondition())) {
|
||||
spElTemplates.add(operation.getCondition());
|
||||
}
|
||||
|
||||
return spElTemplates;
|
||||
}
|
||||
|
||||
/**
|
||||
* 记录日志.
|
||||
*
|
||||
* @param ret
|
||||
* @param method
|
||||
* @param args
|
||||
* @param operations
|
||||
* @param targetClass
|
||||
* @param success
|
||||
* @param errorMsg
|
||||
* @param functionNameAndReturnMap
|
||||
*/
|
||||
private void recordExecute(Object ret, Method method, Object[] args, Collection<LogRecordOps> operations,
|
||||
Class<?> targetClass, boolean success, String errorMsg, Map<String, String> functionNameAndReturnMap) {
|
||||
for (LogRecordOps operation : operations) {
|
||||
try {
|
||||
String action = getActionContent(success, operation);
|
||||
if (StringUtils.isEmpty(action)) {
|
||||
// 没有日志内容则忽略
|
||||
continue;
|
||||
}
|
||||
// 获取需要解析的表达式
|
||||
List<String> spElTemplates = getSpElTemplates(operation, action);
|
||||
String operatorIdFromService = getOperatorIdFromServiceAndPutTemplate(operation, spElTemplates);
|
||||
|
||||
Map<String, String> expressionValues = logRecordValueParser.processTemplate(spElTemplates, ret, targetClass, method, args, errorMsg, functionNameAndReturnMap);
|
||||
if (logConditionPassed(operation.getCondition(), expressionValues)) {
|
||||
String tenant = environment.getProperty("tenant");
|
||||
LogRecordInfo logRecordInfo = LogRecordInfo.builder()
|
||||
.tenant(StringUtils.isEmpty(tenant) ? "hippo4j" : tenant)
|
||||
.bizKey(expressionValues.get(operation.getBizKey()))
|
||||
.bizNo(expressionValues.get(operation.getBizNo()))
|
||||
.operator(getRealOperatorId(operation, operatorIdFromService, expressionValues))
|
||||
.category(operation.getCategory())
|
||||
.detail(expressionValues.get(operation.getDetail()))
|
||||
.action(expressionValues.get(action))
|
||||
.createTime(new Date())
|
||||
.build();
|
||||
|
||||
// 如果 action 为空, 不记录日志
|
||||
if (StringUtils.isEmpty(logRecordInfo.getAction())) {
|
||||
continue;
|
||||
}
|
||||
// save log 需要新开事务, 失败日志不能因为事务回滚而丢失
|
||||
Preconditions.checkNotNull(bizLogService, "bizLogService not init");
|
||||
bizLogService.record(logRecordInfo);
|
||||
}
|
||||
} catch (Exception t) {
|
||||
log.error("log record execute exception", t);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private String getActionContent(boolean success, LogRecordOps operation) {
|
||||
if (success) {
|
||||
return operation.getSuccessLogTemplate();
|
||||
}
|
||||
|
||||
return operation.getFailLogTemplate();
|
||||
}
|
||||
|
||||
private String getOperatorIdFromServiceAndPutTemplate(LogRecordOps operation, List<String> spElTemplates) {
|
||||
String realOperatorId = "";
|
||||
if (StringUtils.isEmpty(operation.getOperatorId())) {
|
||||
realOperatorId = operatorGetService.getUser().getOperatorId();
|
||||
if (StringUtils.isEmpty(realOperatorId)) {
|
||||
throw new IllegalArgumentException("LogRecord operator is null");
|
||||
}
|
||||
} else {
|
||||
spElTemplates.add(operation.getOperatorId());
|
||||
}
|
||||
|
||||
return realOperatorId;
|
||||
}
|
||||
|
||||
private boolean logConditionPassed(String condition, Map<String, String> expressionValues) {
|
||||
return StringUtils.isEmpty(condition) || StringUtils.endsWithIgnoreCase(expressionValues.get(condition), "true");
|
||||
}
|
||||
|
||||
private String getRealOperatorId(LogRecordOps operation, String operatorIdFromService, Map<String, String> expressionValues) {
|
||||
return !StringUtils.isEmpty(operatorIdFromService) ? operatorIdFromService : expressionValues.get(operation.getOperatorId());
|
||||
}
|
||||
|
||||
}
|
@ -1,86 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package cn.hippo4j.tools.logrecord.config;
|
||||
|
||||
import cn.hippo4j.tools.logrecord.parse.LogRecordOperationSource;
|
||||
import cn.hippo4j.tools.logrecord.parse.LogRecordValueParser;
|
||||
import cn.hippo4j.tools.logrecord.service.FunctionService;
|
||||
import cn.hippo4j.tools.logrecord.service.LogRecordService;
|
||||
import cn.hippo4j.tools.logrecord.service.OperatorGetService;
|
||||
import cn.hippo4j.tools.logrecord.service.ParseFunction;
|
||||
import cn.hippo4j.tools.logrecord.service.impl.*;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Role;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 日志记录配置.
|
||||
*
|
||||
* @author chen.ma
|
||||
* @date 2021/10/23 22:49
|
||||
*/
|
||||
@Configuration
|
||||
public class LogRecordConfig {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(ParseFunction.class)
|
||||
public DefaultParseFunction parseFunction() {
|
||||
return new DefaultParseFunction();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ParseFunctionFactory parseFunctionFactory(@Autowired List<ParseFunction> parseFunctions) {
|
||||
return new ParseFunctionFactory(parseFunctions);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(FunctionService.class)
|
||||
public FunctionService functionService(ParseFunctionFactory parseFunctionFactory) {
|
||||
return new DefaultFunctionServiceImpl(parseFunctionFactory);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@Role(BeanDefinition.ROLE_APPLICATION)
|
||||
@ConditionalOnMissingBean(OperatorGetService.class)
|
||||
public OperatorGetService operatorGetService() {
|
||||
return new DefaultOperatorGetServiceImpl();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(LogRecordService.class)
|
||||
@Role(BeanDefinition.ROLE_APPLICATION)
|
||||
public LogRecordService recordService() {
|
||||
return new DefaultLogRecordServiceImpl();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public LogRecordValueParser logRecordValueParser() {
|
||||
return new LogRecordValueParser();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public LogRecordOperationSource logRecordOperationSource() {
|
||||
return new LogRecordOperationSource();
|
||||
}
|
||||
|
||||
}
|
@ -1,63 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package cn.hippo4j.tools.logrecord.context;
|
||||
|
||||
import com.alibaba.ttl.TransmittableThreadLocal;
|
||||
import com.google.common.collect.Maps;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Stack;
|
||||
|
||||
/**
|
||||
* 日志记录上下文.
|
||||
*
|
||||
* @author chen.ma
|
||||
* @date 2021/10/23 21:47
|
||||
*/
|
||||
public class LogRecordContext {
|
||||
|
||||
private static final ThreadLocal<Stack<Map<String, Object>>> VARIABLE_MAP_STACK = new TransmittableThreadLocal();
|
||||
|
||||
/**
|
||||
* 出栈.
|
||||
*/
|
||||
public static void clear() {
|
||||
if (VARIABLE_MAP_STACK.get() != null) {
|
||||
VARIABLE_MAP_STACK.get().pop();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化.
|
||||
*/
|
||||
public static void putEmptySpan() {
|
||||
Stack<Map<String, Object>> mapStack = VARIABLE_MAP_STACK.get();
|
||||
if (mapStack == null) {
|
||||
Stack<Map<String, Object>> stack = new Stack<>();
|
||||
VARIABLE_MAP_STACK.set(stack);
|
||||
}
|
||||
|
||||
VARIABLE_MAP_STACK.get().push(Maps.newHashMap());
|
||||
}
|
||||
|
||||
public static Map<String, Object> getVariables() {
|
||||
Stack<Map<String, Object>> mapStack = VARIABLE_MAP_STACK.get();
|
||||
return mapStack.peek();
|
||||
}
|
||||
|
||||
}
|
@ -1,38 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package cn.hippo4j.tools.logrecord.enums;
|
||||
|
||||
/**
|
||||
* 日志记录类型.
|
||||
*
|
||||
* @author chen.ma
|
||||
* @date 2021/10/24 21:54
|
||||
*/
|
||||
public enum LogRecordTypeEnum {
|
||||
|
||||
/**
|
||||
* 按照文字模版记录
|
||||
*/
|
||||
TEMPLATE,
|
||||
|
||||
/**
|
||||
* 比较修改前后所有区别
|
||||
*/
|
||||
COMPLETE
|
||||
|
||||
}
|
@ -1,49 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package cn.hippo4j.tools.logrecord.model;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 日志操作记录.
|
||||
*
|
||||
* @author chen.ma
|
||||
* @date 2021/10/24 21:07
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
public class LogRecordOps {
|
||||
|
||||
private String successLogTemplate;
|
||||
|
||||
private String failLogTemplate;
|
||||
|
||||
private String operatorId;
|
||||
|
||||
private String bizKey;
|
||||
|
||||
private String bizNo;
|
||||
|
||||
private String category;
|
||||
|
||||
private String detail;
|
||||
|
||||
private String condition;
|
||||
|
||||
}
|
@ -1,50 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package cn.hippo4j.tools.logrecord.model;
|
||||
|
||||
import lombok.*;
|
||||
|
||||
/**
|
||||
* 方法执行结果.
|
||||
*
|
||||
* @author chen.ma
|
||||
* @date 2021/10/24 21:59
|
||||
*/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@RequiredArgsConstructor
|
||||
public class MethodExecuteResult {
|
||||
|
||||
/**
|
||||
* 是否成功
|
||||
*/
|
||||
@NonNull
|
||||
private boolean success;
|
||||
|
||||
/**
|
||||
* 异常
|
||||
*/
|
||||
private Throwable throwable;
|
||||
|
||||
/**
|
||||
* 错误日志
|
||||
*/
|
||||
private String errorMsg;
|
||||
|
||||
}
|
@ -1,40 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package cn.hippo4j.tools.logrecord.model;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* 操作人.
|
||||
*
|
||||
* @author chen.ma
|
||||
* @date 2021/10/24 21:44
|
||||
*/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class Operator {
|
||||
|
||||
/**
|
||||
* 操作人 Id
|
||||
*/
|
||||
private String operatorId;
|
||||
|
||||
}
|
@ -1,49 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package cn.hippo4j.tools.logrecord.parse;
|
||||
|
||||
import cn.hippo4j.tools.logrecord.context.LogRecordContext;
|
||||
import org.springframework.context.expression.MethodBasedEvaluationContext;
|
||||
import org.springframework.core.ParameterNameDiscoverer;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Log record evaluation context.
|
||||
*
|
||||
* @author chen.ma
|
||||
* @date 2021/10/24 21:25
|
||||
*/
|
||||
public class LogRecordEvaluationContext extends MethodBasedEvaluationContext {
|
||||
|
||||
public LogRecordEvaluationContext(Object rootObject, Method method, Object[] arguments,
|
||||
ParameterNameDiscoverer parameterNameDiscoverer, Object ret, String errorMsg) {
|
||||
super(rootObject, method, arguments, parameterNameDiscoverer);
|
||||
|
||||
Map<String, Object> variables = LogRecordContext.getVariables();
|
||||
if (variables != null && variables.size() > 0) {
|
||||
for (Map.Entry<String, Object> entry : variables.entrySet()) {
|
||||
setVariable(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
setVariable("_ret", ret);
|
||||
setVariable("_errorMsg", errorMsg);
|
||||
}
|
||||
}
|
@ -1,70 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package cn.hippo4j.tools.logrecord.parse;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import org.springframework.aop.support.AopUtils;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.context.expression.AnnotatedElementKey;
|
||||
import org.springframework.context.expression.BeanFactoryResolver;
|
||||
import org.springframework.context.expression.CachedExpressionEvaluator;
|
||||
import org.springframework.expression.EvaluationContext;
|
||||
import org.springframework.expression.Expression;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Log record expression evaluator.
|
||||
*
|
||||
* @author chen.ma
|
||||
* @date 2021/10/24 22:22
|
||||
*/
|
||||
public class LogRecordExpressionEvaluator extends CachedExpressionEvaluator {
|
||||
|
||||
private Map<ExpressionKey, Expression> expressionCache = Maps.newConcurrentMap();
|
||||
|
||||
private final Map<AnnotatedElementKey, Method> targetMethodCache = Maps.newConcurrentMap();
|
||||
|
||||
public String parseExpression(String conditionExpression, AnnotatedElementKey methodKey, EvaluationContext evalContext) {
|
||||
Object value = getExpression(this.expressionCache, methodKey, conditionExpression).getValue(evalContext, Object.class);
|
||||
return value == null ? "" : value.toString();
|
||||
}
|
||||
|
||||
public EvaluationContext createEvaluationContext(Method method, Object[] args, Class<?> targetClass,
|
||||
Object result, String errorMsg, BeanFactory beanFactory) {
|
||||
Method targetMethod = getTargetMethod(targetClass, method);
|
||||
LogRecordEvaluationContext evaluationContext = new LogRecordEvaluationContext(
|
||||
null, targetMethod, args, getParameterNameDiscoverer(), result, errorMsg);
|
||||
if (beanFactory != null) {
|
||||
evaluationContext.setBeanResolver(new BeanFactoryResolver(beanFactory));
|
||||
}
|
||||
return evaluationContext;
|
||||
}
|
||||
|
||||
private Method getTargetMethod(Class<?> targetClass, Method method) {
|
||||
AnnotatedElementKey methodKey = new AnnotatedElementKey(method, targetClass);
|
||||
Method targetMethod = this.targetMethodCache.get(methodKey);
|
||||
if (targetMethod == null) {
|
||||
targetMethod = AopUtils.getMostSpecificMethod(method, targetClass);
|
||||
this.targetMethodCache.put(methodKey, targetMethod);
|
||||
}
|
||||
return targetMethod;
|
||||
}
|
||||
|
||||
}
|
@ -1,88 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package cn.hippo4j.tools.logrecord.parse;
|
||||
|
||||
import cn.hippo4j.tools.logrecord.annotation.LogRecord;
|
||||
import cn.hippo4j.tools.logrecord.model.LogRecordOps;
|
||||
import org.springframework.core.BridgeMethodResolver;
|
||||
import org.springframework.core.annotation.AnnotatedElementUtils;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.lang.reflect.AnnotatedElement;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* 日志记录操作解析.
|
||||
*
|
||||
* @author chen.ma
|
||||
* @date 2021/10/23 22:02
|
||||
*/
|
||||
public class LogRecordOperationSource {
|
||||
|
||||
public Collection<LogRecordOps> computeLogRecordOperations(Method method, Class<?> targetClass) {
|
||||
if (!Modifier.isPublic(method.getModifiers())) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Method specificMethod = ClassUtils.getMostSpecificMethod(method, targetClass);
|
||||
specificMethod = BridgeMethodResolver.findBridgedMethod(specificMethod);
|
||||
|
||||
return parseLogRecordAnnotations(specificMethod);
|
||||
}
|
||||
|
||||
private Collection<LogRecordOps> parseLogRecordAnnotations(AnnotatedElement ae) {
|
||||
Collection<LogRecord> logRecordAnnotations = AnnotatedElementUtils.getAllMergedAnnotations(ae, LogRecord.class);
|
||||
Collection<LogRecordOps> ret = null;
|
||||
if (!logRecordAnnotations.isEmpty()) {
|
||||
ret = new ArrayList(1);
|
||||
for (LogRecord logRecord : logRecordAnnotations) {
|
||||
ret.add(parseLogRecordAnnotation(ae, logRecord));
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
private LogRecordOps parseLogRecordAnnotation(AnnotatedElement ae, LogRecord logRecord) {
|
||||
LogRecordOps recordOps = LogRecordOps.builder()
|
||||
.successLogTemplate(logRecord.success())
|
||||
.failLogTemplate(logRecord.fail())
|
||||
.bizKey(logRecord.prefix().concat(logRecord.bizNo()))
|
||||
.bizNo(logRecord.bizNo())
|
||||
.operatorId(logRecord.operator())
|
||||
.category(StringUtils.isEmpty(logRecord.category()) ? logRecord.prefix() : logRecord.category())
|
||||
.detail(logRecord.detail())
|
||||
.condition(logRecord.condition())
|
||||
.build();
|
||||
|
||||
validateLogRecordOperation(ae, recordOps);
|
||||
return recordOps;
|
||||
}
|
||||
|
||||
private void validateLogRecordOperation(AnnotatedElement ae, LogRecordOps recordOps) {
|
||||
if (!StringUtils.hasText(recordOps.getSuccessLogTemplate()) && !StringUtils.hasText(recordOps.getFailLogTemplate())) {
|
||||
throw new IllegalStateException("Invalid logRecord annotation configuration on '" +
|
||||
ae.toString() + "'. 'one of successTemplate and failLogTemplate' attribute must be set.");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,124 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package cn.hippo4j.tools.logrecord.parse;
|
||||
|
||||
import cn.hippo4j.tools.logrecord.service.FunctionService;
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.common.collect.Maps;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.expression.AnnotatedElementKey;
|
||||
import org.springframework.expression.EvaluationContext;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Log record value parser.
|
||||
*
|
||||
* @author chen.ma
|
||||
* @date 2021/10/24 21:27
|
||||
*/
|
||||
public class LogRecordValueParser implements BeanFactoryAware {
|
||||
|
||||
@Autowired
|
||||
private FunctionService functionService;
|
||||
|
||||
protected BeanFactory beanFactory;
|
||||
|
||||
private final LogRecordExpressionEvaluator expressionEvaluator = new LogRecordExpressionEvaluator();
|
||||
|
||||
private static final Pattern PATTERN = Pattern.compile("\\{\\s*(\\w*)\\s*\\{(.*?)}}");
|
||||
|
||||
public Map<String, String> processTemplate(Collection<String> templates, Object ret,
|
||||
Class<?> targetClass, Method method, Object[] args, String errorMsg,
|
||||
Map<String, String> beforeFunctionNameAndReturnMap) {
|
||||
Map<String, String> expressionValues = Maps.newHashMap();
|
||||
EvaluationContext evaluationContext = expressionEvaluator.createEvaluationContext(method, args, targetClass, ret, errorMsg, beanFactory);
|
||||
|
||||
for (String expressionTemplate : templates) {
|
||||
if (expressionTemplate.contains("{")) {
|
||||
Matcher matcher = PATTERN.matcher(expressionTemplate);
|
||||
StringBuffer parsedStr = new StringBuffer();
|
||||
while (matcher.find()) {
|
||||
String expression = matcher.group(2);
|
||||
AnnotatedElementKey annotatedElementKey = new AnnotatedElementKey(method, targetClass);
|
||||
String value = expressionEvaluator.parseExpression(expression, annotatedElementKey, evaluationContext);
|
||||
String functionReturnValue = getFunctionReturnValue(beforeFunctionNameAndReturnMap, value, matcher.group(1));
|
||||
matcher.appendReplacement(parsedStr, Strings.nullToEmpty(functionReturnValue));
|
||||
}
|
||||
matcher.appendTail(parsedStr);
|
||||
expressionValues.put(expressionTemplate, parsedStr.toString());
|
||||
} else {
|
||||
expressionValues.put(expressionTemplate, expressionTemplate);
|
||||
}
|
||||
}
|
||||
|
||||
return expressionValues;
|
||||
}
|
||||
|
||||
public Map<String, String> processBeforeExecuteFunctionTemplate(Collection<String> templates, Class<?> targetClass, Method method, Object[] args) {
|
||||
Map<String, String> functionNameAndReturnValueMap = new HashMap(16);
|
||||
EvaluationContext evaluationContext = expressionEvaluator.createEvaluationContext(method, args, targetClass, null, null, beanFactory);
|
||||
|
||||
for (String expressionTemplate : templates) {
|
||||
if (expressionTemplate.contains("{")) {
|
||||
Matcher matcher = PATTERN.matcher(expressionTemplate);
|
||||
while (matcher.find()) {
|
||||
String expression = matcher.group(2);
|
||||
if (expression.contains("#_ret") || expression.contains("#_errorMsg")) {
|
||||
continue;
|
||||
}
|
||||
AnnotatedElementKey annotatedElementKey = new AnnotatedElementKey(method, targetClass);
|
||||
String functionName = matcher.group(1);
|
||||
if (functionService.beforeFunction(functionName)) {
|
||||
String value = expressionEvaluator.parseExpression(expression, annotatedElementKey, evaluationContext);
|
||||
String functionReturnValue = getFunctionReturnValue(null, value, functionName);
|
||||
functionNameAndReturnValueMap.put(functionName, functionReturnValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return functionNameAndReturnValueMap;
|
||||
}
|
||||
|
||||
private String getFunctionReturnValue(Map<String, String> beforeFunctionNameAndReturnMap, String value, String functionName) {
|
||||
String functionReturnValue = "";
|
||||
if (beforeFunctionNameAndReturnMap != null) {
|
||||
functionReturnValue = beforeFunctionNameAndReturnMap.get(functionName);
|
||||
}
|
||||
if (StringUtils.isEmpty(functionReturnValue)) {
|
||||
functionReturnValue = functionService.apply(functionName, value);
|
||||
}
|
||||
return functionReturnValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
|
||||
this.beanFactory = beanFactory;
|
||||
}
|
||||
|
||||
}
|
@ -1,45 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package cn.hippo4j.tools.logrecord.service;
|
||||
|
||||
/**
|
||||
* 函数服务.
|
||||
*
|
||||
* @author chen.ma
|
||||
* @date 2021/10/24 21:30
|
||||
*/
|
||||
public interface FunctionService {
|
||||
|
||||
/**
|
||||
* 执行.
|
||||
*
|
||||
* @param functionName
|
||||
* @param value
|
||||
* @return
|
||||
*/
|
||||
String apply(String functionName, String value);
|
||||
|
||||
/**
|
||||
* 是否提前执行.
|
||||
*
|
||||
* @param functionName
|
||||
* @return
|
||||
*/
|
||||
boolean beforeFunction(String functionName);
|
||||
|
||||
}
|
@ -1,37 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package cn.hippo4j.tools.logrecord.service;
|
||||
|
||||
import cn.hippo4j.tools.logrecord.model.LogRecordInfo;
|
||||
|
||||
/**
|
||||
* 日志记录.
|
||||
*
|
||||
* @author chen.ma
|
||||
* @date 2021/10/23 22:43
|
||||
*/
|
||||
public interface LogRecordService {
|
||||
|
||||
/**
|
||||
* 保存日志.
|
||||
*
|
||||
* @param logRecordInfo
|
||||
*/
|
||||
void record(LogRecordInfo logRecordInfo);
|
||||
|
||||
}
|
@ -1,37 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package cn.hippo4j.tools.logrecord.service;
|
||||
|
||||
import cn.hippo4j.tools.logrecord.model.Operator;
|
||||
|
||||
/**
|
||||
* 获取操作人.
|
||||
*
|
||||
* @author chen.ma
|
||||
* @date 2021/10/23 22:46
|
||||
*/
|
||||
public interface OperatorGetService {
|
||||
|
||||
/**
|
||||
* 获取操作人.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
Operator getUser();
|
||||
|
||||
}
|
@ -1,52 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package cn.hippo4j.tools.logrecord.service;
|
||||
|
||||
/**
|
||||
* 函数解析.
|
||||
*
|
||||
* @author chen.ma
|
||||
* @date 2021/10/23 22:40
|
||||
*/
|
||||
public interface ParseFunction {
|
||||
|
||||
/**
|
||||
* 是否先执行.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
default boolean executeBefore() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 函数名称.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
String functionName();
|
||||
|
||||
/**
|
||||
* 执行.
|
||||
*
|
||||
* @param value
|
||||
* @return
|
||||
*/
|
||||
String apply(String value);
|
||||
|
||||
}
|
@ -1,49 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package cn.hippo4j.tools.logrecord.service.impl;
|
||||
|
||||
import cn.hippo4j.tools.logrecord.service.FunctionService;
|
||||
import cn.hippo4j.tools.logrecord.service.ParseFunction;
|
||||
import lombok.AllArgsConstructor;
|
||||
|
||||
/**
|
||||
* 默认实现函数接口.
|
||||
*
|
||||
* @author chen.ma
|
||||
* @date 2021/10/24 21:54
|
||||
*/
|
||||
@AllArgsConstructor
|
||||
public class DefaultFunctionServiceImpl implements FunctionService {
|
||||
|
||||
private final ParseFunctionFactory parseFunctionFactory;
|
||||
|
||||
@Override
|
||||
public String apply(String functionName, String value) {
|
||||
ParseFunction function = parseFunctionFactory.getFunction(functionName);
|
||||
if (function == null) {
|
||||
return value;
|
||||
}
|
||||
return function.apply(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean beforeFunction(String functionName) {
|
||||
return parseFunctionFactory.isBeforeFunction(functionName);
|
||||
}
|
||||
|
||||
}
|
@ -1,38 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package cn.hippo4j.tools.logrecord.service.impl;
|
||||
|
||||
import cn.hippo4j.tools.logrecord.model.LogRecordInfo;
|
||||
import cn.hippo4j.tools.logrecord.service.LogRecordService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* 默认实现日志存储.
|
||||
*
|
||||
* @author chen.ma
|
||||
* @date 2021/10/24 17:59
|
||||
*/
|
||||
@Slf4j
|
||||
public class DefaultLogRecordServiceImpl implements LogRecordService {
|
||||
|
||||
@Override
|
||||
public void record(LogRecordInfo logRecordInfo) {
|
||||
log.info("Log print :: {}", logRecordInfo);
|
||||
}
|
||||
|
||||
}
|
@ -1,36 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package cn.hippo4j.tools.logrecord.service.impl;
|
||||
|
||||
import cn.hippo4j.tools.logrecord.model.Operator;
|
||||
import cn.hippo4j.tools.logrecord.service.OperatorGetService;
|
||||
|
||||
/**
|
||||
* 默认实现.
|
||||
*
|
||||
* @author chen.ma
|
||||
* @date 2021/10/24 17:58
|
||||
*/
|
||||
public class DefaultOperatorGetServiceImpl implements OperatorGetService {
|
||||
|
||||
@Override
|
||||
public Operator getUser() {
|
||||
return new Operator("-");
|
||||
}
|
||||
|
||||
}
|
@ -1,45 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package cn.hippo4j.tools.logrecord.service.impl;
|
||||
|
||||
import cn.hippo4j.tools.logrecord.service.ParseFunction;
|
||||
|
||||
/**
|
||||
* 默认实现.
|
||||
*
|
||||
* @author chen.ma
|
||||
* @date 2021/10/24 17:57
|
||||
*/
|
||||
public class DefaultParseFunction implements ParseFunction {
|
||||
|
||||
@Override
|
||||
public boolean executeBefore() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String functionName() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String apply(String value) {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
@ -1,73 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package cn.hippo4j.tools.logrecord.service.impl;
|
||||
|
||||
import cn.hippo4j.tools.logrecord.service.ParseFunction;
|
||||
import com.google.common.collect.Maps;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 函数解析工厂.
|
||||
*
|
||||
* @author chen.ma
|
||||
* @date 2021/10/23 22:39
|
||||
*/
|
||||
public class ParseFunctionFactory {
|
||||
|
||||
private Map<String, ParseFunction> allFunctionMap;
|
||||
|
||||
public ParseFunctionFactory(List<ParseFunction> parseFunctions) {
|
||||
if (CollectionUtils.isEmpty(parseFunctions)) {
|
||||
return;
|
||||
}
|
||||
|
||||
allFunctionMap = Maps.newHashMap();
|
||||
for (ParseFunction parseFunction : parseFunctions) {
|
||||
if (StringUtils.isEmpty(parseFunction.functionName())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
allFunctionMap.put(parseFunction.functionName(), parseFunction);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取函数实例.
|
||||
*
|
||||
* @param functionName
|
||||
* @return
|
||||
*/
|
||||
public ParseFunction getFunction(String functionName) {
|
||||
return allFunctionMap.get(functionName);
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否提前执行.
|
||||
*
|
||||
* @param functionName
|
||||
* @return
|
||||
*/
|
||||
public boolean isBeforeFunction(String functionName) {
|
||||
return allFunctionMap.get(functionName) != null && allFunctionMap.get(functionName).executeBefore();
|
||||
}
|
||||
|
||||
}
|
@ -1,22 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>cn.hippo4j</groupId>
|
||||
<artifactId>hippo4j-all</artifactId>
|
||||
<version>${revision}</version>
|
||||
</parent>
|
||||
<artifactId>hippo4j-tool</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
<name>${project.artifactId}</name>
|
||||
<description>Dynamic thread pool tool class module</description>
|
||||
|
||||
<modules>
|
||||
<module>log-record-tool</module>
|
||||
</modules>
|
||||
|
||||
<properties>
|
||||
<maven.deploy.skip>true</maven.deploy.skip>
|
||||
</properties>
|
||||
</project>
|
Loading…
Reference in new issue