feat: 新增es日志前端,可不通过grafana

This commit is contained in:
2025-05-29 15:51:37 +08:00
parent 1556317547
commit df112f4e43
15 changed files with 980 additions and 615 deletions

View File

@@ -27,11 +27,22 @@
<jjwt.version>0.11.1</jjwt.version>
<!-- oshi监控需要指定jna版本, 问题详见 https://github.com/oshi/oshi/issues/1040 -->
<jna.version>5.9.0</jna.version>
<lucene.version>8.2.0</lucene.version>
<!-- <lucene.version>8.2.0</lucene.version>-->
<configuration.version>1.9</configuration.version>
</properties>
<dependencies>
<!--spring boot 整合 elasticsearch -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
<exclusions>
<exclusion>
<artifactId>HdrHistogram</artifactId>
<groupId>org.hdrhistogram</groupId>
</exclusion>
</exclusions>
</dependency>
<!-- logback appender日志-->
<dependency>
<groupId>com.internetitem</groupId>
@@ -438,39 +449,39 @@
</dependency>
<!-- Lucence核心包 -->
<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-core</artifactId>
<version>${lucene.version}</version>
</dependency>
<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-highlighter</artifactId>
<version>${lucene.version}</version>
</dependency>
<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-analyzers-common</artifactId>
<version>${lucene.version}</version>
</dependency>
<dependency>
<groupId>com.github.magese</groupId>
<artifactId>ik-analyzer</artifactId>
<version>${lucene.version}</version>
</dependency>
<!-- <dependency>-->
<!-- <groupId>org.apache.lucene</groupId>-->
<!-- <artifactId>lucene-core</artifactId>-->
<!-- <version>${lucene.version}</version>-->
<!-- </dependency>-->
<!-- <dependency>-->
<!-- <groupId>org.apache.lucene</groupId>-->
<!-- <artifactId>lucene-highlighter</artifactId>-->
<!-- <version>${lucene.version}</version>-->
<!-- </dependency>-->
<!-- <dependency>-->
<!-- <groupId>org.apache.lucene</groupId>-->
<!-- <artifactId>lucene-analyzers-common</artifactId>-->
<!-- <version>${lucene.version}</version>-->
<!-- </dependency>-->
<!-- <dependency>-->
<!-- <groupId>com.github.magese</groupId>-->
<!-- <artifactId>ik-analyzer</artifactId>-->
<!-- <version>${lucene.version}</version>-->
<!-- </dependency>-->
<!--支持中文分词 -->
<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-analyzers-smartcn</artifactId>
<version>${lucene.version}</version>
</dependency>
<!-- Lucene查询解析包 -->
<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-queryparser</artifactId>
<version>${lucene.version}</version>
</dependency>
<!-- &lt;!&ndash;支持中文分词 &ndash;&gt;-->
<!-- <dependency>-->
<!-- <groupId>org.apache.lucene</groupId>-->
<!-- <artifactId>lucene-analyzers-smartcn</artifactId>-->
<!-- <version>${lucene.version}</version>-->
<!-- </dependency>-->
<!-- &lt;!&ndash; Lucene查询解析包 &ndash;&gt;-->
<!-- <dependency>-->
<!-- <groupId>org.apache.lucene</groupId>-->
<!-- <artifactId>lucene-queryparser</artifactId>-->
<!-- <version>${lucene.version}</version>-->
<!-- </dependency>-->
<!--redisson-->
<dependency>
<groupId>org.redisson</groupId>

View File

@@ -5,6 +5,8 @@ import lombok.extern.slf4j.Slf4j;
import org.dromara.dynamictp.core.spring.EnableDynamicTp;
import org.mybatis.spring.annotation.MapperScan;
import org.nl.config.SpringContextHolder;
import org.nl.config.lucene.TagNameEnum;
import org.slf4j.MDC;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.SpringApplication;
@@ -35,6 +37,7 @@ import org.springframework.web.bind.annotation.RestController;
public class AppRun implements ApplicationRunner {
public static void main(String[] args) {
log.info("Application starting...");
SpringApplication.run(AppRun.class, args);
}
@@ -56,6 +59,7 @@ public class AppRun implements ApplicationRunner {
@Override
public void run(ApplicationArguments args) throws Exception {
MDC.put("tag", TagNameEnum.LMS.getTag());
log.info("noblelift - 项目启动成功!");
System.out.println("项目启动成功!");
}

View File

@@ -1,110 +1,110 @@
package org.nl.config.lucene;
/**
* @author ldjun
* @version 1.0
* @date 2023年08月24日 13:00
* @desc desc
*/
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.AppenderBase;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
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.springframework.beans.factory.config.YamlPropertiesFactoryBean;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.wltea.analyzer.lucene.IKAnalyzer;
import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.nio.file.Paths;
import java.util.Map;
import java.util.Properties;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class LuceneAppender extends AppenderBase<ILoggingEvent> {
private static Directory index;
public static IndexWriter indexWriter;
@Override
public void start() {
super.start();
try {
init();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void init() throws IOException {
Resource resource = new ClassPathResource("config/application.yml");
YamlPropertiesFactoryBean yamlPropertiesFactoryBean = new YamlPropertiesFactoryBean();
yamlPropertiesFactoryBean.setResources(resource);
Properties properties = yamlPropertiesFactoryBean.getObject();
// 获取配置值
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);
}
@Override
protected void append(ILoggingEvent event) {
String message = event.getFormattedMessage();
Map<String, String> mdcPropertyMap = event.getMDCPropertyMap();
Document doc = new Document();
long timeStamp = event.getTimeStamp();
// 获取本机的IP地址
String ipAddress = "-";
try {
ipAddress = InetAddress.getLocalHost().getHostAddress();
} catch (UnknownHostException e) {
throw new RuntimeException(e);
}
String formattedDateTime = DateUtil.format(new java.util.Date(timeStamp), "yyyy-MM-dd HH:mm:ss.SSS");
doc.add(new LongPoint(LogMessageConstant.FIELD_SORT_NAME, timeStamp));
doc.add(new NumericDocValuesField(LogMessageConstant.FIELD_SORT_NAME, timeStamp));
doc.add(new StringField(LogMessageConstant.FIELD_LEVEL, event.getLevel().toString(), Field.Store.YES));
doc.add(new StringField(LogMessageConstant.FIELD_TIMESTAMP, formattedDateTime, Field.Store.YES));
doc.add(new StoredField(LogMessageConstant.FIELD_CLASS_NAME, event.getLoggerName()));
doc.add(new StoredField(LogMessageConstant.FIELD_IP, ipAddress));
doc.add(new StoredField(LogMessageConstant.FIELD_THREAD, event.getThreadName()));
if (ObjectUtil.isNotEmpty(mdcPropertyMap) && ObjectUtil.isNotEmpty(mdcPropertyMap.get(LogMessageConstant.FIELD_TRACEID))) {
String traceId = mdcPropertyMap.get(LogMessageConstant.FIELD_TRACEID);
doc.add(new StringField(LogMessageConstant.FIELD_TRACEID, traceId, Field.Store.YES));
doc.add(new StringField(LogMessageConstant.FIELD_LABEL, ObjectUtil.isNotEmpty(mdcPropertyMap.get("tag_name"))
? mdcPropertyMap.get("tag_name") : "-", Field.Store.YES));
}
doc.add(new TextField(LogMessageConstant.FIELD_MESSAGE, message, Field.Store.YES));
try {
indexWriter.addDocument(doc);
indexWriter.commit();
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void stop() {
super.stop();
try {
indexWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
//package org.nl.config.lucene;
///**
// * @author ldjun
// * @version 1.0
// * @date 2023年08月24日 13:00
// * @desc desc
// */
//
//import ch.qos.logback.classic.spi.ILoggingEvent;
//import ch.qos.logback.core.AppenderBase;
//import cn.hutool.core.date.DateUtil;
//import cn.hutool.core.util.ObjectUtil;
//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.springframework.beans.factory.config.YamlPropertiesFactoryBean;
//import org.springframework.core.io.ClassPathResource;
//import org.springframework.core.io.Resource;
//import org.wltea.analyzer.lucene.IKAnalyzer;
//
//import java.io.IOException;
//import java.net.InetAddress;
//import java.net.UnknownHostException;
//import java.nio.file.Paths;
//import java.util.Map;
//import java.util.Properties;
//import java.util.regex.Matcher;
//import java.util.regex.Pattern;
//
//public class LuceneAppender extends AppenderBase<ILoggingEvent> {
//
// private static Directory index;
// public static IndexWriter indexWriter;
//
//
// @Override
// public void start() {
// super.start();
// try {
// init();
// } catch (Exception e) {
// e.printStackTrace();
// }
// }
//
// public static void init() throws IOException {
// Resource resource = new ClassPathResource("config/application.yml");
// YamlPropertiesFactoryBean yamlPropertiesFactoryBean = new YamlPropertiesFactoryBean();
// yamlPropertiesFactoryBean.setResources(resource);
// Properties properties = yamlPropertiesFactoryBean.getObject();
// // 获取配置值
// 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);
// }
//
//
// @Override
// protected void append(ILoggingEvent event) {
// String message = event.getFormattedMessage();
// Map<String, String> mdcPropertyMap = event.getMDCPropertyMap();
// Document doc = new Document();
// long timeStamp = event.getTimeStamp();
// // 获取本机的IP地址
// String ipAddress = "-";
// try {
// ipAddress = InetAddress.getLocalHost().getHostAddress();
// } catch (UnknownHostException e) {
// throw new RuntimeException(e);
// }
// String formattedDateTime = DateUtil.format(new java.util.Date(timeStamp), "yyyy-MM-dd HH:mm:ss.SSS");
// doc.add(new LongPoint(LogMessageConstant.FIELD_SORT_NAME, timeStamp));
// doc.add(new NumericDocValuesField(LogMessageConstant.FIELD_SORT_NAME, timeStamp));
// doc.add(new StringField(LogMessageConstant.FIELD_LEVEL, event.getLevel().toString(), Field.Store.YES));
// doc.add(new StringField(LogMessageConstant.FIELD_TIMESTAMP, formattedDateTime, Field.Store.YES));
// doc.add(new StoredField(LogMessageConstant.FIELD_CLASS_NAME, event.getLoggerName()));
// doc.add(new StoredField(LogMessageConstant.FIELD_IP, ipAddress));
// doc.add(new StoredField(LogMessageConstant.FIELD_THREAD, event.getThreadName()));
// if (ObjectUtil.isNotEmpty(mdcPropertyMap) && ObjectUtil.isNotEmpty(mdcPropertyMap.get(LogMessageConstant.FIELD_TRACEID))) {
// String traceId = mdcPropertyMap.get(LogMessageConstant.FIELD_TRACEID);
// doc.add(new StringField(LogMessageConstant.FIELD_TRACEID, traceId, Field.Store.YES));
// doc.add(new StringField(LogMessageConstant.FIELD_LABEL, ObjectUtil.isNotEmpty(mdcPropertyMap.get("tag_name"))
// ? mdcPropertyMap.get("tag_name") : "-", Field.Store.YES));
// }
// doc.add(new TextField(LogMessageConstant.FIELD_MESSAGE, message, Field.Store.YES));
// try {
// indexWriter.addDocument(doc);
// indexWriter.commit();
// } catch (IOException e) {
// e.printStackTrace();
// }
// }
//
// @Override
// public void stop() {
// super.stop();
// try {
// indexWriter.close();
// } catch (IOException e) {
// e.printStackTrace();
// }
// }
//}

View File

@@ -1,164 +1,164 @@
package org.nl.config.lucene;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.Term;
import org.apache.lucene.queryparser.classic.QueryParser;
import org.apache.lucene.search.*;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.util.BytesRef;
import org.wltea.analyzer.lucene.IKAnalyzer;
import java.io.IOException;
import java.nio.file.Paths;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.temporal.ChronoUnit;
import java.util.*;
/**
* lucene查询器
*/
@Slf4j
public class Searcher {
public static Map<String, Object> search(String indexDir, JSONObject whereJson) throws Exception {
//获取要查询的路径,也就是索引所在的位置
Directory dir = FSDirectory.open(Paths.get(indexDir));
IndexReader reader = DirectoryReader.open(dir);
//构建IndexSearcher
IndexSearcher searcher = new IndexSearcher(reader);
//标准分词器会自动去掉空格啊is a the等单词
Analyzer analyzer = new IKAnalyzer(true);
// 实际上Lucene本身不支持分页。因此我们需要自己进行逻辑分页。我们要准备分页参数
// 每页条数
int pageSize = Integer.parseInt(whereJson.get("size").toString());
// 当前页码
int pageNum = Integer.parseInt(whereJson.get("page").toString()) - 1;
// 当前页的起始条数
int start = pageNum * pageSize;
// 当前页的结束条数(不能包含)
int end = start + pageSize;
// 创建排序对象,需要排序字段SortField参数字段的名称、字段的类型、是否反转如果是false升序。true降序
Sort sort = new Sort(new SortField(LogMessageConstant.FIELD_SORT_NAME, SortField.Type.LONG, true));
TopDocs docs = null;
BooleanQuery.Builder booleanQueryBuilder = new BooleanQuery.Builder();
Calendar calendar = Calendar.getInstance();
calendar.set(1970, 0, 1);
//时间范围查询
JSONArray createTime = whereJson.getJSONArray("createTime");
String startDate = DateUtil.format(calendar.getTime(), "yyyy-MM-dd HH:mm:ss.SSS");
String endDate = DateUtil.format(new DateTime(), "yyyy-MM-dd HH:mm:ss.SSS");
if (createTime != null) {
startDate = createTime.getString(0);
endDate = createTime.getString(1);
}
// 字段之间的与或非关系MUST表示andMUST_NOT表示notSHOULD表示or有几个fields就必须有几个clauses
TermRangeQuery termRangeQuery = new TermRangeQuery("timestamp", new BytesRef(startDate),
new BytesRef(endDate), true, true);
booleanQueryBuilder.add(termRangeQuery, BooleanClause.Occur.MUST);
if (ObjectUtil.isNotEmpty(whereJson.get(LogMessageConstant.FIELD_MESSAGE))) {
//查询解析器
QueryParser queryParser = new QueryParser("message", analyzer);
Query query = queryParser.parse("message:" + whereJson.getString("message") + "~");
booleanQueryBuilder.add(query, BooleanClause.Occur.MUST);
}
if (ObjectUtil.isNotEmpty(whereJson.get(LogMessageConstant.FIELD_TRACEID))) {
//查询解析器
TermQuery termQuery = new TermQuery(new Term(LogMessageConstant.FIELD_TRACEID,
whereJson.getString(LogMessageConstant.FIELD_TRACEID).trim()));
booleanQueryBuilder.add(termQuery, BooleanClause.Occur.MUST);
}
if (ObjectUtil.isNotEmpty(whereJson.get(LogMessageConstant.FIELD_LABEL))) {
//查询解析器
TermQuery termQuery = new TermQuery(new Term(LogMessageConstant.FIELD_LABEL,
whereJson.getString(LogMessageConstant.FIELD_LABEL).trim()));
booleanQueryBuilder.add(termQuery, BooleanClause.Occur.MUST);
}
if (ObjectUtil.isNotEmpty(whereJson.get(LogMessageConstant.FIELD_LEVEL))) {
//查询解析器
TermQuery termQuery = new TermQuery(new Term(LogMessageConstant.FIELD_LEVEL,
whereJson.get(LogMessageConstant.FIELD_LEVEL).toString()));
booleanQueryBuilder.add(termQuery, BooleanClause.Occur.MUST);
}
// 使用实体接收
List<String> list = new ArrayList<>();
TopFieldCollector collector = TopFieldCollector.create(sort, 20000, 0);
searcher.search(booleanQueryBuilder.build(), collector);
docs = collector.topDocs(pageNum*pageSize, pageSize);
ScoreDoc[] scoreDocs = docs.scoreDocs;
int totalSize = collector.getTotalHits();
for (ScoreDoc scoreDoc : scoreDocs) {
Document doc = reader.document(scoreDoc.doc);
String logInfo = LogMessageConstant.COLOR_RED + doc.get(LogMessageConstant.FIELD_TIMESTAMP) +
LogMessageConstant.COLOR_RESET + " - " +
LogMessageConstant.COLOR_BLUE + doc.get(LogMessageConstant.FIELD_IP) +
LogMessageConstant.COLOR_RESET + " - " +
LogMessageConstant.COLOR_GREEN + "[" + doc.get(LogMessageConstant.FIELD_THREAD) + "]" +
LogMessageConstant.COLOR_RESET + " - " +
LogMessageConstant.COLOR_BLACK + doc.get(LogMessageConstant.FIELD_LEVEL) +
LogMessageConstant.COLOR_RESET + " - " +
LogMessageConstant.COLOR_MAGENTA + doc.get(LogMessageConstant.FIELD_CLASS_NAME) +
LogMessageConstant.COLOR_RESET + " - " +
LogMessageConstant.COLOR_GREEN + "<" + doc.get(LogMessageConstant.FIELD_TRACEID) + ">" +
LogMessageConstant.COLOR_RESET + " - " +
LogMessageConstant.COLOR_BLACK + highlightKeyword(doc.get(LogMessageConstant.FIELD_MESSAGE), whereJson.getString("message"));
list.add(logInfo);
}
reader.close();
JSONObject jo = new JSONObject();
jo.put("content", list);
jo.put("totalElements", totalSize);
return jo;
}
public static String highlightKeyword(String text, String keyword) {
if (ObjectUtil.isEmpty(keyword)) {
return text;
}
int startIndex = text.indexOf(keyword);
if (startIndex != -1) {
int endIndex = startIndex + keyword.length();
String beforeKeyword = text.substring(0, startIndex);
String afterKeyword = text.substring(endIndex);
String highlightedKeyword = LogMessageConstant.BACKGROUND_YELLOW + keyword + LogMessageConstant.COLOR_RESET
+ LogMessageConstant.COLOR_BLACK;
return beforeKeyword + highlightedKeyword + afterKeyword;
} else {
return text;
}
}
public static void main(String[] args) throws IOException, ParseException {
// 获取当前时间
LocalDateTime now = LocalDateTime.now();
// 减去七天
LocalDateTime sevenDaysAgo = now.minus(7, ChronoUnit.DAYS);
// 转换为 Date 类型
Date sevenDaysAgoDate = Date.from(sevenDaysAgo.atZone(ZoneId.systemDefault()).toInstant());
// 获取时间戳
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS");
Date date = dateFormat.parse(String.valueOf(sevenDaysAgo));
long timestamp = date.getTime();
System.out.println(now);
System.out.println(sevenDaysAgo);
System.out.println(sevenDaysAgoDate);
System.out.println(timestamp);
}
}
//package org.nl.config.lucene;
//
//import cn.hutool.core.date.DateTime;
//import cn.hutool.core.date.DateUtil;
//import cn.hutool.core.util.ObjectUtil;
//import com.alibaba.fastjson.JSONArray;
//import com.alibaba.fastjson.JSONObject;
//import lombok.extern.slf4j.Slf4j;
//import org.apache.lucene.analysis.Analyzer;
//import org.apache.lucene.document.Document;
//import org.apache.lucene.index.DirectoryReader;
//import org.apache.lucene.index.IndexReader;
//import org.apache.lucene.index.Term;
//import org.apache.lucene.queryparser.classic.QueryParser;
//import org.apache.lucene.search.*;
//import org.apache.lucene.store.Directory;
//import org.apache.lucene.store.FSDirectory;
//import org.apache.lucene.util.BytesRef;
//import org.wltea.analyzer.lucene.IKAnalyzer;
//
//import java.io.IOException;
//import java.nio.file.Paths;
//import java.text.ParseException;
//import java.text.SimpleDateFormat;
//import java.time.LocalDateTime;
//import java.time.ZoneId;
//import java.time.temporal.ChronoUnit;
//import java.util.*;
//
///**
// * lucene查询器
// */
//@Slf4j
//public class Searcher {
//
// public static Map<String, Object> search(String indexDir, JSONObject whereJson) throws Exception {
// //获取要查询的路径,也就是索引所在的位置
// Directory dir = FSDirectory.open(Paths.get(indexDir));
// IndexReader reader = DirectoryReader.open(dir);
// //构建IndexSearcher
// IndexSearcher searcher = new IndexSearcher(reader);
// //标准分词器会自动去掉空格啊is a the等单词
// Analyzer analyzer = new IKAnalyzer(true);
//
// // 实际上Lucene本身不支持分页。因此我们需要自己进行逻辑分页。我们要准备分页参数
// // 每页条数
// int pageSize = Integer.parseInt(whereJson.get("size").toString());
// // 当前页码
// int pageNum = Integer.parseInt(whereJson.get("page").toString()) - 1;
// // 当前页的起始条数
// int start = pageNum * pageSize;
// // 当前页的结束条数(不能包含)
// int end = start + pageSize;
// // 创建排序对象,需要排序字段SortField参数字段的名称、字段的类型、是否反转如果是false升序。true降序
// Sort sort = new Sort(new SortField(LogMessageConstant.FIELD_SORT_NAME, SortField.Type.LONG, true));
//
// TopDocs docs = null;
// BooleanQuery.Builder booleanQueryBuilder = new BooleanQuery.Builder();
// Calendar calendar = Calendar.getInstance();
// calendar.set(1970, 0, 1);
// //时间范围查询
// JSONArray createTime = whereJson.getJSONArray("createTime");
// String startDate = DateUtil.format(calendar.getTime(), "yyyy-MM-dd HH:mm:ss.SSS");
// String endDate = DateUtil.format(new DateTime(), "yyyy-MM-dd HH:mm:ss.SSS");
//
// if (createTime != null) {
// startDate = createTime.getString(0);
// endDate = createTime.getString(1);
// }
// // 字段之间的与或非关系MUST表示andMUST_NOT表示notSHOULD表示or有几个fields就必须有几个clauses
// TermRangeQuery termRangeQuery = new TermRangeQuery("timestamp", new BytesRef(startDate),
// new BytesRef(endDate), true, true);
// booleanQueryBuilder.add(termRangeQuery, BooleanClause.Occur.MUST);
// if (ObjectUtil.isNotEmpty(whereJson.get(LogMessageConstant.FIELD_MESSAGE))) {
// //查询解析器
// QueryParser queryParser = new QueryParser("message", analyzer);
// Query query = queryParser.parse("message:" + whereJson.getString("message") + "~");
// booleanQueryBuilder.add(query, BooleanClause.Occur.MUST);
// }
// if (ObjectUtil.isNotEmpty(whereJson.get(LogMessageConstant.FIELD_TRACEID))) {
// //查询解析器
// TermQuery termQuery = new TermQuery(new Term(LogMessageConstant.FIELD_TRACEID,
// whereJson.getString(LogMessageConstant.FIELD_TRACEID).trim()));
// booleanQueryBuilder.add(termQuery, BooleanClause.Occur.MUST);
// }
// if (ObjectUtil.isNotEmpty(whereJson.get(LogMessageConstant.FIELD_LABEL))) {
// //查询解析器
// TermQuery termQuery = new TermQuery(new Term(LogMessageConstant.FIELD_LABEL,
// whereJson.getString(LogMessageConstant.FIELD_LABEL).trim()));
// booleanQueryBuilder.add(termQuery, BooleanClause.Occur.MUST);
// }
// if (ObjectUtil.isNotEmpty(whereJson.get(LogMessageConstant.FIELD_LEVEL))) {
// //查询解析器
// TermQuery termQuery = new TermQuery(new Term(LogMessageConstant.FIELD_LEVEL,
// whereJson.get(LogMessageConstant.FIELD_LEVEL).toString()));
// booleanQueryBuilder.add(termQuery, BooleanClause.Occur.MUST);
// }
// // 使用实体接收
// List<String> list = new ArrayList<>();
// TopFieldCollector collector = TopFieldCollector.create(sort, 20000, 0);
// searcher.search(booleanQueryBuilder.build(), collector);
// docs = collector.topDocs(pageNum*pageSize, pageSize);
// ScoreDoc[] scoreDocs = docs.scoreDocs;
// int totalSize = collector.getTotalHits();
//
// for (ScoreDoc scoreDoc : scoreDocs) {
// Document doc = reader.document(scoreDoc.doc);
// String logInfo = LogMessageConstant.COLOR_RED + doc.get(LogMessageConstant.FIELD_TIMESTAMP) +
// LogMessageConstant.COLOR_RESET + " - " +
// LogMessageConstant.COLOR_BLUE + doc.get(LogMessageConstant.FIELD_IP) +
// LogMessageConstant.COLOR_RESET + " - " +
// LogMessageConstant.COLOR_GREEN + "[" + doc.get(LogMessageConstant.FIELD_THREAD) + "]" +
// LogMessageConstant.COLOR_RESET + " - " +
// LogMessageConstant.COLOR_BLACK + doc.get(LogMessageConstant.FIELD_LEVEL) +
// LogMessageConstant.COLOR_RESET + " - " +
// LogMessageConstant.COLOR_MAGENTA + doc.get(LogMessageConstant.FIELD_CLASS_NAME) +
// LogMessageConstant.COLOR_RESET + " - " +
// LogMessageConstant.COLOR_GREEN + "<" + doc.get(LogMessageConstant.FIELD_TRACEID) + ">" +
// LogMessageConstant.COLOR_RESET + " - " +
// LogMessageConstant.COLOR_BLACK + highlightKeyword(doc.get(LogMessageConstant.FIELD_MESSAGE), whereJson.getString("message"));
// list.add(logInfo);
// }
// reader.close();
// JSONObject jo = new JSONObject();
// jo.put("content", list);
// jo.put("totalElements", totalSize);
// return jo;
// }
//
// public static String highlightKeyword(String text, String keyword) {
// if (ObjectUtil.isEmpty(keyword)) {
// return text;
// }
//
// int startIndex = text.indexOf(keyword);
// if (startIndex != -1) {
// int endIndex = startIndex + keyword.length();
// String beforeKeyword = text.substring(0, startIndex);
// String afterKeyword = text.substring(endIndex);
// String highlightedKeyword = LogMessageConstant.BACKGROUND_YELLOW + keyword + LogMessageConstant.COLOR_RESET
// + LogMessageConstant.COLOR_BLACK;
// return beforeKeyword + highlightedKeyword + afterKeyword;
// } else {
// return text;
// }
// }
//
// public static void main(String[] args) throws IOException, ParseException {
// // 获取当前时间
// LocalDateTime now = LocalDateTime.now();
// // 减去七天
// LocalDateTime sevenDaysAgo = now.minus(7, ChronoUnit.DAYS);
// // 转换为 Date 类型
// Date sevenDaysAgoDate = Date.from(sevenDaysAgo.atZone(ZoneId.systemDefault()).toInstant());
// // 获取时间戳
// SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS");
// Date date = dateFormat.parse(String.valueOf(sevenDaysAgo));
// long timestamp = date.getTime();
// System.out.println(now);
// System.out.println(sevenDaysAgo);
// System.out.println(sevenDaysAgoDate);
// System.out.println(timestamp);
// }
//}

View File

@@ -1,18 +1,15 @@
package org.nl.system.controller.lucence;
import com.alibaba.fastjson.JSONObject;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.nl.common.logging.annotation.Log;
import org.nl.system.service.lucene.LuceneService;
import org.springframework.data.domain.Pageable;
import org.nl.system.service.lucene.EsLogService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.Map;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* <p>
@@ -23,20 +20,20 @@ import java.util.Map;
* @since 2023-11-16
*/
@RestController
@RequiredArgsConstructor
@RequestMapping("/api/lucene")
@Slf4j
public class LuceneController {
private final LuceneService luceneService;
@Autowired
private EsLogService esLogService;
@PostMapping("/getAll")
public ResponseEntity<Object> get(@RequestBody JSONObject whereJson) {
return new ResponseEntity<>(luceneService.getAll(whereJson), HttpStatus.OK);
return new ResponseEntity<>(esLogService.page(whereJson), HttpStatus.OK);
}
@PostMapping("/getTagName")
public ResponseEntity<Object> getTagName() {
return new ResponseEntity<>(luceneService.getTagName(), HttpStatus.OK);
return new ResponseEntity<>(esLogService.getTagName(), HttpStatus.OK);
}
}

View File

@@ -0,0 +1,22 @@
package org.nl.system.service.lucene;
import com.alibaba.fastjson.JSONObject;
import org.nl.system.service.lucene.dto.EsLogDto;
import org.springframework.data.domain.Page;
import java.util.List;
/**
* @Author: lyd
* @Date: 2025/5/28
*/
public interface EsLogService {
Page<EsLogDto> page(JSONObject whereJson);
/**
* 获取枚举的标签名称
*
* @return
*/
List<String> getTagName();
}

View File

@@ -1,31 +1,31 @@
package org.nl.system.service.lucene;
import com.alibaba.fastjson.JSONObject;
import java.util.List;
import java.util.Map;
/**
* <p>
* 、
* </p>
*
* @author generator
* @since 2023-11-16
*/
public interface LuceneService {
/**
* 获取数据分页
*
* @param whereJson 条件
* @return Map<String, Object>
*/
Map<String, Object> getAll(JSONObject whereJson);
/**
* 获取枚举的标签名称
* @return
*/
List<String> getTagName();
}
//package org.nl.system.service.lucene;
//
//import com.alibaba.fastjson.JSONObject;
//
//import java.util.List;
//import java.util.Map;
//
///**
// * <p>
// * 、
// * </p>
// *
// * @author generator
// * @since 2023-11-16
// */
//public interface LuceneService {
//
// /**
// * 获取数据分页
// *
// * @param whereJson 条件
// * @return Map<String, Object>
// */
// Map<String, Object> getAll(JSONObject whereJson);
//
// /**
// * 获取枚举的标签名称
// * @return
// */
// List<String> getTagName();
//}

View File

@@ -0,0 +1,11 @@
package org.nl.system.service.lucene.dao;
import org.nl.system.service.lucene.dto.EsLogDto;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
/**
* @Author: lyd
* @Date: 2025/5/28
*/
public interface EsLogRepository extends ElasticsearchRepository<EsLogDto, String> {
}

View File

@@ -0,0 +1,127 @@
package org.nl.system.service.lucene.dto;
import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;
import java.util.Date;
/**
* @Author: lyd
* @Date: 2025/5/28
*/
@Document(indexName = "nl_lms", type = "sever")
public class EsLogDto {
@Id
private String id;
@Field(type = FieldType.Date)
private Date time;
@Field(type = FieldType.Text)
private String message;
@Field(type = FieldType.Ip)
private String host;
@Field(type = FieldType.Ip)
private String currIp;
@Field(type = FieldType.Keyword)
private String tag;
@Field(type = FieldType.Keyword)
private String severity;
@Field(type = FieldType.Keyword)
private String thread;
@Field(type = FieldType.Keyword)
private String logger;
@Field(type = FieldType.Keyword)
private String tlogTraceId;
// 必须添加空构造器
public EsLogDto() {}
// getters/setters
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public Date getTime() {
return time;
}
public void setTime(Date time) {
this.time = time;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public String getHost() {
return host;
}
public void setHost(String host) {
this.host = host;
}
public String getSeverity() {
return severity;
}
public void setSeverity(String severity) {
this.severity = severity;
}
public String getTag() {
return tag;
}
public void setTag(String tag) {
this.tag = tag;
}
public String getThread() {
return thread;
}
public void setThread(String thread) {
this.thread = thread;
}
public String getLogger() {
return logger;
}
public void setLogger(String logger) {
this.logger = logger;
}
public String getCurrIp() {
return currIp;
}
public void setCurrIp(String currIp) {
this.currIp = currIp;
}
public String getTlogTraceId() {
return tlogTraceId;
}
public void setTlogTraceId(String tlogTraceId) {
this.tlogTraceId = tlogTraceId;
}
}

View File

@@ -1,116 +1,116 @@
package org.nl.system.service.lucene.dto;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* <p>
* 日志DTO
* </p>
*
* @author generator
* @since 2023-11-16
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class LuceneLogDto {
/**
* 日志标识
*/
private String log_uuid;
/**
* 日志类型
*/
private String logType;
/**
* 设备编号
*/
private String device_code;
/**
* 内容详情
*/
private String content;
/**
* 任务编码
*/
private String task_code;
/**
* 指令编码
*/
private String instruct_code;
/**
* 任务标识
*/
private String task_id;
/**
* 载具号
*/
private String vehicle_code;
/**
* 备注
*/
private String remark;
/**
* 日志类型
*/
private String log_type;
/**
* 方法
*/
private String method;
/**
* 请求参数
*/
private String requestparam;
/**
* 响应参数
*/
private String responseparam;
/**
* 请求地址
*/
private String requesturl;
/**
* 状态码
*/
private String status_code;
/**
* 是否删除 1:是0
*/
private String is_delete;
/**
* 创建者
*/
private String create_by;
/**
* 创建时间 YYYY-MM-DD hh:mm:ss
*/
private String create_time;
/**
* 修改者
*/
private String update_by;
/**
* 修改时间
*/
private String update_time;
public LuceneLogDto (final String opc_server_code,final String opc_plc_code,
final String device_code,final String to_home,final int last_home,
final int home) {
super ();
this.device_code = device_code;
this.content = "信号"
+ opc_server_code + "."
+ opc_plc_code + "."
+ device_code + "."
+ to_home + "变更从"
+ last_home + "->"
+ home;
}
}
//package org.nl.system.service.lucene.dto;
//
//import lombok.AllArgsConstructor;
//import lombok.Builder;
//import lombok.Data;
//import lombok.NoArgsConstructor;
//
///**
// * <p>
// * 日志DTO
// * </p>
// *
// * @author generator
// * @since 2023-11-16
// */
//@Data
//@Builder
//@NoArgsConstructor
//@AllArgsConstructor
//public class LuceneLogDto {
//
// /**
// * 日志标识
// */
// private String log_uuid;
// /**
// * 日志类型
// */
// private String logType;
// /**
// * 设备编号
// */
// private String device_code;
// /**
// * 内容详情
// */
// private String content;
// /**
// * 任务编码
// */
// private String task_code;
// /**
// * 指令编码
// */
// private String instruct_code;
// /**
// * 任务标识
// */
// private String task_id;
// /**
// * 载具号
// */
// private String vehicle_code;
// /**
// * 备注
// */
// private String remark;
// /**
// * 日志类型
// */
// private String log_type;
// /**
// * 方法
// */
// private String method;
// /**
// * 请求参数
// */
// private String requestparam;
// /**
// * 响应参数
// */
// private String responseparam;
// /**
// * 请求地址
// */
// private String requesturl;
// /**
// * 状态码
// */
// private String status_code;
// /**
// * 是否删除 1:是0
// */
// private String is_delete;
// /**
// * 创建者
// */
// private String create_by;
// /**
// * 创建时间 YYYY-MM-DD hh:mm:ss
// */
// private String create_time;
// /**
// * 修改者
// */
// private String update_by;
// /**
// * 修改时间
// */
// private String update_time;
//
// public LuceneLogDto (final String opc_server_code,final String opc_plc_code,
// final String device_code,final String to_home,final int last_home,
// final int home) {
// super ();
// this.device_code = device_code;
// this.content = "信号"
// + opc_server_code + "."
// + opc_plc_code + "."
// + device_code + "."
// + to_home + "变更从"
// + last_home + "->"
// + home;
// }
//}

View File

@@ -0,0 +1,106 @@
package org.nl.system.service.lucene.impl;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONObject;
import org.elasticsearch.common.unit.Fuzziness;
import org.elasticsearch.index.query.*;
import org.nl.config.lucene.TagNameEnum;
import org.nl.system.service.lucene.EsLogService;
import org.nl.system.service.lucene.dao.EsLogRepository;
import org.nl.system.service.lucene.dto.EsLogDto;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import javax.annotation.Resource;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
/**
* @Author: lyd
* @Date: 2025/5/28
*/
@Service
public class EsLogServiceImpl implements EsLogService {
@Resource
private EsLogRepository esLogRepository;
@Override
public Page<EsLogDto> page(JSONObject whereJson) {
// 分页参数处理
int page = whereJson.getInteger("page") != null ? whereJson.getInteger("page") - 1 : 0;
int size = whereJson.getInteger("size") != null ? whereJson.getInteger("size") : 10;
// 创建分页和排序(按时间倒序)
Pageable pageable = PageRequest.of(page, size, Sort.by(Sort.Direction.DESC, "time"));
// 构建动态查询条件
BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
// 1. message 模糊查询 (使用wildcard实现前后模糊匹配)
if (StringUtils.hasText(whereJson.getString("message"))) {
String message = whereJson.getString("message");
// 模糊查询条件
if (message.contains(" ")) {
// 短语:使用邻近查询 (slop 默认值设为 0 或自定义)
MatchPhraseQueryBuilder phraseQuery = QueryBuilders.matchPhraseQuery("message", message)
.slop(0);
boolQuery.must(phraseQuery);
} else {
// 单词:使用模糊查询 (默认编辑距离为 AUTO)
FuzzyQueryBuilder fuzzyQuery = QueryBuilders.fuzzyQuery("message", message)
.fuzziness(Fuzziness.AUTO);
boolQuery.must(fuzzyQuery);
}
}
// 2. tlogTraceId 精确查询
if (StringUtils.hasText(whereJson.getString("tlogTraceId"))) {
String traceId = whereJson.getString("tlogTraceId").trim();
boolQuery.must(QueryBuilders.termQuery("tlogTraceId.keyword", traceId));
}
// 3. level/severity 精确查询 (假设ES中字段名为"severity")
if (StringUtils.hasText(whereJson.getString("level"))) {
String level = whereJson.getString("level").trim();
boolQuery.must(QueryBuilders.termQuery("severity.keyword", level));
}
// 4. tag查询
if (ObjectUtil.isNotEmpty(whereJson.getString("label"))
&& !"-".equals(whereJson.getString("label"))) {
String label = whereJson.getString("label");
boolQuery.must(QueryBuilders.termQuery("tag.keyword", label));
}
// 5、时间范围查找
if (ObjectUtil.isNotEmpty(whereJson.getString("startTime"))
&& ObjectUtil.isNotEmpty(whereJson.getString("endTime"))) {
String startTime = whereJson.getString("startTime");
String endTime = whereJson.getString("endTime");
// 前端传来的数据startTime -> 2025-05-27T16:00:00.000ZendTime -> 2025-05-29T16:00:00.000Z
// es的time字段: 2025-05-29T14:55:47.498+08:00
// todo: 通过时间范围查询
boolQuery.must(QueryBuilders.rangeQuery("time")
.gte(startTime)
.lte(endTime)
.format("strict_date_optional_time"));
}
// 如果没有添加任何条件则使用matchAllQuery
QueryBuilder finalQuery = boolQuery.hasClauses() ? boolQuery : QueryBuilders.matchAllQuery();
// 执行查询
return esLogRepository.search(finalQuery, pageable);
}
@Override
public List<String> getTagName() {
return Arrays.stream(TagNameEnum.values()).map(TagNameEnum::getTag).collect(Collectors.toList());
}
}

View File

@@ -1,60 +1,60 @@
package org.nl.system.service.lucene.impl;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.nl.config.language.LangProcess;
import org.nl.config.lucene.Searcher;
import org.nl.config.lucene.TagNameEnum;
import org.nl.system.service.lucene.LuceneService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* <p>
* 、
* </p>
*
* @author generator
* @since 2023-11-16
*/
@Service
@RequiredArgsConstructor
@Slf4j
public class LuceneServiceImpl implements LuceneService {
/**
* 日志索引目录
*/
@Value("${lucene.index.path}")
private String luceneUrl;
@Override
public Map<String, Object> getAll(JSONObject whereJson) {
JSONObject jo = new JSONObject();
try {
JSONObject jsonObject = (JSONObject) Searcher.search(luceneUrl, whereJson);
JSONArray array = jsonObject.getJSONArray("content");
int totalElements = Integer.parseInt(jsonObject.get("totalElements").toString());
jo.put("content", array);
jo.put("totalElements", totalElements);
} catch (Exception e) {
log.error("索引查询为空", e);
throw new NullPointerException(LangProcess.msg("error_NullPoint"));
}
return jo;
}
@Override
public List<String> getTagName() {
return Arrays.stream(TagNameEnum.values()).map(TagNameEnum::getTag).collect(Collectors.toList());
}
}
//package org.nl.system.service.lucene.impl;
//
//import com.alibaba.fastjson.JSONArray;
//import com.alibaba.fastjson.JSONObject;
//import lombok.RequiredArgsConstructor;
//import lombok.extern.slf4j.Slf4j;
//import org.nl.config.language.LangProcess;
//import org.nl.config.lucene.Searcher;
//import org.nl.config.lucene.TagNameEnum;
//import org.nl.system.service.lucene.LuceneService;
//import org.springframework.beans.factory.annotation.Value;
//import org.springframework.stereotype.Service;
//
//import java.util.Arrays;
//import java.util.List;
//import java.util.Map;
//import java.util.stream.Collectors;
//
///**
// * <p>
// * 、
// * </p>
// *
// * @author generator
// * @since 2023-11-16
// */
//@Service
//@RequiredArgsConstructor
//@Slf4j
//public class LuceneServiceImpl implements LuceneService {
//
// /**
// * 日志索引目录
// */
// @Value("${lucene.index.path}")
// private String luceneUrl;
//
// @Override
// public Map<String, Object> getAll(JSONObject whereJson) {
// JSONObject jo = new JSONObject();
// try {
// JSONObject jsonObject = (JSONObject) Searcher.search(luceneUrl, whereJson);
// JSONArray array = jsonObject.getJSONArray("content");
// int totalElements = Integer.parseInt(jsonObject.get("totalElements").toString());
// jo.put("content", array);
// jo.put("totalElements", totalElements);
// } catch (Exception e) {
// log.error("索引查询为空", e);
// throw new NullPointerException(LangProcess.msg("error_NullPoint"));
// }
//
// return jo;
// }
//
// @Override
// public List<String> getTagName() {
// return Arrays.stream(TagNameEnum.values()).map(TagNameEnum::getTag).collect(Collectors.toList());
// }
//
//}

View File

@@ -1,46 +1,46 @@
package org.nl.system.service.quartz.task;
import lombok.extern.slf4j.Slf4j;
import org.apache.lucene.document.LongPoint;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.search.Query;
import org.nl.config.lucene.LuceneAppender;
import org.nl.system.service.param.ISysParamService;
import org.nl.system.service.param.dao.Param;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.Date;
/**
* @Author: lyd
* @Description: 自动删除lucene日志
* @Date: 2023/10/26
*/
@Slf4j
@Component
public class AutoClearLuceneData {
@Autowired
private ISysParamService paramService;
public void run() throws ParseException, IOException {
Param log_day = paramService.findByCode("log_day");
IndexWriter writer = LuceneAppender.indexWriter;
// 获取当前时间
LocalDateTime now = LocalDateTime.now();
// 减去七天
LocalDateTime sevenDaysAgo = now.minus(Long.parseLong(log_day.getValue()), ChronoUnit.DAYS);
// 获取时间戳
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS");
Date date = dateFormat.parse(String.valueOf(sevenDaysAgo));
// 获取Unix时间戳
long unixTimestamp = date.getTime();
Query query = LongPoint.newRangeQuery("time", 0L, unixTimestamp);
writer.deleteDocuments(query);
writer.commit();
}
}
//package org.nl.system.service.quartz.task;
//
//import lombok.extern.slf4j.Slf4j;
//import org.apache.lucene.document.LongPoint;
//import org.apache.lucene.index.IndexWriter;
//import org.apache.lucene.search.Query;
//import org.nl.config.lucene.LuceneAppender;
//import org.nl.system.service.param.ISysParamService;
//import org.nl.system.service.param.dao.Param;
//import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.stereotype.Component;
//
//import java.io.IOException;
//import java.text.ParseException;
//import java.text.SimpleDateFormat;
//import java.time.LocalDateTime;
//import java.time.temporal.ChronoUnit;
//import java.util.Date;
//
///**
// * @Author: lyd
// * @Description: 自动删除lucene日志
// * @Date: 2023/10/26
// */
//@Slf4j
//@Component
//public class AutoClearLuceneData {
// @Autowired
// private ISysParamService paramService;
// public void run() throws ParseException, IOException {
// Param log_day = paramService.findByCode("log_day");
// IndexWriter writer = LuceneAppender.indexWriter;
// // 获取当前时间
// LocalDateTime now = LocalDateTime.now();
// // 减去七天
// LocalDateTime sevenDaysAgo = now.minus(Long.parseLong(log_day.getValue()), ChronoUnit.DAYS);
// // 获取时间戳
// SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS");
// Date date = dateFormat.parse(String.valueOf(sevenDaysAgo));
// // 获取Unix时间戳
// long unixTimestamp = date.getTime();
// Query query = LongPoint.newRangeQuery("time", 0L, unixTimestamp);
// writer.deleteDocuments(query);
// writer.commit();
// }
//}

View File

@@ -50,31 +50,31 @@ https://juejin.cn/post/6844903775631572999
</encoder>
</appender>
<appender name="luceneAppender" class="org.nl.config.lucene.LuceneAppender" >
<!-- Filter for INFO level -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>INFO</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>NEXT</onMismatch>
</filter>
<!-- Filter for WARN level -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>WARN</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>NEXT</onMismatch>
</filter>
<!-- Filter for ERROR level -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERROR</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<appender name="asyncLuceneAppender" class="ch.qos.logback.classic.AsyncAppender">
<appender-ref ref="luceneAppender" />
<!-- 设置队列大小 -->
<queueSize>512</queueSize>
</appender>
<!-- <appender name="luceneAppender" class="org.nl.config.lucene.LuceneAppender" >-->
<!-- &lt;!&ndash; Filter for INFO level &ndash;&gt;-->
<!-- <filter class="ch.qos.logback.classic.filter.LevelFilter">-->
<!-- <level>INFO</level>-->
<!-- <onMatch>ACCEPT</onMatch>-->
<!-- <onMismatch>NEXT</onMismatch>-->
<!-- </filter>-->
<!-- &lt;!&ndash; Filter for WARN level &ndash;&gt;-->
<!-- <filter class="ch.qos.logback.classic.filter.LevelFilter">-->
<!-- <level>WARN</level>-->
<!-- <onMatch>ACCEPT</onMatch>-->
<!-- <onMismatch>NEXT</onMismatch>-->
<!-- </filter>-->
<!-- &lt;!&ndash; Filter for ERROR level &ndash;&gt;-->
<!-- <filter class="ch.qos.logback.classic.filter.LevelFilter">-->
<!-- <level>ERROR</level>-->
<!-- <onMatch>ACCEPT</onMatch>-->
<!-- <onMismatch>DENY</onMismatch>-->
<!-- </filter>-->
<!-- </appender>-->
<!-- <appender name="asyncLuceneAppender" class="ch.qos.logback.classic.AsyncAppender">-->
<!-- <appender-ref ref="luceneAppender" />-->
<!-- &lt;!&ndash; 设置队列大小 &ndash;&gt;-->
<!-- <queueSize>512</queueSize>-->
<!-- </appender>-->
<!--异步到文件-->
<appender name="asyncFileAppender" class="com.yomahub.tlog.core.enhance.logback.async.AspectLogbackAsyncAppender">
@@ -106,6 +106,10 @@ https://juejin.cn/post/6844903775631572999
<value>127.0.0.1</value>
<allowEmpty>true</allowEmpty>
</property>
<property>
<name>time</name>
<value>%d{yyyy-MM-dd'T'HH:mm:ss.SSSXXX}</value>
</property>
<property>
<name>severity</name>
<value>%level</value>
@@ -132,28 +136,33 @@ https://juejin.cn/post/6844903775631572999
</appender>
<!--开发环境:打印控制台-->
<springProfile name="dev">
<root level="info">
<root level="DEBUG">
<appender-ref ref="ELASTIC"/>
<!-- <appender-ref ref="asyncLuceneAppender"/>-->
<appender-ref ref="CONSOLE"/>
</root>
<logger name="org.elasticsearch.client.RestClient" level="ERROR" additivity="false">
<appender-ref ref="ELASTIC"/>
<appender-ref ref="asyncFileAppender"/>
</logger>
<logger name="com.baomidou.mybatisplus.core.MybatisConfiguration" level="ERROR" additivity="false">
<appender-ref ref="asyncLuceneAppender"/>
<!-- <appender-ref ref="asyncLuceneAppender"/>-->
<appender-ref ref="asyncFileAppender"/>
</logger>
<logger name="org.redisson.command.RedisExecutor" level="ERROR" additivity="false">
<appender-ref ref="asyncLuceneAppender"/>
<!-- <appender-ref ref="asyncLuceneAppender"/>-->
<appender-ref ref="asyncFileAppender"/>
</logger>
<logger name="org.reflections.Reflections" level="ERROR" additivity="false">
<appender-ref ref="asyncLuceneAppender"/>
<!-- <appender-ref ref="asyncLuceneAppender"/>-->
<appender-ref ref="asyncFileAppender"/>
</logger>
<logger name="org.redisson.connection.ClientConnectionsEntry" level="ERROR" additivity="false">
<appender-ref ref="asyncLuceneAppender"/>
<!-- <appender-ref ref="asyncLuceneAppender"/>-->
<appender-ref ref="asyncFileAppender"/>
</logger>
<logger name="org.mybatis.spring.mapper.ClassPathMapperScanner" level="ERROR" additivity="false">
<appender-ref ref="asyncLuceneAppender"/>
<!-- <appender-ref ref="asyncLuceneAppender"/>-->
<appender-ref ref="asyncFileAppender"/>
</logger>
<logger name="org.springframework" level="ERROR" additivity="true">
@@ -222,7 +231,7 @@ https://juejin.cn/post/6844903775631572999
<springProfile name="prod">
<root level="INFO">
<appender-ref ref="asyncFileAppender"/>
<appender-ref ref="asyncLuceneAppender"/>
<!-- <appender-ref ref="asyncLuceneAppender"/>-->
</root>
<logger name="org.springframework" level="ERROR" additivity="false">
<appender-ref ref="asyncFileAppender"/>

View File

@@ -56,7 +56,6 @@
<el-date-picker
v-model="query.createTime"
type="datetimerange"
value-format="yyyy-MM-dd HH:mm:ss"
:range-separator="$t('Log.to')"
:start-placeholder="$t('Log.start_time')"
:end-placeholder="$t('Log.end_time')"
@@ -82,8 +81,79 @@
<el-card shadow="hover" style="width: 100%" class="log-warpper">
<div style="width: 100%">
<div v-for="(log, index) in logs" :key="index">
<div v-if="compressedView === false" style="margin: 5px;font-size: 16px; word-break: break-all; white-space: pre-wrap;" v-html="log" />
<div v-else style="margin-bottom: 5px; font-size: 16px;" v-html="log" />
<!-- <div v-if="compressedView === false" style="margin: 5px;font-size: 16px; word-break: break-all; white-space: pre-wrap;">-->
<!-- {{ timestampToDate(log.time) }} - {{log.severity}} - {{log.logger}} - [{{log.thread}}] - {{log.tlogTraceId}} - {{log.message}}-->
<!-- </div>-->
<!-- <div v-else style="margin-bottom: 5px; font-size: 16px;">-->
<!-- {{ timestampToDate(log.time) }} - {{log.severity}} - {{log.logger}} - [{{log.thread}}] - {{log.tlogTraceId}} - {{log.message}}-->
<!-- </div>-->
<div v-if="compressedView" style="margin-bottom: 5px; font-size: 16px;">
<span style="color: #000000;">{{ timestampToDate(log.time) }}</span> -
<span style="color: #000569;">{{ log.currIp === null ? '0.0.0.0' : log.currIp }}</span> -
<span style="color: #111fc7;">{{ log.severity }}</span> -
<span style="color: #3498db;">{{ log.logger }}</span> -
<span style="color: #28b23a;">[{{ log.thread }}]</span> -
<span style="color: #d51313;">{{ log.tlogTraceId === null ? '无链路id' : log.tlogTraceId }}</span> -
<span style="color: #000000;">{{ log.message }}</span>
</div>
<div v-else style="margin-bottom: 5px; font-size: 16px; border: #00afff 1px solid; padding: 5px;">
<el-row>
<el-col :span="2">
时间
</el-col>
<el-col :span="22">
<span style="color: #000000;">{{ timestampToDate(log.time) }}</span>
</el-col>
</el-row>
<el-row>
<el-col :span="2">
执行IP
</el-col>
<el-col :span="22">
<span style="color: #000569;">{{ log.currIp === null ? '0.0.0.0' : log.currIp }}</span>
</el-col>
</el-row>
<el-row>
<el-col :span="2">
日志级别
</el-col>
<el-col :span="22">
<span style="color: #111fc7;">{{ log.severity }}</span>
</el-col>
</el-row>
<el-row>
<el-col :span="2">
类名
</el-col>
<el-col :span="22">
<span style="color: #111fc7;">{{ log.logger }}</span>
</el-col>
</el-row>
<el-row>
<el-col :span="2">
线程名
</el-col>
<el-col :span="22">
<span style="color: #28b23a;">{{ log.thread }}</span>
</el-col>
</el-row>
<el-row>
<el-col :span="2">
链路标识
</el-col>
<el-col :span="22">
<span style="color: #d51313;">{{ log.tlogTraceId === null ? '无链路id' : log.tlogTraceId }}</span>
</el-col>
</el-row>
<el-row>
<el-col :span="2">
日志信息
</el-col>
<el-col :span="22">
<span style="color: #000000;">{{ log.message }}</span>
</el-col>
</el-row>
</div>
</div>
</div>
</el-card>
@@ -145,6 +215,19 @@ export default {
this.getTagList()
},
methods: {
timestampToDate(timestamp) {
const date = new Date(timestamp)
const year = date.getFullYear()
const month = String(date.getMonth() + 1).padStart(2, '0')
const day = String(date.getDate()).padStart(2, '0')
const hours = String(date.getHours()).padStart(2, '0')
const minutes = String(date.getMinutes()).padStart(2, '0')
const seconds = String(date.getSeconds()).padStart(2, '0')
// 添加毫秒处理强制3位数
const milliseconds = String(date.getMilliseconds()).padStart(3, '0')
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}.${milliseconds}`
},
handleSizeChange(val) {
this.query.size = val
this.queryData()
@@ -164,13 +247,8 @@ export default {
this.query.endTime = this.query.createTime[1]
}
luceneOperation.getLogData(this.query).then(res => {
this.logs = [] // 清空
var ansi_up = new AnsiUp()
// 数据初始化
for (const i in res.content) {
this.logs[i] = ansi_up.ansi_to_html(res.content[i])
}
// this.logs = res.content
console.log(res)
this.logs = res.content
this.query.total = res.totalElements
})
}