add:luence日志

This commit is contained in:
zhangzq
2024-12-19 18:08:47 +08:00
parent 9754a58422
commit 57ce9b8421
34 changed files with 1987 additions and 157 deletions

View File

@@ -47,6 +47,11 @@
<artifactId>hutool-all</artifactId>
<version>${hutool.version}</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.20</version>
</dependency>
<!-- 日志链路追踪 https://tlog.yomahub.com/pages/f62a84/#%E5%90%8C%E6%AD%A5%E6%97%A5%E5%BF%97-->
<dependency>
@@ -199,11 +204,6 @@
</dependency>
<!--Mysql依赖包-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!-- druid数据源驱动 -->
<dependency>

View File

@@ -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("<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 "";
}
}
}

View File

@@ -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<String, String> 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);
}
}

View File

@@ -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";
}

View File

@@ -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<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"," ", 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;
}
}

View File

@@ -0,0 +1,23 @@
package org.nl.common.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);
}
}

View File

@@ -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();
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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();
}
};
}

View File

@@ -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<String,Object> 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<String,String> 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;
}
}

View File

@@ -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);
}
}

View File

@@ -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<String> {
@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);
}
}

View File

@@ -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<SocketChannel>() {
@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;
}
}
}

View File

@@ -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<SocketChannel>() {
@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();
}
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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<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);
}
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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();
}

View File

@@ -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表示andMUST_NOT表示notSHOULD表示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());
}
}

View File

@@ -0,0 +1 @@
druid.filters.DruidFilter=org.nl.config.DruidFilter

View File

@@ -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

View File

@@ -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}

View File

@@ -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}

View File

@@ -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:

View File

@@ -1,24 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--配置说明:
https://www.cnblogs.com/jybky/p/12204586.html
https://blog.csdn.net/wzygis/article/details/103189490
https://www.cnblogs.com/xrq730/p/8628945.html
https://www.jianshu.com/p/af5a7bab0e59
https://blog.csdn.net/wzygis/article/details/103189490
https://juejin.cn/post/6844903775631572999
-->
<configuration scan="true" scanPeriod="30 seconds" debug="false">
<contextName>nlAdmin</contextName>
<property name="log.charset" value="utf-8"/>
<property name="log.pattern"
value="%black(%contextName-) %red(%d{yyyy-MM-dd HH:mm:ss.SSS}) %green([%thread]) %highlight(%-5level) %boldMagenta(%logger{36}) - %gray(%msg%n)"/>
<springProperty scope="context" name="logPath" source="logging.file.path" defaultValue="logs"/>
<property name="LOG_HOME" value="${logPath}"/>
<!--引入默认的一些设置-->
<!--<include resource="log/XrToMes.xml"/>
<include resource="log/MesToErp.xml"/>-->
<!-- <include resource="log/XgAgvDeviceDriver.xml"/>-->
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<!-- 控制台高亮-->
@@ -27,18 +15,32 @@ https://juejin.cn/post/6844903775631572999
<pattern>${log.pattern}</pattern>
</encoder>
</appender>
<!--定义日志文件的存储地址 勿在 LogBack 的配置中使用相对路径-->
<property name="LOG_HOME" value="${logPath}"/>
<!-- 按照每天生成日志文件 -->
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<!--日志文件输出的文件名-->
<FileNamePattern>${LOG_HOME}/%d{yyyy-MM-dd}.%i.log</FileNamePattern>
<!--日志文件保留天数-->
<maxHistory>15</maxHistory>
<maxHistory>10</maxHistory>
<!--单个日志最大容量 至少10MB才能看得出来-->
<maxFileSize>50MB</maxFileSize>
<maxFileSize>100MB</maxFileSize>
<!--所有日志最多占多大容量-->
<totalSizeCap>20GB</totalSizeCap>
</rollingPolicy>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!--格式化输出:%d表示日期%thread表示线程名%-5level级别从左显示5个字符宽度%msg日志消息%n是换行符-->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
</encoder>
</appender>
<appender name="ErpLogFile" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<!--日志文件输出的文件名-->
<FileNamePattern>${LOG_HOME}/ErpLog/%d{yyyy-MM-dd}.%i.log</FileNamePattern>
<!--日志文件保留天数-->
<maxHistory>7</maxHistory>
<!--单个日志最大容量 至少10MB才能看得出来-->
<maxFileSize>100MB</maxFileSize>
<!--所有日志最多占多大容量-->
<totalSizeCap>20GB</totalSizeCap>
</rollingPolicy>
@@ -46,122 +48,121 @@ https://juejin.cn/post/6844903775631572999
<!--格式化输出:%d表示日期%thread表示线程名%-5level级别从左显示5个字符宽度%msg日志消息%n是换行符-->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
</encoder>
</appender>
<!--异步到文件-->
<appender name="asyncFileAppender" class="com.yomahub.tlog.core.enhance.logback.async.AspectLogbackAsyncAppender">
<discardingThreshold>0</discardingThreshold>
<discardingThreshold>2</discardingThreshold>
<queueSize>500</queueSize>
<appender-ref ref="FILE"/>
</appender>
<appender name="asyncERPFileAppender" class="ch.qos.logback.classic.AsyncAppender">
<discardingThreshold>2</discardingThreshold>
<queueSize>500</queueSize>
<appender-ref ref="ErpLogFile"/>
</appender>
<appender name="luceneAppender" class="org.nl.common.lucene.LuceneAppender" >
<properties>
<property>
<name>system</name>
<value>lms</value>
</property>
<property>
<name>logLevel</name>
<value>%level</value>
</property>
<property>
<name>requestMethod</name>
<value>%X{requestMethod}</value>
</property>
<property>
<name>requestTime</name>
<value>%d{yyyy-MM-dd HH:mm:ss.SSS}</value>
</property>
<property>
<name>requestIp</name>
<value>%X{requestIp}</value>
</property>
<property>
<name>thread</name>
<value>%thread</value>
</property>
<property>
<name>logger</name>
<value>%logger</value>
</property>
</properties>
</appender>
<appender name="asyncLuceneAppender" class="org.nl.common.lucene.AsyncLuceneAppender">
<appender-ref ref="luceneAppender" />
<queueSize>512</queueSize>
</appender>
<!--开发环境:打印控制台-->
<springProfile name="dev">
<root level="debug">
<root level="info">
<appender-ref ref="asyncLuceneAppender"/>
<appender-ref ref="CONSOLE"/>
</root>
<logger name="org.springframework" level="ERROR" additivity="false">
<logger name="jdbc" level="ERROR" additivity="true">
<appender-ref ref="asyncFileAppender"/>
</logger>
<logger name="org.apache" level="ERROR" additivity="false">
<logger name="com.yomahub.tlog.web.interceptor.TLogWebInvokeTimeInterceptor" level="ERROR" additivity="true">
<appender-ref ref="asyncFileAppender"/>
</logger>
<logger name="org.hibernate" level="ERROR" additivity="false">
<logger name="org.springframework" level="ERROR" additivity="true">
<appender-ref ref="asyncFileAppender"/>
</logger>
<logger name="io.netty" level="ERROR" additivity="false">
<logger name="org.hibernate" level="ERROR" additivity="true">
<appender-ref ref="asyncFileAppender"/>
</logger>
<logger name="jdbc" level="ERROR" additivity="false">
<logger name="org.quartz" level="ERROR" additivity="true">
<appender-ref ref="asyncFileAppender"/>
</logger>
<logger name="io.lettuce" level="ERROR" additivity="false">
<logger name="com.google" level="ERROR" additivity="true">
<appender-ref ref="asyncFileAppender"/>
</logger>
<logger name="com.fasterxml" level="ERROR" additivity="false">
<logger name="org.redisson" level="ERROR" additivity="true">
<appender-ref ref="asyncFileAppender"/>
</logger>
<logger name="org.quartz" level="ERROR" additivity="false">
<logger name="org.nl.modules.wql" level="ERROR" additivity="true">
<appender-ref ref="asyncFileAppender"/>
</logger>
<logger name="com.google" level="ERROR" additivity="false">
<appender-ref ref="asyncFileAppender"/>
</logger>
<logger name="springfox" level="ERROR" additivity="false">
<appender-ref ref="asyncFileAppender"/>
</logger>
<logger name="log4jdbc" level="ERROR" additivity="false">
<appender-ref ref="asyncFileAppender"/>
</logger>
<logger name="nl.basjes" level="ERROR" additivity="false">
<logger name="org.springframework.data" level="ERROR" additivity="true">
<appender-ref ref="asyncFileAppender"/>
</logger>
</springProfile>
<springProfile name="prod">
<root level="info">
<appender-ref ref="asyncLuceneAppender"/>
<appender-ref ref="CONSOLE"/>
</root>
<logger name="jdbc" level="ERROR" additivity="true">
<appender-ref ref="asyncFileAppender"/>
</logger>
<logger name="org.springframework" level="ERROR" additivity="true">
<appender-ref ref="asyncFileAppender"/>
</logger>
<logger name="org.hibernate" level="ERROR" additivity="true">
<appender-ref ref="asyncFileAppender"/>
</logger>
<logger name="org.quartz" level="ERROR" additivity="true">
<appender-ref ref="asyncFileAppender"/>
</logger>
<logger name="com.google" level="ERROR" additivity="true">
<appender-ref ref="asyncFileAppender"/>
</logger>
<logger name="org.redisson" level="ERROR" additivity="true">
<appender-ref ref="asyncFileAppender"/>
</logger>
<logger name="org.nl.modules.wql" level="ERROR" additivity="true">
<appender-ref ref="asyncFileAppender"/>
</logger>
<logger name="org.springframework.data" level="ERROR" additivity="true">
<appender-ref ref="asyncFileAppender"/>
</logger>
</springProfile>
<!--测试环境:打印控制台-->
<!--生产环境:打印控制台和输出到文件-->
<springProfile name="prod">
<root level="debug">
<appender-ref ref="asyncFileAppender"/>
</root>
<logger name="org.springframework" level="ERROR" additivity="false">
<appender-ref ref="asyncFileAppender"/>
</logger>
<logger name="org.apache" level="ERROR" additivity="false">
<appender-ref ref="asyncFileAppender"/>
</logger>
<logger name="org.hibernate" level="ERROR" additivity="false">
<appender-ref ref="asyncFileAppender"/>
</logger>
<logger name="io.netty" level="ERROR" additivity="false">
<appender-ref ref="asyncFileAppender"/>
</logger>
<logger name="jdbc" level="ERROR" additivity="false">
<appender-ref ref="asyncFileAppender"/>
</logger>
<logger name="io.lettuce" level="ERROR" additivity="false">
<appender-ref ref="asyncFileAppender"/>
</logger>
<logger name="com.fasterxml" level="ERROR" additivity="false">
<appender-ref ref="asyncFileAppender"/>
</logger>
<logger name="org.quartz" level="ERROR" additivity="false">
<appender-ref ref="asyncFileAppender"/>
</logger>
<logger name="com.google" level="ERROR" additivity="false">
<appender-ref ref="asyncFileAppender"/>
</logger>
<logger name="springfox" level="ERROR" additivity="false">
<appender-ref ref="asyncFileAppender"/>
</logger>
<logger name="log4jdbc" level="ERROR" additivity="false">
<appender-ref ref="asyncFileAppender"/>
</logger>
<logger name="nl.basjes" level="ERROR" additivity="false">
<appender-ref ref="asyncFileAppender"/>
</logger>
</springProfile>
<!--测试环境:打印控制台-->
<springProfile name="test">
<root level="info">
<appender-ref ref="asyncFileAppender"/>
</root>
<logger name="jdbc.audit" level="ERROR" additivity="false">
<appender-ref ref="CONSOLE"/>
</logger>
<logger name="jdbc.resultset" level="ERROR" additivity="false">
<appender-ref ref="CONSOLE"/>
</logger>
<logger name="springfox.documentation" level="ERROR" additivity="false">
<appender-ref ref="CONSOLE"/>
</logger>
<logger name="jdbc.resultsettable" level="ERROR" additivity="false">
<appender-ref ref="CONSOLE"/>
</logger>
<logger name="jdbc.sqlonly" level="ERROR" additivity="false">
<appender-ref ref="CONSOLE"/>
</logger>
</springProfile>
</configuration>