Browse Source

opt:优化日志

main
龚宝雄 4 months ago
parent
commit
ac35c138d6
  1. 5
      nladmin-system/nlsso-server/src/main/java/org/nl/acs/auto/run/OneNDCSocketConnectionAutoRun.java
  2. 66
      nladmin-system/nlsso-server/src/main/java/org/nl/acs/device_driver/basedriver/agv/ndcone/AgvNdcOneDeviceDriver.java
  3. 4
      nladmin-system/nlsso-server/src/main/java/org/nl/acs/device_driver/basedriver/standard_ordinary_site/StandardOrdinarySiteDeviceDriver.java
  4. 142
      nladmin-system/nlsso-server/src/main/java/org/nl/acs/log/rest/LogController.java
  5. 106
      nladmin-system/nlsso-server/src/main/java/org/nl/acs/log/service/LogService.java
  6. 256
      nladmin-system/nlsso-server/src/main/java/org/nl/acs/log/service/impl/LogServiceImpl.java
  7. 28
      nladmin-system/nlsso-server/src/main/java/org/nl/acs/utils/YmlConfigFileUtil.java
  8. 23
      nladmin-system/nlsso-server/src/main/java/org/nl/config/lucene/AsyncLuceneAppender.java
  9. 6
      nladmin-system/nlsso-server/src/main/java/org/nl/config/lucene/LogMessageConstant.java
  10. 111
      nladmin-system/nlsso-server/src/main/java/org/nl/config/lucene/LuceneAppender.java
  11. 60
      nladmin-system/nlsso-server/src/main/java/org/nl/config/lucene/LuceneIndexWriter.java
  12. 23
      nladmin-system/nlsso-server/src/main/java/org/nl/config/lucene/LuceneProperties.java
  13. 38
      nladmin-system/nlsso-server/src/main/java/org/nl/config/lucene/LucenePropertyAndEncoder.java
  14. 44
      nladmin-system/nlsso-server/src/main/java/org/nl/config/lucene/Property.java
  15. 21
      nladmin-system/nlsso-server/src/main/java/org/nl/config/lucene/StaticConfig.java
  16. 45
      nladmin-system/nlsso-server/src/main/java/org/nl/config/lucene/remote/AbstraceServer.java
  17. 94
      nladmin-system/nlsso-server/src/main/java/org/nl/config/lucene/remote/RemoteLogServer.java
  18. 44
      nladmin-system/nlsso-server/src/main/java/org/nl/config/lucene/remote/coder/LogConsumerHandler.java
  19. 33
      nladmin-system/nlsso-server/src/main/java/org/nl/config/lucene/remote/coder/LogProviderHandler.java
  20. 75
      nladmin-system/nlsso-server/src/main/java/org/nl/config/lucene/remote/impl/ClientServer.java
  21. 83
      nladmin-system/nlsso-server/src/main/java/org/nl/config/lucene/remote/impl/RemoteServer.java
  22. 31
      nladmin-system/nlsso-server/src/main/java/org/nl/system/controller/lucence/LuceneController.java
  23. 28
      nladmin-system/nlsso-server/src/main/java/org/nl/system/service/lucene/LuceneService.java
  24. 47
      nladmin-system/nlsso-server/src/main/java/org/nl/system/service/lucene/dto/LogQuery.java
  25. 27
      nladmin-system/nlsso-server/src/main/java/org/nl/system/service/lucene/dto/LogRepositoryDTO.java
  26. 204
      nladmin-system/nlsso-server/src/main/java/org/nl/system/service/lucene/impl/LuceneServiceImpl.java
  27. 1
      nladmin-system/nlsso-server/src/main/resources/logback-spring.xml
  28. 4
      nladmin-ui/src/views/acs/instruction/index.vue
  29. 18
      nladmin-ui/src/views/monitor/lucene/api/lucene.js
  30. 139
      nladmin-ui/src/views/monitor/lucene/errorLog.vue
  31. 472
      nladmin-ui/src/views/monitor/lucene/index.vue
  32. 26
      nladmin-ui/src/views/monitor/lucene/loki.js
  33. 136
      nladmin-ui/src/views/monitor/lucene/search.vue

5
nladmin-system/nlsso-server/src/main/java/org/nl/acs/auto/run/OneNDCSocketConnectionAutoRun.java

@ -14,11 +14,10 @@ import org.nl.acs.instruction.service.InstructionService;
import org.nl.acs.instruction.service.impl.InstructionServiceImpl;
import org.nl.acs.log.service.DeviceExecuteLogService;
import org.nl.acs.opc.DeviceAppService;
import org.nl.config.SpringContextHolder;
import org.nl.system.service.dict.ISysDictService;
import org.nl.system.service.dict.dao.Dict;
import org.nl.system.service.lucene.LuceneExecuteLogService;
import org.nl.system.service.param.ISysParamService;
import org.nl.config.SpringContextHolder;
import org.nl.system.service.param.impl.SysParamServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
@ -166,8 +165,8 @@ public class OneNDCSocketConnectionAutoRun extends AbstractAutoRunnable {
inst.setAgv_jobno(String.valueOf(index));
inst.setSend_status("1");
instructionService.update(inst);
data = NDCAgvService.sendAgvOneModeInst(phase, index, 0, 0, 0, 0, 0);
}
data = NDCAgvService.sendAgvOneModeInst(phase, index, 0, 0, 0, 0, 0);
}
//任务完毕
//(无车id及状态)

66
nladmin-system/nlsso-server/src/main/java/org/nl/acs/device_driver/basedriver/agv/ndcone/AgvNdcOneDeviceDriver.java

@ -14,6 +14,7 @@ import org.nl.acs.device.domain.Device;
import org.nl.acs.device.service.DeviceService;
import org.nl.acs.device_driver.DeviceDriver;
import org.nl.acs.device_driver.basedriver.agv.utils.AgvActionEnum;
import org.nl.acs.device_driver.basedriver.standard_ordinary_site.StandardOrdinarySiteDeviceDriver;
import org.nl.acs.device_driver.driver.AbstractDeviceDriver;
import org.nl.acs.device_driver.yinfei.hj1.Hj1DeviceDriver;
import org.nl.acs.device_driver.yinfei.hj2.Hj2DeviceDriver;
@ -236,8 +237,6 @@ public class AgvNdcOneDeviceDriver extends AbstractDeviceDriver implements Devic
lucene.deviceExecuteLog(new LuceneLogDto(this.device_code, message));
}
}
//到达桁架2请求取货
if (device.getDeviceDriver() instanceof Hj2DeviceDriver) {
hj2DeviceDriver = (Hj2DeviceDriver) device.getDeviceDriver();
@ -281,7 +280,9 @@ public class AgvNdcOneDeviceDriver extends AbstractDeviceDriver implements Devic
if (device.getDeviceDriver() instanceof SsxDeviceDriver) {
ssxDeviceDriver = (SsxDeviceDriver) device.getDeviceDriver();
//有货,待机,运行取货
log.info("tofix==================agv到达取货点==================");
if (ssxDeviceDriver.getMove() == 1 & ssxDeviceDriver.getMode() == 1 & ssxDeviceDriver.getAction() == 1) {
log.info("tofix==================agv到达取货点,有货,待机,运行取货,允许AGV取货==================");
//agv进入取货
inst.setExecute_status("1");
instructionService.update(inst);
@ -290,6 +291,7 @@ public class AgvNdcOneDeviceDriver extends AbstractDeviceDriver implements Devic
ssxDeviceDriver.setMessage("");
flag = true;
} else {
log.info("tofix==================agv到达取货点,不允许取货==================");
String message = "";
if (ssxDeviceDriver.getMode() == 0) {
message += "输送线故障,";
@ -306,6 +308,15 @@ public class AgvNdcOneDeviceDriver extends AbstractDeviceDriver implements Devic
lucene.deviceExecuteLog(new LuceneLogDto(this.device_code, message));
}
}
//到达普通站点
if (device.getDeviceDriver() instanceof StandardOrdinarySiteDeviceDriver) {
log.info("tofix==================agv到达普通站点取货点===================agvphase:" + phase + "反馈成功");
inst.setExecute_status("1");
instructionService.update(inst);
//让agv进入,phase agv运行阶段,index agv任务号 0 用不上
data = ndcAgvService.sendAgvOneModeInst(phase, index, 0);
flag = true;
}
if (flag) {
log.info("==================允许AGV取货==================");
logServer.deviceExecuteLog(device_code, "", "", "允许AGV取货。");
@ -352,8 +363,6 @@ public class AgvNdcOneDeviceDriver extends AbstractDeviceDriver implements Devic
logServer.deviceExecuteLog(this.device_code, "", "", "未找到关联编号对应的指令" + ikey);
return;
}
//到达桁架1取货完成
if (device.getDeviceDriver() instanceof Hj1DeviceDriver) {
hj1DeviceDriver = (Hj1DeviceDriver) device.getDeviceDriver();
@ -385,8 +394,6 @@ public class AgvNdcOneDeviceDriver extends AbstractDeviceDriver implements Devic
lucene.deviceExecuteLog(new LuceneLogDto(this.device_code, message));
}
}
//到达桁架2取货完成
if (device.getDeviceDriver() instanceof Hj2DeviceDriver) {
hj2DeviceDriver = (Hj2DeviceDriver) device.getDeviceDriver();
@ -418,10 +425,10 @@ public class AgvNdcOneDeviceDriver extends AbstractDeviceDriver implements Devic
lucene.deviceExecuteLog(new LuceneLogDto(this.device_code, message));
}
}
//到达输送线取货完成
if (device.getDeviceDriver() instanceof SsxDeviceDriver) {
ssxDeviceDriver = (SsxDeviceDriver) device.getDeviceDriver();
log.info("tofix==================agv取货完成==================");
if (ssxDeviceDriver.getMode() != 0 && ssxDeviceDriver.getMove() == 0) {
if (ssxDeviceDriver.getTo_command() == 3) {
//反馈车辆动作
@ -433,6 +440,7 @@ public class AgvNdcOneDeviceDriver extends AbstractDeviceDriver implements Devic
ssxDeviceDriver.setMessage("");
flag = true;
} else {
log.info("tofix==================agv允许取货离开==================");
String message = "";
if (ssxDeviceDriver.getMode() == 0) {
message += "站点未联机,";
@ -449,14 +457,19 @@ public class AgvNdcOneDeviceDriver extends AbstractDeviceDriver implements Devic
lucene.deviceExecuteLog(new LuceneLogDto(this.device_code, message));
}
}
//到达普通站点
if (device.getDeviceDriver() instanceof StandardOrdinarySiteDeviceDriver) {
log.info("tofix==================agv到达普通站点取货完成==================agvphase:" + phase + "反馈成功");
//让agv进入,phase agv运行阶段,index agv任务号 0 用不上
data = ndcAgvService.sendAgvOneModeInst(phase, index, 0);
flag = true;
}
if (flag) {
log.info("================允许AGV取货后离开=================");
logServer.deviceExecuteLog(device_code, "", "", "允许AGV取货后离开。");
log.info("{},{}", device_code, "允许AGV取货后离开。");
lucene.deviceExecuteLog(new LuceneLogDto(this.device_code, "允许AGV取货后离开。"));
}
//到达放货等待点
//(需要WCS反馈)
} else if (phase == 0x06) {
@ -485,7 +498,7 @@ public class AgvNdcOneDeviceDriver extends AbstractDeviceDriver implements Devic
}
}
device = deviceAppService.findDeviceByCode(device_code);
if (ObjectUtil.isEmpty(device_code)) {
if (ObjectUtil.isEmpty(device_code)&&!device_code.equals("0")) {
log.info(agvaddr + "对应设备号为空!");
return;
}
@ -494,8 +507,6 @@ public class AgvNdcOneDeviceDriver extends AbstractDeviceDriver implements Devic
log.info("未找到关联编号{}对应的指令", ikey);
return;
}
//到达桁架1请求放货
if (device.getDeviceDriver() instanceof Hj1DeviceDriver) {
hj1DeviceDriver = (Hj1DeviceDriver) device.getDeviceDriver();
@ -536,8 +547,6 @@ public class AgvNdcOneDeviceDriver extends AbstractDeviceDriver implements Devic
lucene.deviceExecuteLog(new LuceneLogDto(this.device_code, message));
}
}
//到达桁架2请求放货
if (device.getDeviceDriver() instanceof Hj2DeviceDriver) {
hj2DeviceDriver = (Hj2DeviceDriver) device.getDeviceDriver();
@ -578,12 +587,13 @@ public class AgvNdcOneDeviceDriver extends AbstractDeviceDriver implements Devic
lucene.deviceExecuteLog(new LuceneLogDto(this.device_code, message));
}
}
//输送线到达放货点
if (device.getDeviceDriver() instanceof SsxDeviceDriver) {
log.info("tofix==================agv到达放货点==================");
ssxDeviceDriver = (SsxDeviceDriver) device.getDeviceDriver();
//无货,待机,运行放货
if (ssxDeviceDriver.getMove() == 0 & ssxDeviceDriver.getMode() == 1 & ssxDeviceDriver.getAction() == 1) {
log.info("tofix==================agv到达放货点,无货,待机,运行放货,允许AGV放货==================");
if (inst != null) {
inst.setExecute_status("3");
instructionService.update(inst);
@ -592,6 +602,7 @@ public class AgvNdcOneDeviceDriver extends AbstractDeviceDriver implements Devic
ssxDeviceDriver.setMessage("");
flag = true;
} else {
log.info("tofix==================agv到达放货点,不允许放货==================");
String message = "";
if (ssxDeviceDriver.getMode() == 0) {
message += "站点未联机,";
@ -608,13 +619,19 @@ public class AgvNdcOneDeviceDriver extends AbstractDeviceDriver implements Devic
lucene.deviceExecuteLog(new LuceneLogDto(this.device_code, message));
}
}
//普通站点
if (device.getDeviceDriver() instanceof StandardOrdinarySiteDeviceDriver) {
log.info("tofix==================agv到达放货点==================agvphase:" + phase + "反馈成功");
//让agv进入,phase agv运行阶段,index agv任务号 0 用不上
data = ndcAgvService.sendAgvOneModeInst(phase, index, 0);
flag = true;
}
if (flag) {
log.info("==================允许AGV放货==================");
logServer.deviceExecuteLog(device_code, "", "", "允许AGV放货。");
log.info("{},{}", device_code, "允许AGV放货。");
lucene.deviceExecuteLog(new LuceneLogDto(this.device_code, "允许AGV放货。"));
}
//放货完毕
//(需要WCS反馈)
} else if (phase == 0x09) {
@ -638,7 +655,6 @@ public class AgvNdcOneDeviceDriver extends AbstractDeviceDriver implements Devic
device_code = old_device_code;
}
}
device = deviceAppService.findDeviceByCode(device_code);
if (ObjectUtil.isEmpty(device_code)) {
log.info(agvaddr + "对应设备号为空!");
@ -651,8 +667,6 @@ public class AgvNdcOneDeviceDriver extends AbstractDeviceDriver implements Devic
return;
}
transportOrder = "";
//到达桁架1放货完成
if (device.getDeviceDriver() instanceof Hj1DeviceDriver) {
hj1DeviceDriver = (Hj1DeviceDriver) device.getDeviceDriver();
@ -684,7 +698,6 @@ public class AgvNdcOneDeviceDriver extends AbstractDeviceDriver implements Devic
lucene.deviceExecuteLog(new LuceneLogDto(this.device_code, message));
}
}
//到达桁架2放货完成
if (device.getDeviceDriver() instanceof Hj2DeviceDriver) {
hj2DeviceDriver = (Hj2DeviceDriver) device.getDeviceDriver();
@ -716,9 +729,9 @@ public class AgvNdcOneDeviceDriver extends AbstractDeviceDriver implements Devic
lucene.deviceExecuteLog(new LuceneLogDto(this.device_code, message));
}
}
//到达输送线放货完成
if (device.getDeviceDriver() instanceof SsxDeviceDriver) {
log.info("tofix==================agv放货完成==================");
ssxDeviceDriver = (SsxDeviceDriver) device.getDeviceDriver();
ssxDeviceDriver.writing(4);
if (ssxDeviceDriver.getMode() != 0 && ssxDeviceDriver.getMove() != 0) {
@ -740,6 +753,7 @@ public class AgvNdcOneDeviceDriver extends AbstractDeviceDriver implements Devic
message += "站点无货,";
}
}
log.info("tofix==================agv放货完成,不允许离开==================");
message += "不允许AGV放货后离开。";
ssxDeviceDriver.setMessage(message);
agv_message = ssxDeviceDriver.getDevice_code() + message;
@ -748,7 +762,13 @@ public class AgvNdcOneDeviceDriver extends AbstractDeviceDriver implements Devic
lucene.deviceExecuteLog(new LuceneLogDto(this.device_code, message));
}
}
//agv普通站点放货完成
if (device.getDeviceDriver() instanceof StandardOrdinarySiteDeviceDriver) {
log.info("tofix==================agv普通站点放货完成==================agvphase:" + phase + "反馈成功");
//让agv进入,phase agv运行阶段,index agv任务号 0 用不上
data = ndcAgvService.sendAgvOneModeInst(phase, index, 0);
flag = true;
}
if (flag) {
log.info("================允许AGV放货后离开=================");
logServer.deviceExecuteLog(device_code, "", "", "允许AGV放货后离开。");
@ -795,8 +815,6 @@ public class AgvNdcOneDeviceDriver extends AbstractDeviceDriver implements Devic
} else if (phase == 0x75) {
is_have = ikey;
}
if (!ObjectUtil.isEmpty(data)) {
logServer.deviceExecuteLog(this.device_code, "", "", "agvphase:" + phase + "反馈:" + data);
OneNDCSocketConnectionAutoRun.write(data);

4
nladmin-system/nlsso-server/src/main/java/org/nl/acs/device_driver/basedriver/standard_ordinary_site/StandardOrdinarySiteDeviceDriver.java

@ -126,6 +126,7 @@ public class StandardOrdinarySiteDeviceDriver extends AbstractDeviceDriver imple
if (ObjectUtil.isNotEmpty(inst)) {
inst.setExecute_status("1");
instructionService.update(inst);
log.info("agvphase:" + agvphase + "反馈成功,到达普通站点。");
byte[] data = agvService.sendAgvOneModeInst(agvphase, index, 0,0,0,0,0);
agvphase = 0;
index = 0;
@ -141,6 +142,7 @@ public class StandardOrdinarySiteDeviceDriver extends AbstractDeviceDriver imple
if (ObjectUtil.isNotEmpty(inst)) {
inst.setExecute_status("2");
instructionService.update(inst);
log.info("agvphase:" + agvphase + "反馈成功,取货完成离开普通站点。");
byte[] data = agvService.sendAgvOneModeInst(agvphase, index, 0,0,0,0,0);
// OneNDCSocketConnectionAutoRun.write(data);
agvphase = 0;
@ -157,6 +159,7 @@ public class StandardOrdinarySiteDeviceDriver extends AbstractDeviceDriver imple
if (ObjectUtil.isNotEmpty(inst)) {
inst.setExecute_status("5");
instructionService.update(inst);
log.info("agvphase:" + agvphase + "反馈成功,放货完成。");
byte[] data = agvService.sendAgvOneModeInst(agvphase, index, 0,0,0,0,0);
// OneNDCSocketConnectionAutoRun.write(data);
agvphase = 0;
@ -172,6 +175,7 @@ public class StandardOrdinarySiteDeviceDriver extends AbstractDeviceDriver imple
if (ObjectUtil.isNotEmpty(inst)) {
inst.setExecute_status("6");
instructionService.update(inst);
log.info("agvphase:" + agvphase + "反馈成功,取货完成请求离开普通站点。");
byte[] data = agvService.sendAgvOneModeInst(agvphase, index, 0,0,0,0,0);
// OneNDCSocketConnectionAutoRun.write(data);
agvphase = 0;

142
nladmin-system/nlsso-server/src/main/java/org/nl/acs/log/rest/LogController.java

@ -1,71 +1,71 @@
//package org.nl.acs.log.rest;
//
//import org.nl.common.logging.annotation.Log;
//import org.nl.acs.log.service.LogService;
//import org.nl.acs.log.service.dto.LogDto;
//import org.nl.acs.log.service.dto.LogQueryParam;
//import org.springframework.data.domain.Pageable;
//import lombok.RequiredArgsConstructor;
//import org.springframework.http.HttpStatus;
//import org.springframework.http.ResponseEntity;
//import org.springframework.validation.annotation.Validated;
//import org.springframework.web.bind.annotation.*;
//import io.swagger.annotations.*;
//import java.util.Set;
//
///**
//* @author jiaolm
//* @date 2023-05-09
//**/
//@RestController
//@RequiredArgsConstructor
//@Api(tags = "acs日志管理")
//@RequestMapping("/api/log")
//public class LogController {
//
// private final LogService logService;
//
// @GetMapping
// @Log("查询acs日志")
// @ApiOperation("查询acs日志")
// //@PreAuthorize("@el.check('log:list')")
// public ResponseEntity query(LogQueryParam query, Pageable pageable){
// return new ResponseEntity<>(logService.queryAll(query,pageable),HttpStatus.OK);
// }
//
// @PostMapping
// @Log("新增acs日志")
// @ApiOperation("新增acs日志")
// //@PreAuthorize("@el.check('log:add')")
// public ResponseEntity create(@Validated @RequestBody LogDto resources){
// return new ResponseEntity<>(logService.insert(resources),HttpStatus.CREATED);
// }
//
// @PutMapping
// @Log("修改acs日志")
// @ApiOperation("修改acs日志")
// //@PreAuthorize("@el.check('log:edit')")
// public ResponseEntity update(@Validated @RequestBody LogDto resources){
// logService.updateById(resources);
// return new ResponseEntity<>(HttpStatus.NO_CONTENT);
// }
//
// @DeleteMapping
// @Log("删除acs日志")
// @ApiOperation("删除acs日志")
// //@PreAuthorize("@el.check('log:del')")
// public ResponseEntity delete(@RequestBody Set<String> ids) {
// logService.removeByIds(ids);
// return new ResponseEntity<>(HttpStatus.OK);
// }
//
// /*
// @Log("导出acs日志")
// @ApiOperation("导出acs日志")
// @GetMapping(value = "/download")
// //@PreAuthorize("@el.check('log:list')")
// public void download(HttpServletResponse response, LogQueryParam query) throws IOException {
// logService.download(logService.queryAll(query), response);
// }*/
//
//}
package org.nl.acs.log.rest;
import org.nl.common.logging.annotation.Log;
import org.nl.acs.log.service.LogService;
import org.nl.acs.log.service.dto.LogDto;
import org.nl.acs.log.service.dto.LogQueryParam;
import org.springframework.data.domain.Pageable;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import io.swagger.annotations.*;
import java.util.Set;
/**
* @author jiaolm
* @date 2023-05-09
**/
@RestController
@RequiredArgsConstructor
@Api(tags = "acs日志管理")
@RequestMapping("/api/log")
public class LogController {
private final LogService logService;
@GetMapping
@Log("查询acs日志")
@ApiOperation("查询acs日志")
//@PreAuthorize("@el.check('log:list')")
public ResponseEntity query(LogQueryParam query, Pageable pageable){
return new ResponseEntity<>(logService.queryAll(query,pageable),HttpStatus.OK);
}
@PostMapping
@Log("新增acs日志")
@ApiOperation("新增acs日志")
//@PreAuthorize("@el.check('log:add')")
public ResponseEntity create(@Validated @RequestBody LogDto resources){
return new ResponseEntity<>(logService.insert(resources),HttpStatus.CREATED);
}
@PutMapping
@Log("修改acs日志")
@ApiOperation("修改acs日志")
//@PreAuthorize("@el.check('log:edit')")
public ResponseEntity update(@Validated @RequestBody LogDto resources){
logService.updateById(resources);
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
}
@DeleteMapping
@Log("删除acs日志")
@ApiOperation("删除acs日志")
//@PreAuthorize("@el.check('log:del')")
public ResponseEntity delete(@RequestBody Set<String> ids) {
logService.removeByIds(ids);
return new ResponseEntity<>(HttpStatus.OK);
}
/*
@Log("导出acs日志")
@ApiOperation("导出acs日志")
@GetMapping(value = "/download")
//@PreAuthorize("@el.check('log:list')")
public void download(HttpServletResponse response, LogQueryParam query) throws IOException {
logService.download(logService.queryAll(query), response);
}*/
}

106
nladmin-system/nlsso-server/src/main/java/org/nl/acs/log/service/LogService.java

@ -1,53 +1,53 @@
//package org.nl.acs.log.service;
//
//import org.nl.acs.common.base.PageInfo;
//import org.nl.acs.common.base.CommonService;
//import org.nl.acs.log.domain.Log;
//import org.nl.acs.log.service.dto.LogDto;
//import org.nl.acs.log.service.dto.LogQueryParam;
//import org.springframework.data.domain.Pageable;
//import java.util.List;
//import java.util.Set;
//
///**
//* @author jiaolm
//* @date 2023-05-09
//*/
//public interface LogService extends CommonService<Log> {
//
// static final String CACHE_KEY = "log";
//
// /**
// * 查询数据分页
// * @param query 条件
// * @param pageable 分页参数
// * @return PageInfo<LogDto>
// */
// PageInfo<LogDto> queryAll(LogQueryParam query, Pageable pageable);
//
// /**
// * 查询所有数据不分页
// * @param query 条件参数
// * @return List<LogDto>
// */
// List<LogDto> queryAll(LogQueryParam query);
//
// Log getById(String id);
// LogDto findById(String id);
//
// /**
// * 插入一条新数据。
// */
// int insert(LogDto resources);
// int updateById(LogDto resources);
// int removeById(String id);
// int removeByIds(Set<String> ids);
//
// /**
// * 导出数据
// * @param all 待导出的数据
// * @param response /
// * @throws IOException /
// */
// // void download(List<LogDto> all, HttpServletResponse response) throws IOException;
//}
package org.nl.acs.log.service;
import org.nl.acs.common.base.PageInfo;
import org.nl.acs.common.base.CommonService;
import org.nl.acs.log.domain.Log;
import org.nl.acs.log.service.dto.LogDto;
import org.nl.acs.log.service.dto.LogQueryParam;
import org.springframework.data.domain.Pageable;
import java.util.List;
import java.util.Set;
/**
* @author jiaolm
* @date 2023-05-09
*/
public interface LogService extends CommonService<Log> {
static final String CACHE_KEY = "log";
/**
* 查询数据分页
* @param query 条件
* @param pageable 分页参数
* @return PageInfo<LogDto>
*/
PageInfo<LogDto> queryAll(LogQueryParam query, Pageable pageable);
/**
* 查询所有数据不分页
* @param query 条件参数
* @return List<LogDto>
*/
List<LogDto> queryAll(LogQueryParam query);
Log getById(String id);
LogDto findById(String id);
/**
* 插入一条新数据
*/
int insert(LogDto resources);
int updateById(LogDto resources);
int removeById(String id);
int removeByIds(Set<String> ids);
/**
* 导出数据
* @param all 待导出的数据
* @param response /
* @throws IOException /
*/
// void download(List<LogDto> all, HttpServletResponse response) throws IOException;
}

256
nladmin-system/nlsso-server/src/main/java/org/nl/acs/log/service/impl/LogServiceImpl.java

@ -1,128 +1,128 @@
//package org.nl.acs.log.service.impl;
//
//import com.baomidou.mybatisplus.core.metadata.IPage;
//import lombok.AllArgsConstructor;
//import org.nl.acs.common.base.PageInfo;
//import org.nl.acs.common.base.QueryHelpMybatisPlus;
//import org.nl.acs.common.base.impl.CommonServiceImpl;
//import org.nl.acs.utils.ConvertUtil;
//import org.nl.acs.utils.PageUtil;
//import org.nl.acs.log.domain.Log;
//import org.nl.acs.log.service.LogService;
//import org.nl.acs.log.service.dto.LogDto;
//import org.nl.acs.log.service.dto.LogQueryParam;
//import org.nl.acs.log.service.mapper.LogMapper;
//import org.springframework.stereotype.Service;
//import org.springframework.transaction.annotation.Propagation;
//import org.springframework.transaction.annotation.Transactional;
//// 默认不使用缓存
////import org.springframework.cache.annotation.CacheConfig;
////import org.springframework.cache.annotation.CacheEvict;
////import org.springframework.cache.annotation.Cacheable;
//import org.springframework.data.domain.Pageable;
//import java.util.*;
//
///**
//* @author jiaolm
//* @date 2023-05-09
//*/
//@Service
//@AllArgsConstructor
//// @CacheConfig(cacheNames = LogService.CACHE_KEY)
//@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
//public class LogServiceImpl extends CommonServiceImpl<LogMapper, Log> implements LogService {
//
// // private final RedisUtils redisUtils;
// private final LogMapper logMapper;
//
// @Override
// public PageInfo<LogDto> queryAll(LogQueryParam query, Pageable pageable) {
// IPage<Log> queryPage = PageUtil.toMybatisPage(pageable);
// IPage<Log> page = logMapper.selectPage(queryPage, QueryHelpMybatisPlus.getPredicate(query));
// return ConvertUtil.convertPage(page, LogDto.class);
// }
//
// @Override
// public List<LogDto> queryAll(LogQueryParam query){
// return ConvertUtil.convertList(logMapper.selectList(QueryHelpMybatisPlus.getPredicate(query)), LogDto.class);
// }
//
// @Override
// public Log getById(String id) {
// return logMapper.selectById(id);
// }
//
// @Override
// // @Cacheable(key = "'id:' + #p0")
// public LogDto findById(String id) {
// return ConvertUtil.convert(getById(id), LogDto.class);
// }
//
// @Override
// @Transactional(rollbackFor = Exception.class)
// public int insert(LogDto resources) {
// Log entity = ConvertUtil.convert(resources, Log.class);
// return logMapper.insert(entity);
// }
//
// @Override
// @Transactional(rollbackFor = Exception.class)
// public int updateById(LogDto resources){
// Log entity = ConvertUtil.convert(resources, Log.class);
// int ret = logMapper.updateById(entity);
// // delCaches(resources.id);
// return ret;
// }
//
// @Override
// @Transactional(rollbackFor = Exception.class)
// public int removeByIds(Set<String> ids){
// // delCaches(ids);
// return logMapper.deleteBatchIds(ids);
// }
//
// @Override
// @Transactional(rollbackFor = Exception.class)
// public int removeById(String id){
// Set<String> set = new HashSet<>(1);
// set.add(id);
// return this.removeByIds(set);
// }
//
// /*
// private void delCaches(String id) {
// redisUtils.delByKey(CACHE_KEY + "::id:", id);
// }
//
// private void delCaches(Set<String> ids) {
// for (String id: ids) {
// delCaches(id);
// }
// }*/
//
// /*
// @Override
// public void download(List<LogDto> all, HttpServletResponse response) throws IOException {
// List<Map<String, Object>> list = new ArrayList<>();
// for (LogDto log : all) {
// Map<String,Object> map = new LinkedHashMap<>();
// map.put("任务编码", log.getTaskCode());
// map.put("任务标识", log.getTaskId());
// map.put(" vehicleCode", log.getVehicleCode());
// map.put("备注", log.getRemark());
// map.put("日志类型", log.getLogType());
// map.put("方法", log.getMethod());
// map.put("请求参数", log.getRequestparam());
// map.put("返回参数", log.getResponseparam());
// map.put("请求地址", log.getRequesturl());
// map.put("状态码", log.getStatusCode());
// map.put("是否删除", log.getIsDelete());
// map.put("创建者", log.getCreateBy());
// map.put("创建时间", log.getCreateTime());
// map.put("修改者", log.getUpdateBy());
// map.put("修改时间", log.getUpdateTime());
// list.add(map);
// }
// FileUtil.downloadExcel(list, response);
// }*/
//}
package org.nl.acs.log.service.impl;
import com.baomidou.mybatisplus.core.metadata.IPage;
import lombok.AllArgsConstructor;
import org.nl.acs.common.base.PageInfo;
import org.nl.acs.common.base.QueryHelpMybatisPlus;
import org.nl.acs.common.base.impl.CommonServiceImpl;
import org.nl.acs.utils.ConvertUtil;
import org.nl.acs.utils.PageUtil;
import org.nl.acs.log.domain.Log;
import org.nl.acs.log.service.LogService;
import org.nl.acs.log.service.dto.LogDto;
import org.nl.acs.log.service.dto.LogQueryParam;
import org.nl.acs.log.service.mapper.LogMapper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
// 默认不使用缓存
//import org.springframework.cache.annotation.CacheConfig;
//import org.springframework.cache.annotation.CacheEvict;
//import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.domain.Pageable;
import java.util.*;
/**
* @author jiaolm
* @date 2023-05-09
*/
@Service
@AllArgsConstructor
// @CacheConfig(cacheNames = LogService.CACHE_KEY)
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class LogServiceImpl extends CommonServiceImpl<LogMapper, Log> implements LogService {
// private final RedisUtils redisUtils;
private final LogMapper logMapper;
@Override
public PageInfo<LogDto> queryAll(LogQueryParam query, Pageable pageable) {
IPage<Log> queryPage = PageUtil.toMybatisPage(pageable);
IPage<Log> page = logMapper.selectPage(queryPage, QueryHelpMybatisPlus.getPredicate(query));
return ConvertUtil.convertPage(page, LogDto.class);
}
@Override
public List<LogDto> queryAll(LogQueryParam query){
return ConvertUtil.convertList(logMapper.selectList(QueryHelpMybatisPlus.getPredicate(query)), LogDto.class);
}
@Override
public Log getById(String id) {
return logMapper.selectById(id);
}
@Override
// @Cacheable(key = "'id:' + #p0")
public LogDto findById(String id) {
return ConvertUtil.convert(getById(id), LogDto.class);
}
@Override
@Transactional(rollbackFor = Exception.class)
public int insert(LogDto resources) {
Log entity = ConvertUtil.convert(resources, Log.class);
return logMapper.insert(entity);
}
@Override
@Transactional(rollbackFor = Exception.class)
public int updateById(LogDto resources){
Log entity = ConvertUtil.convert(resources, Log.class);
int ret = logMapper.updateById(entity);
// delCaches(resources.id);
return ret;
}
@Override
@Transactional(rollbackFor = Exception.class)
public int removeByIds(Set<String> ids){
// delCaches(ids);
return logMapper.deleteBatchIds(ids);
}
@Override
@Transactional(rollbackFor = Exception.class)
public int removeById(String id){
Set<String> set = new HashSet<>(1);
set.add(id);
return this.removeByIds(set);
}
/*
private void delCaches(String id) {
redisUtils.delByKey(CACHE_KEY + "::id:", id);
}
private void delCaches(Set<String> ids) {
for (String id: ids) {
delCaches(id);
}
}*/
/*
@Override
public void download(List<LogDto> all, HttpServletResponse response) throws IOException {
List<Map<String, Object>> list = new ArrayList<>();
for (LogDto log : all) {
Map<String,Object> map = new LinkedHashMap<>();
map.put("任务编码", log.getTaskCode());
map.put("任务标识", log.getTaskId());
map.put(" vehicleCode", log.getVehicleCode());
map.put("备注", log.getRemark());
map.put("日志类型", log.getLogType());
map.put("方法", log.getMethod());
map.put("请求参数", log.getRequestparam());
map.put("返回参数", log.getResponseparam());
map.put("请求地址", log.getRequesturl());
map.put("状态码", log.getStatusCode());
map.put("是否删除", log.getIsDelete());
map.put("创建者", log.getCreateBy());
map.put("创建时间", log.getCreateTime());
map.put("修改者", log.getUpdateBy());
map.put("修改时间", log.getUpdateTime());
list.add(map);
}
FileUtil.downloadExcel(list, response);
}*/
}

28
nladmin-system/nlsso-server/src/main/java/org/nl/acs/utils/YmlConfigFileUtil.java

@ -0,0 +1,28 @@
package org.nl.acs.utils;
import org.springframework.beans.factory.config.YamlPropertiesFactoryBean;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import java.util.Properties;
/**
* @Author: lyd
* @Description: 配置文件获取方法
* @Date: 2023/12/6
*/
public class YmlConfigFileUtil {
public static Properties readConfig(String configFile) {
// 创建 Resource 对象
Resource resource = new ClassPathResource(configFile);
// 创建 YamlPropertiesFactoryBean
YamlPropertiesFactoryBean yamlPropertiesFactoryBean = new YamlPropertiesFactoryBean();
yamlPropertiesFactoryBean.setResources(resource);
// 获取 Properties 对象
Properties properties = yamlPropertiesFactoryBean.getObject();
return properties;
}
}

23
nladmin-system/nlsso-server/src/main/java/org/nl/config/lucene/AsyncLuceneAppender.java

@ -7,10 +7,10 @@ package org.nl.config.lucene;
*/
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.nl.config.lucene.remote.RemoteLogServer;
import org.slf4j.MDC;
import java.util.Map;
@ -18,25 +18,24 @@ import java.util.Map;
public class AsyncLuceneAppender extends AspectLogbackAsyncAppender {
public AsyncLuceneAppender() {
RemoteLogServer.asyncLuceneAppender = this;
}
@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+"@");
}
}
String traceId = LuceneAppender.traceIdTL.get();
if (StringUtils.isNotEmpty(traceId)){
MDC.put("traceId",traceId);
MDC.put("traceId",traceId);
Map<String, String> mdcPropertyMap = event.getMDCPropertyMap();
if (mdcPropertyMap.getClass().getName().contains("SynchronizedMap")){
mdcPropertyMap.put("traceId",traceId);
}
MDC.clear();
}
RemoteLogServer.writeLog(event);
}
public void appendSync(ILoggingEvent event){
super.append(event);
}

6
nladmin-system/nlsso-server/src/main/java/org/nl/config/lucene/LogMessageConstant.java

@ -6,6 +6,8 @@ package org.nl.config.lucene;
* @Date: 2023/8/25
*/
public class LogMessageConstant {
/** */
public final static String SORT_NAME = "time";
/** 级别 */
public final static String FIELD_LEVEL = "level";
/** 时间 */
@ -38,7 +40,7 @@ public class LogMessageConstant {
public final static String COLOR_RESET = "\u001B[0m";
/** 背景颜色:黄色 */
public final static String BACKGROUND_YELLOW = "\u001B[43m";
/** 索引路径 */
public final static String INDEX_DIR = "D:\\lucene\\index";
public final static String INDEX_DIR = "E:\\lucene\\index";
}

111
nladmin-system/nlsso-server/src/main/java/org/nl/config/lucene/LuceneAppender.java

@ -8,47 +8,48 @@ package org.nl.config.lucene;
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.commons.lang3.StringUtils;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.NumericDocValuesField;
import org.apache.lucene.document.StringField;
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.system.service.lucene.dto.LuceneLogDto;
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> {
private Directory index;
private IndexWriter indexWriter;
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 {
index = FSDirectory.open(Paths.get(LogMessageConstant.INDEX_DIR));
} catch (IOException e) {
e.printStackTrace();
}
// 读取配置文件
Properties properties = org.nl.acs.utils.YmlConfigFileUtil.readConfig("config/application.yml");
// 初始化 Lucene 索引
Analyzer analyzer = new IKAnalyzer();
IndexWriterConfig config = new IndexWriterConfig(analyzer);
try {
// 获取配置值
String luceneDir = properties.getProperty("lucene.index.path");
System.out.println("---index地址----"+luceneDir);
index = FSDirectory.open(Paths.get(luceneDir));
// 初始化 Lucene 索引
Analyzer analyzer = new IKAnalyzer();
IndexWriterConfig config = new IndexWriterConfig(analyzer);
indexWriter = new IndexWriter(index, config);
} catch (IOException e) {
} catch (Exception e) {
e.printStackTrace();
}
}
@ -56,52 +57,27 @@ public class LuceneAppender extends AppenderBase<ILoggingEvent> {
@Override
protected void append(ILoggingEvent event) {
String message = event.getFormattedMessage();
try {
// String[] split = message.split("@");
LuceneLogDto luceneLogDto = JSONObject.parseObject(message, 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("time",System.currentTimeMillis()));//排序
Document doc = new Document();
for (Property property : this.properties.getProperties()) {
LucenePropertyAndEncoder encoder = new LucenePropertyAndEncoder(property, this.context);
String encode = encoder.encode(event);
doc.add(new StringField(property.getName(), encode, Field.Store.YES));
}
Map<String, String> map = event.getMDCPropertyMap();
if (!map.isEmpty() && StringUtils.isNotEmpty(map.get("traceId"))){
doc.add(new StringField("traceId",map.get("traceId"), Field.Store.YES));
}else {
doc.add(new StringField("traceId"," ", Field.Store.YES));
}
try {
indexWriter.addDocument(document);
indexWriter.commit();
} catch (IOException e) {
e.printStackTrace();
}
} catch (Exception e) {
return;
}
} catch (Exception e){
return;
doc.add(new TextField(LogMessageConstant.FIELD_MESSAGE, event.getFormattedMessage(), Field.Store.YES));
doc.add(new StringField(LogMessageConstant.FIELD_TIMESTAMP, String.valueOf(event.getTimeStamp()),Field.Store.YES));
doc.add(new NumericDocValuesField(LogMessageConstant.SORT_NAME, event.getTimeStamp()));
try {
indexWriter.addDocument(doc);
indexWriter.commit();
} catch (Exception e) {
e.printStackTrace();
}
}
@ -114,4 +90,9 @@ public class LuceneAppender extends AppenderBase<ILoggingEvent> {
e.printStackTrace();
}
}
public void setProperties(LuceneProperties properties) {
this.properties = properties;
}
}

60
nladmin-system/nlsso-server/src/main/java/org/nl/config/lucene/LuceneIndexWriter.java

@ -1,60 +0,0 @@
package org.nl.config.lucene;//package org.nl.config.lucene;
//
//import cn.hutool.core.date.DateUtil;
//import org.apache.lucene.index.CorruptIndexException;
//import org.apache.lucene.index.IndexWriter;
//import org.apache.lucene.index.IndexWriterConfig;
//import org.apache.lucene.store.Directory;
//import org.apache.lucene.store.FSDirectory;
//import org.wltea.analyzer.lucene.IKAnalyzer;
//
//import java.io.File;
//import java.io.IOException;
//import java.text.ParseException;
//import java.text.SimpleDateFormat;
//import java.util.Date;
//
//public class LuceneIndexWriter {
// private static IndexWriter indexWriter;
//
// static {
// try {
// Directory directory = FSDirectory.open(new File(UrlConfig.luceneUrl).toPath());
// IndexWriterConfig config = new IndexWriterConfig(new IKAnalyzer());
// indexWriter = new IndexWriter(directory, config);
// } catch (Exception e) {
// e.printStackTrace();
// }
// /**当当前线程结束时,自动关闭IndexWriter,使用Runtime对象*/
// Runtime.getRuntime().addShutdownHook(new Thread(() -> {
// try {
// closeIndexWriter();
// } catch (Exception e) {
// e.printStackTrace();
// }
// }));
// }
// /**在线程结束时,自动关闭IndexWriter*/
// public static IndexWriter getIndexWriter() {
// return indexWriter;
// }
// /**关闭IndexWriter
// * @throws IOException
// * @throws CorruptIndexException */
// public static void closeIndexWriter() throws Exception {
// if(indexWriter != null) {
// indexWriter.close();
// }
// }
//
// public static void main(String[] args) throws IOException {
// indexWriter.deleteAll();
// }
//
// 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;
// }
//}

23
nladmin-system/nlsso-server/src/main/java/org/nl/config/lucene/LuceneProperties.java

@ -0,0 +1,23 @@
package org.nl.config.lucene;
import java.util.ArrayList;
import java.util.List;
public class LuceneProperties {
private List<Property> properties;
public LuceneProperties() {
this.properties = new ArrayList<Property>();
}
public List<Property> getProperties() {
return properties;
}
public void addProperty(Property property) {
properties.add(property);
}
}

38
nladmin-system/nlsso-server/src/main/java/org/nl/config/lucene/LucenePropertyAndEncoder.java

@ -0,0 +1,38 @@
package org.nl.config.lucene;
import ch.qos.logback.classic.PatternLayout;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.Context;
import ch.qos.logback.core.pattern.PatternLayoutBase;
/*
* @author ZZQ
* @Date 2023/12/22 18:11
*/
public class LucenePropertyAndEncoder {
private Property property;
private PatternLayoutBase layout = new PatternLayout();
public LucenePropertyAndEncoder(Property property, Context context) {
this.property = property;
this.layout.setContext(context);
this.layout.setPattern(String.valueOf(property.getValue()));
this.layout.setPostCompileProcessor(null);
this.layout.start();
}
public String encode(ILoggingEvent event) {
return layout.doLayout(event);
}
public String getName() {
return property.getName();
}
public boolean allowEmpty() {
return property.isAllowEmpty();
}
}

44
nladmin-system/nlsso-server/src/main/java/org/nl/config/lucene/Property.java

@ -0,0 +1,44 @@
package org.nl.config.lucene;
/*
* @author ZZQ
* @Date 2023/12/26 15:30
*/
public class Property {
private String name;
private String value;
private boolean allowEmpty;
public Property() {
}
public Property(String name, String value, boolean allowEmpty) {
this.name = name;
this.value = value;
this.allowEmpty = allowEmpty;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public boolean isAllowEmpty() {
return allowEmpty;
}
public void setAllowEmpty(boolean allowEmpty) {
this.allowEmpty = allowEmpty;
}
}

21
nladmin-system/nlsso-server/src/main/java/org/nl/config/lucene/StaticConfig.java

@ -1,21 +0,0 @@
package org.nl.config.lucene;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @deprecated 设置静态参数初始化
*/
@Configuration
public class StaticConfig {
//日志索引目录
@Value("${lucene.index.path}")
private String luceneDir;
@Bean
public int initStatic() {
UrlConfig.setLuceneUrl(luceneDir);
return 0;
}
}

45
nladmin-system/nlsso-server/src/main/java/org/nl/config/lucene/remote/AbstraceServer.java

@ -0,0 +1,45 @@
package org.nl.config.lucene.remote;
import io.netty.bootstrap.AbstractBootstrap;
import io.netty.channel.Channel;
import java.net.SocketAddress;
/*
* @author ZZQ
* @Date 2024/1/22 10:01
*/
public abstract class AbstraceServer {
public AbstraceServer(SocketAddress address) {
this.address = address;
if (channel!=null){
doDestroy();
}
doOpen();
doConnect();
}
public AbstractBootstrap server;
public SocketAddress address;
public Channel channel;
public abstract void doOpen();
public void doDestroy(){
if (channel!=null){
channel.close();
}
};
public abstract void doConnect() ;
public void doDisConnect(){
if (channel!=null){
channel.close();
channel.flush();
doConnect();
}
};
}

94
nladmin-system/nlsso-server/src/main/java/org/nl/config/lucene/remote/RemoteLogServer.java

@ -0,0 +1,94 @@
package org.nl.config.lucene.remote;
import ch.qos.logback.classic.spi.ILoggingEvent;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.util.CharsetUtil;
import lombok.SneakyThrows;
import org.apache.commons.lang3.StringUtils;
import org.nl.config.MapOf;
import org.nl.config.lucene.AsyncLuceneAppender;
import org.nl.config.lucene.remote.impl.ClientServer;
import org.nl.config.lucene.remote.impl.RemoteServer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.SmartLifecycle;
import org.springframework.data.redis.core.StringRedisTemplate;
import java.net.Inet4Address;
import java.net.InetSocketAddress;
import java.util.HashMap;
import java.util.Map;
/*
* @author ZZQ
* @Date 2024/1/22 09:06
*/
//@Component
public class RemoteLogServer implements SmartLifecycle {
@Autowired
private StringRedisTemplate redisTemplate;
public static volatile Boolean LOCAL_LOG = Boolean.TRUE;
private Integer port = 20888;
public static AbstraceServer server;
public static AsyncLuceneAppender asyncLuceneAppender;
public static void writeLog(ILoggingEvent event){
if (LOCAL_LOG){
asyncLuceneAppender.appendSync(event);
}else {
ByteBuf log = Unpooled.copiedBuffer(JSON.toJSONString(event), CharsetUtil.UTF_8);
server.channel.writeAndFlush(log);
}
};
@SneakyThrows
@Override
public void start() {
try {
String provider = redisTemplate.opsForValue().get("providers");
if (StringUtils.isEmpty(provider)){
String ip = Inet4Address.getLocalHost().getHostAddress();
Map<String,Object> config = MapOf.of("ip", ip, "port", port);
redisTemplate.opsForValue().set("provider", JSON.toJSONString(config));
Runtime.getRuntime().addShutdownHook(new Thread(() ->{
System.out.println("------服务关闭-升级从变主-------");
server.doDestroy();
redisTemplate.delete("providers");
try {
Thread.sleep(5000);
}catch (Exception ex){}
}));
server = new RemoteServer(new InetSocketAddress(ip, port));
LOCAL_LOG =Boolean.TRUE;
}else {
Map<String,String> map = JSONObject.parseObject(provider, HashMap.class);
String ip = map.get("ip");
Integer port = Integer.valueOf(map.get("port"));
server = new ClientServer(new InetSocketAddress(ip, port));
LOCAL_LOG = Boolean.FALSE;
}
}catch (Exception ex){
ex.printStackTrace();
throw ex;
}
}
@Override
public void stop() {
}
@Override
public boolean isRunning() {
return false;
}
}

44
nladmin-system/nlsso-server/src/main/java/org/nl/config/lucene/remote/coder/LogConsumerHandler.java

@ -0,0 +1,44 @@
package org.nl.config.lucene.remote.coder;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.handler.timeout.IdleStateEvent;
import org.nl.config.lucene.remote.RemoteLogServer;
/*
* @author ZZQ
* @Date 2024/1/22 10:24
*/
public class LogConsumerHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
System.out.println("断开连接---");
RemoteLogServer.LOCAL_LOG = Boolean.TRUE;
RemoteLogServer.server.doDestroy();
//重新建立
super.channelInactive(ctx);
}
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
System.out.println("连接");
super.channelActive(ctx);
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
System.out.println("接收到消息");
super.channelRead(ctx, msg);
}
@Override
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
if (evt instanceof IdleStateEvent){
IdleStateEvent stateEvent = (IdleStateEvent) evt;
System.out.println(stateEvent.state());
}
super.userEventTriggered(ctx, evt);
}
}

33
nladmin-system/nlsso-server/src/main/java/org/nl/config/lucene/remote/coder/LogProviderHandler.java

@ -0,0 +1,33 @@
package org.nl.config.lucene.remote.coder;
import ch.qos.logback.classic.spi.LoggingEvent;
import com.alibaba.fastjson.JSONObject;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import org.nl.config.lucene.remote.RemoteLogServer;
/*
* @author ZZQ
* @Date 2024/1/22 10:24
*/
public class LogProviderHandler extends SimpleChannelInboundHandler<String> {
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
System.out.println("断开连接---");
super.channelInactive(ctx);
}
@Override
protected void channelRead0(ChannelHandlerContext ctx, String c){
LoggingEvent event = JSONObject.parseObject(c, LoggingEvent.class);
RemoteLogServer.asyncLuceneAppender.appendSync(event);
}
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
System.out.println("创建了连接----");
super.channelActive(ctx);
}
}

75
nladmin-system/nlsso-server/src/main/java/org/nl/config/lucene/remote/impl/ClientServer.java

@ -0,0 +1,75 @@
package org.nl.config.lucene.remote.impl;
import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.PooledByteBufAllocator;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.LengthFieldPrepender;
import io.netty.handler.timeout.IdleStateHandler;
import io.netty.util.concurrent.Future;
import org.nl.config.lucene.remote.AbstraceServer;
import org.nl.config.lucene.remote.coder.LogConsumerHandler;
import java.net.SocketAddress;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
/*
* @author ZZQ
* @Date 2024/1/22 10:01
*/
public class ClientServer extends AbstraceServer {
private static EventLoopGroup group = new NioEventLoopGroup();
public ClientServer(SocketAddress address) {
super(address);
}
// 非阻塞IO线程组
@Override
public void doOpen() {
server = new Bootstrap();
server.group(group)
.option(ChannelOption.SO_KEEPALIVE, true)
.option(ChannelOption.TCP_NODELAY, true)
.option(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT)
.channel(NioSocketChannel.class);
server.handler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ch.pipeline()
.addLast("client-idle-handler", new IdleStateHandler(500, 0,0 , MILLISECONDS))
.addLast(new LengthFieldPrepender(2))
.addLast( new LogConsumerHandler());
}
});
}
@Override
public void doDestroy() {
super.doDestroy();
Future<?> bossGroupShutdownFuture = group.shutdownGracefully();
bossGroupShutdownFuture.syncUninterruptibly();
}
@Override
public void doConnect() {
try {
ChannelFuture connect = ((Bootstrap) server).connect(address);
connect.syncUninterruptibly();
channel = connect.channel();
} catch (Throwable t) {
this.doDestroy();
throw t;
}
}
}

83
nladmin-system/nlsso-server/src/main/java/org/nl/config/lucene/remote/impl/RemoteServer.java

@ -0,0 +1,83 @@
package org.nl.config.lucene.remote.impl;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.PooledByteBufAllocator;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import io.netty.handler.codec.LengthFieldPrepender;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.timeout.IdleStateHandler;
import io.netty.util.concurrent.Future;
import org.nl.config.lucene.remote.AbstraceServer;
import org.nl.config.lucene.remote.coder.LogProviderHandler;
import java.net.SocketAddress;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
/*
* @author ZZQ
* @Date 2024/1/22 10:01
*/
public class RemoteServer extends AbstraceServer {
private static EventLoopGroup boss = new NioEventLoopGroup();
private static EventLoopGroup worker = new NioEventLoopGroup();
public RemoteServer(SocketAddress address) {
super(address);
}
// 非阻塞IO线程组
@Override
public void doOpen() {
ServerBootstrap bootstrap = new ServerBootstrap();
bootstrap
.group(boss, worker)
.channel(NioServerSocketChannel.class)
.option(ChannelOption.SO_REUSEADDR, Boolean.TRUE)
.childOption(ChannelOption.TCP_NODELAY, Boolean.TRUE)
.childOption(ChannelOption.SO_KEEPALIVE, Boolean.TRUE)
.childOption(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT)
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ch.pipeline()
.addLast("client-idle-handler", new IdleStateHandler(500, 0, 0, MILLISECONDS))
.addLast(new LengthFieldBasedFrameDecoder(8089, 0, 2, 0, 2))
.addLast(new LengthFieldPrepender(2))
.addLast("encode",new StringDecoder())
.addLast(new LogProviderHandler());
}
});
server = bootstrap;
}
@Override
public void doDestroy(){
Future<?> bossGroupShutdownFuture = boss.shutdownGracefully();
Future<?> workerGroupShutdownFuture = worker.shutdownGracefully();
bossGroupShutdownFuture.syncUninterruptibly();
workerGroupShutdownFuture.syncUninterruptibly();
}
@Override
public void doConnect() {
ChannelFuture future = server.bind(address);
boolean ret = future.awaitUninterruptibly(3000, MILLISECONDS);
if (ret && future.isSuccess()) {
Channel newChannel = future.channel();
if (channel != null) {
channel.close();
channel = newChannel;
}
} else if (future.cause() != null) {
Throwable cause = future.cause();
cause.printStackTrace();
}
}
}

31
nladmin-system/nlsso-server/src/main/java/org/nl/system/controller/lucence/LuceneController.java

@ -1,25 +1,24 @@
package org.nl.system.controller.lucence;
import cn.dev33.satoken.annotation.SaIgnore;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.nl.common.logging.annotation.Log;
import org.nl.system.service.lucene.LuceneService;
import org.nl.system.service.lucene.dto.LogQuery;
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 org.springframework.web.bind.annotation.*;
import java.util.Map;
@RestController
@RequiredArgsConstructor
@Api(tags = "日志检索")
@RequestMapping("/api/lucene")
@RequestMapping("/api/esLog")
@Slf4j
public class LuceneController {
@ -32,4 +31,26 @@ public class LuceneController {
public ResponseEntity<Object> get(@RequestParam Map whereJson, Pageable page) {
return new ResponseEntity<>(luceneService.getAll(whereJson, page), HttpStatus.OK);
}
@PostMapping("/query")
//("日志查询")
public ResponseEntity<Object> query(@RequestBody LogQuery query) {
return new ResponseEntity<>(luceneService.query(query), HttpStatus.OK);
}
@GetMapping("/labels/{type}")
//("获取标签")
public ResponseEntity<Object> labelsValues(@PathVariable String type) {
return new ResponseEntity<>(luceneService.getLabelsValues(type), HttpStatus.OK);
}
@DeleteMapping("/clearLogs")
//("清空日志")
public ResponseEntity<Object> clearLogs(@RequestBody LogQuery query) {
luceneService.clearLogs(query);
return new ResponseEntity<>(HttpStatus.OK);
}
}

28
nladmin-system/nlsso-server/src/main/java/org/nl/system/service/lucene/LuceneService.java

@ -1,6 +1,8 @@
package org.nl.system.service.lucene;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.nl.system.service.lucene.dto.LogQuery;
import org.springframework.data.domain.Pageable;
import java.util.Map;
@ -21,4 +23,30 @@ public interface LuceneService {
* @return Map<String, Object>
*/
Map<String, Object> getAll(Map whereJson, Pageable page);
/**
* 日志查询
*
* @param logQuery
* @return
*/
JSONObject query(LogQuery logQuery);
/**
* 清空日志
*/
void clearLogs(LogQuery query);
/**
* 获取labels和values树
*
* @return
*/
JSONArray getLabelsValues(String type);
}

47
nladmin-system/nlsso-server/src/main/java/org/nl/system/service/lucene/dto/LogQuery.java

@ -0,0 +1,47 @@
package org.nl.system.service.lucene.dto;
import lombok.Data;
import java.util.Date;
/*
* @author ZZQ
* @Date 2023/2/8 5:18 下午
*/
@Data
public class LogQuery {
/**
* 创建时间范围查询
*/
private Date startTime;
private Date endTime;
/**
* 追踪id
*/
private String traceId;
private String requestMethod;
/**
* 日志内容模糊匹配
*/
private String message;
/**
* 日志级别
*/
private String logLevel;
/**
* 系统标签
*/
private String system;
/**
* 是否只查询Http相关请求
*/
private Boolean isRequest = Boolean.TRUE;
/**
* 是否过滤wql日志
*/
private Boolean filterSql = Boolean.TRUE;
private Integer size = 20;
private Integer page = 1;
}

27
nladmin-system/nlsso-server/src/main/java/org/nl/system/service/lucene/dto/LogRepositoryDTO.java

@ -0,0 +1,27 @@
package org.nl.system.service.lucene.dto;
import lombok.Data;
import org.springframework.data.annotation.Id;
/*
* @author ZZQ
* @Date 2023/2/8 4:06 下午
*/
//@Document(indexName = "#{@ESConfig.index}", type = "mes_log")
@Data
public class LogRepositoryDTO {
private String message;
private String host;
private String logLevel;
private String logger;
private String requestTime;
private String requestIp;
@Id
private String id;
private String traceId;
private String requestMethod;
private String thread;
private String system;
}

204
nladmin-system/nlsso-server/src/main/java/org/nl/system/service/lucene/impl/LuceneServiceImpl.java

@ -1,18 +1,44 @@
package org.nl.system.service.lucene.impl;
import cn.dev33.satoken.annotation.SaIgnore;
import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.db.PageResult;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSONArray;
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.IndexWriter;
import org.apache.lucene.index.Term;
import org.apache.lucene.queryparser.classic.QueryParser;
import org.apache.lucene.search.*;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.util.BytesRef;
import org.nl.common.exception.BadRequestException;
import org.nl.config.lucene.LuceneAppender;
import org.nl.config.lucene.Searcher;
import org.nl.system.service.lucene.LuceneService;
import org.nl.system.service.lucene.dto.LogQuery;
import org.nl.system.service.lucene.dto.LogRepositoryDTO;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Pageable;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.wltea.analyzer.lucene.IKAnalyzer;
import java.util.Map;
import java.nio.file.Paths;
import java.util.*;
@Service
@ -20,56 +46,147 @@ import java.util.Map;
@Slf4j
public class LuceneServiceImpl implements LuceneService {
// @Value("${loki.url}")
// private String lokiUrl;
// @Value("${loki.systemName}")
// private String systemName;
//日志索引目录
static String[] INFO_LEVEL = new String[]{"DEBUG","INFO","WARN","ERROR"};
@Value("${lucene.index.path}")
private String luceneUrl;
/**
* 获取labels和values树
*
* @return
*/
// @Override
// public JSONArray getLabelsValues() {
// 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;
// }
private String indexUrl;
@Override
public JSONObject query(LogQuery logQuery) {
JSONObject res = new JSONObject();
PageResult page = new PageResult();
page.setPage(logQuery.getPage());
page.setPageSize(logQuery.getSize());
try {
FSDirectory directory = FSDirectory.open(Paths.get(indexUrl));
DirectoryReader open = DirectoryReader.open(directory);
IndexSearcher searcher = new IndexSearcher(open);
// 创建排序对象,需要排序字段SortField,参数:字段的名称、字段的类型、是否反转如果是false,升序。true降序
BooleanQuery.Builder booleanQueryBuilder = new BooleanQuery.Builder();
//时间范围查询
Date startDate = logQuery.getStartTime();
Date endDate = logQuery.getEndTime();
if (startDate == null){
Calendar calendar=Calendar.getInstance();
calendar.set(1970, 0, 1);
startDate = calendar.getTime(); }
if (endDate == null){ endDate = new DateTime(); }
TermRangeQuery termRangeQuery = new TermRangeQuery(
"requestTime",
new BytesRef(DateUtil.format(startDate, "yyyy-MM-dd HH:mm:ss.SSS")),
new BytesRef(DateUtil.format(endDate, "yyyy-MM-dd HH:mm:ss.SSS")), true, true);
booleanQueryBuilder.add(termRangeQuery, BooleanClause.Occur.MUST);
// 字段之间的与或非关系,MUST表示and,MUST_NOT表示not,SHOULD表示or,有几个fields就必须有几个clauses
if (ObjectUtil.isNotEmpty(logQuery.getTraceId())){
TermQuery termQuery = new TermQuery(new Term("traceId", logQuery.getTraceId()));
booleanQueryBuilder.add(termQuery, BooleanClause.Occur.MUST);
}
if (ObjectUtil.isNotEmpty(logQuery.getLogLevel())){
TermQuery termQuery = new TermQuery(new Term("logLevel", logQuery.getLogLevel()));
booleanQueryBuilder.add(termQuery, BooleanClause.Occur.MUST);
}
if (ObjectUtil.isNotEmpty(logQuery.getSystem())) {
TermQuery termQuery = new TermQuery(new Term("system", logQuery.getSystem()));
booleanQueryBuilder.add(termQuery, BooleanClause.Occur.MUST);
}
if (ObjectUtil.isNotEmpty(logQuery.getRequestMethod())) {
TermQuery termQuery = new TermQuery(new Term("requestMethod", logQuery.getRequestMethod()));
booleanQueryBuilder.add(termQuery, BooleanClause.Occur.MUST);
}
if (Boolean.TRUE.equals(logQuery.getIsRequest())) {
Term traceid = new Term("traceId");
TermQuery termQuery = new TermQuery(traceid);
booleanQueryBuilder.add(termQuery, BooleanClause.Occur.MUST_NOT);
}
if (ObjectUtil.isNotEmpty(logQuery.getMessage())){
//查询解析器
QueryParser queryParser = new QueryParser("message", new IKAnalyzer(true));
Query query = queryParser.parse(logQuery.getMessage());
booleanQueryBuilder.add(query, BooleanClause.Occur.MUST);
}
TopFieldCollector collector = TopFieldCollector.create(new Sort(new SortField("time", SortField.Type.LONG,true)), 20000, 0);
searcher.search(booleanQueryBuilder.build(), collector);
TopDocs topDocs = collector.topDocs((logQuery.getPage()-1)*logQuery.getSize(), logQuery.getSize());
int totalSize = collector.getTotalHits();
ScoreDoc[] scoreDocs = topDocs.scoreDocs;
List<LogRepositoryDTO> list = new ArrayList<>();
for (ScoreDoc scoreDoc : scoreDocs) {
Document doc = open.document(scoreDoc.doc);
LogRepositoryDTO dto = new LogRepositoryDTO();
dto.setSystem(doc.get("system"));
dto.setTraceId(doc.get("traceId"));
dto.setLogger(doc.get("logger"));
dto.setLogLevel(doc.get("logLevel"));
dto.setMessage(doc.get("message"));
dto.setRequestIp(doc.get("requestIp"));
dto.setRequestMethod(doc.get("requestMethod"));
dto.setRequestTime(doc.get("requestTime"));
dto.setThread(doc.get("thread"));
list.add(dto);
}
open.close();
directory.close();
page.addAll(list);
page.setTotal(scoreDocs.length);
res.put("total", totalSize);
}catch (Exception ex){
ex.printStackTrace();
}
res.put("page",page);
return res;
}
@Override
public void clearLogs(LogQuery query) {
try {
IndexWriter indexWriter = LuceneAppender.indexWriter;
if (indexWriter != null){
BooleanQuery.Builder booleanQueryBuilder = new BooleanQuery.Builder();
DateTime offset = DateUtil.offset(new Date(), DateField.HOUR_OF_DAY, -10);
TermRangeQuery termRangeQuery = new TermRangeQuery(
"requestTime",null,
new BytesRef(DateUtil.format(offset, "yyyy-MM-dd HH:mm:ss.SSS")), true, true);
booleanQueryBuilder.add(termRangeQuery,BooleanClause.Occur.MUST);
indexWriter.deleteDocuments(termRangeQuery);
indexWriter.commit();
}
}catch (Exception ex){
throw new BadRequestException("删除失败:"+ex.getMessage());
}
}
@Override
public JSONArray getLabelsValues(String type) {
JSONArray result = new JSONArray();
for (String v : INFO_LEVEL) {
JSONObject item = new JSONObject();
item.put("label", v);
item.put("value", v);
result.add(item);
}
return result;
}
@Override
public Map<String, Object> getAll(Map whereJson, Pageable page) {
JSONObject jo = new JSONObject();
try {
JSONObject jsonObject = (JSONObject) Searcher.search(luceneUrl, "", whereJson);
JSONObject jsonObject = (JSONObject) Searcher.search(indexUrl, "", whereJson);
JSONArray array = jsonObject.getJSONArray("content");
int totalElements = Integer.parseInt(jsonObject.get("totalElements").toString());
jo.put("content", array);
@ -78,7 +195,6 @@ public class LuceneServiceImpl implements LuceneService {
log.error("索引查询为空", e);
throw new NullPointerException("索引查询为空");
}
return jo;
}

1
nladmin-system/nlsso-server/src/main/resources/logback-spring.xml

@ -74,7 +74,6 @@ https://juejin.cn/post/6844903775631572999
<root level="debug">
<appender-ref ref="asyncLuceneAppender"/>
<appender-ref ref="asyncFileAppender"/>
<appender-ref ref="CONSOLE"/>
</root>
<logger name="jdbc" level="ERROR" additivity="true">
<appender-ref ref="asyncFileAppender"/>

4
nladmin-ui/src/views/acs/instruction/index.vue

@ -139,8 +139,8 @@
</el-table-column>
<el-table-column prop="send_status" label="下发状态">
<template slot-scope="scope">
<span v-if="scope.row.send_status==null ">下发</span>
<span v-if="scope.row.send_status=='0' ">下发</span>
<span v-if="scope.row.send_status==null ">下发</span>
<span v-if="scope.row.send_status=='0' ">下发</span>
<span v-if="scope.row.send_status=='1' ">成功</span>
<span v-if="scope.row.send_status=='2' ">失败</span>
</template>

18
nladmin-ui/src/views/monitor/lucene/api/lucene.js

@ -1,18 +0,0 @@
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 }

139
nladmin-ui/src/views/monitor/lucene/errorLog.vue

@ -0,0 +1,139 @@
<template>
<div class="app-container">
<div class="head-container">
<Search />
<crudOperation>
<el-button
slot="left"
class="filter-item"
type="danger"
icon="el-icon-delete"
size="mini"
:loading="crud.delAllLoading"
@click="confirmDelAll()"
>
清空
</el-button>
</crudOperation>
</div>
<!--表格渲染-->
<el-table ref="table" v-loading="crud.loading" :data="crud.data" style="width: 100%;" @selection-change="crud.selectionChangeHandler">
<el-table-column type="expand">
<template slot-scope="props">
<el-form label-position="left" inline class="demo-table-expand">
<el-form-item label="请求方法">
<span>{{ props.row.method }}</span>
</el-form-item>
<el-form-item label="请求参数">
<span>{{ props.row.params }}</span>
</el-form-item>
</el-form>
</template>
</el-table-column>
<el-table-column prop="username" label="用户名" />
<el-table-column prop="requestIp" label="IP" />
<el-table-column :show-overflow-tooltip="true" prop="address" label="IP来源" />
<el-table-column prop="description" label="描述" />
<el-table-column prop="browser" label="浏览器" />
<el-table-column prop="createTime" label="创建日期">
<template slot-scope="scope">
<span>{{ parseTime(scope.row.createTime) }}</span>
</template>
</el-table-column>
<el-table-column label="异常详情" width="100px">
<template slot-scope="scope">
<el-button size="mini" type="text" @click="info(scope.row.id)">查看详情</el-button>
</template>
</el-table-column>
</el-table>
<el-dialog :visible.sync="dialog" title="异常详情" append-to-body top="30px" width="85%">
<pre v-highlightjs="errorInfo"><code class="java" /></pre>
</el-dialog>
<!--分页组件-->
<pagination />
</div>
</template>
<script>
import { getErrDetail, delAllError } from '@/api/monitor/log'
import Search from './search'
import CRUD, { presenter } from '@crud/crud'
import crudOperation from '@crud/CRUD.operation.vue'
import pagination from '@crud/Pagination.vue'
export default {
name: 'ErrorLog',
components: { Search, crudOperation, pagination },
cruds() {
return CRUD({ title: '异常日志', url: 'api/logs/error' })
},
mixins: [presenter()],
data() {
return {
errorInfo: '', dialog: false
}
},
created() {
this.crud.optShow = {
add: false,
edit: false,
del: false,
download: true
}
},
methods: {
//
info(id) {
this.dialog = true
getErrDetail(id).then(res => {
this.errorInfo = res.exception
})
},
confirmDelAll() {
this.$confirm(`确认清空所有异常日志吗?`, '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
this.crud.delAllLoading = true
delAllError().then(res => {
this.crud.delAllLoading = false
this.crud.dleChangePage(1)
this.crud.delSuccessNotify()
this.crud.toQuery()
}).catch(err => {
this.crud.delAllLoading = false
console.log(err.response.data.message)
})
}).catch(() => {
})
}
}
}
</script>
<style scoped>
.demo-table-expand {
font-size: 0;
}
.demo-table-expand label {
width: 70px;
color: #99a9bf;
}
.demo-table-expand .el-form-item {
margin-right: 0;
margin-bottom: 0;
width: 100%;
}
.demo-table-expand .el-form-item__content {
font-size: 12px;
}
/deep/ .el-dialog__body {
padding: 0 20px 10px 20px !important;
}
.java.hljs {
color: #444;
background: #ffffff !important;
height: 630px !important;
}
</style>

472
nladmin-ui/src/views/monitor/lucene/index.vue

@ -1,109 +1,417 @@
<template>
<div class="app-container">
<div class="head-container">
<Search />
<crudOperation />
</div>
<!--表格渲染-->
<el-table
ref="table"
v-loading="crud.loading"
:data="crud.data"
style="width: 100%;"
@selection-change="crud.selectionChangeHandler"
>
<!-- <el-table-column type="selection" width="55"/>-->
<!-- <el-table-column v-if="false" prop="id" label="id"/>-->
<el-table-column prop="operate" width="50" label="操作" />
<el-table-column prop="device_code" label="设备号" min-width="130" show-overflow-tooltip />
<el-table-column prop="task_code" label="任务编号" />
<el-table-column prop="instruct_code" label="指令编号" />
<el-table-column prop="method" label="方法" />
<el-table-column prop="status_code" label="状态码" />
<el-table-column prop="requestparam" label="请求参数" />
<el-table-column prop="responseparam" label="返回参数" />
<el-table-column prop="logTime" width="170" label="记录时间" />
<el-table-column prop="content" width="500" label="内容详情" />
<!--工具栏-->
<el-form :inline="true" class="demo-form-inline" label-suffix=":" label-width="90px">
<el-form-item label="标签">
<el-select
v-model="system"
clearable
style="width: 100px; height: 35px;top: -5px;"
placeholder="所属标签"
>
<el-option
v-for="item in systemOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
<el-form-item label="级别">
<el-select
v-model="logLevelValue"
clearable
style="width: 100px; height: 35px;top: -5px;"
placeholder="日志级别"
>
<el-option
v-for="item in labelsOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
<el-form-item label="接口">
<el-input
v-model="requestMethod"
size="mini"
placeholder="请输入接口"
clearable
/>
</el-form-item>
<el-form-item label="关键字">
<el-input
v-model="message"
size="mini"
placeholder="请输入内容"
clearable
/>
</el-form-item>
<el-form-item label="链路追踪">
<el-input
v-model="traceId"
size="mini"
placeholder="请输入链路id"
clearable
/>
</el-form-item>
<el-form-item label="SQL日志" prop="filterSql">
<el-switch
v-model="filterSql"
active-color="#F56C6C"
inactive-color="#409EFF"
active-value="1"
inactive-valu="0"
/>
</el-form-item>
<el-form-item label="HTTP日志" prop="isRequest">
<el-switch
v-model="isRequest"
active-color="#409EFF"
inactive-color="#F56C6C"
active-value="1"
inactive-valu="0"
/>
</el-form-item>
</el-table>
<!--分页组件-->
<pagination />
<el-form-item v-show="!showOptions" label="时间范围">
<el-date-picker
v-model="timeRange"
size="mini"
clearable
type="datetimerange"
range-separator="至"
start-placeholder="开始日期"
end-placeholder="结束日期"
align="right"
@change="queryData"
@blur="queryData"
/>
</el-form-item>
<el-form-item v-show="showOptions" label="时间段">
<el-select v-model="timeZoneValue" filterable placeholder="请选择标签" size="mini" @change="queryData">
<el-option
v-for="item in timeZoneOptions"
:key="item.index"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
<el-form-item>
<el-tooltip class="item" effect="dark" content="切换查询条件" placement="top">
<span class="el-icon-sort" @click="changeShow" />
</el-tooltip>
</el-form-item>
<el-form-item label="显示条数">
<el-input-number
v-model="size"
size="mini"
controls-position="right"
:min="20"
:max="5000"
:step="10"
/>
</el-form-item>
<el-form-item label="当前页">
<el-input-number
v-model="page"
size="mini"
controls-position="right"
:min="1"
:max="2000"
:step="1"
/>
</el-form-item>
<el-form-item label="总条数">
<el-input
v-model="total"
size="small"
disabled
style="width: 110px"
/>
</el-form-item>
<el-form-item>
<el-dropdown split-button type="primary" size="mini" @click="queryData">
查询
<el-dropdown-menu slot="dropdown">
<el-dropdown-item v-for="(item, index) in runStatuOptions" :key="index" @click.native="startInterval(item)">{{ item.label }}</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</el-form-item>
<el-form-item>
<el-button @click="clearLogs">清空日志</el-button>
</el-form-item>
</el-form>
</div>
<!-- <div style="margin: 3px; min-height: 80vh;">
<el-table :data="logs">
<el-table-column label="ip" prop="requestIp" />
<el-table-column label="所属系统" prop="system" />
<el-table-column label="请求时间" prop="requestTime" />
<el-table-column label="traceId" prop="traceId" />
<el-table-column label="请求时间" prop="requestTime" />
<el-table-column label="请求接口" prop="requestMethod" />
<el-table-column label="logger" prop="logger" />
<el-table-column label="thread" prop="thread" />
<el-table-column label="message" prop="message" show-overflow-tooltip/>
</el-table>
</div>
-->
<div style="margin: 3px; min-height: 80vh;">
<!--数据判空-->
<el-empty v-if="showEmpty" :description="emptyText" />
<!--数据加载-->
<el-card v-else shadow="hover" style="width: 100%;overflow-x: scroll" class="log-warpper">
<div style="width: 100%">
<div v-for="(log, index) in logs" :key="index">
<div>
<span style="color: #6c0a99;font-weight: 700">{{ log.system }}</span>
<span style="color: #13ce66">{{ log.thread }}</span>
<span :style="fontType(log.logLevel)">{{ log.logLevel }}</span>
<span>{{ log.requestIp }}</span>
<span style="color: #7c8db0">{{ log.requestTime }}</span>
<span style="color: chocolate">{{ log.traceId }}</span>
<span style="color: #7a6df0">{{ log.requestMethod }}</span>
<span style="margin: 5px;font-size: 15px" v-html="log.message">{{ log.message }}</span>
</div>
</div>
</div>
</el-card>
</div>
</div>
</template>
<script>
import Search from './search'
import CRUD, { crud, header, presenter } from '@crud/crud'
import crudOperation from '@crud/CRUD.operation'
import pagination from '@crud/Pagination'
import { delAll } from '@/api/acs/lucene/log'
import logOperation from '@/views/monitor/lucene/loki'
let queryParam = {
logLevel: null,
system: null,
startTime: null,
endTime: null,
traceId: null,
requestMethod: null,
message: null,
filterSql: true,
isRequest: true,
page: null,
total: 0,
size: 20
}
export default {
name: 'LuceneLog',
components: { Search, pagination, crudOperation },
mixins: [presenter(), header(), crud()],
cruds: function() {
return CRUD({
title: '系统参数', url: 'api/lucene/getAll', idField: 'id', sort: 'id,desc',
queryOnPresenterCreated: true,
optShow: {
add: false,
edit: false,
del: false,
download: false
},
page: {
size: 40,
total: 0,
page: 0
},
query: {
createTime: [new Date(new Date().setTime(new Date().getTime() - 3600 * 1000)), new Date(new Date().setTime(new Date().getTime() + 3600 * 1000))]
}
})
},
name: 'ES',
data() {
return {
query: { blurry: '123' },
permission: {
add: ['admin', 'param:add'],
edit: ['admin', 'param:edit'],
del: ['admin', 'param:del']
},
rules: {}
labelsOptions: [], //
systemOptions: [], //
logLevelValue: '',
system: '',
timeRange: [],
message: '',
requestMethod: '',
traceId: '',
size: 20,
logData: [],
filterSql: '1',
isRequest: '1',
logs: [], //
showEmpty: true,
emptyText: '请选择标签',
page: 1,
runStatu: 'off',
runStatuOptions: [{
label: 'off',
value: 0
}, {
label: '5s',
value: 5000
}, {
label: '10s',
value: 10000
}, {
label: '1m',
value: 60000
}, {
label: '5m',
value: 300000
}, {
label: '30m',
value: 1800000
}],
timeZoneOptions: [{
label: '最近5分钟',
value: 300 * 1000
}, {
label: '最近15分钟',
value: 900 * 1000
}, {
label: '最近30分钟',
value: 1800 * 1000
}, {
label: '最近1小时',
value: 3600 * 1000
}, {
label: '最近3小时',
value: 3600 * 1000 * 3
}, {
label: '最近6小时',
value: 3600 * 1000 * 6
}, {
label: '最近12小时',
value: 3600 * 1000 * 12
}, {
label: '最近24小时',
value: 3600 * 1000 * 24
}, {
label: '最近2天',
value: 3600 * 1000 * 24 * 2
}, {
label: '最近7天',
value: 3600 * 1000 * 24 * 7
}, {
label: '最近15天',
value: 3600 * 1000 * 24 * 15
}],
timeZoneValue: '',
showOptions: true
}
},
created() {
this.initLabelsValues('logLevel')
this.initLabelsValues('system')
},
methods: {
// false
[CRUD.HOOK.beforeRefresh]() {
return true
fontType(level) {
if (level === 'INFO') {
return { 'color': '#1b6cc4' }
}
if (level === 'ERROR') {
return { 'color': '#e30a0a' }
}
if (level === 'DEBUG') {
return { 'color': '#1e2022' }
}
return { 'color': '#a74dc6' }
},
initLabelsValues(type) {
logOperation.labelsValues(type).then(res => {
if (type === 'logLevel') {
this.labelsOptions = res
}
if (type === 'system') {
this.systemOptions = res
}
})
},
queryData() {
//
this.clearParam()
queryParam.logLevel = this.logLevelValue
const time = new Date()
if (this.timeZoneValue !== '') {
queryParam.startTime = new Date(((time.getTime() - this.timeZoneValue)))
}
if (this.timeRange !== '' && this.timeRange.length > 0) {
queryParam.startTime = this.timeRange[0]
queryParam.endTime = this.timeRange[1]
}
queryParam.message = this.message.replace(/^\s*|\s*$/g, '')
queryParam.filterSql = this.filterSql === '1'
queryParam.isRequest = this.filterSql === '1'
queryParam.traceId = this.traceId
queryParam.requestMethod = this.requestMethod
queryParam.size = this.size
queryParam.page = this.page
queryParam.system = this.system
logOperation.getLogData(queryParam).then(res => {
this.showEmpty = false
this.total = res.total
//
this.logs = []
for (const j in res.page) { // push
this.logs.push(res.page[j])
}
})
},
confirmDelAll() {
this.$confirm(`确认清空所有操作日志吗?`, '提示', {
clearLogs() {
var message = '您确定要清空'
if (this.system !== '' && this.system !== null) {
message += '标签为:' + this.system + ' '
}
message += '10天前的日志吗 ?'
this.$confirm(message, '确认信息', {
distinguishCancelAndClose: true,
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
this.crud.delAllLoading = true
delAll('device_execute').then(res => {
this.crud.delAllLoading = false
this.crud.dleChangePage(1)
this.crud.delSuccessNotify()
this.crud.toQuery()
}).catch(err => {
this.crud.delAllLoading = false
console.log(err.response.data.message)
})
}).catch(() => {
cancelButtonText: '取消'
})
.then(() => {
//
this.clearParam()
queryParam.logLevel = this.logLevelValue
const time = new Date()
if (this.timeZoneValue !== '') {
queryParam.startTime = new Date(((time.getTime() - this.timeZoneValue)))
}
if (this.timeRange !== '' && this.timeRange.length > 0) {
queryParam.startTime = this.timeRange[0]
queryParam.endTime = this.timeRange[1]
}
queryParam.message = this.message.replace(/^\s*|\s*$/g, '')
queryParam.traceId = this.traceId
queryParam.requestMethod = this.requestMethod
queryParam.system = this.system
logOperation.clearLogs(queryParam).then(res => {
this.queryData()
this.$message({
type: 'info',
message: '清除成功'
})
})
})
.catch(action => {
this.$message({
type: 'info',
message: action === 'cancel'
? '已取消'
: '已取消'
})
})
},
changetype() {
},
clearParam() {
queryParam = {
logLevel: null,
startTime: null,
endTime: null,
message: null,
traceId: null,
isRequest: true,
filterSql: true,
size: 20
}
},
changeShow() {
//
this.timeZoneValue = ''
this.timeRange = []
this.showOptions = !this.showOptions
}
}
}
</script>
<style scoped>
.log-warpper {
white-space: nowrap;
word-break: break-word;
}
</style>

26
nladmin-ui/src/views/monitor/lucene/loki.js

@ -0,0 +1,26 @@
import request from '@/utils/request'
export function getLogData(param) {
return request({
url: '/api/esLog/query',
method: 'post',
data: param
})
}
export function labelsValues(type) {
return request({
url: '/api/esLog/labels/' + type,
method: 'get'
})
}
export function clearLogs(param) {
return request({
url: '/api/esLog/clearLogs',
method: 'delete',
data: param
})
}
export default { getLogData, labelsValues, clearLogs }

136
nladmin-ui/src/views/monitor/lucene/search.vue

@ -1,98 +1,14 @@
<template>
<div v-if="crud.props.searchToggle">
<!-- <el-input
v-model="query.device_code"
clearable
size="small"
placeholder="请输入你要搜索的设备号"
style="width: 200px;"
class="filter-item"
/> -->
<!-- <el-select
v-model="query.device_code"
clearable
filterable
size="small"
placeholder="请输入你要搜索的设备号"
class="filter-item"
style="width: 190px"
@change="crud.toQuery"
>
<el-option v-for="item in device_codes" :key="item.id" :label="item.label" :value="item.value" />
</el-select> -->
<el-select
ref="test"
v-model="query.device_code"
filterable
clearable
reserve-keyword
placeholder="设备号"
style="width: 190px;"
@change="crud.toQuery"
>
<el-option
v-for="item in deviceList"
:key="item.device_code"
:label="item.device_code"
:value="item.device_code"
/>
</el-select>
<el-input
v-model="query.method"
clearable
size="small"
placeholder="请输入你要搜索的方法名"
style="width: 200px;"
class="filter-item"
/>
<el-input
v-model="query.status_code"
clearable
size="small"
placeholder="请输入你要搜索的状态码"
style="width: 200px;"
class="filter-item"
/>
<el-input
v-model="query.requestparam"
clearable
size="small"
placeholder="请输入你要搜索的请求参数"
style="width: 200px;"
class="filter-item"
/>
<el-input
v-model="query.responseparam"
clearable
size="small"
placeholder="请输入你要搜索的返回参数"
style="width: 200px;"
class="filter-item"
/>
<el-input
v-model="query.blurry"
clearable
size="small"
placeholder="请输入你要搜索的内容详情"
placeholder="请输入你要搜索的内容"
style="width: 200px;"
class="filter-item"
/>
<!--
<date-range-picker v-model="query.createTime" class="date-item" />
-->
<el-date-picker
v-model="query.createTime"
type="datetimerange"
:picker-options="pickerOptions"
format="yyyy-MM-dd HH:mm:ss"
range-separator="至"
start-placeholder="开始日期"
end-placeholder="结束日期"
align="right"
/>
<date-range-picker v-model="query.createTime" class="date-item" />
<rrOperation />
</div>
</template>
@ -100,51 +16,9 @@
<script>
import { header } from '@crud/crud'
import rrOperation from '@crud/RR.operation'
import deviceCrud from '@/api/acs/device/device'
import DateRangePicker from '@/components/DateRangePicker'
export default {
components: { rrOperation },
mixins: [header()],
data() {
return {
pickerOptions: {
shortcuts: [{
text: '最近一周',
onClick(picker) {
const end = new Date()
const start = new Date()
start.setTime(start.getTime() - 3600 * 1000 * 24 * 7)
picker.$emit('pick', [start, end])
}
}, {
text: '最近一个月',
onClick(picker) {
const end = new Date()
const start = new Date()
start.setTime(start.getTime() - 3600 * 1000 * 24 * 30)
picker.$emit('pick', [start, end])
}
}, {
text: '最近三个月',
onClick(picker) {
const end = new Date()
const start = new Date()
start.setTime(start.getTime() - 3600 * 1000 * 24 * 90)
picker.$emit('pick', [start, end])
}
}]
},
value1: [new Date(2000, 10, 10, 10, 10), new Date(2000, 10, 11, 10, 10)],
value2: '',
deviceList: [],
device_code: ''
}
},
created() {
deviceCrud.selectDeviceList().then(data => {
this.deviceList = data
})
}
components: { rrOperation, DateRangePicker },
mixins: [header()]
}
</script>

Loading…
Cancel
Save