gengby
11 months ago
27 changed files with 955 additions and 403 deletions
@ -1,40 +0,0 @@ |
|||||
package org.nl.modules.loki.rest; |
|
||||
|
|
||||
import com.alibaba.fastjson.JSONObject; |
|
||||
import io.swagger.annotations.Api; |
|
||||
import io.swagger.annotations.ApiOperation; |
|
||||
import lombok.RequiredArgsConstructor; |
|
||||
import lombok.extern.slf4j.Slf4j; |
|
||||
import org.nl.modules.common.annotation.RateLimiter; |
|
||||
import org.nl.modules.loki.service.LokiService; |
|
||||
import org.springframework.http.HttpStatus; |
|
||||
import org.springframework.http.ResponseEntity; |
|
||||
import org.springframework.web.bind.annotation.*; |
|
||||
|
|
||||
/** |
|
||||
* @Author: lyd |
|
||||
* @Description: 日志监控 |
|
||||
* @Date: 2022-08-15 |
|
||||
*/ |
|
||||
@RestController |
|
||||
@RequiredArgsConstructor |
|
||||
@Api(tags = "日志监控") |
|
||||
@RequestMapping("/api/loki") |
|
||||
@Slf4j |
|
||||
public class LokiController { |
|
||||
|
|
||||
private final LokiService lokiService; |
|
||||
|
|
||||
@GetMapping("/labels/values") |
|
||||
@ApiOperation("获取标签") |
|
||||
public ResponseEntity<Object> labelsValues() { |
|
||||
return new ResponseEntity<>(lokiService.getLabelsValues(), HttpStatus.OK); |
|
||||
} |
|
||||
|
|
||||
@PostMapping("/logs") |
|
||||
@ApiOperation("获取日志") |
|
||||
@RateLimiter(value = 1, timeout = 300) // 限流
|
|
||||
public ResponseEntity<Object> getLogData(@RequestBody JSONObject json) { |
|
||||
return new ResponseEntity<>(lokiService.getLogData(json), HttpStatus.OK); |
|
||||
} |
|
||||
} |
|
@ -1,25 +0,0 @@ |
|||||
package org.nl.modules.loki.service; |
|
||||
|
|
||||
import com.alibaba.fastjson.JSONArray; |
|
||||
import com.alibaba.fastjson.JSONObject; |
|
||||
|
|
||||
/** |
|
||||
* @Author: lyd |
|
||||
* @Description: 服务类 |
|
||||
* @Date: 2022-08-15 |
|
||||
*/ |
|
||||
public interface LokiService { |
|
||||
|
|
||||
/** |
|
||||
* 获取日志信息 |
|
||||
* @param json |
|
||||
* @return |
|
||||
*/ |
|
||||
JSONObject getLogData(JSONObject json); |
|
||||
|
|
||||
/** |
|
||||
* 获取labels和values树 |
|
||||
* @return |
|
||||
*/ |
|
||||
JSONArray getLabelsValues(); |
|
||||
} |
|
@ -1,113 +0,0 @@ |
|||||
package org.nl.modules.loki.service.impl; |
|
||||
|
|
||||
import cn.hutool.core.util.CharsetUtil; |
|
||||
import cn.hutool.http.HttpUtil; |
|
||||
import com.alibaba.fastjson.JSONArray; |
|
||||
import com.alibaba.fastjson.JSONObject; |
|
||||
import lombok.RequiredArgsConstructor; |
|
||||
import org.nl.modules.loki.service.LokiService; |
|
||||
import org.springframework.beans.factory.annotation.Value; |
|
||||
import org.springframework.stereotype.Service; |
|
||||
|
|
||||
/** |
|
||||
* @Author: lyd |
|
||||
* @Description: 实现类 |
|
||||
* @Date: 2022-08-15 |
|
||||
*/ |
|
||||
@Service |
|
||||
@RequiredArgsConstructor |
|
||||
public class LokiServiceImpl implements LokiService { |
|
||||
|
|
||||
@Value("${loki.url}") |
|
||||
private String lokiUrl; |
|
||||
|
|
||||
@Value("${loki.systemName}") |
|
||||
private String systemName; |
|
||||
|
|
||||
@Override |
|
||||
public JSONObject getLogData(JSONObject json) { |
|
||||
String logLabel = ""; |
|
||||
String logLabelValue = ""; |
|
||||
Long start = 0L; |
|
||||
Long end = 0L; |
|
||||
String text = ""; |
|
||||
String limit = "100"; |
|
||||
String direction = "backward"; |
|
||||
if (json.get("logLabel") != null) logLabel = json.getString("logLabel"); |
|
||||
if (json.get("logLabelValue") != null) logLabelValue = json.getString("logLabelValue"); |
|
||||
if (json.get("text") != null) text = json.getString("text"); |
|
||||
if (json.get("start") != null) start = json.getLong("start"); |
|
||||
if (json.get("end") != null) end = json.getLong("end"); |
|
||||
if (json.get("limits") != null) limit = json.getString("limits"); |
|
||||
if (json.get("direction") != null) direction = json.getString("direction"); |
|
||||
/** |
|
||||
* 组织参数 |
|
||||
* 纳秒数 |
|
||||
* 1660037391880000000 |
|
||||
* 1641453208415000000 |
|
||||
* http://localhost:3100/loki/api/v1/query_range?query={host="localhost"} |= ``&limit=1500&start=1641453208415000000&end=1660027623419419002
|
|
||||
*/ |
|
||||
JSONObject parse = null; |
|
||||
String query = lokiUrl + "/query_range?query={system=\"" + systemName + "\", " + logLabel + "=\"" + logLabelValue + "\"} |= `" + text + "`"; |
|
||||
String result = ""; |
|
||||
if (start==0L) { |
|
||||
result = HttpUtil.get(query + "&limit=" + limit + "&direction=" + direction, CharsetUtil.CHARSET_UTF_8); |
|
||||
} else { |
|
||||
result = HttpUtil.get(query + "&limit=" + limit + "&start=" + start + "&end=" + end + "&direction=" + direction, CharsetUtil.CHARSET_UTF_8); |
|
||||
} |
|
||||
try { |
|
||||
parse = (JSONObject) JSONObject.parse(result); |
|
||||
} catch (Exception e) { |
|
||||
// reslut的值可能为:too many outstanding requests,无法转化成Json
|
|
||||
System.out.println("reslut:" + result); |
|
||||
// e.printStackTrace();
|
|
||||
} |
|
||||
return parse; |
|
||||
} |
|
||||
|
|
||||
/** |
|
||||
* 获取labels和values树 |
|
||||
* |
|
||||
* @return |
|
||||
*/ |
|
||||
@Override |
|
||||
public JSONArray getLabelsValues() { |
|
||||
/** |
|
||||
* [{ |
|
||||
* label: |
|
||||
* value: |
|
||||
* children:[{ |
|
||||
* label |
|
||||
* value |
|
||||
* }] |
|
||||
* }] |
|
||||
*/ |
|
||||
JSONArray result = new JSONArray(); |
|
||||
// 获取所有标签
|
|
||||
String labelString = HttpUtil.get(lokiUrl + "/labels", CharsetUtil.CHARSET_UTF_8); |
|
||||
JSONObject parse = (JSONObject) JSONObject.parse(labelString); |
|
||||
JSONArray labels = parse.getJSONArray("data"); |
|
||||
for (int i=0; i<labels.size(); i++) { |
|
||||
// 获取标签下的所有值
|
|
||||
String valueString = HttpUtil.get(lokiUrl + "/label/" + labels.getString(i) + "/values", CharsetUtil.CHARSET_UTF_8); |
|
||||
JSONObject parse2 = (JSONObject) JSONObject.parse(valueString); |
|
||||
JSONArray values = parse2.getJSONArray("data"); |
|
||||
JSONArray children = new JSONArray(); |
|
||||
// 组成树形状态 两级
|
|
||||
for (int j=0; j<values.size(); j++) { |
|
||||
JSONObject leaf = new JSONObject(); |
|
||||
leaf.put("label", values.getString(j)); |
|
||||
leaf.put("value", values.getString(j)); |
|
||||
children.add(leaf); |
|
||||
} |
|
||||
|
|
||||
JSONObject node = new JSONObject(); |
|
||||
node.put("label", labels.getString(i)); |
|
||||
node.put("value", labels.getString(i)); |
|
||||
node.put("children", children); |
|
||||
result.add(node); |
|
||||
} |
|
||||
return result; |
|
||||
} |
|
||||
|
|
||||
} |
|
@ -0,0 +1,43 @@ |
|||||
|
package org.nl.modules.lucene.config; |
||||
|
/** |
||||
|
* @author ldjun |
||||
|
* @version 1.0 |
||||
|
* @date 2023年08月24日 13:00 |
||||
|
* @desc desc |
||||
|
*/ |
||||
|
|
||||
|
import ch.qos.logback.classic.spi.ILoggingEvent; |
||||
|
import cn.hutool.core.util.IdUtil; |
||||
|
import com.yomahub.tlog.core.context.AspectLogContext; |
||||
|
import com.yomahub.tlog.core.enhance.logback.async.AspectLogbackAsyncAppender; |
||||
|
import org.apache.commons.lang3.StringUtils; |
||||
|
import org.slf4j.MDC; |
||||
|
|
||||
|
import java.util.Map; |
||||
|
|
||||
|
public class AsyncLuceneAppender extends AspectLogbackAsyncAppender { |
||||
|
|
||||
|
|
||||
|
@Override |
||||
|
protected void append(ILoggingEvent event) { |
||||
|
String traceId = AspectLogContext.getLogValue(); |
||||
|
if (StringUtils.isEmpty(traceId)){ |
||||
|
traceId = IdUtil.nanoId()+"@"; |
||||
|
AspectLogContext.putLogValue(traceId); |
||||
|
}else { |
||||
|
if (!traceId.contains("@")){ |
||||
|
AspectLogContext.putLogValue(traceId+"@"); |
||||
|
} |
||||
|
} |
||||
|
if (StringUtils.isNotEmpty(traceId)){ |
||||
|
MDC.put("traceId",traceId); |
||||
|
Map<String, String> mdcPropertyMap = event.getMDCPropertyMap(); |
||||
|
if (mdcPropertyMap.getClass().getName().contains("SynchronizedMap")){ |
||||
|
mdcPropertyMap.put("traceId",traceId); |
||||
|
} |
||||
|
MDC.clear(); |
||||
|
} |
||||
|
super.append(event); |
||||
|
} |
||||
|
|
||||
|
} |
@ -0,0 +1,80 @@ |
|||||
|
package org.nl.modules.lucene.config; |
||||
|
|
||||
|
/** |
||||
|
* @Author: lyd |
||||
|
* @Description: 定义lucene相关常量 |
||||
|
* @Date: 2023/8/25 |
||||
|
*/ |
||||
|
public class LogMessageConstant { |
||||
|
/** |
||||
|
* |
||||
|
*/ |
||||
|
public final static String SORT_NAME = "time"; |
||||
|
/** |
||||
|
* 级别 |
||||
|
*/ |
||||
|
public final static String FIELD_LEVEL = "level"; |
||||
|
/** |
||||
|
* 时间 |
||||
|
*/ |
||||
|
public final static String FIELD_TIMESTAMP = "timestamp"; |
||||
|
/** |
||||
|
* 类的限定名 |
||||
|
*/ |
||||
|
public final static String FIELD_CLASS_NAME = "logger"; |
||||
|
/** |
||||
|
* 线程名 |
||||
|
*/ |
||||
|
public final static String FIELD_THREAD = "thread"; |
||||
|
/** |
||||
|
* 日志内容 |
||||
|
*/ |
||||
|
public final static String FIELD_MESSAGE = "message"; |
||||
|
public final static String FIELD_TRACEID = "tlogTraceId"; |
||||
|
// 定义颜色值
|
||||
|
/** |
||||
|
* 文本颜色:黑色 |
||||
|
*/ |
||||
|
public final static String COLOR_BLACK = "\u001B[30m"; |
||||
|
/** |
||||
|
* 文本颜色:红色 |
||||
|
*/ |
||||
|
public final static String COLOR_RED = "\u001B[31m"; |
||||
|
/** |
||||
|
* 文本颜色:绿色 |
||||
|
*/ |
||||
|
public final static String COLOR_GREEN = "\u001B[32m"; |
||||
|
/** |
||||
|
* 文本颜色:黄色 |
||||
|
*/ |
||||
|
public final static String COLOR_YELLOW = "\u001B[33m"; |
||||
|
/** |
||||
|
* 文本颜色:蓝色 |
||||
|
*/ |
||||
|
public final static String COLOR_BLUE = "\u001B[34m"; |
||||
|
/** |
||||
|
* 文本颜色:品红色 |
||||
|
*/ |
||||
|
public final static String COLOR_MAGENTA = "\u001B[35m"; |
||||
|
/** |
||||
|
* 文本颜色:青色 |
||||
|
*/ |
||||
|
public final static String COLOR_CYAN = "\u001B[36m"; |
||||
|
/** |
||||
|
* 文本颜色:白色 |
||||
|
*/ |
||||
|
public final static String COLOR_WHITE = "\u001B[37m"; |
||||
|
/** |
||||
|
* 文本颜色重置 |
||||
|
*/ |
||||
|
public final static String COLOR_RESET = "\u001B[0m"; |
||||
|
/** |
||||
|
* 背景颜色:黄色 |
||||
|
*/ |
||||
|
public final static String BACKGROUND_YELLOW = "\u001B[43m"; |
||||
|
/** |
||||
|
* 索引路径 |
||||
|
*/ |
||||
|
public final static String INDEX_DIR = "E:\\lucene\\index"; |
||||
|
|
||||
|
} |
@ -0,0 +1,130 @@ |
|||||
|
package org.nl.modules.lucene.config; |
||||
|
/** |
||||
|
* @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.DateTime; |
||||
|
import cn.hutool.core.date.DateUtil; |
||||
|
import cn.hutool.core.util.ObjectUtil; |
||||
|
import com.alibaba.fastjson.JSONObject; |
||||
|
import com.alibaba.ttl.TransmittableThreadLocal; |
||||
|
import org.apache.lucene.analysis.Analyzer; |
||||
|
import org.apache.lucene.document.*; |
||||
|
import org.apache.lucene.index.IndexWriter; |
||||
|
import org.apache.lucene.index.IndexWriterConfig; |
||||
|
import org.apache.lucene.store.Directory; |
||||
|
import org.apache.lucene.store.FSDirectory; |
||||
|
import org.nl.modules.lucene.service.dto.LuceneLogDto; |
||||
|
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.nio.file.Paths; |
||||
|
import java.util.List; |
||||
|
import java.util.Map; |
||||
|
import java.util.Properties; |
||||
|
|
||||
|
public class LuceneAppender extends AppenderBase<ILoggingEvent> { |
||||
|
|
||||
|
public static final TransmittableThreadLocal<String> traceIdTL = new TransmittableThreadLocal(); |
||||
|
public LuceneProperties properties; |
||||
|
public static Directory index; |
||||
|
private List<LucenePropertyAndEncoder> encoders; |
||||
|
public static IndexWriter indexWriter; |
||||
|
|
||||
|
|
||||
|
@Override |
||||
|
public void start() { |
||||
|
super.start(); |
||||
|
try { |
||||
|
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(); |
||||
|
String[] split = message.split("@"); |
||||
|
LuceneLogDto luceneLogDto = JSONObject.parseObject(split[1], LuceneLogDto.class); |
||||
|
Document document = new Document(); |
||||
|
try { |
||||
|
//向document对象中添加域。
|
||||
|
Map<String, String> mdcPropertyMap = event.getMDCPropertyMap(); |
||||
|
String traceId = mdcPropertyMap.get("traceId"); |
||||
|
System.out.println("---追踪号---"+traceId); |
||||
|
if (ObjectUtil.isNotEmpty(traceId)) { |
||||
|
document.add(new StringField("trace_id", traceId, Field.Store.YES)); |
||||
|
} |
||||
|
if (ObjectUtil.isNotEmpty(luceneLogDto.getDevice_code())) { |
||||
|
document.add(new StringField("device_code", luceneLogDto.getDevice_code(), Field.Store.YES)); |
||||
|
} |
||||
|
if (ObjectUtil.isNotEmpty(luceneLogDto.getContent())) { |
||||
|
document.add(new StringField("fieldContent", luceneLogDto.getContent(), Field.Store.YES)); |
||||
|
} |
||||
|
if (ObjectUtil.isNotEmpty(luceneLogDto.getMethod())) { |
||||
|
document.add(new StringField("method", luceneLogDto.getMethod(), Field.Store.YES)); |
||||
|
} |
||||
|
if (ObjectUtil.isNotEmpty(luceneLogDto.getStatus_code())) { |
||||
|
document.add(new StringField("status_code", luceneLogDto.getStatus_code(), Field.Store.YES)); |
||||
|
} |
||||
|
if (ObjectUtil.isNotEmpty(luceneLogDto.getRequestparam())) { |
||||
|
document.add(new StringField("requestparam", luceneLogDto.getRequestparam(), Field.Store.YES)); |
||||
|
} |
||||
|
if (ObjectUtil.isNotEmpty(luceneLogDto.getResponseparam())) { |
||||
|
document.add(new StringField("responseparam", luceneLogDto.getResponseparam(), Field.Store.YES)); |
||||
|
} |
||||
|
document.add(new StringField("logType", luceneLogDto.getLogType(), Field.Store.YES)); |
||||
|
document.add(new StringField("logTime", DateUtil.format(new DateTime(), "yyyy-MM-dd HH:mm:ss.SSS"), Field.Store.YES)); |
||||
|
document.add(new NumericDocValuesField("logTime",System.currentTimeMillis()));//排序
|
||||
|
|
||||
|
try { |
||||
|
indexWriter.addDocument(document); |
||||
|
indexWriter.commit(); |
||||
|
} catch (IOException e) { |
||||
|
e.printStackTrace(); |
||||
|
} |
||||
|
} catch (Exception e) { |
||||
|
return; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void stop() { |
||||
|
super.stop(); |
||||
|
try { |
||||
|
indexWriter.close(); |
||||
|
} catch (IOException e) { |
||||
|
e.printStackTrace(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public void setProperties(LuceneProperties properties) { |
||||
|
this.properties = properties; |
||||
|
|
||||
|
} |
||||
|
} |
@ -0,0 +1,23 @@ |
|||||
|
package org.nl.modules.lucene.config; |
||||
|
|
||||
|
|
||||
|
import java.util.ArrayList; |
||||
|
import java.util.List; |
||||
|
|
||||
|
public class LuceneProperties { |
||||
|
|
||||
|
private List<Property> properties; |
||||
|
|
||||
|
public LuceneProperties() { |
||||
|
this.properties = new ArrayList<Property>(); |
||||
|
} |
||||
|
|
||||
|
public List<Property> getProperties() { |
||||
|
return properties; |
||||
|
} |
||||
|
|
||||
|
public void addProperty(Property property) { |
||||
|
properties.add(property); |
||||
|
} |
||||
|
|
||||
|
} |
@ -0,0 +1,38 @@ |
|||||
|
package org.nl.modules.lucene.config; |
||||
|
|
||||
|
import ch.qos.logback.classic.PatternLayout; |
||||
|
import ch.qos.logback.classic.spi.ILoggingEvent; |
||||
|
import ch.qos.logback.core.Context; |
||||
|
import ch.qos.logback.core.pattern.PatternLayoutBase; |
||||
|
|
||||
|
/* |
||||
|
* @author ZZQ |
||||
|
* @Date 2023/12/22 18:11 |
||||
|
*/ |
||||
|
public class LucenePropertyAndEncoder { |
||||
|
|
||||
|
private Property property; |
||||
|
|
||||
|
private PatternLayoutBase layout = new PatternLayout(); |
||||
|
|
||||
|
public LucenePropertyAndEncoder(Property property, Context context) { |
||||
|
this.property = property; |
||||
|
this.layout.setContext(context); |
||||
|
this.layout.setPattern(String.valueOf(property.getValue())); |
||||
|
this.layout.setPostCompileProcessor(null); |
||||
|
this.layout.start(); |
||||
|
} |
||||
|
|
||||
|
public String encode(ILoggingEvent event) { |
||||
|
return layout.doLayout(event); |
||||
|
} |
||||
|
|
||||
|
public String getName() { |
||||
|
return property.getName(); |
||||
|
} |
||||
|
|
||||
|
public boolean allowEmpty() { |
||||
|
return property.isAllowEmpty(); |
||||
|
} |
||||
|
} |
||||
|
|
@ -0,0 +1,44 @@ |
|||||
|
package org.nl.modules.lucene.config; |
||||
|
|
||||
|
/* |
||||
|
* @author ZZQ |
||||
|
* @Date 2023/12/26 15:30 |
||||
|
*/ |
||||
|
public class Property { |
||||
|
private String name; |
||||
|
private String value; |
||||
|
private boolean allowEmpty; |
||||
|
|
||||
|
public Property() { |
||||
|
} |
||||
|
|
||||
|
public Property(String name, String value, boolean allowEmpty) { |
||||
|
this.name = name; |
||||
|
this.value = value; |
||||
|
this.allowEmpty = allowEmpty; |
||||
|
} |
||||
|
|
||||
|
public String getName() { |
||||
|
return name; |
||||
|
} |
||||
|
|
||||
|
public void setName(String name) { |
||||
|
this.name = name; |
||||
|
} |
||||
|
|
||||
|
public String getValue() { |
||||
|
return value; |
||||
|
} |
||||
|
|
||||
|
public void setValue(String value) { |
||||
|
this.value = value; |
||||
|
} |
||||
|
|
||||
|
public boolean isAllowEmpty() { |
||||
|
return allowEmpty; |
||||
|
} |
||||
|
|
||||
|
public void setAllowEmpty(boolean allowEmpty) { |
||||
|
this.allowEmpty = allowEmpty; |
||||
|
} |
||||
|
} |
@ -0,0 +1,15 @@ |
|||||
|
package org.nl.modules.lucene.enums; |
||||
|
|
||||
|
public enum LogTypeEnum { |
||||
|
DEVICE_LOG("设备日志"), |
||||
|
INTERFACE_LOG("接口日志"); |
||||
|
|
||||
|
private String desc; |
||||
|
|
||||
|
LogTypeEnum(String desc) { |
||||
|
this.desc = desc; |
||||
|
} |
||||
|
public String getDesc() { |
||||
|
return desc; |
||||
|
} |
||||
|
} |
@ -0,0 +1,38 @@ |
|||||
|
package org.nl.modules.lucene.rest; |
||||
|
|
||||
|
import io.swagger.annotations.Api; |
||||
|
import io.swagger.annotations.ApiOperation; |
||||
|
import lombok.RequiredArgsConstructor; |
||||
|
import lombok.extern.slf4j.Slf4j; |
||||
|
import org.nl.modules.logging.annotation.Log; |
||||
|
import org.nl.modules.lucene.service.LuceneService; |
||||
|
import org.springframework.data.domain.Pageable; |
||||
|
import org.springframework.http.HttpStatus; |
||||
|
import org.springframework.http.ResponseEntity; |
||||
|
import org.springframework.web.bind.annotation.GetMapping; |
||||
|
import org.springframework.web.bind.annotation.RequestMapping; |
||||
|
import org.springframework.web.bind.annotation.RequestParam; |
||||
|
import org.springframework.web.bind.annotation.RestController; |
||||
|
|
||||
|
import java.util.Map; |
||||
|
|
||||
|
|
||||
|
@RestController |
||||
|
@RequiredArgsConstructor |
||||
|
@Api(tags = "日志检索") |
||||
|
@RequestMapping("/api/lucene") |
||||
|
@Slf4j |
||||
|
public class LuceneController { |
||||
|
|
||||
|
private final LuceneService luceneService; |
||||
|
|
||||
|
|
||||
|
|
||||
|
@GetMapping("/getAll") |
||||
|
@Log("日志检索") |
||||
|
@ApiOperation("日志检索") |
||||
|
//@PreAuthorize("@el.check('task:list')")
|
||||
|
public ResponseEntity<Object> get(@RequestParam Map whereJson, Pageable page) { |
||||
|
return new ResponseEntity<>(luceneService.getAll(whereJson, page), HttpStatus.OK); |
||||
|
} |
||||
|
} |
@ -0,0 +1,39 @@ |
|||||
|
package org.nl.modules.lucene.service; |
||||
|
|
||||
|
|
||||
|
import org.nl.modules.lucene.service.dto.LuceneLogDto; |
||||
|
|
||||
|
public interface LuceneExecuteLogService { |
||||
|
/** |
||||
|
* 设备光电变化实时光电信号 |
||||
|
* |
||||
|
* @param device_code 设备编号 |
||||
|
* @param key plc信号 |
||||
|
* @param value plc信号值 |
||||
|
*/ |
||||
|
void deviceItemValue(String device_code, String key, String value); |
||||
|
|
||||
|
/** |
||||
|
* 设备执行日志,会保留历史记录 |
||||
|
* |
||||
|
* @param luceneLogDto 日志结果对象 |
||||
|
*/ |
||||
|
void deviceExecuteLog(LuceneLogDto luceneLogDto); |
||||
|
|
||||
|
/** |
||||
|
* 接口日志,会保留历史记录 |
||||
|
* |
||||
|
* @param luceneLogDto 日志结果对象 |
||||
|
*/ |
||||
|
void interfaceExecuteLog(LuceneLogDto luceneLogDto); |
||||
|
|
||||
|
/** |
||||
|
* 设备执行日志,会保留历史记录 |
||||
|
* |
||||
|
* @param name 日志名称 |
||||
|
* @param message 日志信息 |
||||
|
*/ |
||||
|
void extLog(String name, String message); |
||||
|
|
||||
|
|
||||
|
} |
@ -0,0 +1,18 @@ |
|||||
|
package org.nl.modules.lucene.service; |
||||
|
|
||||
|
import org.springframework.data.domain.Pageable; |
||||
|
|
||||
|
import java.util.Map; |
||||
|
|
||||
|
|
||||
|
public interface LuceneService { |
||||
|
|
||||
|
/** |
||||
|
* 获取数据分页 |
||||
|
* |
||||
|
* @param whereJson 条件 |
||||
|
* @param page 分页参数 |
||||
|
* @return Map<String, Object> |
||||
|
*/ |
||||
|
Map<String, Object> getAll(Map whereJson, Pageable page); |
||||
|
} |
@ -0,0 +1,117 @@ |
|||||
|
package org.nl.modules.lucene.service.dto; |
||||
|
|
||||
|
import lombok.AllArgsConstructor; |
||||
|
import lombok.Builder; |
||||
|
import lombok.Data; |
||||
|
import lombok.NoArgsConstructor; |
||||
|
|
||||
|
@Data |
||||
|
@Builder |
||||
|
@NoArgsConstructor |
||||
|
@AllArgsConstructor |
||||
|
public class LuceneLogDto { |
||||
|
|
||||
|
/* 日志标识 */ |
||||
|
private String log_uuid; |
||||
|
/*日志类型*/ |
||||
|
private String logType; |
||||
|
/*设备编号*/ |
||||
|
private String device_code; |
||||
|
/*内容详情*/ |
||||
|
private String content; |
||||
|
|
||||
|
/* 任务编码 */ |
||||
|
private String task_code; |
||||
|
|
||||
|
/* 指令编码 */ |
||||
|
private String instruct_code; |
||||
|
|
||||
|
/* 任务标识 */ |
||||
|
private String task_id; |
||||
|
|
||||
|
/* 载具号 */ |
||||
|
private String vehicle_code; |
||||
|
|
||||
|
/* 备注 */ |
||||
|
private String remark; |
||||
|
|
||||
|
/* 日志类型 */ |
||||
|
private String log_type; |
||||
|
|
||||
|
/* 方法 */ |
||||
|
private String method; |
||||
|
|
||||
|
/* 请求参数 */ |
||||
|
private String requestparam; |
||||
|
|
||||
|
/* 响应参数 */ |
||||
|
private String responseparam; |
||||
|
|
||||
|
/* 请求地址 */ |
||||
|
private String requesturl; |
||||
|
|
||||
|
/* 状态码 */ |
||||
|
private String status_code; |
||||
|
|
||||
|
/* 是否删除 1:是;0:否 */ |
||||
|
private String is_delete; |
||||
|
|
||||
|
/* 创建者 */ |
||||
|
private String create_by; |
||||
|
|
||||
|
/* 创建时间 YYYY-MM-DD hh:mm:ss */ |
||||
|
private String create_time; |
||||
|
|
||||
|
/* 修改者 */ |
||||
|
private String update_by; |
||||
|
|
||||
|
/* 修改时间 */ |
||||
|
private String update_time; |
||||
|
|
||||
|
|
||||
|
public LuceneLogDto(final String opc_server_code, final String opc_plc_code, |
||||
|
final String device_code, final String to_home, final String last_home, |
||||
|
final String home) { |
||||
|
super(); |
||||
|
this.device_code = device_code; |
||||
|
this.content = "信号 [" |
||||
|
+ opc_server_code + "." |
||||
|
+ opc_plc_code + "." |
||||
|
+ device_code + "." |
||||
|
+ to_home + "] 发生变更 " |
||||
|
+ last_home + " -> " |
||||
|
+ home; |
||||
|
} |
||||
|
|
||||
|
public LuceneLogDto(final String device_code, final String task_code, |
||||
|
final String instruct_code, final String method, |
||||
|
final String remark){ |
||||
|
super(); |
||||
|
this.device_code = device_code; |
||||
|
this.task_code = task_code; |
||||
|
this.instruct_code = instruct_code; |
||||
|
this.method = method; |
||||
|
this.content = remark; |
||||
|
} |
||||
|
|
||||
|
public LuceneLogDto(final String device_code, final String remark) { |
||||
|
super(); |
||||
|
this.device_code = device_code; |
||||
|
this.content = "设备 [" |
||||
|
+ device_code |
||||
|
+ "] - " |
||||
|
+ remark; |
||||
|
} |
||||
|
|
||||
|
public LuceneLogDto(final LuceneLogDto dto) { |
||||
|
super(); |
||||
|
this.device_code = device_code; |
||||
|
this.method = method; |
||||
|
|
||||
|
this.content = "设备 [" |
||||
|
+ device_code |
||||
|
+ "] - " |
||||
|
+ remark; |
||||
|
} |
||||
|
|
||||
|
} |
@ -0,0 +1,51 @@ |
|||||
|
package org.nl.modules.lucene.service.impl; |
||||
|
|
||||
|
import cn.hutool.core.date.DateUtil; |
||||
|
import com.alibaba.fastjson.JSON; |
||||
|
import lombok.RequiredArgsConstructor; |
||||
|
import lombok.extern.slf4j.Slf4j; |
||||
|
import org.nl.modules.lucene.enums.LogTypeEnum; |
||||
|
import org.nl.modules.lucene.service.LuceneExecuteLogService; |
||||
|
import org.nl.modules.lucene.service.dto.LuceneLogDto; |
||||
|
import org.slf4j.MDC; |
||||
|
import org.springframework.stereotype.Service; |
||||
|
|
||||
|
/** |
||||
|
* @author jlm |
||||
|
* @description 服务实现 |
||||
|
* @date 2023-04-11 |
||||
|
*/ |
||||
|
@Service |
||||
|
@RequiredArgsConstructor |
||||
|
@Slf4j |
||||
|
public class LuceneExecuteLogServiceImpl implements LuceneExecuteLogService { |
||||
|
|
||||
|
@Override |
||||
|
public void deviceItemValue(String device_code, String key, String value) { |
||||
|
String now = DateUtil.now(); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void deviceExecuteLog(LuceneLogDto luceneLogDto) { |
||||
|
luceneLogDto.setLogType(LogTypeEnum.DEVICE_LOG.getDesc()); |
||||
|
log.info("{}", JSON.toJSONString(luceneLogDto)); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void interfaceExecuteLog(LuceneLogDto luceneLogDto) { |
||||
|
luceneLogDto.setLogType(LogTypeEnum.INTERFACE_LOG.getDesc()); |
||||
|
log.info("{}", JSON.toJSONString(luceneLogDto)); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void extLog(String name, String message) { |
||||
|
try { |
||||
|
MDC.put(name, name); |
||||
|
log.info("{}", message); |
||||
|
} catch (Exception e) { |
||||
|
e.printStackTrace(); |
||||
|
} finally { |
||||
|
MDC.remove(name); |
||||
|
} |
||||
|
} |
||||
|
} |
@ -0,0 +1,127 @@ |
|||||
|
package org.nl.modules.lucene.service.impl; |
||||
|
|
||||
|
import cn.hutool.core.date.DateTime; |
||||
|
import cn.hutool.core.date.DateUtil; |
||||
|
import com.alibaba.fastjson.JSONObject; |
||||
|
import lombok.RequiredArgsConstructor; |
||||
|
import lombok.extern.slf4j.Slf4j; |
||||
|
import org.apache.lucene.document.Document; |
||||
|
import org.apache.lucene.index.DirectoryReader; |
||||
|
import org.apache.lucene.index.Term; |
||||
|
import org.apache.lucene.search.*; |
||||
|
import org.apache.lucene.store.FSDirectory; |
||||
|
import org.apache.lucene.util.BytesRef; |
||||
|
import org.nl.modules.lucene.service.LuceneService; |
||||
|
import org.springframework.data.domain.Pageable; |
||||
|
import org.springframework.stereotype.Service; |
||||
|
|
||||
|
import java.nio.file.Paths; |
||||
|
import java.text.ParseException; |
||||
|
import java.text.SimpleDateFormat; |
||||
|
import java.util.*; |
||||
|
|
||||
|
|
||||
|
@Service |
||||
|
@RequiredArgsConstructor |
||||
|
@Slf4j |
||||
|
public class LuceneServiceImpl implements LuceneService { |
||||
|
|
||||
|
//日志索引目录
|
||||
|
|
||||
|
|
||||
|
@Override |
||||
|
public Map<String, Object> getAll(Map whereJson, Pageable page) { |
||||
|
//获取要查询的路径,也就是索引所在的位置
|
||||
|
try { |
||||
|
FSDirectory directory = FSDirectory.open(Paths.get("C:\\acs\\lucene\\index")); |
||||
|
DirectoryReader open = DirectoryReader.open(directory); |
||||
|
IndexSearcher searcher = new IndexSearcher(open); |
||||
|
// 实际上Lucene本身不支持分页。因此我们需要自己进行逻辑分页。我们要准备分页参数:
|
||||
|
int pageSize = Integer.parseInt(whereJson.get("size").toString());// 每页条数
|
||||
|
int pageNum = Integer.parseInt(whereJson.get("page").toString());// 当前页码
|
||||
|
|
||||
|
BooleanQuery.Builder booleanQueryBuilder = new BooleanQuery.Builder(); |
||||
|
//时间范围查询
|
||||
|
String startDate = (String) whereJson.get("begin_time"); |
||||
|
String endDate = (String) whereJson.get("end_time"); |
||||
|
|
||||
|
if (startDate == null){ |
||||
|
Calendar calendar=Calendar.getInstance(); |
||||
|
calendar.set(1970, 0, 1); |
||||
|
startDate = DateUtil.format(calendar.getTime(),"yyyy-MM-dd HH:mm:ss.SSS"); |
||||
|
}else{ |
||||
|
startDate = getDate(startDate); |
||||
|
} |
||||
|
if (endDate == null){ |
||||
|
endDate = DateUtil.format(new DateTime(),"yyyy-MM-dd HH:mm:ss.SSS"); |
||||
|
} else { |
||||
|
endDate = getDate(endDate); |
||||
|
} |
||||
|
TermRangeQuery termRangeQuery = new TermRangeQuery("logTime", new BytesRef(startDate), new BytesRef(endDate), true, true); |
||||
|
booleanQueryBuilder.add(termRangeQuery,BooleanClause.Occur.MUST); |
||||
|
if (whereJson.get("device_code") != null){ |
||||
|
Query termQuery = new TermQuery(new Term("device_code", (String) whereJson.get("device_code"))); |
||||
|
booleanQueryBuilder.add(termQuery,BooleanClause.Occur.MUST); |
||||
|
} |
||||
|
if (whereJson.get("method") != null){ |
||||
|
Query termQuery = new TermQuery(new Term("method", (String) whereJson.get("method"))); |
||||
|
booleanQueryBuilder.add(termQuery,BooleanClause.Occur.MUST); |
||||
|
} |
||||
|
if (whereJson.get("status_code") != null){ |
||||
|
Query termQuery = new TermQuery(new Term("status_code", (String) whereJson.get("status_code"))); |
||||
|
booleanQueryBuilder.add(termQuery,BooleanClause.Occur.MUST); |
||||
|
} |
||||
|
if (whereJson.get("requestparam") != null){ |
||||
|
WildcardQuery query = new WildcardQuery(new Term("requestparam", "*"+(String) whereJson.get("requestparam")+"*")); |
||||
|
booleanQueryBuilder.add(query,BooleanClause.Occur.MUST); |
||||
|
} |
||||
|
if (whereJson.get("responseparam") != null){ |
||||
|
WildcardQuery query = new WildcardQuery(new Term("responseparam", "*"+(String) whereJson.get("responseparam")+"*")); |
||||
|
booleanQueryBuilder.add(query,BooleanClause.Occur.MUST); |
||||
|
} |
||||
|
if (whereJson.get("blurry") != null) { |
||||
|
WildcardQuery query = new WildcardQuery(new Term("fieldContent", "*"+(String) whereJson.get("blurry")+"*")); |
||||
|
booleanQueryBuilder.add(query, BooleanClause.Occur.MUST); |
||||
|
} |
||||
|
|
||||
|
TopFieldCollector collector = TopFieldCollector.create(new Sort(new SortField("logTime", SortField.Type.LONG,true)), 20000, 0); |
||||
|
searcher.search(booleanQueryBuilder.build(), collector); |
||||
|
TopDocs topDocs = collector.topDocs(pageNum*pageSize, pageSize); |
||||
|
int totalSize = collector.getTotalHits(); |
||||
|
ScoreDoc[] scoreDocs = topDocs.scoreDocs; |
||||
|
|
||||
|
List<JSONObject> list = new ArrayList<>(); |
||||
|
for (ScoreDoc scoreDoc : scoreDocs) { |
||||
|
Document doc = open.document(scoreDoc.doc); |
||||
|
JSONObject object = new JSONObject(); |
||||
|
object.put("content",doc.get("fieldContent")); |
||||
|
object.put("device_code",doc.get("device_code")); |
||||
|
object.put("logTime",doc.get("logTime")); |
||||
|
object.put("method",doc.get("method")); |
||||
|
object.put("status_code",doc.get("status_code")); |
||||
|
object.put("requestparam",doc.get("requestparam")); |
||||
|
object.put("responseparam",doc.get("responseparam")); |
||||
|
if(doc.get("fieldContent") != null) { |
||||
|
list.add(object); |
||||
|
} |
||||
|
} |
||||
|
open.close(); |
||||
|
directory.close(); |
||||
|
JSONObject jo = new JSONObject(); |
||||
|
jo.put("content", list); |
||||
|
jo.put("totalElements", totalSize); |
||||
|
return jo; |
||||
|
} catch (Exception e) { |
||||
|
log.error("索引查询为空", e); |
||||
|
throw new NullPointerException("索引查询为空"); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public static String getDate(String timeString) throws ParseException { |
||||
|
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSX");//时间格式
|
||||
|
Date date = sdf.parse(timeString); |
||||
|
timeString = DateUtil.format(date, "yyyy-MM-dd HH:mm:ss.SSS");//格式化后的时间
|
||||
|
return timeString; |
||||
|
} |
||||
|
|
||||
|
} |
@ -0,0 +1,18 @@ |
|||||
|
import request from '@/utils/request' |
||||
|
|
||||
|
export function getLogData(param) { |
||||
|
return request({ |
||||
|
url: 'api/lucene/getAll', |
||||
|
method: 'get', |
||||
|
data: param |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
export function labelsValues() { |
||||
|
return request({ |
||||
|
url: 'api/loki/labels/values', |
||||
|
method: 'get' |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
export default { getLogData, labelsValues } |
Loading…
Reference in new issue