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

View File

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

View File

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

View File

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

View File

@@ -1,18 +1,15 @@
package org.nl.system.controller.lucence; package org.nl.system.controller.lucence;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.nl.common.logging.annotation.Log; import org.nl.system.service.lucene.EsLogService;
import org.nl.system.service.lucene.LuceneService; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Pageable;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import java.util.Map; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/** /**
* <p> * <p>
@@ -23,20 +20,20 @@ import java.util.Map;
* @since 2023-11-16 * @since 2023-11-16
*/ */
@RestController @RestController
@RequiredArgsConstructor
@RequestMapping("/api/lucene") @RequestMapping("/api/lucene")
@Slf4j @Slf4j
public class LuceneController { public class LuceneController {
private final LuceneService luceneService; @Autowired
private EsLogService esLogService;
@PostMapping("/getAll") @PostMapping("/getAll")
public ResponseEntity<Object> get(@RequestBody JSONObject whereJson) { 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") @PostMapping("/getTagName")
public ResponseEntity<Object> 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; //package org.nl.system.service.lucene;
//
import com.alibaba.fastjson.JSONObject; //import com.alibaba.fastjson.JSONObject;
//
import java.util.List; //import java.util.List;
import java.util.Map; //import java.util.Map;
//
/** ///**
* <p> // * <p>
* 、 // * 、
* </p> // * </p>
* // *
* @author generator // * @author generator
* @since 2023-11-16 // * @since 2023-11-16
*/ // */
public interface LuceneService { //public interface LuceneService {
//
/** // /**
* 获取数据分页 // * 获取数据分页
* // *
* @param whereJson 条件 // * @param whereJson 条件
* @return Map<String, Object> // * @return Map<String, Object>
*/ // */
Map<String, Object> getAll(JSONObject whereJson); // Map<String, Object> getAll(JSONObject whereJson);
//
/** // /**
* 获取枚举的标签名称 // * 获取枚举的标签名称
* @return // * @return
*/ // */
List<String> getTagName(); // 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; //package org.nl.system.service.lucene.dto;
//
import lombok.AllArgsConstructor; //import lombok.AllArgsConstructor;
import lombok.Builder; //import lombok.Builder;
import lombok.Data; //import lombok.Data;
import lombok.NoArgsConstructor; //import lombok.NoArgsConstructor;
//
/** ///**
* <p> // * <p>
* 日志DTO // * 日志DTO
* </p> // * </p>
* // *
* @author generator // * @author generator
* @since 2023-11-16 // * @since 2023-11-16
*/ // */
@Data //@Data
@Builder //@Builder
@NoArgsConstructor //@NoArgsConstructor
@AllArgsConstructor //@AllArgsConstructor
public class LuceneLogDto { //public class LuceneLogDto {
//
/** // /**
* 日志标识 // * 日志标识
*/ // */
private String log_uuid; // private String log_uuid;
/** // /**
* 日志类型 // * 日志类型
*/ // */
private String logType; // private String logType;
/** // /**
* 设备编号 // * 设备编号
*/ // */
private String device_code; // private String device_code;
/** // /**
* 内容详情 // * 内容详情
*/ // */
private String content; // private String content;
/** // /**
* 任务编码 // * 任务编码
*/ // */
private String task_code; // private String task_code;
/** // /**
* 指令编码 // * 指令编码
*/ // */
private String instruct_code; // private String instruct_code;
/** // /**
* 任务标识 // * 任务标识
*/ // */
private String task_id; // private String task_id;
/** // /**
* 载具号 // * 载具号
*/ // */
private String vehicle_code; // private String vehicle_code;
/** // /**
* 备注 // * 备注
*/ // */
private String remark; // private String remark;
/** // /**
* 日志类型 // * 日志类型
*/ // */
private String log_type; // private String log_type;
/** // /**
* 方法 // * 方法
*/ // */
private String method; // private String method;
/** // /**
* 请求参数 // * 请求参数
*/ // */
private String requestparam; // private String requestparam;
/** // /**
* 响应参数 // * 响应参数
*/ // */
private String responseparam; // private String responseparam;
/** // /**
* 请求地址 // * 请求地址
*/ // */
private String requesturl; // private String requesturl;
/** // /**
* 状态码 // * 状态码
*/ // */
private String status_code; // private String status_code;
/** // /**
* 是否删除 1:是0 // * 是否删除 1:是0
*/ // */
private String is_delete; // private String is_delete;
/** // /**
* 创建者 // * 创建者
*/ // */
private String create_by; // private String create_by;
/** // /**
* 创建时间 YYYY-MM-DD hh:mm:ss // * 创建时间 YYYY-MM-DD hh:mm:ss
*/ // */
private String create_time; // private String create_time;
/** // /**
* 修改者 // * 修改者
*/ // */
private String update_by; // private String update_by;
/** // /**
* 修改时间 // * 修改时间
*/ // */
private String update_time; // private String update_time;
//
public LuceneLogDto (final String opc_server_code,final String opc_plc_code, // 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 String device_code,final String to_home,final int last_home,
final int home) { // final int home) {
super (); // super ();
this.device_code = device_code; // this.device_code = device_code;
this.content = "信号" // this.content = "信号"
+ opc_server_code + "." // + opc_server_code + "."
+ opc_plc_code + "." // + opc_plc_code + "."
+ device_code + "." // + device_code + "."
+ to_home + "变更从" // + to_home + "变更从"
+ last_home + "->" // + last_home + "->"
+ 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; //package org.nl.system.service.lucene.impl;
//
import com.alibaba.fastjson.JSONArray; //import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject; //import com.alibaba.fastjson.JSONObject;
import lombok.RequiredArgsConstructor; //import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; //import lombok.extern.slf4j.Slf4j;
import org.nl.config.language.LangProcess; //import org.nl.config.language.LangProcess;
import org.nl.config.lucene.Searcher; //import org.nl.config.lucene.Searcher;
import org.nl.config.lucene.TagNameEnum; //import org.nl.config.lucene.TagNameEnum;
import org.nl.system.service.lucene.LuceneService; //import org.nl.system.service.lucene.LuceneService;
import org.springframework.beans.factory.annotation.Value; //import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service; //import org.springframework.stereotype.Service;
//
import java.util.Arrays; //import java.util.Arrays;
import java.util.List; //import java.util.List;
import java.util.Map; //import java.util.Map;
import java.util.stream.Collectors; //import java.util.stream.Collectors;
//
/** ///**
* <p> // * <p>
* 、 // * 、
* </p> // * </p>
* // *
* @author generator // * @author generator
* @since 2023-11-16 // * @since 2023-11-16
*/ // */
@Service //@Service
@RequiredArgsConstructor //@RequiredArgsConstructor
@Slf4j //@Slf4j
public class LuceneServiceImpl implements LuceneService { //public class LuceneServiceImpl implements LuceneService {
//
/** // /**
* 日志索引目录 // * 日志索引目录
*/ // */
@Value("${lucene.index.path}") // @Value("${lucene.index.path}")
private String luceneUrl; // private String luceneUrl;
//
@Override // @Override
public Map<String, Object> getAll(JSONObject whereJson) { // public Map<String, Object> getAll(JSONObject whereJson) {
JSONObject jo = new JSONObject(); // JSONObject jo = new JSONObject();
try { // try {
JSONObject jsonObject = (JSONObject) Searcher.search(luceneUrl, whereJson); // JSONObject jsonObject = (JSONObject) Searcher.search(luceneUrl, whereJson);
JSONArray array = jsonObject.getJSONArray("content"); // JSONArray array = jsonObject.getJSONArray("content");
int totalElements = Integer.parseInt(jsonObject.get("totalElements").toString()); // int totalElements = Integer.parseInt(jsonObject.get("totalElements").toString());
jo.put("content", array); // jo.put("content", array);
jo.put("totalElements", totalElements); // jo.put("totalElements", totalElements);
} catch (Exception e) { // } catch (Exception e) {
log.error("索引查询为空", e); // log.error("索引查询为空", e);
throw new NullPointerException(LangProcess.msg("error_NullPoint")); // throw new NullPointerException(LangProcess.msg("error_NullPoint"));
} // }
//
return jo; // return jo;
} // }
//
@Override // @Override
public List<String> getTagName() { // public List<String> getTagName() {
return Arrays.stream(TagNameEnum.values()).map(TagNameEnum::getTag).collect(Collectors.toList()); // return Arrays.stream(TagNameEnum.values()).map(TagNameEnum::getTag).collect(Collectors.toList());
} // }
//
} //}

View File

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

View File

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

View File

@@ -56,7 +56,6 @@
<el-date-picker <el-date-picker
v-model="query.createTime" v-model="query.createTime"
type="datetimerange" type="datetimerange"
value-format="yyyy-MM-dd HH:mm:ss"
:range-separator="$t('Log.to')" :range-separator="$t('Log.to')"
:start-placeholder="$t('Log.start_time')" :start-placeholder="$t('Log.start_time')"
:end-placeholder="$t('Log.end_time')" :end-placeholder="$t('Log.end_time')"
@@ -82,8 +81,79 @@
<el-card shadow="hover" style="width: 100%" class="log-warpper"> <el-card shadow="hover" style="width: 100%" class="log-warpper">
<div style="width: 100%"> <div style="width: 100%">
<div v-for="(log, index) in logs" :key="index"> <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-if="compressedView === false" style="margin: 5px;font-size: 16px; word-break: break-all; white-space: pre-wrap;">-->
<div v-else style="margin-bottom: 5px; font-size: 16px;" v-html="log" /> <!-- {{ 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>
</div> </div>
</el-card> </el-card>
@@ -145,6 +215,19 @@ export default {
this.getTagList() this.getTagList()
}, },
methods: { 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) { handleSizeChange(val) {
this.query.size = val this.query.size = val
this.queryData() this.queryData()
@@ -164,13 +247,8 @@ export default {
this.query.endTime = this.query.createTime[1] this.query.endTime = this.query.createTime[1]
} }
luceneOperation.getLogData(this.query).then(res => { luceneOperation.getLogData(this.query).then(res => {
this.logs = [] // 清空 console.log(res)
var ansi_up = new AnsiUp() this.logs = res.content
// 数据初始化
for (const i in res.content) {
this.logs[i] = ansi_up.ansi_to_html(res.content[i])
}
// this.logs = res.content
this.query.total = res.totalElements this.query.total = res.totalElements
}) })
} }