43 changed files with 1685 additions and 949 deletions
@ -0,0 +1,150 @@ |
|||
2024-08-07 19:38:55.856 [main] ERROR org.springframework.boot.SpringApplication - Application run failed |
|||
org.springframework.beans.factory.BeanDefinitionStoreException: Failed to parse configuration class [org.nl.AppRun]; nested exception is org.springframework.context.annotation.ConflictingBeanDefinitionException: Annotation-specified bean name 'SortingCNTTask' for bean class [org.nl.wms.sch.task_manage.task.tasks.sorting.SortingSMTTask] conflicts with existing, non-compatible bean definition of same name and class [org.nl.wms.sch.task_manage.task.tasks.sorting.SortingCNTTask] |
|||
at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:189) |
|||
at org.springframework.context.annotation.ConfigurationClassPostProcessor.processConfigBeanDefinitions(ConfigurationClassPostProcessor.java:319) |
|||
at org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(ConfigurationClassPostProcessor.java:236) |
|||
at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors(PostProcessorRegistrationDelegate.java:280) |
|||
at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:96) |
|||
at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:707) |
|||
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:533) |
|||
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:141) |
|||
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:747) |
|||
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397) |
|||
at org.springframework.boot.SpringApplication.run(SpringApplication.java:315) |
|||
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1226) |
|||
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1215) |
|||
at org.nl.AppRun.main(AppRun.java:45) |
|||
Caused by: org.springframework.context.annotation.ConflictingBeanDefinitionException: Annotation-specified bean name 'SortingCNTTask' for bean class [org.nl.wms.sch.task_manage.task.tasks.sorting.SortingSMTTask] conflicts with existing, non-compatible bean definition of same name and class [org.nl.wms.sch.task_manage.task.tasks.sorting.SortingCNTTask] |
|||
at org.springframework.context.annotation.ClassPathBeanDefinitionScanner.checkCandidate(ClassPathBeanDefinitionScanner.java:349) |
|||
at org.springframework.context.annotation.ClassPathBeanDefinitionScanner.doScan(ClassPathBeanDefinitionScanner.java:287) |
|||
at org.springframework.context.annotation.ComponentScanAnnotationParser.parse(ComponentScanAnnotationParser.java:132) |
|||
at org.springframework.context.annotation.ConfigurationClassParser.doProcessConfigurationClass(ConfigurationClassParser.java:296) |
|||
at org.springframework.context.annotation.ConfigurationClassParser.processConfigurationClass(ConfigurationClassParser.java:250) |
|||
at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:207) |
|||
at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:175) |
|||
... 13 common frames omitted |
|||
2024-08-07 19:41:03.291 [main] ERROR org.springframework.boot.SpringApplication - Application run failed |
|||
org.springframework.beans.factory.BeanDefinitionStoreException: Failed to parse configuration class [org.nl.AppRun]; nested exception is org.springframework.context.annotation.ConflictingBeanDefinitionException: Annotation-specified bean name 'SortingCNTTask' for bean class [org.nl.wms.sch.task_manage.task.tasks.sorting.SortingSMTTask] conflicts with existing, non-compatible bean definition of same name and class [org.nl.wms.sch.task_manage.task.tasks.sorting.SortingCNTTask] |
|||
at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:189) |
|||
at org.springframework.context.annotation.ConfigurationClassPostProcessor.processConfigBeanDefinitions(ConfigurationClassPostProcessor.java:319) |
|||
at org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(ConfigurationClassPostProcessor.java:236) |
|||
at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors(PostProcessorRegistrationDelegate.java:280) |
|||
at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:96) |
|||
at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:707) |
|||
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:533) |
|||
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:141) |
|||
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:747) |
|||
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397) |
|||
at org.springframework.boot.SpringApplication.run(SpringApplication.java:315) |
|||
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1226) |
|||
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1215) |
|||
at org.nl.AppRun.main(AppRun.java:45) |
|||
Caused by: org.springframework.context.annotation.ConflictingBeanDefinitionException: Annotation-specified bean name 'SortingCNTTask' for bean class [org.nl.wms.sch.task_manage.task.tasks.sorting.SortingSMTTask] conflicts with existing, non-compatible bean definition of same name and class [org.nl.wms.sch.task_manage.task.tasks.sorting.SortingCNTTask] |
|||
at org.springframework.context.annotation.ClassPathBeanDefinitionScanner.checkCandidate(ClassPathBeanDefinitionScanner.java:349) |
|||
at org.springframework.context.annotation.ClassPathBeanDefinitionScanner.doScan(ClassPathBeanDefinitionScanner.java:287) |
|||
at org.springframework.context.annotation.ComponentScanAnnotationParser.parse(ComponentScanAnnotationParser.java:132) |
|||
at org.springframework.context.annotation.ConfigurationClassParser.doProcessConfigurationClass(ConfigurationClassParser.java:296) |
|||
at org.springframework.context.annotation.ConfigurationClassParser.processConfigurationClass(ConfigurationClassParser.java:250) |
|||
at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:207) |
|||
at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:175) |
|||
... 13 common frames omitted |
|||
2024-08-07 19:42:46.264 [main] ERROR org.springframework.boot.SpringApplication - Application run failed |
|||
org.springframework.beans.factory.BeanDefinitionStoreException: Failed to parse configuration class [org.nl.AppRun]; nested exception is org.springframework.context.annotation.ConflictingBeanDefinitionException: Annotation-specified bean name 'SortingCNTTask' for bean class [org.nl.wms.sch.task_manage.task.tasks.sorting.SortingSMTTask] conflicts with existing, non-compatible bean definition of same name and class [org.nl.wms.sch.task_manage.task.tasks.sorting.SortingCNTTask] |
|||
at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:189) |
|||
at org.springframework.context.annotation.ConfigurationClassPostProcessor.processConfigBeanDefinitions(ConfigurationClassPostProcessor.java:319) |
|||
at org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(ConfigurationClassPostProcessor.java:236) |
|||
at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors(PostProcessorRegistrationDelegate.java:280) |
|||
at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:96) |
|||
at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:707) |
|||
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:533) |
|||
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:141) |
|||
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:747) |
|||
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397) |
|||
at org.springframework.boot.SpringApplication.run(SpringApplication.java:315) |
|||
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1226) |
|||
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1215) |
|||
at org.nl.AppRun.main(AppRun.java:45) |
|||
Caused by: org.springframework.context.annotation.ConflictingBeanDefinitionException: Annotation-specified bean name 'SortingCNTTask' for bean class [org.nl.wms.sch.task_manage.task.tasks.sorting.SortingSMTTask] conflicts with existing, non-compatible bean definition of same name and class [org.nl.wms.sch.task_manage.task.tasks.sorting.SortingCNTTask] |
|||
at org.springframework.context.annotation.ClassPathBeanDefinitionScanner.checkCandidate(ClassPathBeanDefinitionScanner.java:349) |
|||
at org.springframework.context.annotation.ClassPathBeanDefinitionScanner.doScan(ClassPathBeanDefinitionScanner.java:287) |
|||
at org.springframework.context.annotation.ComponentScanAnnotationParser.parse(ComponentScanAnnotationParser.java:132) |
|||
at org.springframework.context.annotation.ConfigurationClassParser.doProcessConfigurationClass(ConfigurationClassParser.java:296) |
|||
at org.springframework.context.annotation.ConfigurationClassParser.processConfigurationClass(ConfigurationClassParser.java:250) |
|||
at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:207) |
|||
at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:175) |
|||
... 13 common frames omitted |
|||
2024-08-07 19:44:09.391 [main] ERROR org.springframework.boot.SpringApplication - Application run failed |
|||
org.springframework.beans.factory.BeanDefinitionStoreException: Failed to parse configuration class [org.nl.AppRun]; nested exception is org.springframework.context.annotation.ConflictingBeanDefinitionException: Annotation-specified bean name 'SortingCNTTask' for bean class [org.nl.wms.sch.task_manage.task.tasks.sorting.SortingSMTTask] conflicts with existing, non-compatible bean definition of same name and class [org.nl.wms.sch.task_manage.task.tasks.sorting.SortingCNTTask] |
|||
at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:189) |
|||
at org.springframework.context.annotation.ConfigurationClassPostProcessor.processConfigBeanDefinitions(ConfigurationClassPostProcessor.java:319) |
|||
at org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(ConfigurationClassPostProcessor.java:236) |
|||
at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors(PostProcessorRegistrationDelegate.java:280) |
|||
at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:96) |
|||
at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:707) |
|||
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:533) |
|||
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:141) |
|||
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:747) |
|||
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397) |
|||
at org.springframework.boot.SpringApplication.run(SpringApplication.java:315) |
|||
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1226) |
|||
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1215) |
|||
at org.nl.AppRun.main(AppRun.java:45) |
|||
Caused by: org.springframework.context.annotation.ConflictingBeanDefinitionException: Annotation-specified bean name 'SortingCNTTask' for bean class [org.nl.wms.sch.task_manage.task.tasks.sorting.SortingSMTTask] conflicts with existing, non-compatible bean definition of same name and class [org.nl.wms.sch.task_manage.task.tasks.sorting.SortingCNTTask] |
|||
at org.springframework.context.annotation.ClassPathBeanDefinitionScanner.checkCandidate(ClassPathBeanDefinitionScanner.java:349) |
|||
at org.springframework.context.annotation.ClassPathBeanDefinitionScanner.doScan(ClassPathBeanDefinitionScanner.java:287) |
|||
at org.springframework.context.annotation.ComponentScanAnnotationParser.parse(ComponentScanAnnotationParser.java:132) |
|||
at org.springframework.context.annotation.ConfigurationClassParser.doProcessConfigurationClass(ConfigurationClassParser.java:296) |
|||
at org.springframework.context.annotation.ConfigurationClassParser.processConfigurationClass(ConfigurationClassParser.java:250) |
|||
at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:207) |
|||
at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:175) |
|||
... 13 common frames omitted |
|||
2024-08-07 19:44:47.020 [main] ERROR org.springframework.boot.SpringApplication - Application run failed |
|||
org.springframework.beans.factory.BeanDefinitionStoreException: Failed to parse configuration class [org.nl.AppRun]; nested exception is org.springframework.context.annotation.ConflictingBeanDefinitionException: Annotation-specified bean name 'SortingCNTTask' for bean class [org.nl.wms.sch.task_manage.task.tasks.sorting.SortingSMTTask] conflicts with existing, non-compatible bean definition of same name and class [org.nl.wms.sch.task_manage.task.tasks.sorting.SortingCNTTask] |
|||
at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:189) |
|||
at org.springframework.context.annotation.ConfigurationClassPostProcessor.processConfigBeanDefinitions(ConfigurationClassPostProcessor.java:319) |
|||
at org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(ConfigurationClassPostProcessor.java:236) |
|||
at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors(PostProcessorRegistrationDelegate.java:280) |
|||
at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:96) |
|||
at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:707) |
|||
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:533) |
|||
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:141) |
|||
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:747) |
|||
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397) |
|||
at org.springframework.boot.SpringApplication.run(SpringApplication.java:315) |
|||
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1226) |
|||
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1215) |
|||
at org.nl.AppRun.main(AppRun.java:45) |
|||
Caused by: org.springframework.context.annotation.ConflictingBeanDefinitionException: Annotation-specified bean name 'SortingCNTTask' for bean class [org.nl.wms.sch.task_manage.task.tasks.sorting.SortingSMTTask] conflicts with existing, non-compatible bean definition of same name and class [org.nl.wms.sch.task_manage.task.tasks.sorting.SortingCNTTask] |
|||
at org.springframework.context.annotation.ClassPathBeanDefinitionScanner.checkCandidate(ClassPathBeanDefinitionScanner.java:349) |
|||
at org.springframework.context.annotation.ClassPathBeanDefinitionScanner.doScan(ClassPathBeanDefinitionScanner.java:287) |
|||
at org.springframework.context.annotation.ComponentScanAnnotationParser.parse(ComponentScanAnnotationParser.java:132) |
|||
at org.springframework.context.annotation.ConfigurationClassParser.doProcessConfigurationClass(ConfigurationClassParser.java:296) |
|||
at org.springframework.context.annotation.ConfigurationClassParser.processConfigurationClass(ConfigurationClassParser.java:250) |
|||
at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:207) |
|||
at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:175) |
|||
... 13 common frames omitted |
|||
2024-08-07 19:45:38.452 [main] ERROR org.springframework.boot.SpringApplication - Application run failed |
|||
org.springframework.beans.factory.BeanDefinitionStoreException: Failed to parse configuration class [org.nl.AppRun]; nested exception is org.springframework.context.annotation.ConflictingBeanDefinitionException: Annotation-specified bean name 'SortingCNTTask' for bean class [org.nl.wms.sch.task_manage.task.tasks.sorting.SortingSMTTask] conflicts with existing, non-compatible bean definition of same name and class [org.nl.wms.sch.task_manage.task.tasks.sorting.SortingCNTTask] |
|||
at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:189) |
|||
at org.springframework.context.annotation.ConfigurationClassPostProcessor.processConfigBeanDefinitions(ConfigurationClassPostProcessor.java:319) |
|||
at org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(ConfigurationClassPostProcessor.java:236) |
|||
at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors(PostProcessorRegistrationDelegate.java:280) |
|||
at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:96) |
|||
at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:707) |
|||
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:533) |
|||
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:141) |
|||
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:747) |
|||
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397) |
|||
at org.springframework.boot.SpringApplication.run(SpringApplication.java:315) |
|||
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1226) |
|||
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1215) |
|||
at org.nl.AppRun.main(AppRun.java:45) |
|||
Caused by: org.springframework.context.annotation.ConflictingBeanDefinitionException: Annotation-specified bean name 'SortingCNTTask' for bean class [org.nl.wms.sch.task_manage.task.tasks.sorting.SortingSMTTask] conflicts with existing, non-compatible bean definition of same name and class [org.nl.wms.sch.task_manage.task.tasks.sorting.SortingCNTTask] |
|||
at org.springframework.context.annotation.ClassPathBeanDefinitionScanner.checkCandidate(ClassPathBeanDefinitionScanner.java:349) |
|||
at org.springframework.context.annotation.ClassPathBeanDefinitionScanner.doScan(ClassPathBeanDefinitionScanner.java:287) |
|||
at org.springframework.context.annotation.ComponentScanAnnotationParser.parse(ComponentScanAnnotationParser.java:132) |
|||
at org.springframework.context.annotation.ConfigurationClassParser.doProcessConfigurationClass(ConfigurationClassParser.java:296) |
|||
at org.springframework.context.annotation.ConfigurationClassParser.processConfigurationClass(ConfigurationClassParser.java:250) |
|||
at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:207) |
|||
at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:175) |
|||
... 13 common frames omitted |
@ -0,0 +1,143 @@ |
|||
/* |
|||
* Copyright 2019-2020 Zheng Jie |
|||
* |
|||
* Licensed 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 org.nl.common.aspect; |
|||
|
|||
import cn.hutool.core.date.DateUtil; |
|||
import cn.hutool.core.util.StrUtil; |
|||
import com.alibaba.fastjson.JSON; |
|||
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.nl.common.utils.BaseCode; |
|||
import org.nl.common.utils.IPUtil; |
|||
import org.nl.common.utils.RequestHolder; |
|||
import org.nl.common.utils.SecurityUtils; |
|||
import org.nl.config.IdUtil; |
|||
import org.nl.config.lucene.LuceneAppender; |
|||
import org.slf4j.MDC; |
|||
import org.springframework.stereotype.Component; |
|||
import org.springframework.web.bind.annotation.RequestBody; |
|||
import org.springframework.web.bind.annotation.RequestParam; |
|||
|
|||
import javax.servlet.http.HttpServletRequest; |
|||
import java.lang.reflect.Method; |
|||
import java.lang.reflect.Parameter; |
|||
import java.util.ArrayList; |
|||
import java.util.HashMap; |
|||
import java.util.List; |
|||
import java.util.Map; |
|||
|
|||
/** |
|||
* @author Zheng Jie |
|||
* @date 2018-11-24 |
|||
*/ |
|||
@Component |
|||
@Aspect |
|||
@Slf4j |
|||
public class LogAspect { |
|||
|
|||
|
|||
|
|||
/** |
|||
* 配置环绕通知,使用在方法logPointcut()上注册的切入点 |
|||
* |
|||
* @param joinPoint join point for advice |
|||
*/ |
|||
@Around("@annotation(logInfo)") |
|||
public Object logAround(ProceedingJoinPoint joinPoint,org.nl.common.logging.annotation.Log logInfo) throws Throwable { |
|||
MethodSignature signature = (MethodSignature) joinPoint.getSignature(); |
|||
Method method = signature.getMethod(); |
|||
String params = getParameter(method, joinPoint.getArgs()); |
|||
HttpServletRequest request = RequestHolder.getHttpServletRequest(); |
|||
String url = request.getRequestURI(); |
|||
String requestIp = IPUtil.getIp(request); |
|||
MDC.put("requestMethod",url); |
|||
MDC.put("requestIp", requestIp); |
|||
MDC.put("requestTime", DateUtil.now()); |
|||
LuceneAppender.traceIdTL.set(BaseCode.intToChars(IdUtil.getLongId())); |
|||
Object result = null; |
|||
long comming = System.currentTimeMillis(); |
|||
try { |
|||
log.info("[--request--][请求接口:{}][请求参数:{}]",url,params); |
|||
result = joinPoint.proceed(); |
|||
// //是否把日志存到日志表
|
|||
// if (logInfo.isAddLogTable()) {
|
|||
// Log log = new Log("INFO", System.currentTimeMillis() - comming);
|
|||
// logService.save(getUsername(), StringUtils.getBrowser(request), requestIp, joinPoint, log);
|
|||
// }
|
|||
}catch (Exception ex){ |
|||
|
|||
StringBuffer errorStack = new StringBuffer(); |
|||
errorStack.append("<br/>【异常堆栈:"); |
|||
String errorMsg = ex.getMessage(); |
|||
int x = 0; |
|||
StackTraceElement[] stackTrace = ex.getStackTrace(); |
|||
if (stackTrace!=null && stackTrace.length>0){ |
|||
for (StackTraceElement stack : stackTrace) { |
|||
x++;errorStack.append(stack.toString().replaceAll("<",">")).append("<br/>"); |
|||
if (x>10){ break; } |
|||
} |
|||
} |
|||
log.error("[-requestError-][请求接口:{}]【异常信息:{}】[请求参数:{}] {}", url,errorMsg,params, errorStack.append("】").toString()); |
|||
throw ex; |
|||
}finally { |
|||
log.info("[--response--][请求接口:{} 执行结束][耗时:{}s]",url,(System.currentTimeMillis() - comming)/1000); |
|||
MDC.clear(); |
|||
LuceneAppender.traceIdTL.remove(); |
|||
} |
|||
return result; |
|||
} |
|||
|
|||
/** |
|||
* 根据方法和传入的参数获取请求参数 |
|||
*/ |
|||
private String getParameter(Method method, Object[] args) { |
|||
List<Object> argList = new ArrayList<>(); |
|||
Parameter[] parameters = method.getParameters(); |
|||
for (int i = 0; i < parameters.length; i++) { |
|||
//将RequestBody注解修饰的参数作为请求参数
|
|||
RequestBody requestBody = parameters[i].getAnnotation(RequestBody.class); |
|||
if (requestBody != null) { |
|||
argList.add(args[i]); |
|||
} |
|||
//将RequestParam注解修饰的参数作为请求参数
|
|||
RequestParam requestParam = parameters[i].getAnnotation(RequestParam.class); |
|||
if (requestParam != null) { |
|||
Map<String, Object> map = new HashMap<>(); |
|||
String key = parameters[i].getName(); |
|||
if (!StrUtil.isEmpty(requestParam.value())) { |
|||
key = requestParam.value(); |
|||
} |
|||
map.put(key, args[i]); |
|||
argList.add(map); |
|||
} |
|||
} |
|||
if (argList.size() == 0) { |
|||
return ""; |
|||
} |
|||
return JSON.toJSONString(argList); |
|||
} |
|||
|
|||
public String getUsername() { |
|||
try { |
|||
return SecurityUtils.getCurrentUsername(); |
|||
} catch (Exception e) { |
|||
return ""; |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,33 @@ |
|||
package org.nl.common.utils; |
|||
|
|||
/* |
|||
* @author ZZQ |
|||
* @Date 2023/2/9 2:54 下午 |
|||
*/ |
|||
public class BaseCode { |
|||
|
|||
static final char[] MySerials = new char[]{ |
|||
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', |
|||
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', |
|||
'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p','q','r','s','t','u','v','w','x','y','z', |
|||
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', |
|||
'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P','Q','R','S','T','U','V','W','X','Y','Z'}; |
|||
|
|||
|
|||
public static final String intToChars(long n){ |
|||
String s = ""; |
|||
if (n == 0) { |
|||
s = "0"; |
|||
} |
|||
while (n != 0) { |
|||
int i = (int) (n % MySerials.length); |
|||
char c = MySerials[i]; |
|||
s = c + s; |
|||
n = n / MySerials.length; |
|||
} |
|||
for (int x = s.length();x<5;x++){ |
|||
s="0"+s; |
|||
} |
|||
return s; |
|||
} |
|||
} |
@ -0,0 +1,97 @@ |
|||
/* |
|||
* Copyright 2019-2020 Zheng Jie |
|||
* |
|||
* Licensed 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 org.nl.common.utils; |
|||
|
|||
import lombok.extern.slf4j.Slf4j; |
|||
|
|||
import javax.servlet.http.HttpServletRequest; |
|||
import java.net.InetAddress; |
|||
import java.net.NetworkInterface; |
|||
import java.util.Enumeration; |
|||
|
|||
/** |
|||
* @author Zheng Jie |
|||
* 字符串工具类, 继承org.apache.commons.lang3.StringUtils类 |
|||
*/ |
|||
@Slf4j |
|||
public class IPUtil { |
|||
|
|||
public static String IP = null; |
|||
/** |
|||
* 获取当前机器的IP |
|||
* |
|||
* @return / |
|||
*/ |
|||
public static String getLocalIp() { |
|||
if (IP!=null){ |
|||
return IP; |
|||
} |
|||
try { |
|||
InetAddress candidateAddress = null; |
|||
// 遍历所有的网络接口
|
|||
for (Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces(); interfaces.hasMoreElements();) { |
|||
NetworkInterface anInterface = interfaces.nextElement(); |
|||
// 在所有的接口下再遍历IP
|
|||
for (Enumeration<InetAddress> inetAddresses = anInterface.getInetAddresses(); inetAddresses.hasMoreElements();) { |
|||
InetAddress inetAddr = inetAddresses.nextElement(); |
|||
// 排除loopback类型地址
|
|||
if (!inetAddr.isLoopbackAddress()) { |
|||
if (inetAddr.isSiteLocalAddress()) { |
|||
// 如果是site-local地址,就是它了
|
|||
return inetAddr.getHostAddress(); |
|||
} else if (candidateAddress == null) { |
|||
// site-local类型的地址未被发现,先记录候选地址
|
|||
candidateAddress = inetAddr; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
if (candidateAddress != null) { |
|||
return candidateAddress.getHostAddress(); |
|||
} |
|||
// 如果没有发现 non-loopback地址.只能用最次选的方案
|
|||
InetAddress jdkSuppliedAddress = InetAddress.getLocalHost(); |
|||
if (jdkSuppliedAddress == null) { |
|||
return ""; |
|||
} |
|||
IP = jdkSuppliedAddress.getHostAddress(); |
|||
return jdkSuppliedAddress.getHostAddress(); |
|||
} catch (Exception e) { |
|||
return ""; |
|||
} |
|||
} |
|||
public static String getIp(HttpServletRequest request) { |
|||
String ip = request.getHeader("X-Forwarded-For"); |
|||
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { |
|||
ip = request.getHeader("Proxy-Client-IP"); |
|||
} |
|||
|
|||
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { |
|||
ip = request.getHeader("WL-Proxy-Client-IP"); |
|||
} |
|||
|
|||
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { |
|||
ip = request.getRemoteAddr(); |
|||
} |
|||
|
|||
if (ip != null && ip.contains(",")) { |
|||
String[] ipArray = ip.split(","); |
|||
ip = ipArray[0]; |
|||
} |
|||
|
|||
return ip; |
|||
} |
|||
} |
@ -0,0 +1,91 @@ |
|||
package org.nl.config; |
|||
|
|||
import com.alibaba.druid.filter.FilterChain; |
|||
import com.alibaba.druid.filter.FilterEventAdapter; |
|||
import com.alibaba.druid.proxy.jdbc.JdbcParameter; |
|||
import com.alibaba.druid.proxy.jdbc.PreparedStatementProxy; |
|||
import com.alibaba.druid.proxy.jdbc.ResultSetProxy; |
|||
import com.alibaba.druid.proxy.jdbc.StatementProxy; |
|||
import com.alibaba.druid.sql.SQLUtils; |
|||
import com.alibaba.druid.util.JdbcUtils; |
|||
import com.mysql.cj.jdbc.result.ResultSetImpl; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
|
|||
import java.sql.SQLException; |
|||
import java.util.ArrayList; |
|||
import java.util.Collection; |
|||
import java.util.List; |
|||
|
|||
/* |
|||
* @author ZZQ |
|||
* @Date 2023/2/10 11:27 上午 |
|||
*/ |
|||
@Slf4j |
|||
public class DruidFilter extends FilterEventAdapter { |
|||
|
|||
@Override |
|||
public int preparedStatement_executeUpdate(FilterChain chain, PreparedStatementProxy statement) throws SQLException { |
|||
|
|||
return super.preparedStatement_executeUpdate(chain, statement); |
|||
} |
|||
|
|||
@Override |
|||
public int statement_executeUpdate(FilterChain chain, StatementProxy statement, String sql) throws SQLException { |
|||
|
|||
return super.statement_executeUpdate(chain, statement, sql); |
|||
} |
|||
|
|||
@Override |
|||
protected void statementExecuteAfter(StatementProxy statement, String sql, boolean result) { |
|||
int size = statement.getParametersSize(); |
|||
String executeSql = sql; |
|||
int count = 0; |
|||
try { |
|||
count=statement.getUpdateCount(); |
|||
}catch (Exception ex){ } |
|||
if (count>0) { |
|||
if (size > 0) { |
|||
Collection<JdbcParameter> values = statement.getParameters().values(); |
|||
List<Object> params = new ArrayList<>(); |
|||
for (JdbcParameter value : values) { |
|||
params.add(value.getValue()); |
|||
} |
|||
executeSql = SQLUtils.format(executeSql, JdbcUtils.MYSQL, params); |
|||
} |
|||
log.info("[----SQL----][update][ SQL: {} ]", executeSql); |
|||
} |
|||
super.statementExecuteAfter(statement, sql, result); |
|||
} |
|||
@Override |
|||
public ResultSetProxy statement_getResultSet(FilterChain chain, StatementProxy statement) throws SQLException { |
|||
ResultSetProxy rs = super.statement_getResultSet(chain, statement); |
|||
String executeSql = statement.getLastExecuteSql(); |
|||
if (true){ |
|||
int result = 0; |
|||
if (rs != null) { |
|||
ResultSetImpl rss = rs.getResultSetRaw().unwrap(ResultSetImpl.class); |
|||
result = rss.getRows().size(); |
|||
} |
|||
try { |
|||
int size = statement.getParametersSize(); |
|||
if (size>0){ |
|||
Collection<JdbcParameter> values = statement.getParameters().values(); |
|||
List<Object> params = new ArrayList<>(); |
|||
for (JdbcParameter value : values) { |
|||
params.add(value.getValue()); |
|||
} |
|||
executeSql = SQLUtils.format(executeSql, JdbcUtils.MYSQL, params); |
|||
} |
|||
}catch (Exception ex){ |
|||
log.warn("[-SQL解析异常-][{}]",ex.getMessage()); |
|||
} |
|||
log.info("[----SQL----][select][执行结果:{}][ SQL: {} ]",result, executeSql); |
|||
} |
|||
return rs; |
|||
} |
|||
|
|||
|
|||
|
|||
|
|||
|
|||
} |
@ -0,0 +1,34 @@ |
|||
package org.nl.config.lucene; |
|||
/** |
|||
* @author ldjun |
|||
* @version 1.0 |
|||
* @date 2023年08月24日 13:00 |
|||
* @desc desc |
|||
*/ |
|||
|
|||
import ch.qos.logback.classic.spi.ILoggingEvent; |
|||
import com.yomahub.tlog.core.enhance.logback.async.AspectLogbackAsyncAppender; |
|||
import org.apache.commons.lang3.StringUtils; |
|||
import org.slf4j.MDC; |
|||
|
|||
import java.util.Map; |
|||
|
|||
public class AsyncLuceneAppender extends AspectLogbackAsyncAppender { |
|||
|
|||
@Override |
|||
protected void append(ILoggingEvent event) { |
|||
String traceId = LuceneAppender.traceIdTL.get(); |
|||
if (StringUtils.isNotEmpty(traceId)){ |
|||
MDC.put("traceId",traceId); |
|||
Map<String, String> mdcPropertyMap = event.getMDCPropertyMap(); |
|||
if (mdcPropertyMap.getClass().getName().contains("SynchronizedMap")){ |
|||
mdcPropertyMap.put("traceId",traceId); |
|||
} |
|||
MDC.clear(); |
|||
} |
|||
} |
|||
public void appendSync(ILoggingEvent event){ |
|||
super.append(event); |
|||
} |
|||
|
|||
} |
@ -1,49 +0,0 @@ |
|||
package org.nl.config.lucene; |
|||
|
|||
import ch.qos.logback.classic.LoggerContext; |
|||
import ch.qos.logback.classic.encoder.PatternLayoutEncoder; |
|||
import ch.qos.logback.core.rolling.RollingFileAppender; |
|||
import ch.qos.logback.core.rolling.TimeBasedRollingPolicy; |
|||
import cn.hutool.core.date.DateTime; |
|||
import cn.hutool.core.date.DateUtil; |
|||
import org.slf4j.LoggerFactory; |
|||
|
|||
import java.io.File; |
|||
import java.nio.charset.Charset; |
|||
|
|||
public class DynamicLogAppender { |
|||
/** |
|||
* 通过传入的动态名字,动态设置appender |
|||
* @param dynamicName |
|||
* @return |
|||
*/ |
|||
public RollingFileAppender getAppender(String oldLogPath,String dynamicName) { |
|||
LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory(); |
|||
RollingFileAppender appender = new RollingFileAppender(); |
|||
//appender的name属性
|
|||
appender.setName(dynamicName); |
|||
appender.setContext(context); |
|||
|
|||
//设置文件名
|
|||
appender.setFile(new File(oldLogPath, dynamicName + "\\" + DateUtil.format(new DateTime(),"yyyy-MM-dd")+".log").getAbsolutePath()); |
|||
//设置日志文件输出格式
|
|||
PatternLayoutEncoder encoder = new PatternLayoutEncoder(); |
|||
encoder.setContext(context); |
|||
encoder.setPattern("%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n"); |
|||
encoder.setCharset(Charset.forName("UTF-8")); |
|||
encoder.start(); |
|||
|
|||
//设置日志记录器的滚动策略
|
|||
TimeBasedRollingPolicy policy = new TimeBasedRollingPolicy(); |
|||
policy.setFileNamePattern(oldLogPath+dynamicName+".%d{yyyy-MM-dd}.log"); |
|||
policy.setParent(appender); //设置父节点是appender
|
|||
policy.setContext(context); |
|||
policy.start(); |
|||
|
|||
//加入下面两个节点
|
|||
appender.setRollingPolicy(policy); |
|||
appender.setEncoder(encoder); |
|||
appender.start(); |
|||
return appender; |
|||
} |
|||
} |
@ -1,35 +0,0 @@ |
|||
package org.nl.config.lucene; |
|||
|
|||
import ch.qos.logback.classic.Logger; |
|||
import ch.qos.logback.classic.LoggerContext; |
|||
import ch.qos.logback.core.rolling.RollingFileAppender; |
|||
import org.slf4j.LoggerFactory; |
|||
|
|||
import java.util.HashMap; |
|||
import java.util.Map; |
|||
|
|||
public class DynamicLogger { |
|||
String logPath;//日志存储路径
|
|||
public DynamicLogger(String logPath) { |
|||
this.logPath = logPath; |
|||
} |
|||
//对外暴露日志对象:每次拿的对象从内存里拿,没有再构建
|
|||
private static Map<String,Logger> container = new HashMap<>(); |
|||
public Logger getLogger(String dynamicName) { |
|||
Logger logger = container.get(dynamicName); |
|||
if(logger != null) { |
|||
return logger; |
|||
} |
|||
logger = build(dynamicName); |
|||
container.put(dynamicName,logger); |
|||
return logger; |
|||
} |
|||
//构建Logger对象,给Logger指定appender
|
|||
private Logger build(String dynamicName) { |
|||
RollingFileAppender runTaskAppender =new DynamicLogAppender().getAppender(this.logPath,dynamicName); |
|||
LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory(); |
|||
Logger logger = context.getLogger(dynamicName); |
|||
logger.addAppender(runTaskAppender); |
|||
return logger; |
|||
} |
|||
} |
@ -1,184 +0,0 @@ |
|||
package org.nl.config.lucene; |
|||
|
|||
import com.alibaba.fastjson.JSONObject; |
|||
import org.apache.commons.io.FileUtils; |
|||
import org.apache.lucene.analysis.Analyzer; |
|||
import org.apache.lucene.document.Document; |
|||
import org.apache.lucene.document.Field; |
|||
import org.apache.lucene.document.TextField; |
|||
import org.apache.lucene.index.IndexWriter; |
|||
import org.apache.lucene.index.IndexWriterConfig; |
|||
import org.apache.lucene.store.Directory; |
|||
import org.apache.lucene.store.FSDirectory; |
|||
import org.springframework.beans.factory.annotation.Value; |
|||
import org.wltea.analyzer.lucene.IKAnalyzer; |
|||
|
|||
import java.io.BufferedReader; |
|||
import java.io.File; |
|||
import java.io.FileReader; |
|||
import java.io.IOException; |
|||
import java.nio.file.Paths; |
|||
import java.util.Set; |
|||
|
|||
/** |
|||
* lucene索引器 |
|||
*/ |
|||
public class Indexer { |
|||
/** |
|||
* 写索引实例 |
|||
*/ |
|||
private IndexWriter writer; |
|||
|
|||
public IndexWriter getWriter() { |
|||
return writer; |
|||
} |
|||
|
|||
/** |
|||
* 构造方法,实例化IndexWriter |
|||
* |
|||
* @param indexDir |
|||
* @throws Exception |
|||
*/ |
|||
public Indexer(String indexDir) throws Exception { |
|||
Directory dir = FSDirectory.open(Paths.get(indexDir)); |
|||
//标准分词器,会自动去掉空格啊,is a the等单词
|
|||
// Analyzer analyzer = new StandardAnalyzer();
|
|||
Analyzer analyzer = new IKAnalyzer(); |
|||
//将标准分词器配到写索引的配置中
|
|||
IndexWriterConfig config = new IndexWriterConfig(analyzer); |
|||
//实例化写索引对象
|
|||
writer = new IndexWriter(dir, config); |
|||
} |
|||
|
|||
/** |
|||
* 索引指定目录下的所有文件 |
|||
* |
|||
* @param dataDir |
|||
* @return |
|||
* @throws Exception |
|||
*/ |
|||
public int indexAll(String dataDir) throws Exception { |
|||
// 获取该路径下的所有文件
|
|||
File[] files = new File(dataDir).listFiles(); |
|||
if (null != files) { |
|||
for (File file : files) { |
|||
//调用下面的indexFile方法,对每个文件进行索引
|
|||
indexFile(file); |
|||
} |
|||
} |
|||
//返回索引的文件数
|
|||
// return writer.numDocs();
|
|||
return writer.numRamDocs(); |
|||
} |
|||
|
|||
/** |
|||
* 索引指定的文件 |
|||
* |
|||
* @param file |
|||
* @throws Exception |
|||
*/ |
|||
private void indexFile(File file) throws Exception { |
|||
System.out.println("索引文件的路径:" + file.getCanonicalPath()); |
|||
//调用下面的getDocument方法,获取该文件的document
|
|||
Document doc = getDocument(file); |
|||
//添加索引文档
|
|||
//Document doc = json2Doc(jsonDoc);
|
|||
// Document doc = new Document();
|
|||
// doc.add(new TextField("content", jsonDoc, Field.Store.YES));
|
|||
Field fieldContent = new TextField("fieldContent", FileUtils.readFileToString(null, "UTF-8"), Field.Store.YES); |
|||
|
|||
//将doc添加到索引中
|
|||
writer.addDocument(doc); |
|||
} |
|||
|
|||
/** |
|||
* 获取文档,文档里再设置每个字段,就类似于数据库中的一行记录 |
|||
* |
|||
* @param file |
|||
* @return |
|||
* @throws Exception |
|||
*/ |
|||
private Document getDocument(File file) throws Exception { |
|||
Document doc = new Document(); |
|||
//开始添加字段
|
|||
//添加内容
|
|||
doc.add(new TextField("contents", new FileReader(file))); |
|||
//添加文件名,并把这个字段存到索引文件里
|
|||
doc.add(new TextField("fileName", file.getName(), Field.Store.YES)); |
|||
//添加文件路径
|
|||
doc.add(new TextField("fullPath", file.getCanonicalPath(), Field.Store.YES)); |
|||
return doc; |
|||
} |
|||
|
|||
public Document json2Doc(String strDoc) { |
|||
Document doc = new Document(); |
|||
JSONObject jsonDoc = JSONObject.parseObject(strDoc); |
|||
Set<String> keys = jsonDoc.keySet(); |
|||
for (String key : keys) { |
|||
doc.add(new TextField(key, jsonDoc.getString(key), Field.Store.YES)); |
|||
} |
|||
return doc; |
|||
} |
|||
|
|||
public void addLogIndex(String msg) throws IOException { |
|||
//步骤一:创建Directory对象,用于指定索引库的位置 RAMDirectory内存
|
|||
Directory directory = FSDirectory.open(new File("D:\\lucene\\index").toPath()); |
|||
//步骤二:创建一个IndexWriter对象,用于写索引
|
|||
// Analyzer analyzer = new StandardAnalyzer();
|
|||
IndexWriter indexWriter = new IndexWriter(directory, new IndexWriterConfig(new IKAnalyzer(false))); |
|||
// indexWriter.deleteAll();//清理所有索引库
|
|||
// IndexWriter indexWriter=new IndexWriter(directory,new IndexWriterConfig(new StandardAnalyzer()));
|
|||
//记录索引开始时间
|
|||
long startTime = System.currentTimeMillis(); |
|||
//步骤三:读取磁盘中文件,对应每一个文件创建一个文档对象
|
|||
Document document = new Document(); |
|||
// document.add(new TextField("fieldContent", device_id, Field.Store.YES));
|
|||
document.add(new TextField("fieldContent", msg, Field.Store.YES)); |
|||
indexWriter.addDocument(document); |
|||
//记录索引结束时间
|
|||
long endTime = System.currentTimeMillis(); |
|||
System.out.println("建立索引" + "共耗时" + (endTime - startTime) + "毫秒"); |
|||
indexWriter.commit(); |
|||
//步骤八:关闭资源
|
|||
indexWriter.close(); |
|||
System.out.println("建立索引成功-----关闭资源"); |
|||
} |
|||
|
|||
//系统的日志文件路径
|
|||
@Value("${logging.file.path}") |
|||
private String logUrl; |
|||
|
|||
public static void main(String[] args) throws IOException { |
|||
//步骤一:创建Directory对象,用于指定索引库的位置 RAMDirectory内存
|
|||
Directory directory = FSDirectory.open(new File("D:\\lucene\\index").toPath()); |
|||
//步骤二:创建一个IndexWriter对象,用于写索引
|
|||
// Analyzer analyzer = new StandardAnalyzer();
|
|||
IndexWriter indexWriter = new IndexWriter(directory, new IndexWriterConfig(new IKAnalyzer(false))); |
|||
|
|||
indexWriter.deleteAll();//清理所有索引库
|
|||
// indexWriter=new IndexWriter(directory,new IndexWriterConfig(new StandardAnalyzer()));
|
|||
//记录索引开始时间
|
|||
long startTime = System.currentTimeMillis(); |
|||
//步骤三:读取磁盘中文件,对应每一个文件创建一个文档对象
|
|||
File file = new File("D:\\testlog"); |
|||
//步骤四:获取文件列表
|
|||
File[] files = file.listFiles(); |
|||
for (File item : files) { |
|||
BufferedReader bufferedReader = new BufferedReader(new FileReader(item)); |
|||
String strLine = null; |
|||
while (null != (strLine = bufferedReader.readLine())) { |
|||
Document document = new Document(); |
|||
// document.add(new Field());
|
|||
document.add(new TextField("fieldContent", strLine, Field.Store.YES)); |
|||
indexWriter.addDocument(document); |
|||
} |
|||
} |
|||
//记录索引结束时间
|
|||
long endTime = System.currentTimeMillis(); |
|||
System.out.println("建立索引" + "共耗时" + (endTime - startTime) + "毫秒"); |
|||
indexWriter.commit(); |
|||
//步骤八:关闭资源
|
|||
indexWriter.close(); |
|||
System.out.println("建立索引成功-----关闭资源"); |
|||
} |
|||
} |
@ -0,0 +1,46 @@ |
|||
package org.nl.config.lucene; |
|||
|
|||
/** |
|||
* @Author: lyd |
|||
* @Description: 定义lucene相关常量 |
|||
* @Date: 2023/8/25 |
|||
*/ |
|||
public class LogMessageConstant { |
|||
/** */ |
|||
public final static String SORT_NAME = "time"; |
|||
/** 级别 */ |
|||
public final static String FIELD_LEVEL = "level"; |
|||
/** 时间 */ |
|||
public final static String FIELD_TIMESTAMP = "timestamp"; |
|||
/** 类的限定名 */ |
|||
public final static String FIELD_CLASS_NAME = "logger"; |
|||
/** 线程名 */ |
|||
public final static String FIELD_THREAD = "thread"; |
|||
/** 日志内容 */ |
|||
public final static String FIELD_MESSAGE = "message"; |
|||
public final static String FIELD_TRACEID = "tlogTraceId"; |
|||
// 定义颜色值
|
|||
/** 文本颜色:黑色 */ |
|||
public final static String COLOR_BLACK = "\u001B[30m"; |
|||
/** 文本颜色:红色 */ |
|||
public final static String COLOR_RED = "\u001B[31m"; |
|||
/** 文本颜色:绿色 */ |
|||
public final static String COLOR_GREEN = "\u001B[32m"; |
|||
/** 文本颜色:黄色 */ |
|||
public final static String COLOR_YELLOW = "\u001B[33m"; |
|||
/** 文本颜色:蓝色 */ |
|||
public final static String COLOR_BLUE = "\u001B[34m"; |
|||
/** 文本颜色:品红色 */ |
|||
public final static String COLOR_MAGENTA = "\u001B[35m"; |
|||
/** 文本颜色:青色 */ |
|||
public final static String COLOR_CYAN = "\u001B[36m"; |
|||
/** 文本颜色:白色 */ |
|||
public final static String COLOR_WHITE = "\u001B[37m"; |
|||
/** 文本颜色重置 */ |
|||
public final static String COLOR_RESET = "\u001B[0m"; |
|||
/** 背景颜色:黄色 */ |
|||
public final static String BACKGROUND_YELLOW = "\u001B[43m"; |
|||
/** 索引路径 */ |
|||
public final static String INDEX_DIR = "E:\\lucene\\index"; |
|||
|
|||
} |
@ -0,0 +1,99 @@ |
|||
package org.nl.config.lucene; |
|||
/** |
|||
* @author ldjun |
|||
* @version 1.0 |
|||
* @date 2023年08月24日 13:00 |
|||
* @desc desc |
|||
*/ |
|||
|
|||
import ch.qos.logback.classic.spi.ILoggingEvent; |
|||
import ch.qos.logback.core.AppenderBase; |
|||
import com.alibaba.ttl.TransmittableThreadLocal; |
|||
import org.apache.commons.lang3.StringUtils; |
|||
import org.apache.lucene.analysis.Analyzer; |
|||
import org.apache.lucene.document.*; |
|||
import org.apache.lucene.index.IndexWriter; |
|||
import org.apache.lucene.index.IndexWriterConfig; |
|||
import org.apache.lucene.store.Directory; |
|||
import org.apache.lucene.store.FSDirectory; |
|||
import org.nl.config.IdUtil; |
|||
import org.wltea.analyzer.lucene.IKAnalyzer; |
|||
|
|||
import java.io.IOException; |
|||
import java.nio.file.Paths; |
|||
import java.util.List; |
|||
import java.util.Map; |
|||
import java.util.Properties; |
|||
|
|||
public class LuceneAppender extends AppenderBase<ILoggingEvent> { |
|||
|
|||
public static final TransmittableThreadLocal<String> traceIdTL = new TransmittableThreadLocal(); |
|||
public LuceneProperties properties; |
|||
public static Directory index; |
|||
private List<LucenePropertyAndEncoder> encoders; |
|||
public static IndexWriter indexWriter; |
|||
|
|||
|
|||
|
|||
@Override |
|||
public void start() { |
|||
super.start(); |
|||
try { |
|||
// 读取配置文件
|
|||
Properties properties = YmlConfigFileUtil.readConfig("config/application.yml"); |
|||
|
|||
// 获取配置值
|
|||
String luceneDir = properties.getProperty("lucene.index.path"); |
|||
System.out.println("---index地址----"+luceneDir); |
|||
index = FSDirectory.open(Paths.get(luceneDir)); |
|||
// 初始化 Lucene 索引
|
|||
Analyzer analyzer = new IKAnalyzer(); |
|||
IndexWriterConfig config = new IndexWriterConfig(analyzer); |
|||
indexWriter = new IndexWriter(index, config); |
|||
} catch (Exception e) { |
|||
e.printStackTrace(); |
|||
} |
|||
} |
|||
|
|||
|
|||
@Override |
|||
protected void append(ILoggingEvent event) { |
|||
Document doc = new Document(); |
|||
for (Property property : this.properties.getProperties()) { |
|||
LucenePropertyAndEncoder encoder = new LucenePropertyAndEncoder(property, this.context); |
|||
String encode = encoder.encode(event); |
|||
doc.add(new StringField(property.getName(), encode, Field.Store.YES)); |
|||
} |
|||
Map<String, String> map = event.getMDCPropertyMap(); |
|||
if (!map.isEmpty() && StringUtils.isNotEmpty(map.get("traceId"))){ |
|||
doc.add(new StringField("traceId",map.get("traceId"), Field.Store.YES)); |
|||
}else { |
|||
doc.add(new StringField("traceId", IdUtil.getStringId(), Field.Store.YES)); |
|||
} |
|||
|
|||
doc.add(new TextField(LogMessageConstant.FIELD_MESSAGE, event.getFormattedMessage(), Field.Store.YES)); |
|||
doc.add(new StringField(LogMessageConstant.FIELD_TIMESTAMP, String.valueOf(event.getTimeStamp()),Field.Store.YES)); |
|||
doc.add(new NumericDocValuesField(LogMessageConstant.SORT_NAME, event.getTimeStamp())); |
|||
try { |
|||
indexWriter.addDocument(doc); |
|||
indexWriter.commit(); |
|||
} catch (Exception e) { |
|||
e.printStackTrace(); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public void stop() { |
|||
super.stop(); |
|||
try { |
|||
indexWriter.close(); |
|||
} catch (IOException e) { |
|||
e.printStackTrace(); |
|||
} |
|||
} |
|||
|
|||
public void setProperties(LuceneProperties properties) { |
|||
this.properties = properties; |
|||
|
|||
} |
|||
} |
@ -1,60 +0,0 @@ |
|||
package org.nl.config.lucene; |
|||
|
|||
import cn.hutool.core.date.DateUtil; |
|||
import org.apache.lucene.index.CorruptIndexException; |
|||
import org.apache.lucene.index.IndexWriter; |
|||
import org.apache.lucene.index.IndexWriterConfig; |
|||
import org.apache.lucene.store.Directory; |
|||
import org.apache.lucene.store.FSDirectory; |
|||
import org.wltea.analyzer.lucene.IKAnalyzer; |
|||
|
|||
import java.io.File; |
|||
import java.io.IOException; |
|||
import java.text.ParseException; |
|||
import java.text.SimpleDateFormat; |
|||
import java.util.Date; |
|||
|
|||
public class LuceneIndexWriter { |
|||
private static IndexWriter indexWriter; |
|||
|
|||
static { |
|||
try { |
|||
Directory directory = FSDirectory.open(new File(UrlConfig.luceneUrl).toPath()); |
|||
IndexWriterConfig config = new IndexWriterConfig(new IKAnalyzer()); |
|||
indexWriter = new IndexWriter(directory, config); |
|||
} catch (Exception e) { |
|||
e.printStackTrace(); |
|||
} |
|||
/**当当前线程结束时,自动关闭IndexWriter,使用Runtime对象*/ |
|||
Runtime.getRuntime().addShutdownHook(new Thread(() -> { |
|||
try { |
|||
closeIndexWriter(); |
|||
} catch (Exception e) { |
|||
e.printStackTrace(); |
|||
} |
|||
})); |
|||
} |
|||
/**在线程结束时,自动关闭IndexWriter*/ |
|||
public static IndexWriter getIndexWriter() { |
|||
return indexWriter; |
|||
} |
|||
/**关闭IndexWriter |
|||
* @throws IOException |
|||
* @throws CorruptIndexException */ |
|||
public static void closeIndexWriter() throws Exception { |
|||
if(indexWriter != null) { |
|||
indexWriter.close(); |
|||
} |
|||
} |
|||
|
|||
public static void main(String[] args) throws IOException { |
|||
indexWriter.deleteAll(); |
|||
} |
|||
|
|||
public static String getDate(String timeString) throws ParseException { |
|||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSX");//时间格式
|
|||
Date date = sdf.parse(timeString); |
|||
timeString = DateUtil.format(date, "yyyy-MM-dd HH:mm:ss.SSS");//格式化后的时间
|
|||
return timeString; |
|||
} |
|||
} |
@ -0,0 +1,23 @@ |
|||
package org.nl.config.lucene; |
|||
|
|||
|
|||
import java.util.ArrayList; |
|||
import java.util.List; |
|||
|
|||
public class LuceneProperties { |
|||
|
|||
private List<Property> properties; |
|||
|
|||
public LuceneProperties() { |
|||
this.properties = new ArrayList<Property>(); |
|||
} |
|||
|
|||
public List<Property> getProperties() { |
|||
return properties; |
|||
} |
|||
|
|||
public void addProperty(Property property) { |
|||
properties.add(property); |
|||
} |
|||
|
|||
} |
@ -0,0 +1,38 @@ |
|||
package org.nl.config.lucene; |
|||
|
|||
import ch.qos.logback.classic.PatternLayout; |
|||
import ch.qos.logback.classic.spi.ILoggingEvent; |
|||
import ch.qos.logback.core.Context; |
|||
import ch.qos.logback.core.pattern.PatternLayoutBase; |
|||
|
|||
/* |
|||
* @author ZZQ |
|||
* @Date 2023/12/22 18:11 |
|||
*/ |
|||
public class LucenePropertyAndEncoder { |
|||
|
|||
private Property property; |
|||
|
|||
private PatternLayoutBase layout = new PatternLayout(); |
|||
|
|||
public LucenePropertyAndEncoder(Property property, Context context) { |
|||
this.property = property; |
|||
this.layout.setContext(context); |
|||
this.layout.setPattern(String.valueOf(property.getValue())); |
|||
this.layout.setPostCompileProcessor(null); |
|||
this.layout.start(); |
|||
} |
|||
|
|||
public String encode(ILoggingEvent event) { |
|||
return layout.doLayout(event); |
|||
} |
|||
|
|||
public String getName() { |
|||
return property.getName(); |
|||
} |
|||
|
|||
public boolean allowEmpty() { |
|||
return property.isAllowEmpty(); |
|||
} |
|||
} |
|||
|
@ -0,0 +1,44 @@ |
|||
package org.nl.config.lucene; |
|||
|
|||
/* |
|||
* @author ZZQ |
|||
* @Date 2023/12/26 15:30 |
|||
*/ |
|||
public class Property { |
|||
private String name; |
|||
private String value; |
|||
private boolean allowEmpty; |
|||
|
|||
public Property() { |
|||
} |
|||
|
|||
public Property(String name, String value, boolean allowEmpty) { |
|||
this.name = name; |
|||
this.value = value; |
|||
this.allowEmpty = allowEmpty; |
|||
} |
|||
|
|||
public String getName() { |
|||
return name; |
|||
} |
|||
|
|||
public void setName(String name) { |
|||
this.name = name; |
|||
} |
|||
|
|||
public String getValue() { |
|||
return value; |
|||
} |
|||
|
|||
public void setValue(String value) { |
|||
this.value = value; |
|||
} |
|||
|
|||
public boolean isAllowEmpty() { |
|||
return allowEmpty; |
|||
} |
|||
|
|||
public void setAllowEmpty(boolean allowEmpty) { |
|||
this.allowEmpty = allowEmpty; |
|||
} |
|||
} |
@ -1,140 +0,0 @@ |
|||
package org.nl.config.lucene; |
|||
|
|||
import cn.hutool.core.date.DateTime; |
|||
import cn.hutool.core.date.DateUtil; |
|||
import com.alibaba.fastjson.JSONArray; |
|||
import com.alibaba.fastjson.JSONObject; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.apache.lucene.document.Document; |
|||
import org.apache.lucene.index.DirectoryReader; |
|||
import org.apache.lucene.index.IndexReader; |
|||
import org.apache.lucene.index.Term; |
|||
import org.apache.lucene.search.*; |
|||
import org.apache.lucene.store.Directory; |
|||
import org.apache.lucene.store.FSDirectory; |
|||
import org.apache.lucene.util.BytesRef; |
|||
|
|||
import java.nio.file.Paths; |
|||
import java.util.ArrayList; |
|||
import java.util.Calendar; |
|||
import java.util.List; |
|||
import java.util.Map; |
|||
|
|||
/** |
|||
* lucene查询器 |
|||
*/ |
|||
@Slf4j |
|||
public class Searcher { |
|||
|
|||
public static Map<String, Object> search(String indexDir, String ext,Map whereJson) throws Exception { |
|||
//获取要查询的路径,也就是索引所在的位置
|
|||
Directory dir = FSDirectory.open(Paths.get(indexDir)); |
|||
IndexReader reader = DirectoryReader.open(dir); |
|||
//构建IndexSearcher
|
|||
IndexSearcher searcher = new IndexSearcher(reader); |
|||
//标准分词器,会自动去掉空格啊,is a the等单词
|
|||
// Analyzer analyzer = new StandardAnalyzer();
|
|||
// Analyzer analyzer = new IKAnalyzer(false);
|
|||
//查询解析器
|
|||
// QueryParser queryParser = new QueryParser("fieldContent", analyzer);
|
|||
|
|||
//记录索引开始时间
|
|||
long startTime = System.currentTimeMillis(); |
|||
// 实际上Lucene本身不支持分页。因此我们需要自己进行逻辑分页。我们要准备分页参数:
|
|||
int pageSize = Integer.parseInt(whereJson.get("size").toString());// 每页条数
|
|||
int pageNum = Integer.parseInt(whereJson.get("page").toString());// 当前页码
|
|||
int start = pageNum * pageSize;// 当前页的起始条数
|
|||
int end = start + pageSize;// 当前页的结束条数(不能包含)
|
|||
// 创建排序对象,需要排序字段SortField,参数:字段的名称、字段的类型、是否反转如果是false,升序。true降序
|
|||
Sort sort = new Sort(new SortField("logTime", SortField.Type.DOC,true)); |
|||
|
|||
TopDocs docs = null; |
|||
BooleanQuery.Builder booleanQueryBuilder = new BooleanQuery.Builder(); |
|||
//时间范围查询
|
|||
String startDate = (String) whereJson.get("begin_time"); |
|||
String endDate = (String) whereJson.get("end_time"); |
|||
Calendar calendar=Calendar.getInstance(); |
|||
calendar.set(1970, 0, 1); |
|||
if (startDate == null){ |
|||
startDate = DateUtil.format(calendar.getTime(),"yyyy-MM-dd HH:mm:ss.SSS"); |
|||
}else{ |
|||
startDate = LuceneIndexWriter.getDate(startDate); |
|||
} |
|||
if (endDate == null){ |
|||
endDate = DateUtil.format(new DateTime(),"yyyy-MM-dd HH:mm:ss.SSS"); |
|||
} else { |
|||
endDate = LuceneIndexWriter.getDate(endDate); |
|||
} |
|||
TermRangeQuery termRangeQuery = new TermRangeQuery("logTime", new BytesRef(startDate), new BytesRef(endDate), true, true); |
|||
booleanQueryBuilder.add(termRangeQuery,BooleanClause.Occur.MUST); |
|||
if (whereJson.get("device_code") != null){ |
|||
Query termQuery = new TermQuery(new Term("device_code", (String) whereJson.get("device_code"))); |
|||
booleanQueryBuilder.add(termQuery,BooleanClause.Occur.MUST); |
|||
} |
|||
if (whereJson.get("method") != null){ |
|||
Query termQuery = new TermQuery(new Term("method", (String) whereJson.get("method"))); |
|||
booleanQueryBuilder.add(termQuery,BooleanClause.Occur.MUST); |
|||
} |
|||
if (whereJson.get("status_code") != null){ |
|||
Query termQuery = new TermQuery(new Term("status_code", (String) whereJson.get("status_code"))); |
|||
booleanQueryBuilder.add(termQuery,BooleanClause.Occur.MUST); |
|||
} |
|||
if (whereJson.get("requestparam") != null){ |
|||
WildcardQuery query = new WildcardQuery(new Term("requestparam", "*"+(String) whereJson.get("requestparam")+"*")); |
|||
booleanQueryBuilder.add(query,BooleanClause.Occur.MUST); |
|||
} |
|||
if (whereJson.get("responseparam") != null){ |
|||
WildcardQuery query = new WildcardQuery(new Term("responseparam", "*"+(String) whereJson.get("responseparam")+"*")); |
|||
booleanQueryBuilder.add(query,BooleanClause.Occur.MUST); |
|||
} |
|||
if (whereJson.get("blurry") != null) { |
|||
WildcardQuery query = new WildcardQuery(new Term("fieldContent", "*"+(String) whereJson.get("blurry")+"*")); |
|||
booleanQueryBuilder.add(query, BooleanClause.Occur.MUST); |
|||
} |
|||
docs = searcher.search(booleanQueryBuilder.build(), end,sort); |
|||
//记录索引时间
|
|||
long endTime = System.currentTimeMillis(); |
|||
log.info("匹配{}共耗时{}毫秒",booleanQueryBuilder.build(),(endTime-startTime)); |
|||
log.info("查询到{}条日志文件", docs.totalHits.value); |
|||
List<String> list = new ArrayList<>(); |
|||
ScoreDoc[] scoreDocs = docs.scoreDocs; |
|||
if (end > docs.totalHits.value) end = (int) docs.totalHits.value; |
|||
JSONArray array = new JSONArray(); |
|||
|
|||
for (int i = start; i < end; i++) { |
|||
ScoreDoc scoreDoc = scoreDocs[i]; |
|||
Document doc = reader.document(scoreDoc.doc); |
|||
JSONObject object = new JSONObject(); |
|||
object.put("content",doc.get("fieldContent")); |
|||
object.put("device_code",doc.get("device_code")); |
|||
object.put("logTime",doc.get("logTime")); |
|||
object.put("method",doc.get("method")); |
|||
object.put("status_code",doc.get("status_code")); |
|||
object.put("requestparam",doc.get("requestparam")); |
|||
object.put("responseparam",doc.get("responseparam")); |
|||
if(doc.get("fieldContent") != null) { |
|||
array.add(object); |
|||
} |
|||
} |
|||
for(Object logDto:array){ |
|||
log.info(logDto.toString()); |
|||
} |
|||
reader.close(); |
|||
JSONObject jo = new JSONObject(); |
|||
jo.put("content", array); |
|||
jo.put("totalElements", docs.totalHits.value); |
|||
return jo; |
|||
} |
|||
|
|||
public static void main(String[] args) { |
|||
String indexDir = "D:\\lucene\\index"; |
|||
//查询这个字符串
|
|||
String q = "07.832"; |
|||
Map whereJson = null; |
|||
try { |
|||
search(indexDir, q,whereJson); |
|||
} catch (Exception e) { |
|||
e.printStackTrace(); |
|||
} |
|||
} |
|||
} |
@ -1,21 +0,0 @@ |
|||
package org.nl.config.lucene; |
|||
|
|||
import org.springframework.beans.factory.annotation.Value; |
|||
import org.springframework.context.annotation.Bean; |
|||
import org.springframework.context.annotation.Configuration; |
|||
|
|||
/** |
|||
* @deprecated 设置静态参数初始化 |
|||
*/ |
|||
@Configuration |
|||
public class StaticConfig { |
|||
//日志索引目录
|
|||
@Value("${lucene.index.path}") |
|||
private String luceneDir; |
|||
|
|||
@Bean |
|||
public int initStatic() { |
|||
UrlConfig.setLuceneUrl(luceneDir); |
|||
return 0; |
|||
} |
|||
} |
@ -1,13 +0,0 @@ |
|||
package org.nl.config.lucene; |
|||
|
|||
public class UrlConfig { |
|||
public static String luceneUrl; |
|||
|
|||
public static String getLuceneUrl() { |
|||
return luceneUrl; |
|||
} |
|||
|
|||
public static void setLuceneUrl(String luceneUrl) { |
|||
UrlConfig.luceneUrl = luceneUrl; |
|||
} |
|||
} |
@ -0,0 +1,28 @@ |
|||
package org.nl.config.lucene; |
|||
|
|||
import org.springframework.beans.factory.config.YamlPropertiesFactoryBean; |
|||
import org.springframework.core.io.ClassPathResource; |
|||
import org.springframework.core.io.Resource; |
|||
|
|||
import java.util.Properties; |
|||
|
|||
/** |
|||
* @Author: lyd |
|||
* @Description: 配置文件获取方法 |
|||
* @Date: 2023/12/6 |
|||
*/ |
|||
public class YmlConfigFileUtil { |
|||
public static Properties readConfig(String configFile) { |
|||
// 创建 Resource 对象
|
|||
Resource resource = new ClassPathResource(configFile); |
|||
|
|||
// 创建 YamlPropertiesFactoryBean
|
|||
YamlPropertiesFactoryBean yamlPropertiesFactoryBean = new YamlPropertiesFactoryBean(); |
|||
yamlPropertiesFactoryBean.setResources(resource); |
|||
|
|||
// 获取 Properties 对象
|
|||
Properties properties = yamlPropertiesFactoryBean.getObject(); |
|||
|
|||
return properties; |
|||
} |
|||
} |
@ -0,0 +1,69 @@ |
|||
package org.nl.system.controller.logserver; |
|||
|
|||
import cn.dev33.satoken.annotation.SaIgnore; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.nl.common.logging.annotation.Log; |
|||
import org.nl.system.service.logserver.LogQuery; |
|||
import org.nl.system.service.logserver.LuceneLogService; |
|||
import org.springframework.beans.factory.annotation.Autowired; |
|||
import org.springframework.http.HttpStatus; |
|||
import org.springframework.http.ResponseEntity; |
|||
import org.springframework.web.bind.annotation.*; |
|||
|
|||
/** |
|||
* @author ldjun |
|||
* @version 1.0 |
|||
* @date 2023年01月29日 18:55 |
|||
* @desc desc |
|||
*/ |
|||
|
|||
@RestController |
|||
@RequestMapping("/api/esLog") |
|||
@Slf4j |
|||
public class LuceneLogController { |
|||
|
|||
@Autowired |
|||
private LuceneLogService luceneLogService; |
|||
|
|||
|
|||
@GetMapping("/labels/{type}") |
|||
//("获取标签")
|
|||
public ResponseEntity<Object> labelsValues(@PathVariable String type) { |
|||
return new ResponseEntity<>(luceneLogService.getLabelsValues(type), HttpStatus.OK); |
|||
} |
|||
|
|||
@PostMapping("/query") |
|||
//("日志查询")
|
|||
public ResponseEntity<Object> queryAll(@RequestBody LogQuery query) { |
|||
return new ResponseEntity<>(luceneLogService.query(query), HttpStatus.OK); |
|||
} |
|||
@DeleteMapping("/clearLogs") |
|||
//("清空日志")
|
|||
public ResponseEntity<Object> clearLogs(@RequestBody LogQuery query) { |
|||
luceneLogService.clearLogs(query); |
|||
return new ResponseEntity<>(HttpStatus.OK); |
|||
} |
|||
|
|||
@GetMapping("/thread") |
|||
@SaIgnore |
|||
@Log("线程追踪测试") |
|||
//("清空日志")
|
|||
public ResponseEntity<Object> thread(@RequestBody LogQuery query) { |
|||
log.info("线程链路测试"+Thread.currentThread().getName()); |
|||
log.error("线程链路测试"+Thread.currentThread().getName()); |
|||
luceneLogService.syncdemo(); |
|||
Thread thread = new Thread(()->{ |
|||
try { |
|||
Thread.sleep(5000); |
|||
log.info("线程链路测试"+Thread.currentThread().getName()); |
|||
log.error("线程链路测试"+Thread.currentThread().getName()); |
|||
log.info("线程链路测试"+Thread.currentThread().getName()); |
|||
}catch (Exception ex){ |
|||
ex.printStackTrace(); |
|||
} |
|||
}); |
|||
thread.start(); |
|||
return new ResponseEntity<>(HttpStatus.OK); |
|||
} |
|||
|
|||
} |
@ -1,35 +0,0 @@ |
|||
package org.nl.system.controller.lucence; |
|||
|
|||
import io.swagger.annotations.Api; |
|||
import io.swagger.annotations.ApiOperation; |
|||
import lombok.RequiredArgsConstructor; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.nl.common.logging.annotation.Log; |
|||
import org.nl.system.service.lucene.LuceneService; |
|||
import org.springframework.data.domain.Pageable; |
|||
import org.springframework.http.HttpStatus; |
|||
import org.springframework.http.ResponseEntity; |
|||
import org.springframework.web.bind.annotation.GetMapping; |
|||
import org.springframework.web.bind.annotation.RequestMapping; |
|||
import org.springframework.web.bind.annotation.RequestParam; |
|||
import org.springframework.web.bind.annotation.RestController; |
|||
|
|||
import java.util.Map; |
|||
|
|||
@RestController |
|||
@RequiredArgsConstructor |
|||
@Api(tags = "日志检索") |
|||
@RequestMapping("/api/lucene") |
|||
@Slf4j |
|||
public class LuceneController { |
|||
|
|||
private final LuceneService luceneService; |
|||
|
|||
@GetMapping("/getAll") |
|||
@Log("日志检索") |
|||
@ApiOperation("日志检索") |
|||
//@PreAuthorize("@el.check('task:list')")
|
|||
public ResponseEntity<Object> get(@RequestParam Map whereJson, Pageable page) { |
|||
return new ResponseEntity<>(luceneService.getAll(whereJson, page), HttpStatus.OK); |
|||
} |
|||
} |
@ -0,0 +1,47 @@ |
|||
package org.nl.system.service.logserver; |
|||
|
|||
import lombok.Data; |
|||
|
|||
import java.util.Date; |
|||
|
|||
/* |
|||
* @author ZZQ |
|||
* @Date 2023/2/8 5:18 下午 |
|||
*/ |
|||
@Data |
|||
public class LogQuery { |
|||
/** |
|||
* 创建时间范围查询 |
|||
*/ |
|||
private Date startTime; |
|||
private Date endTime; |
|||
/** |
|||
* 追踪id |
|||
*/ |
|||
private String traceId; |
|||
private String requestMethod; |
|||
/** |
|||
* 日志内容模糊匹配 |
|||
*/ |
|||
private String message; |
|||
/** |
|||
* 日志级别 |
|||
*/ |
|||
private String logLevel; |
|||
/** |
|||
* 系统标签 |
|||
*/ |
|||
private String system; |
|||
/** |
|||
* 是否只查询Http相关请求 |
|||
*/ |
|||
private Boolean isRequest = Boolean.TRUE; |
|||
/** |
|||
* 是否过滤wql日志 |
|||
*/ |
|||
private Boolean filterSql = Boolean.TRUE; |
|||
|
|||
private Integer size = 20; |
|||
|
|||
private Integer page = 1; |
|||
} |
@ -0,0 +1,27 @@ |
|||
package org.nl.system.service.logserver; |
|||
|
|||
import lombok.Data; |
|||
import org.springframework.data.annotation.Id; |
|||
|
|||
/* |
|||
* @author ZZQ |
|||
* @Date 2023/2/8 4:06 下午 |
|||
*/ |
|||
//@Document(indexName = "#{@ESConfig.index}", type = "mes_log")
|
|||
@Data |
|||
public class LogRepositoryDTO { |
|||
|
|||
private String message; |
|||
private String host; |
|||
private String logLevel; |
|||
private String logger; |
|||
private String requestTime; |
|||
private String requestIp; |
|||
@Id |
|||
private String id; |
|||
private String traceId; |
|||
private String requestMethod; |
|||
private String thread; |
|||
private String system; |
|||
|
|||
} |
@ -0,0 +1,32 @@ |
|||
package org.nl.system.service.logserver; |
|||
|
|||
import com.alibaba.fastjson.JSONArray; |
|||
import com.alibaba.fastjson.JSONObject; |
|||
|
|||
/** |
|||
* @author ldjun |
|||
* @version 1.0 |
|||
* @date 2023年02月07日 14:34 |
|||
* @desc desc |
|||
*/ |
|||
public interface LuceneLogService { |
|||
|
|||
/** |
|||
* 清空日志 |
|||
*/ |
|||
void clearLogs(LogQuery query); |
|||
/** |
|||
* 获取labels和values树 |
|||
* @return |
|||
*/ |
|||
JSONArray getLabelsValues(String type); |
|||
|
|||
/** |
|||
* 日志查询 |
|||
* @param logQuery |
|||
* @return |
|||
*/ |
|||
JSONObject query(LogQuery logQuery); |
|||
|
|||
void syncdemo(); |
|||
} |
@ -0,0 +1,172 @@ |
|||
package org.nl.system.service.logserver; |
|||
|
|||
import cn.hutool.core.date.DateField; |
|||
import cn.hutool.core.date.DateTime; |
|||
import cn.hutool.core.date.DateUtil; |
|||
import cn.hutool.core.util.ObjectUtil; |
|||
import cn.hutool.db.PageResult; |
|||
import com.alibaba.fastjson.JSONArray; |
|||
import com.alibaba.fastjson.JSONObject; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.apache.lucene.document.Document; |
|||
import org.apache.lucene.index.DirectoryReader; |
|||
import org.apache.lucene.index.IndexWriter; |
|||
import org.apache.lucene.index.Term; |
|||
import org.apache.lucene.queryparser.classic.QueryParser; |
|||
import org.apache.lucene.search.*; |
|||
import org.apache.lucene.store.FSDirectory; |
|||
import org.apache.lucene.util.BytesRef; |
|||
import org.nl.common.exception.BadRequestException; |
|||
import org.nl.config.lucene.LuceneAppender; |
|||
import org.springframework.beans.factory.annotation.Value; |
|||
import org.springframework.scheduling.annotation.Async; |
|||
import org.springframework.stereotype.Service; |
|||
import org.wltea.analyzer.lucene.IKAnalyzer; |
|||
|
|||
import java.nio.file.Paths; |
|||
import java.util.ArrayList; |
|||
import java.util.Calendar; |
|||
import java.util.Date; |
|||
import java.util.List; |
|||
|
|||
@Service |
|||
@Slf4j |
|||
public class LuceneLogServiceImpl implements LuceneLogService { |
|||
|
|||
static String[] INFO_LEVEL = new String[]{"DEBUG","INFO","WARN","ERROR"}; |
|||
|
|||
@Value("${lucene.index.path}") |
|||
private String indexUrl; |
|||
|
|||
@Override |
|||
public void clearLogs(LogQuery query) { |
|||
try { |
|||
IndexWriter indexWriter = LuceneAppender.indexWriter; |
|||
if (indexWriter != null){ |
|||
BooleanQuery.Builder booleanQueryBuilder = new BooleanQuery.Builder(); |
|||
DateTime offset = DateUtil.offset(new Date(), DateField.HOUR_OF_DAY, -10); |
|||
TermRangeQuery termRangeQuery = new TermRangeQuery( |
|||
"requestTime",null, |
|||
new BytesRef(DateUtil.format(offset, "yyyy-MM-dd HH:mm:ss.SSS")), true, true); |
|||
booleanQueryBuilder.add(termRangeQuery,BooleanClause.Occur.MUST); |
|||
indexWriter.deleteDocuments(termRangeQuery); |
|||
indexWriter.commit(); |
|||
} |
|||
}catch (Exception ex){ |
|||
throw new BadRequestException("删除失败:"+ex.getMessage()); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public JSONArray getLabelsValues(String type) { |
|||
JSONArray result = new JSONArray(); |
|||
for (String v : INFO_LEVEL) { |
|||
JSONObject item = new JSONObject(); |
|||
item.put("label", v); |
|||
item.put("value", v); |
|||
result.add(item); |
|||
} |
|||
return result; |
|||
} |
|||
|
|||
|
|||
@Override |
|||
public JSONObject query(LogQuery logQuery) { |
|||
JSONObject res = new JSONObject(); |
|||
PageResult page = new PageResult(); |
|||
page.setPage(logQuery.getPage()); |
|||
page.setPageSize(logQuery.getSize()); |
|||
try { |
|||
FSDirectory directory = FSDirectory.open(Paths.get(indexUrl)); |
|||
DirectoryReader open = DirectoryReader.open(directory); |
|||
IndexSearcher searcher = new IndexSearcher(open); |
|||
// 创建排序对象,需要排序字段SortField,参数:字段的名称、字段的类型、是否反转如果是false,升序。true降序
|
|||
BooleanQuery.Builder booleanQueryBuilder = new BooleanQuery.Builder(); |
|||
//时间范围查询
|
|||
Date startDate = logQuery.getStartTime(); |
|||
Date endDate = logQuery.getEndTime(); |
|||
|
|||
if (startDate == null){ |
|||
Calendar calendar=Calendar.getInstance(); |
|||
calendar.set(1970, 0, 1); |
|||
startDate = calendar.getTime(); } |
|||
if (endDate == null){ endDate = new DateTime(); } |
|||
TermRangeQuery termRangeQuery = new TermRangeQuery( |
|||
"requestTime", |
|||
new BytesRef(DateUtil.format(startDate, "yyyy-MM-dd HH:mm:ss.SSS")), |
|||
new BytesRef(DateUtil.format(endDate, "yyyy-MM-dd HH:mm:ss.SSS")), true, true); |
|||
booleanQueryBuilder.add(termRangeQuery,BooleanClause.Occur.MUST); |
|||
|
|||
// 字段之间的与或非关系,MUST表示and,MUST_NOT表示not,SHOULD表示or,有几个fields就必须有几个clauses
|
|||
if (ObjectUtil.isNotEmpty(logQuery.getTraceId())){ |
|||
TermQuery termQuery = new TermQuery(new Term("traceId", logQuery.getTraceId())); |
|||
booleanQueryBuilder.add(termQuery, BooleanClause.Occur.MUST); |
|||
} |
|||
if (ObjectUtil.isNotEmpty(logQuery.getLogLevel())){ |
|||
TermQuery termQuery = new TermQuery(new Term("logLevel", logQuery.getLogLevel())); |
|||
booleanQueryBuilder.add(termQuery, BooleanClause.Occur.MUST); |
|||
} |
|||
if (ObjectUtil.isNotEmpty(logQuery.getSystem())) { |
|||
TermQuery termQuery = new TermQuery(new Term("system", logQuery.getSystem())); |
|||
booleanQueryBuilder.add(termQuery, BooleanClause.Occur.MUST); |
|||
} |
|||
if (ObjectUtil.isNotEmpty(logQuery.getRequestMethod())) { |
|||
TermQuery termQuery = new TermQuery(new Term("requestMethod", logQuery.getRequestMethod())); |
|||
booleanQueryBuilder.add(termQuery, BooleanClause.Occur.MUST); |
|||
} |
|||
if (Boolean.TRUE.equals(logQuery.getIsRequest())) { |
|||
Term traceid = new Term("traceId"); |
|||
TermQuery termQuery = new TermQuery(traceid); |
|||
booleanQueryBuilder.add(termQuery, BooleanClause.Occur.MUST_NOT); |
|||
} |
|||
if (ObjectUtil.isNotEmpty(logQuery.getMessage())){ |
|||
//查询解析器
|
|||
QueryParser queryParser = new QueryParser("message", new IKAnalyzer(true)); |
|||
Query query = queryParser.parse(logQuery.getMessage()); |
|||
booleanQueryBuilder.add(query, BooleanClause.Occur.MUST); |
|||
} |
|||
|
|||
TopFieldCollector collector = TopFieldCollector.create(new Sort(new SortField("time", SortField.Type.LONG,true)), 20000, 0); |
|||
searcher.search(booleanQueryBuilder.build(), collector); |
|||
TopDocs topDocs = collector.topDocs((logQuery.getPage()-1)*logQuery.getSize(), logQuery.getSize()); |
|||
int totalSize = collector.getTotalHits(); |
|||
ScoreDoc[] scoreDocs = topDocs.scoreDocs; |
|||
|
|||
List<LogRepositoryDTO> list = new ArrayList<>(); |
|||
for (ScoreDoc scoreDoc : scoreDocs) { |
|||
Document doc = open.document(scoreDoc.doc); |
|||
LogRepositoryDTO dto = new LogRepositoryDTO(); |
|||
dto.setSystem(doc.get("system")); |
|||
dto.setTraceId(doc.get("traceId")); |
|||
dto.setLogger(doc.get("logger")); |
|||
dto.setLogLevel(doc.get("logLevel")); |
|||
dto.setMessage(doc.get("message")); |
|||
dto.setRequestIp(doc.get("requestIp")); |
|||
dto.setRequestMethod(doc.get("requestMethod")); |
|||
dto.setRequestTime(doc.get("requestTime")); |
|||
dto.setThread(doc.get("thread")); |
|||
list.add(dto); |
|||
} |
|||
open.close(); |
|||
directory.close(); |
|||
page.addAll(list); |
|||
page.setTotal(scoreDocs.length); |
|||
res.put("total", totalSize); |
|||
}catch (Exception ex){ |
|||
ex.printStackTrace(); |
|||
} |
|||
res.put("page",page); |
|||
return res; |
|||
|
|||
} |
|||
|
|||
|
|||
@Override |
|||
@Async |
|||
public void syncdemo() { |
|||
log.info("Async线程链路测试"+Thread.currentThread().getName()); |
|||
log.error("Async线程链路测试"+Thread.currentThread().getName()); |
|||
log.info("Async线程链路测试"+Thread.currentThread().getName()); |
|||
log.info("线程链路测试"+Thread.currentThread().getName()); |
|||
} |
|||
} |
@ -1,40 +0,0 @@ |
|||
package org.nl.system.service.lucene; |
|||
|
|||
import org.nl.system.service.lucene.dto.LuceneLogDto; |
|||
|
|||
import java.io.IOException; |
|||
|
|||
public interface LuceneExecuteLogService { |
|||
/** |
|||
* 设备光电变化实时光电信号 |
|||
* |
|||
* @param device_code 设备编号 |
|||
* @param key plc信号 |
|||
* @param value plc信号值 |
|||
*/ |
|||
void deviceItemValue(String device_code, String key, String value); |
|||
|
|||
/** |
|||
* 设备执行日志,会保留历史记录 |
|||
* |
|||
* @param luceneLogDto 日志结果对象 |
|||
*/ |
|||
void deviceExecuteLog(LuceneLogDto luceneLogDto); |
|||
|
|||
/** |
|||
* 接口日志,会保留历史记录 |
|||
* |
|||
* @param luceneLogDto 日志结果对象 |
|||
*/ |
|||
void interfaceExecuteLog(LuceneLogDto luceneLogDto) throws IOException; |
|||
|
|||
/** |
|||
* 设备执行日志,会保留历史记录 |
|||
* |
|||
* @param name 日志名称 |
|||
* @param message 日志信息 |
|||
*/ |
|||
void extLog(String name, String message); |
|||
|
|||
|
|||
} |
@ -1,19 +0,0 @@ |
|||
package org.nl.system.service.lucene; |
|||
|
|||
import com.alibaba.fastjson.JSONArray; |
|||
import org.springframework.data.domain.Pageable; |
|||
|
|||
import java.util.Map; |
|||
|
|||
|
|||
public interface LuceneService { |
|||
|
|||
/** |
|||
* 获取数据分页 |
|||
* |
|||
* @param whereJson 条件 |
|||
* @param page 分页参数 |
|||
* @return Map<String, Object> |
|||
*/ |
|||
Map<String, Object> getAll(Map whereJson, Pageable page); |
|||
} |
@ -1,86 +0,0 @@ |
|||
package org.nl.system.service.lucene.dto; |
|||
|
|||
import lombok.AllArgsConstructor; |
|||
import lombok.Builder; |
|||
import lombok.Data; |
|||
import lombok.NoArgsConstructor; |
|||
|
|||
@Data |
|||
@Builder |
|||
@NoArgsConstructor |
|||
@AllArgsConstructor |
|||
public class LuceneLogDto { |
|||
|
|||
/* 日志标识 */ |
|||
private String log_uuid; |
|||
/*日志类型*/ |
|||
private String logType; |
|||
/*设备编号*/ |
|||
private String device_code; |
|||
/*内容详情*/ |
|||
private String content; |
|||
|
|||
/* 任务编码 */ |
|||
private String task_code; |
|||
|
|||
/* 指令编码 */ |
|||
private String instruct_code; |
|||
|
|||
/* 任务标识 */ |
|||
private String task_id; |
|||
|
|||
/* 载具号 */ |
|||
private String vehicle_code; |
|||
|
|||
/* 备注 */ |
|||
private String remark; |
|||
|
|||
/* 日志类型 */ |
|||
private String log_type; |
|||
|
|||
/* 方法 */ |
|||
private String method; |
|||
|
|||
/* 请求参数 */ |
|||
private String requestparam; |
|||
|
|||
/* 响应参数 */ |
|||
private String responseparam; |
|||
|
|||
/* 请求地址 */ |
|||
private String requesturl; |
|||
|
|||
/* 状态码 */ |
|||
private String status_code; |
|||
|
|||
/* 是否删除 1:是;0:否 */ |
|||
private String is_delete; |
|||
|
|||
/* 创建者 */ |
|||
private String create_by; |
|||
|
|||
/* 创建时间 YYYY-MM-DD hh:mm:ss */ |
|||
private String create_time; |
|||
|
|||
/* 修改者 */ |
|||
private String update_by; |
|||
|
|||
/* 修改时间 */ |
|||
private String update_time; |
|||
|
|||
|
|||
|
|||
public LuceneLogDto (final String opc_server_code,final String opc_plc_code, |
|||
final String device_code,final String to_home,final int last_home, |
|||
final int home) { |
|||
super (); |
|||
this.device_code = device_code; |
|||
this.content = "信号" |
|||
+ opc_server_code + "." |
|||
+ opc_plc_code + "." |
|||
+ device_code + "." |
|||
+ to_home + "变更从" |
|||
+ last_home + "->" |
|||
+ home; |
|||
} |
|||
} |
@ -1,111 +0,0 @@ |
|||
package org.nl.system.service.lucene.impl; |
|||
|
|||
import cn.hutool.core.date.DateTime; |
|||
import cn.hutool.core.date.DateUtil; |
|||
import cn.hutool.core.util.ObjectUtil; |
|||
import lombok.RequiredArgsConstructor; |
|||
import lombok.SneakyThrows; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.apache.lucene.document.Document; |
|||
import org.apache.lucene.document.Field; |
|||
import org.apache.lucene.document.StringField; |
|||
import org.apache.lucene.index.IndexWriter; |
|||
import org.nl.common.enums.LogTypeEnum; |
|||
import org.nl.config.lucene.DynamicLogger; |
|||
import org.nl.config.lucene.LuceneIndexWriter; |
|||
import org.nl.system.service.lucene.LuceneExecuteLogService; |
|||
import org.nl.system.service.lucene.dto.LuceneLogDto; |
|||
import org.slf4j.Logger; |
|||
import org.slf4j.MDC; |
|||
import org.springframework.beans.factory.annotation.Value; |
|||
import org.springframework.stereotype.Service; |
|||
|
|||
import java.io.IOException; |
|||
|
|||
/** |
|||
* @author jlm |
|||
* @description 服务实现 |
|||
* @date 2023-04-11 |
|||
*/ |
|||
@Service |
|||
@RequiredArgsConstructor |
|||
@Slf4j |
|||
public class LuceneExecuteLogServiceImpl implements LuceneExecuteLogService { |
|||
|
|||
//日志目录
|
|||
@Value("${logging.file.path}") |
|||
private String logPath; |
|||
|
|||
@Override |
|||
public void deviceItemValue(String device_code, String key, String value) { |
|||
String now = DateUtil.now(); |
|||
} |
|||
|
|||
@SneakyThrows |
|||
@Override |
|||
public void deviceExecuteLog(LuceneLogDto luceneLogDto) { |
|||
luceneLogDto.setLogType(LogTypeEnum.DEVICE_LOG.getDesc()); |
|||
addIndex(luceneLogDto); |
|||
} |
|||
|
|||
@Override |
|||
public void interfaceExecuteLog(LuceneLogDto luceneLogDto) throws IOException { |
|||
luceneLogDto.setLogType(LogTypeEnum.INTERFACE_LOG.getDesc()); |
|||
addIndex(luceneLogDto); |
|||
} |
|||
|
|||
private void addIndex(LuceneLogDto luceneLogDto) throws IOException { |
|||
IndexWriter indexWriter = LuceneIndexWriter.getIndexWriter(); |
|||
//创建一个Document对象
|
|||
Document document = new Document(); |
|||
try { |
|||
//记录索引开始时间
|
|||
long startTime = System.currentTimeMillis(); |
|||
//向document对象中添加域。
|
|||
if (ObjectUtil.isNotEmpty(luceneLogDto.getDevice_code())) { |
|||
document.add(new StringField("device_code", luceneLogDto.getDevice_code(), Field.Store.YES)); |
|||
// document.add(new TextField("device_code", luceneLogDto.getDevice_code(), Field.Store.YES));
|
|||
} |
|||
if (ObjectUtil.isNotEmpty(luceneLogDto.getContent())) { |
|||
document.add(new StringField("fieldContent", luceneLogDto.getContent(), Field.Store.YES)); |
|||
} |
|||
if (ObjectUtil.isNotEmpty(luceneLogDto.getMethod())) { |
|||
document.add(new StringField("method", luceneLogDto.getMethod(), Field.Store.YES)); |
|||
} |
|||
if (ObjectUtil.isNotEmpty(luceneLogDto.getStatus_code())) { |
|||
document.add(new StringField("status_code", luceneLogDto.getStatus_code(), Field.Store.YES)); |
|||
} |
|||
if (ObjectUtil.isNotEmpty(luceneLogDto.getRequestparam())) { |
|||
document.add(new StringField("requestparam", luceneLogDto.getRequestparam(), Field.Store.YES)); |
|||
} |
|||
if (ObjectUtil.isNotEmpty(luceneLogDto.getResponseparam())) { |
|||
document.add(new StringField("responseparam", luceneLogDto.getResponseparam(), Field.Store.YES)); |
|||
} |
|||
document.add(new StringField("logType", luceneLogDto.getLogType(), Field.Store.YES)); |
|||
document.add(new StringField("logTime", DateUtil.format(new DateTime(), "yyyy-MM-dd HH:mm:ss.SSS"), Field.Store.YES)); |
|||
indexWriter.addDocument(document); |
|||
//记录索引结束时间
|
|||
long endTime = System.currentTimeMillis(); |
|||
indexWriter.commit(); |
|||
//实现日志文件按业务独立生成日志文件到指定路径
|
|||
DynamicLogger loggerBuilder =new DynamicLogger(logPath+"\\"+luceneLogDto.getLogType()+"\\"); |
|||
Logger logger = loggerBuilder.getLogger(luceneLogDto.getDevice_code()); |
|||
// logger.info("设备{}建立索引共耗时{}毫秒",luceneLogDto.getDevice_code(),endTime-startTime);
|
|||
logger.info("{}",luceneLogDto.toString()); |
|||
} catch (Exception e) { |
|||
log.error(e.getMessage(), e); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public void extLog(String name, String message) { |
|||
try { |
|||
MDC.put(name, name); |
|||
log.info("{}", message); |
|||
} catch (Exception e) { |
|||
e.printStackTrace(); |
|||
} finally { |
|||
MDC.remove(name); |
|||
} |
|||
} |
|||
} |
@ -1,44 +0,0 @@ |
|||
package org.nl.system.service.lucene.impl; |
|||
|
|||
import cn.hutool.core.util.CharsetUtil; |
|||
import cn.hutool.http.HttpUtil; |
|||
import com.alibaba.fastjson.JSONArray; |
|||
import com.alibaba.fastjson.JSONObject; |
|||
import lombok.RequiredArgsConstructor; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.nl.config.lucene.Searcher; |
|||
import org.nl.system.service.lucene.LuceneService; |
|||
import org.springframework.beans.factory.annotation.Value; |
|||
import org.springframework.data.domain.Pageable; |
|||
import org.springframework.stereotype.Service; |
|||
|
|||
import java.util.Map; |
|||
|
|||
|
|||
@Service |
|||
@RequiredArgsConstructor |
|||
@Slf4j |
|||
public class LuceneServiceImpl implements LuceneService { |
|||
|
|||
//日志索引目录
|
|||
@Value("${lucene.index.path}") |
|||
private String luceneUrl; |
|||
|
|||
@Override |
|||
public Map<String, Object> getAll(Map whereJson, Pageable page) { |
|||
JSONObject jo = new JSONObject(); |
|||
try { |
|||
JSONObject jsonObject = (JSONObject) Searcher.search(luceneUrl, "", whereJson); |
|||
JSONArray array = jsonObject.getJSONArray("content"); |
|||
int totalElements = Integer.parseInt(jsonObject.get("totalElements").toString()); |
|||
jo.put("content", array); |
|||
jo.put("totalElements", totalElements); |
|||
} catch (Exception e) { |
|||
log.error("索引查询为空", e); |
|||
throw new NullPointerException("索引查询为空"); |
|||
} |
|||
|
|||
return jo; |
|||
} |
|||
|
|||
} |
@ -0,0 +1 @@ |
|||
druid.filters.DruidFilter=org.nl.config.DruidFilter |
@ -0,0 +1,404 @@ |
|||
<template> |
|||
<div class="app-container"> |
|||
<div class="head-container"> |
|||
<!--工具栏--> |
|||
<el-form :inline="true" class="demo-form-inline" label-suffix=":" label-width="90px"> |
|||
<el-form-item label="标签"> |
|||
<el-select |
|||
v-model="system" |
|||
clearable |
|||
style="width: 100px; height: 35px;top: -5px;" |
|||
placeholder="所属标签" |
|||
> |
|||
<el-option |
|||
v-for="item in systemOptions" |
|||
:key="item.value" |
|||
:label="item.label" |
|||
:value="item.value" |
|||
/> |
|||
</el-select> |
|||
</el-form-item> |
|||
<el-form-item label="级别"> |
|||
<el-select |
|||
v-model="logLevelValue" |
|||
clearable |
|||
style="width: 100px; height: 35px;top: -5px;" |
|||
placeholder="日志级别" |
|||
> |
|||
<el-option |
|||
v-for="item in labelsOptions" |
|||
:key="item.value" |
|||
:label="item.label" |
|||
:value="item.value" |
|||
/> |
|||
</el-select> |
|||
</el-form-item> |
|||
<el-form-item label="关键字"> |
|||
<el-input |
|||
v-model="message" |
|||
size="mini" |
|||
placeholder="请输入内容" |
|||
clearable |
|||
/> |
|||
</el-form-item> |
|||
<el-form-item label="链路追踪"> |
|||
<el-input |
|||
v-model="traceId" |
|||
size="mini" |
|||
placeholder="请输入链路id" |
|||
clearable |
|||
/> |
|||
</el-form-item> |
|||
|
|||
<el-form-item label="SQL日志" prop="filterSql"> |
|||
<el-switch |
|||
v-model="filterSql" |
|||
active-color="#F56C6C" |
|||
inactive-color="#409EFF" |
|||
active-value="1" |
|||
inactive-valu="0" |
|||
/> |
|||
</el-form-item> |
|||
<el-form-item label="HTTP日志" prop="isRequest"> |
|||
<el-switch |
|||
v-model="isRequest" |
|||
active-color="#409EFF" |
|||
inactive-color="#F56C6C" |
|||
active-value="1" |
|||
inactive-valu="0" |
|||
/> |
|||
</el-form-item> |
|||
|
|||
<el-form-item v-show="!showOptions" label="时间范围"> |
|||
<el-date-picker |
|||
v-model="timeRange" |
|||
size="mini" |
|||
clearable |
|||
type="datetimerange" |
|||
range-separator="至" |
|||
start-placeholder="开始日期" |
|||
end-placeholder="结束日期" |
|||
align="right" |
|||
@change="queryData" |
|||
@blur="queryData" |
|||
/> |
|||
</el-form-item> |
|||
<el-form-item v-show="showOptions" label="时间段"> |
|||
<el-select v-model="timeZoneValue" filterable placeholder="请选择标签" size="mini" @change="queryData"> |
|||
<el-option |
|||
v-for="item in timeZoneOptions" |
|||
:key="item.index" |
|||
:label="item.label" |
|||
:value="item.value" |
|||
/> |
|||
</el-select> |
|||
</el-form-item> |
|||
<el-form-item> |
|||
<el-tooltip class="item" effect="dark" content="切换查询条件" placement="top"> |
|||
<span class="el-icon-sort" @click="changeShow" /> |
|||
</el-tooltip> |
|||
</el-form-item> |
|||
<el-form-item label="显示条数"> |
|||
<el-input-number |
|||
v-model="size" |
|||
size="mini" |
|||
controls-position="right" |
|||
:min="20" |
|||
:max="5000" |
|||
:step="10" |
|||
/> |
|||
</el-form-item> |
|||
<el-form-item label="当前页"> |
|||
<el-input-number |
|||
v-model="page" |
|||
size="mini" |
|||
controls-position="right" |
|||
:min="1" |
|||
:max="2000" |
|||
:step="1" |
|||
/> |
|||
</el-form-item> |
|||
<el-form-item label="总条数"> |
|||
<el-input |
|||
v-model="total" |
|||
size="small" |
|||
disabled |
|||
style="width: 110px" |
|||
/> |
|||
</el-form-item> |
|||
<el-form-item> |
|||
<el-dropdown split-button type="primary" size="mini" @click="queryData"> |
|||
查询 |
|||
<el-dropdown-menu slot="dropdown"> |
|||
<el-dropdown-item v-for="(item, index) in runStatuOptions" :key="index" @click.native="startInterval(item)">{{ item.label }}</el-dropdown-item> |
|||
</el-dropdown-menu> |
|||
</el-dropdown> |
|||
</el-form-item> |
|||
<el-form-item> |
|||
<el-button @click="clearLogs">清空日志</el-button> |
|||
</el-form-item> |
|||
</el-form> |
|||
</div> |
|||
<!-- <div style="margin: 3px; min-height: 80vh;"> |
|||
<el-table :data="logs"> |
|||
<el-table-column label="ip" prop="requestIp" /> |
|||
<el-table-column label="所属系统" prop="system" /> |
|||
<el-table-column label="请求时间" prop="requestTime" /> |
|||
<el-table-column label="traceId" prop="traceId" /> |
|||
<el-table-column label="请求时间" prop="requestTime" /> |
|||
<el-table-column label="请求接口" prop="requestMethod" /> |
|||
<el-table-column label="logger" prop="logger" /> |
|||
<el-table-column label="thread" prop="thread" /> |
|||
<el-table-column label="message" prop="message" show-overflow-tooltip/> |
|||
</el-table> |
|||
</div> |
|||
--> |
|||
<div style="margin: 3px; min-height: 80vh;"> |
|||
<!--数据判空--> |
|||
<el-empty v-if="showEmpty" :description="emptyText" /> |
|||
<!--数据加载--> |
|||
<el-card v-else shadow="hover" style="width: 100%;overflow-x: scroll" class="log-warpper"> |
|||
<div style="width: 100%"> |
|||
<div v-for="(log, index) in logs" :key="index"> |
|||
<div> |
|||
<span style="color: #6c0a99;font-weight: 700">{{ log.system }}</span> |
|||
<span style="color: #13ce66">{{ log.thread }}</span> |
|||
<span :style="fontType(log.logLevel)">{{ log.logLevel }}</span> |
|||
<span>{{ log.requestIp }}</span> |
|||
<span style="color: #7c8db0">{{ log.requestTime }}</span> |
|||
<span style="color: chocolate">{{ log.traceId }}</span> |
|||
<span style="color: #7a6df0">{{ log.requestMethod }}</span> |
|||
<span style="margin: 5px;font-size: 15px" v-html="log.message">{{ log.message }}</span> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</el-card> |
|||
</div> |
|||
</div> |
|||
</template> |
|||
|
|||
<script> |
|||
import logOperation from '@/views/system/monitor/eslog/view/loki' |
|||
|
|||
let queryParam = { |
|||
logLevel: null, |
|||
system: null, |
|||
startTime: null, |
|||
endTime: null, |
|||
traceId: null, |
|||
message: null, |
|||
filterSql: true, |
|||
isRequest: true, |
|||
page: null, |
|||
total: 0, |
|||
size: 20 |
|||
} |
|||
export default { |
|||
name: 'ES', |
|||
data() { |
|||
return { |
|||
labelsOptions: [], // 所有标签和对应所有值数据 |
|||
systemOptions: [], // 所有标签和对应所有值数据 |
|||
logLevelValue: '', |
|||
system: '', |
|||
timeRange: [], |
|||
message: '', |
|||
traceId: '', |
|||
size: 20, |
|||
logData: [], |
|||
filterSql: '1', |
|||
isRequest: '1', |
|||
logs: [], // 所有日志 |
|||
showEmpty: true, |
|||
emptyText: '请选择标签', |
|||
page: 1, |
|||
runStatu: 'off', |
|||
runStatuOptions: [{ |
|||
label: 'off', |
|||
value: 0 |
|||
}, { |
|||
label: '5s', |
|||
value: 5000 |
|||
}, { |
|||
label: '10s', |
|||
value: 10000 |
|||
}, { |
|||
label: '1m', |
|||
value: 60000 |
|||
}, { |
|||
label: '5m', |
|||
value: 300000 |
|||
}, { |
|||
label: '30m', |
|||
value: 1800000 |
|||
}], |
|||
timeZoneOptions: [{ |
|||
label: '最近5分钟', |
|||
value: 300 * 1000 |
|||
}, { |
|||
label: '最近15分钟', |
|||
value: 900 * 1000 |
|||
}, { |
|||
label: '最近30分钟', |
|||
value: 1800 * 1000 |
|||
}, { |
|||
label: '最近1小时', |
|||
value: 3600 * 1000 |
|||
}, { |
|||
label: '最近3小时', |
|||
value: 3600 * 1000 * 3 |
|||
}, { |
|||
label: '最近6小时', |
|||
value: 3600 * 1000 * 6 |
|||
}, { |
|||
label: '最近12小时', |
|||
value: 3600 * 1000 * 12 |
|||
}, { |
|||
label: '最近24小时', |
|||
value: 3600 * 1000 * 24 |
|||
}, { |
|||
label: '最近2天', |
|||
value: 3600 * 1000 * 24 * 2 |
|||
}, { |
|||
label: '最近7天', |
|||
value: 3600 * 1000 * 24 * 7 |
|||
}, { |
|||
label: '最近15天', |
|||
value: 3600 * 1000 * 24 * 15 |
|||
}], |
|||
timeZoneValue: '', |
|||
showOptions: true |
|||
} |
|||
}, |
|||
created() { |
|||
this.initLabelsValues('logLevel') |
|||
this.initLabelsValues('system') |
|||
}, |
|||
methods: { |
|||
fontType(level) { |
|||
if (level === 'INFO') { |
|||
return { 'color': '#1b6cc4' } |
|||
} |
|||
if (level === 'ERROR') { |
|||
return { 'color': '#e30a0a' } |
|||
} |
|||
if (level === 'DEBUG') { |
|||
return { 'color': '#1e2022' } |
|||
} |
|||
return { 'color': '#a74dc6' } |
|||
}, |
|||
initLabelsValues(type) { |
|||
logOperation.labelsValues(type).then(res => { |
|||
if (type === 'logLevel') { |
|||
this.labelsOptions = res |
|||
} |
|||
if (type === 'system') { |
|||
this.systemOptions = res |
|||
} |
|||
}) |
|||
}, |
|||
queryData() { |
|||
// 清空查询数据 |
|||
this.clearParam() |
|||
queryParam.logLevel = this.logLevelValue |
|||
const time = new Date() |
|||
if (this.timeZoneValue !== '') { |
|||
queryParam.startTime = new Date(((time.getTime() - this.timeZoneValue))) |
|||
} |
|||
if (this.timeRange !== '' && this.timeRange.length > 0) { |
|||
queryParam.startTime = this.timeRange[0] |
|||
queryParam.endTime = this.timeRange[1] |
|||
} |
|||
queryParam.message = this.message.replace(/^\s*|\s*$/g, '') |
|||
queryParam.filterSql = this.filterSql === '1' |
|||
queryParam.isRequest = this.filterSql === '1' |
|||
queryParam.traceId = this.traceId |
|||
queryParam.size = this.size |
|||
queryParam.page = this.page |
|||
queryParam.system = this.system |
|||
|
|||
logOperation.getLogData(queryParam).then(res => { |
|||
this.showEmpty = false |
|||
this.total = res.total |
|||
// 清空 |
|||
this.logs = [] |
|||
for (const j in res.page) { // 用push的方式将所有日志数组添加进去 |
|||
this.logs.push(res.page[j]) |
|||
} |
|||
}) |
|||
}, |
|||
clearLogs() { |
|||
var message = '您确定要清空' |
|||
if (this.system !== '' && this.system !== null) { |
|||
message += '标签为:' + this.system + ' ' |
|||
} |
|||
message += '10天前的日志吗 ?' |
|||
this.$confirm(message, '确认信息', { |
|||
distinguishCancelAndClose: true, |
|||
confirmButtonText: '确定', |
|||
cancelButtonText: '取消' |
|||
}) |
|||
.then(() => { |
|||
// 清空查询数据 |
|||
this.clearParam() |
|||
queryParam.logLevel = this.logLevelValue |
|||
const time = new Date() |
|||
if (this.timeZoneValue !== '') { |
|||
queryParam.startTime = new Date(((time.getTime() - this.timeZoneValue))) |
|||
} |
|||
if (this.timeRange !== '' && this.timeRange.length > 0) { |
|||
queryParam.startTime = this.timeRange[0] |
|||
queryParam.endTime = this.timeRange[1] |
|||
} |
|||
queryParam.message = this.message.replace(/^\s*|\s*$/g, '') |
|||
queryParam.traceId = this.traceId |
|||
queryParam.system = this.system |
|||
|
|||
logOperation.clearLogs(queryParam).then(res => { |
|||
this.queryData() |
|||
this.$message({ |
|||
type: 'info', |
|||
message: '清除成功' |
|||
}) |
|||
}) |
|||
}) |
|||
.catch(action => { |
|||
this.$message({ |
|||
type: 'info', |
|||
message: action === 'cancel' |
|||
? '已取消' |
|||
: '已取消' |
|||
}) |
|||
}) |
|||
}, |
|||
changetype() { |
|||
|
|||
}, |
|||
clearParam() { |
|||
queryParam = { |
|||
logLevel: null, |
|||
startTime: null, |
|||
endTime: null, |
|||
message: null, |
|||
traceId: null, |
|||
isRequest: true, |
|||
filterSql: true, |
|||
size: 20 |
|||
} |
|||
}, |
|||
changeShow() { |
|||
// 清空数据 |
|||
this.timeZoneValue = '' |
|||
this.timeRange = [] |
|||
this.showOptions = !this.showOptions |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style scoped> |
|||
.log-warpper { |
|||
white-space: nowrap; |
|||
word-break: break-word; |
|||
} |
|||
</style> |
@ -0,0 +1,26 @@ |
|||
import request from '@/utils/request' |
|||
|
|||
export function getLogData(param) { |
|||
return request({ |
|||
url: '/api/esLog/query', |
|||
method: 'post', |
|||
data: param |
|||
}) |
|||
} |
|||
|
|||
export function labelsValues(type) { |
|||
return request({ |
|||
url: '/api/esLog/labels/' + type, |
|||
method: 'get' |
|||
}) |
|||
} |
|||
|
|||
export function clearLogs(param) { |
|||
return request({ |
|||
url: '/api/esLog/clearLogs', |
|||
method: 'delete', |
|||
data: param |
|||
}) |
|||
} |
|||
|
|||
export default { getLogData, labelsValues, clearLogs } |
Loading…
Reference in new issue