diff --git a/lms/nladmin-system/nlsso-server/pom.xml b/lms/nladmin-system/nlsso-server/pom.xml index 32853f1..17ab57b 100644 --- a/lms/nladmin-system/nlsso-server/pom.xml +++ b/lms/nladmin-system/nlsso-server/pom.xml @@ -47,6 +47,11 @@ hutool-all ${hutool.version} + + mysql + mysql-connector-java + 8.0.20 + @@ -199,11 +204,6 @@ - - mysql - mysql-connector-java - runtime - diff --git a/lms/nladmin-system/nlsso-server/src/main/java/org/nl/common/aspect/LogAspect.java b/lms/nladmin-system/nlsso-server/src/main/java/org/nl/common/aspect/LogAspect.java new file mode 100644 index 0000000..dead8d3 --- /dev/null +++ b/lms/nladmin-system/nlsso-server/src/main/java/org/nl/common/aspect/LogAspect.java @@ -0,0 +1,144 @@ +/* + * 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.lucene.LuceneAppender; +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.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("
【异常堆栈:"); + 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("
"); + 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 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 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 ""; + } + } +} diff --git a/lms/nladmin-system/nlsso-server/src/main/java/org/nl/common/lucene/AsyncLuceneAppender.java b/lms/nladmin-system/nlsso-server/src/main/java/org/nl/common/lucene/AsyncLuceneAppender.java new file mode 100644 index 0000000..0945d43 --- /dev/null +++ b/lms/nladmin-system/nlsso-server/src/main/java/org/nl/common/lucene/AsyncLuceneAppender.java @@ -0,0 +1,42 @@ +package org.nl.common.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.nl.common.lucene.remote.RemoteLogServer; +import org.slf4j.MDC; + +import java.util.Map; + +public class AsyncLuceneAppender extends AspectLogbackAsyncAppender { + + + public AsyncLuceneAppender() { + + RemoteLogServer.asyncLuceneAppender = this; + } + + @Override + protected void append(ILoggingEvent event) { + String traceId = LuceneAppender.traceIdTL.get(); + if (StringUtils.isNotEmpty(traceId)){ + MDC.put("traceId",traceId); + Map mdcPropertyMap = event.getMDCPropertyMap(); + if (mdcPropertyMap.getClass().getName().contains("SynchronizedMap")){ + mdcPropertyMap.put("traceId",traceId); + } + MDC.clear(); + } + RemoteLogServer.writeLog(event); + } + public void appendSync(ILoggingEvent event){ + super.append(event); + } + +} diff --git a/lms/nladmin-system/nlsso-server/src/main/java/org/nl/common/lucene/LogMessageConstant.java b/lms/nladmin-system/nlsso-server/src/main/java/org/nl/common/lucene/LogMessageConstant.java new file mode 100644 index 0000000..89d0621 --- /dev/null +++ b/lms/nladmin-system/nlsso-server/src/main/java/org/nl/common/lucene/LogMessageConstant.java @@ -0,0 +1,46 @@ +package org.nl.common.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"; + +} diff --git a/lms/nladmin-system/nlsso-server/src/main/java/org/nl/common/lucene/LuceneAppender.java b/lms/nladmin-system/nlsso-server/src/main/java/org/nl/common/lucene/LuceneAppender.java new file mode 100644 index 0000000..0d86adb --- /dev/null +++ b/lms/nladmin-system/nlsso-server/src/main/java/org/nl/common/lucene/LuceneAppender.java @@ -0,0 +1,98 @@ +package org.nl.common.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.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 { + + public static final TransmittableThreadLocal traceIdTL = new TransmittableThreadLocal(); + public LuceneProperties properties; + public static Directory index; + private List 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 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"," ", 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; + + } +} diff --git a/lms/nladmin-system/nlsso-server/src/main/java/org/nl/common/lucene/LuceneProperties.java b/lms/nladmin-system/nlsso-server/src/main/java/org/nl/common/lucene/LuceneProperties.java new file mode 100644 index 0000000..bcfd0d5 --- /dev/null +++ b/lms/nladmin-system/nlsso-server/src/main/java/org/nl/common/lucene/LuceneProperties.java @@ -0,0 +1,23 @@ +package org.nl.common.lucene; + + +import java.util.ArrayList; +import java.util.List; + +public class LuceneProperties { + + private List properties; + + public LuceneProperties() { + this.properties = new ArrayList(); + } + + public List getProperties() { + return properties; + } + + public void addProperty(Property property) { + properties.add(property); + } + +} diff --git a/lms/nladmin-system/nlsso-server/src/main/java/org/nl/common/lucene/LucenePropertyAndEncoder.java b/lms/nladmin-system/nlsso-server/src/main/java/org/nl/common/lucene/LucenePropertyAndEncoder.java new file mode 100644 index 0000000..450fc3f --- /dev/null +++ b/lms/nladmin-system/nlsso-server/src/main/java/org/nl/common/lucene/LucenePropertyAndEncoder.java @@ -0,0 +1,38 @@ +package org.nl.common.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(); + } +} + diff --git a/lms/nladmin-system/nlsso-server/src/main/java/org/nl/common/lucene/Property.java b/lms/nladmin-system/nlsso-server/src/main/java/org/nl/common/lucene/Property.java new file mode 100644 index 0000000..c4740bb --- /dev/null +++ b/lms/nladmin-system/nlsso-server/src/main/java/org/nl/common/lucene/Property.java @@ -0,0 +1,44 @@ +package org.nl.common.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; + } +} diff --git a/lms/nladmin-system/nlsso-server/src/main/java/org/nl/common/lucene/YmlConfigFileUtil.java b/lms/nladmin-system/nlsso-server/src/main/java/org/nl/common/lucene/YmlConfigFileUtil.java new file mode 100644 index 0000000..fdeb8e5 --- /dev/null +++ b/lms/nladmin-system/nlsso-server/src/main/java/org/nl/common/lucene/YmlConfigFileUtil.java @@ -0,0 +1,28 @@ +package org.nl.common.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; + } +} diff --git a/lms/nladmin-system/nlsso-server/src/main/java/org/nl/common/lucene/remote/AbstraceServer.java b/lms/nladmin-system/nlsso-server/src/main/java/org/nl/common/lucene/remote/AbstraceServer.java new file mode 100644 index 0000000..4c7f14b --- /dev/null +++ b/lms/nladmin-system/nlsso-server/src/main/java/org/nl/common/lucene/remote/AbstraceServer.java @@ -0,0 +1,45 @@ +package org.nl.common.lucene.remote; + +import io.netty.bootstrap.AbstractBootstrap; +import io.netty.channel.Channel; + +import java.net.SocketAddress; + +/* + * @author ZZQ + * @Date 2024/1/22 10:01 + */ +public abstract class AbstraceServer { + + + public AbstraceServer(SocketAddress address) { + this.address = address; + if (channel!=null){ + doDestroy(); + } + doOpen(); + doConnect(); + } + + public AbstractBootstrap server; + public SocketAddress address; + public Channel channel; + + public abstract void doOpen(); + + public void doDestroy(){ + if (channel!=null){ + channel.close(); + } + }; + + public abstract void doConnect() ; + + public void doDisConnect(){ + if (channel!=null){ + channel.close(); + channel.flush(); + doConnect(); + } + }; +} diff --git a/lms/nladmin-system/nlsso-server/src/main/java/org/nl/common/lucene/remote/RemoteLogServer.java b/lms/nladmin-system/nlsso-server/src/main/java/org/nl/common/lucene/remote/RemoteLogServer.java new file mode 100644 index 0000000..a87ec9d --- /dev/null +++ b/lms/nladmin-system/nlsso-server/src/main/java/org/nl/common/lucene/remote/RemoteLogServer.java @@ -0,0 +1,94 @@ +package org.nl.common.lucene.remote; + +import ch.qos.logback.classic.spi.ILoggingEvent; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import io.netty.util.CharsetUtil; +import lombok.SneakyThrows; +import org.apache.commons.lang3.StringUtils; +import org.nl.common.lucene.AsyncLuceneAppender; +import org.nl.common.lucene.remote.impl.ClientServer; +import org.nl.common.lucene.remote.impl.RemoteServer; +import org.nl.common.utils.MapOf; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.SmartLifecycle; +import org.springframework.data.redis.core.StringRedisTemplate; + +import java.net.Inet4Address; +import java.net.InetSocketAddress; +import java.util.HashMap; +import java.util.Map; + +/* + * @author ZZQ + * @Date 2024/1/22 09:06 + */ +//@Component +public class RemoteLogServer implements SmartLifecycle { + + @Autowired + private StringRedisTemplate redisTemplate; + + public static volatile Boolean LOCAL_LOG = Boolean.TRUE; + + private Integer port = 20888; + + public static AbstraceServer server; + + public static AsyncLuceneAppender asyncLuceneAppender; + + public static void writeLog(ILoggingEvent event){ + if (LOCAL_LOG){ + asyncLuceneAppender.appendSync(event); + }else { + ByteBuf log = Unpooled.copiedBuffer(JSON.toJSONString(event), CharsetUtil.UTF_8); + server.channel.writeAndFlush(log); + } + }; + + @SneakyThrows + @Override + public void start() { + try { + String provider = redisTemplate.opsForValue().get("providers"); + if (StringUtils.isEmpty(provider)){ + String ip = Inet4Address.getLocalHost().getHostAddress(); + Map config = MapOf.of("ip", ip, "port", port); + redisTemplate.opsForValue().set("provider", JSON.toJSONString(config)); + Runtime.getRuntime().addShutdownHook(new Thread(() ->{ + System.out.println("------服务关闭-升级从变主-------"); + server.doDestroy(); + redisTemplate.delete("providers"); + try { + Thread.sleep(5000); + }catch (Exception ex){} + })); + server = new RemoteServer(new InetSocketAddress(ip, port)); + LOCAL_LOG =Boolean.TRUE; + }else { + Map map = JSONObject.parseObject(provider, HashMap.class); + String ip = map.get("ip"); + Integer port = Integer.valueOf(map.get("port")); + server = new ClientServer(new InetSocketAddress(ip, port)); + LOCAL_LOG = Boolean.FALSE; + } + }catch (Exception ex){ + ex.printStackTrace(); + throw ex; + } + + + } + + @Override + public void stop() { + + } + + @Override + public boolean isRunning() { + return false; + } +} diff --git a/lms/nladmin-system/nlsso-server/src/main/java/org/nl/common/lucene/remote/coder/LogConsumerHandler.java b/lms/nladmin-system/nlsso-server/src/main/java/org/nl/common/lucene/remote/coder/LogConsumerHandler.java new file mode 100644 index 0000000..2c5f07b --- /dev/null +++ b/lms/nladmin-system/nlsso-server/src/main/java/org/nl/common/lucene/remote/coder/LogConsumerHandler.java @@ -0,0 +1,44 @@ +package org.nl.common.lucene.remote.coder; + +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelInboundHandlerAdapter; +import io.netty.handler.timeout.IdleStateEvent; +import org.nl.common.lucene.remote.RemoteLogServer; + +/* + * @author ZZQ + * @Date 2024/1/22 10:24 + */ +public class LogConsumerHandler extends ChannelInboundHandlerAdapter { + + @Override + public void channelInactive(ChannelHandlerContext ctx) throws Exception { + System.out.println("断开连接---"); + RemoteLogServer.LOCAL_LOG = Boolean.TRUE; + RemoteLogServer.server.doDestroy(); + //重新建立 + super.channelInactive(ctx); + } + + @Override + public void channelActive(ChannelHandlerContext ctx) throws Exception { + System.out.println("连接"); + super.channelActive(ctx); + } + + + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + System.out.println("接收到消息"); + super.channelRead(ctx, msg); + } + + @Override + public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { + if (evt instanceof IdleStateEvent){ + IdleStateEvent stateEvent = (IdleStateEvent) evt; + System.out.println(stateEvent.state()); + } + super.userEventTriggered(ctx, evt); + } +} diff --git a/lms/nladmin-system/nlsso-server/src/main/java/org/nl/common/lucene/remote/coder/LogProviderHandler.java b/lms/nladmin-system/nlsso-server/src/main/java/org/nl/common/lucene/remote/coder/LogProviderHandler.java new file mode 100644 index 0000000..f236330 --- /dev/null +++ b/lms/nladmin-system/nlsso-server/src/main/java/org/nl/common/lucene/remote/coder/LogProviderHandler.java @@ -0,0 +1,33 @@ +package org.nl.common.lucene.remote.coder; + +import ch.qos.logback.classic.spi.LoggingEvent; +import com.alibaba.fastjson.JSONObject; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.SimpleChannelInboundHandler; +import org.nl.common.lucene.remote.RemoteLogServer; + +/* + * @author ZZQ + * @Date 2024/1/22 10:24 + */ +public class LogProviderHandler extends SimpleChannelInboundHandler { + + @Override + public void channelInactive(ChannelHandlerContext ctx) throws Exception { + System.out.println("断开连接---"); + super.channelInactive(ctx); + } + + @Override + protected void channelRead0(ChannelHandlerContext ctx, String c){ + LoggingEvent event = JSONObject.parseObject(c, LoggingEvent.class); + RemoteLogServer.asyncLuceneAppender.appendSync(event); + } + + @Override + public void channelActive(ChannelHandlerContext ctx) throws Exception { + System.out.println("创建了连接----"); + super.channelActive(ctx); + } + +} diff --git a/lms/nladmin-system/nlsso-server/src/main/java/org/nl/common/lucene/remote/impl/ClientServer.java b/lms/nladmin-system/nlsso-server/src/main/java/org/nl/common/lucene/remote/impl/ClientServer.java new file mode 100644 index 0000000..2807924 --- /dev/null +++ b/lms/nladmin-system/nlsso-server/src/main/java/org/nl/common/lucene/remote/impl/ClientServer.java @@ -0,0 +1,76 @@ +package org.nl.common.lucene.remote.impl; + +import io.netty.bootstrap.Bootstrap; +import io.netty.buffer.PooledByteBufAllocator; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelOption; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.SocketChannel; +import io.netty.channel.socket.nio.NioSocketChannel; +import io.netty.handler.codec.LengthFieldPrepender; +import io.netty.handler.timeout.IdleStateHandler; +import io.netty.util.concurrent.Future; +import org.nl.common.lucene.remote.AbstraceServer; +import org.nl.common.lucene.remote.coder.LogConsumerHandler; + + +import java.net.SocketAddress; + +import static java.util.concurrent.TimeUnit.MILLISECONDS; + +/* + * @author ZZQ + * @Date 2024/1/22 10:01 + */ +public class ClientServer extends AbstraceServer { + + private static EventLoopGroup group = new NioEventLoopGroup(); + + public ClientServer(SocketAddress address) { + super(address); + } + + // 非阻塞IO线程组 + @Override + public void doOpen() { + server = new Bootstrap(); + server.group(group) + .option(ChannelOption.SO_KEEPALIVE, true) + .option(ChannelOption.TCP_NODELAY, true) + .option(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT) + .channel(NioSocketChannel.class); + + server.handler(new ChannelInitializer() { + @Override + protected void initChannel(SocketChannel ch) throws Exception { + ch.pipeline() + .addLast("client-idle-handler", new IdleStateHandler(500, 0,0 , MILLISECONDS)) + .addLast(new LengthFieldPrepender(2)) + .addLast( new LogConsumerHandler()); + } + }); + } + + @Override + public void doDestroy() { + super.doDestroy(); + Future bossGroupShutdownFuture = group.shutdownGracefully(); + bossGroupShutdownFuture.syncUninterruptibly(); + } + + @Override + public void doConnect() { + try { + ChannelFuture connect = ((Bootstrap) server).connect(address); + connect.syncUninterruptibly(); + channel = connect.channel(); + } catch (Throwable t) { + this.doDestroy(); + throw t; + } + } + + +} diff --git a/lms/nladmin-system/nlsso-server/src/main/java/org/nl/common/lucene/remote/impl/RemoteServer.java b/lms/nladmin-system/nlsso-server/src/main/java/org/nl/common/lucene/remote/impl/RemoteServer.java new file mode 100644 index 0000000..941a4ee --- /dev/null +++ b/lms/nladmin-system/nlsso-server/src/main/java/org/nl/common/lucene/remote/impl/RemoteServer.java @@ -0,0 +1,83 @@ +package org.nl.common.lucene.remote.impl; + +import io.netty.bootstrap.ServerBootstrap; +import io.netty.buffer.PooledByteBufAllocator; +import io.netty.channel.*; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.SocketChannel; +import io.netty.channel.socket.nio.NioServerSocketChannel; +import io.netty.handler.codec.LengthFieldBasedFrameDecoder; +import io.netty.handler.codec.LengthFieldPrepender; +import io.netty.handler.codec.string.StringDecoder; +import io.netty.handler.timeout.IdleStateHandler; +import io.netty.util.concurrent.Future; +import org.nl.common.lucene.remote.AbstraceServer; +import org.nl.common.lucene.remote.coder.LogProviderHandler; + +import java.net.SocketAddress; + +import static java.util.concurrent.TimeUnit.MILLISECONDS; + +/* + * @author ZZQ + * @Date 2024/1/22 10:01 + */ +public class RemoteServer extends AbstraceServer { + + private static EventLoopGroup boss = new NioEventLoopGroup(); + private static EventLoopGroup worker = new NioEventLoopGroup(); + + public RemoteServer(SocketAddress address) { + super(address); + } + + // 非阻塞IO线程组 + @Override + public void doOpen() { + ServerBootstrap bootstrap = new ServerBootstrap(); + bootstrap + .group(boss, worker) + .channel(NioServerSocketChannel.class) + .option(ChannelOption.SO_REUSEADDR, Boolean.TRUE) + .childOption(ChannelOption.TCP_NODELAY, Boolean.TRUE) + .childOption(ChannelOption.SO_KEEPALIVE, Boolean.TRUE) + .childOption(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT) + .childHandler(new ChannelInitializer() { + @Override + protected void initChannel(SocketChannel ch) throws Exception { + ch.pipeline() + .addLast("client-idle-handler", new IdleStateHandler(500, 0, 0, MILLISECONDS)) + .addLast(new LengthFieldBasedFrameDecoder(8089, 0, 2, 0, 2)) + .addLast(new LengthFieldPrepender(2)) + .addLast("encode",new StringDecoder()) + .addLast(new LogProviderHandler()); + } + }); + server = bootstrap; + } + + @Override + public void doDestroy(){ + Future bossGroupShutdownFuture = boss.shutdownGracefully(); + Future workerGroupShutdownFuture = worker.shutdownGracefully(); + bossGroupShutdownFuture.syncUninterruptibly(); + workerGroupShutdownFuture.syncUninterruptibly(); + } + + @Override + public void doConnect() { + ChannelFuture future = server.bind(address); + boolean ret = future.awaitUninterruptibly(3000, MILLISECONDS); + if (ret && future.isSuccess()) { + Channel newChannel = future.channel(); + if (channel != null) { + channel.close(); + channel = newChannel; + } + } else if (future.cause() != null) { + Throwable cause = future.cause(); + cause.printStackTrace(); + } + } + +} diff --git a/lms/nladmin-system/nlsso-server/src/main/java/org/nl/common/utils/BaseCode.java b/lms/nladmin-system/nlsso-server/src/main/java/org/nl/common/utils/BaseCode.java new file mode 100644 index 0000000..ab729b4 --- /dev/null +++ b/lms/nladmin-system/nlsso-server/src/main/java/org/nl/common/utils/BaseCode.java @@ -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; + } +} diff --git a/lms/nladmin-system/nlsso-server/src/main/java/org/nl/common/utils/IPUtil.java b/lms/nladmin-system/nlsso-server/src/main/java/org/nl/common/utils/IPUtil.java new file mode 100644 index 0000000..bb82737 --- /dev/null +++ b/lms/nladmin-system/nlsso-server/src/main/java/org/nl/common/utils/IPUtil.java @@ -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 interfaces = NetworkInterface.getNetworkInterfaces(); interfaces.hasMoreElements();) { + NetworkInterface anInterface = interfaces.nextElement(); + // 在所有的接口下再遍历IP + for (Enumeration 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; + } +} diff --git a/lms/nladmin-system/nlsso-server/src/main/java/org/nl/config/DruidFilter.java b/lms/nladmin-system/nlsso-server/src/main/java/org/nl/config/DruidFilter.java new file mode 100644 index 0000000..1c823d5 --- /dev/null +++ b/lms/nladmin-system/nlsso-server/src/main/java/org/nl/config/DruidFilter.java @@ -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 values = statement.getParameters().values(); + List 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 values = statement.getParameters().values(); + List 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; + } + + + + + +} diff --git a/lms/nladmin-system/nlsso-server/src/main/java/org/nl/system/logserver/LuceneLogController.java b/lms/nladmin-system/nlsso-server/src/main/java/org/nl/system/logserver/LuceneLogController.java new file mode 100644 index 0000000..9f9ffa3 --- /dev/null +++ b/lms/nladmin-system/nlsso-server/src/main/java/org/nl/system/logserver/LuceneLogController.java @@ -0,0 +1,69 @@ +package org.nl.system.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 labelsValues(@PathVariable String type) { + return new ResponseEntity<>(luceneLogService.getLabelsValues(type), HttpStatus.OK); + } + + @PostMapping("/query") + //("日志查询") + public ResponseEntity queryAll(@RequestBody LogQuery query) { + return new ResponseEntity<>(luceneLogService.query(query), HttpStatus.OK); + } + @DeleteMapping("/clearLogs") + //("清空日志") + public ResponseEntity clearLogs(@RequestBody LogQuery query) { + luceneLogService.clearLogs(query); + return new ResponseEntity<>(HttpStatus.OK); + } + + @GetMapping("/thread") + @SaIgnore + @Log("线程追踪测试") + //("清空日志") + public ResponseEntity 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); + } + +} diff --git a/lms/nladmin-system/nlsso-server/src/main/java/org/nl/system/service/logserver/LogQuery.java b/lms/nladmin-system/nlsso-server/src/main/java/org/nl/system/service/logserver/LogQuery.java new file mode 100644 index 0000000..67988c4 --- /dev/null +++ b/lms/nladmin-system/nlsso-server/src/main/java/org/nl/system/service/logserver/LogQuery.java @@ -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; +} diff --git a/lms/nladmin-system/nlsso-server/src/main/java/org/nl/system/service/logserver/LogRepositoryDTO.java b/lms/nladmin-system/nlsso-server/src/main/java/org/nl/system/service/logserver/LogRepositoryDTO.java new file mode 100644 index 0000000..0ca1d6d --- /dev/null +++ b/lms/nladmin-system/nlsso-server/src/main/java/org/nl/system/service/logserver/LogRepositoryDTO.java @@ -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; + +} diff --git a/lms/nladmin-system/nlsso-server/src/main/java/org/nl/system/service/logserver/LuceneLogService.java b/lms/nladmin-system/nlsso-server/src/main/java/org/nl/system/service/logserver/LuceneLogService.java new file mode 100644 index 0000000..0197ac8 --- /dev/null +++ b/lms/nladmin-system/nlsso-server/src/main/java/org/nl/system/service/logserver/LuceneLogService.java @@ -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(); +} diff --git a/lms/nladmin-system/nlsso-server/src/main/java/org/nl/system/service/logserver/LuceneLogServiceImpl.java b/lms/nladmin-system/nlsso-server/src/main/java/org/nl/system/service/logserver/LuceneLogServiceImpl.java new file mode 100644 index 0000000..b211892 --- /dev/null +++ b/lms/nladmin-system/nlsso-server/src/main/java/org/nl/system/service/logserver/LuceneLogServiceImpl.java @@ -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.common.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 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()); + } +} diff --git a/lms/nladmin-system/nlsso-server/src/main/resources/META-INF/druid-filter.properties b/lms/nladmin-system/nlsso-server/src/main/resources/META-INF/druid-filter.properties new file mode 100644 index 0000000..9b025c1 --- /dev/null +++ b/lms/nladmin-system/nlsso-server/src/main/resources/META-INF/druid-filter.properties @@ -0,0 +1 @@ +druid.filters.DruidFilter=org.nl.config.DruidFilter diff --git a/lms/nladmin-system/nlsso-server/src/main/resources/config/application-dev.yml b/lms/nladmin-system/nlsso-server/src/main/resources/config/application-dev.yml index 41f7cc3..4be8972 100644 --- a/lms/nladmin-system/nlsso-server/src/main/resources/config/application-dev.yml +++ b/lms/nladmin-system/nlsso-server/src/main/resources/config/application-dev.yml @@ -42,16 +42,8 @@ spring: enabled: true url-pattern: /druid/* reset-enable: false - filter: - stat: - enabled: true - # 记录慢SQL - log-slow-sql: true - slow-sql-millis: 1000 - merge-sql: true - wall: - config: - multi-statement-allow: true + filters: + DruidFilter,stat redis: #数据库索引 database: ${REDIS_DB:2} @@ -162,3 +154,6 @@ sa-token: password: # 连接超时时间 timeout: 10s +lucene: + index: + path: D:\lucene\index diff --git a/lms/nladmin-system/nlsso-server/src/main/resources/config/application-prod.yml b/lms/nladmin-system/nlsso-server/src/main/resources/config/application-prod.yml index 26c66b2..066d0f8 100644 --- a/lms/nladmin-system/nlsso-server/src/main/resources/config/application-prod.yml +++ b/lms/nladmin-system/nlsso-server/src/main/resources/config/application-prod.yml @@ -42,16 +42,8 @@ spring: enabled: true url-pattern: /druid/* reset-enable: false - filter: - stat: - enabled: true - # 记录慢SQL - log-slow-sql: true - slow-sql-millis: 1000 - merge-sql: true - wall: - config: - multi-statement-allow: true + filters: + DruidFilter,stat redis: #数据库索引 database: ${REDIS_DB:2} diff --git a/lms/nladmin-system/nlsso-server/src/main/resources/config/application-test.yml b/lms/nladmin-system/nlsso-server/src/main/resources/config/application-test.yml index 986a2f0..e5b2cab 100644 --- a/lms/nladmin-system/nlsso-server/src/main/resources/config/application-test.yml +++ b/lms/nladmin-system/nlsso-server/src/main/resources/config/application-test.yml @@ -41,16 +41,8 @@ spring: reset-enable: false login-username: admin login-password: 123456 - filter: - stat: - enabled: true - # 记录慢SQL - log-slow-sql: true - slow-sql-millis: 1000 - merge-sql: true - wall: - config: - multi-statement-allow: true + filters: + DruidFilter,stat redis: #数据库索引 database: ${REDIS_DB:15} diff --git a/lms/nladmin-system/nlsso-server/src/main/resources/config/application.yml b/lms/nladmin-system/nlsso-server/src/main/resources/config/application.yml index ce9b539..9796683 100644 --- a/lms/nladmin-system/nlsso-server/src/main/resources/config/application.yml +++ b/lms/nladmin-system/nlsso-server/src/main/resources/config/application.yml @@ -104,7 +104,7 @@ security: mybatis-plus: configuration: map-underscore-to-camel-case: false - log-impl: org.apache.ibatis.logging.stdout.StdOutImpl +# log-impl: org.apache.ibatis.logging.stdout.StdOutImpl mapper-locations: - classpath:org.nl.**.mapper/*.xml global-config: diff --git a/lms/nladmin-system/nlsso-server/src/main/resources/logback-spring.xml b/lms/nladmin-system/nlsso-server/src/main/resources/logback-spring.xml index 1691377..e63d766 100644 --- a/lms/nladmin-system/nlsso-server/src/main/resources/logback-spring.xml +++ b/lms/nladmin-system/nlsso-server/src/main/resources/logback-spring.xml @@ -1,24 +1,12 @@ - nlAdmin - - - - + @@ -27,18 +15,32 @@ https://juejin.cn/post/6844903775631572999 ${log.pattern} - - ${LOG_HOME}/%d{yyyy-MM-dd}.%i.log - 15 + 10 - 50MB + 100MB + + 20GB + + + + %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n + + + + + + ${LOG_HOME}/ErpLog/%d{yyyy-MM-dd}.%i.log + + 7 + + 100MB 20GB @@ -46,122 +48,121 @@ https://juejin.cn/post/6844903775631572999 %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n - - - 0 + 2 500 + + 2 + 500 + + + + + + system + lms + + + logLevel + %level + + + requestMethod + %X{requestMethod} + + + requestTime + %d{yyyy-MM-dd HH:mm:ss.SSS} + + + requestIp + %X{requestIp} + + + thread + %thread + + + logger + %logger + + + + + + 512 + + - + + - + - + - + - + - + - + - + - + - - - - - - - - - - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/lms/nladmin-ui/src/views/monitor/eslog/view/index.vue b/lms/nladmin-ui/src/views/monitor/eslog/view/index.vue new file mode 100644 index 0000000..37bdb7a --- /dev/null +++ b/lms/nladmin-ui/src/views/monitor/eslog/view/index.vue @@ -0,0 +1,417 @@ + + + + + diff --git a/lms/nladmin-ui/src/views/monitor/eslog/view/loki.js b/lms/nladmin-ui/src/views/monitor/eslog/view/loki.js new file mode 100644 index 0000000..8cc509d --- /dev/null +++ b/lms/nladmin-ui/src/views/monitor/eslog/view/loki.js @@ -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 } diff --git a/lms/nladmin-ui/src/views/monitor/log/errorLog.vue b/lms/nladmin-ui/src/views/monitor/log/errorLog.vue index fbee23f..30a7fb8 100644 --- a/lms/nladmin-ui/src/views/monitor/log/errorLog.vue +++ b/lms/nladmin-ui/src/views/monitor/log/errorLog.vue @@ -31,18 +31,18 @@ - - - - - + + + + + @@ -78,14 +78,14 @@ export default { add: false, edit: false, del: false, - download: false + download: true } }, methods: { // 获取异常详情 - info(log_id) { + info(id) { this.dialog = true - getErrDetail(log_id).then(res => { + getErrDetail(id).then(res => { this.errorInfo = res.exception }) }, diff --git a/lms/nladmin-ui/src/views/monitor/log/index.vue b/lms/nladmin-ui/src/views/monitor/log/index.vue index f37d57a..15d70fe 100644 --- a/lms/nladmin-ui/src/views/monitor/log/index.vue +++ b/lms/nladmin-ui/src/views/monitor/log/index.vue @@ -31,10 +31,10 @@ - - - - + + + + - + @@ -72,7 +72,7 @@ export default { add: false, edit: false, del: false, - download: false + download: true } }, methods: { diff --git a/lms/nladmin-ui/src/views/monitor/log/search.vue b/lms/nladmin-ui/src/views/monitor/log/search.vue index cc9f175..ffbcc06 100644 --- a/lms/nladmin-ui/src/views/monitor/log/search.vue +++ b/lms/nladmin-ui/src/views/monitor/log/search.vue @@ -3,7 +3,7 @@