From 63b01db83d9aad8a15276b4236a9a22e4aeef065 Mon Sep 17 00:00:00 2001
From: Junjie <fallin.jie@qq.com>
Date: 星期二, 05 五月 2026 12:30:59 +0800
Subject: [PATCH] # Agent数据分析V3.0.1.7
---
src/main/java/com/zy/core/task/DeviceLogScheduler.java | 254 +++++++++++++++-----------------------------------
1 files changed, 76 insertions(+), 178 deletions(-)
diff --git a/src/main/java/com/zy/core/task/DeviceLogScheduler.java b/src/main/java/com/zy/core/task/DeviceLogScheduler.java
index 8f5ff54..480753e 100644
--- a/src/main/java/com/zy/core/task/DeviceLogScheduler.java
+++ b/src/main/java/com/zy/core/task/DeviceLogScheduler.java
@@ -1,41 +1,34 @@
package com.zy.core.task;
-
-import com.alibaba.fastjson.JSON;
-import com.alibaba.fastjson.serializer.SerializerFeature;
-import com.zy.asrs.entity.DeviceDataLog;
-import com.zy.asrs.service.DeviceDataLogService;
-import com.zy.common.utils.RedisUtil;
-import com.zy.core.enums.RedisKeyType;
+import jakarta.annotation.PostConstruct;
import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
-import java.nio.charset.StandardCharsets;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
-import java.nio.file.StandardOpenOption;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
-import java.text.SimpleDateFormat;
-import java.util.Comparator;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.Set;
-import java.util.List;
+import java.time.LocalDate;
+import java.time.format.DateTimeFormatter;
+import java.time.format.DateTimeParseException;
+import java.time.format.ResolverStyle;
import java.util.ArrayList;
-import java.util.Map;
+import java.util.List;
import java.util.concurrent.locks.ReentrantLock;
import java.util.stream.Stream;
-import java.util.stream.Collectors;
@Slf4j
@Component
public class DeviceLogScheduler {
+
+ private static final ReentrantLock FILE_OP_LOCK = new ReentrantLock();
+ private static final int DEFAULT_EXPIRE_DAYS = 1;
+ private static final DateTimeFormatter DAY_FORMATTER = DateTimeFormatter.ofPattern("uuuuMMdd")
+ .withResolverStyle(ResolverStyle.STRICT);
@Value("${deviceLogStorage.type}")
private String storageType;
@@ -43,151 +36,51 @@
private String loggingPath;
@Value("${deviceLogStorage.expireDays}")
private Integer expireDays;
- @Autowired
- private DeviceDataLogService deviceDataLogService;
- @Autowired
- private RedisUtil redisUtil;
- private static final ReentrantLock FILE_OP_LOCK = new ReentrantLock();
-
- @Scheduled(cron = "0/3 * * * * ? ")
- public void delDeviceLog() {
- if ("mysql".equals(storageType)) {
- deviceDataLogService.clearLog(expireDays == null ? 1 : expireDays);
- }else if ("file".equals(storageType)) {
- if (!FILE_OP_LOCK.tryLock()) {
- return;
- }
- try {
- clearFileLog(expireDays == null ? 1 : expireDays);
- } finally {
- FILE_OP_LOCK.unlock();
- }
- }else {
- log.error("鏈畾涔夌殑瀛樺偍绫诲瀷锛歿}", storageType);
+ @PostConstruct
+ public void validateStorageMode() {
+ if (!"file".equalsIgnoreCase(storageType)) {
+ throw new IllegalStateException("deviceLogStorage.type 浠呮敮鎸� file锛屽綋鍓嶉厤缃负: " + storageType);
}
+ ensureLoggingDirectoryExistsOrThrow();
}
- @Scheduled(cron = "0/3 * * * * ? ")
- public void execute() {
- int maxCount = 100;
- Set<String> keys = redisUtil.scanKeys(RedisKeyType.DEVICE_LOG_KEY.key, maxCount);
- if (keys == null || keys.isEmpty()) {
+ @Scheduled(cron = "${deviceLogStorage.cleanupScanCron:0 0 3 * * ?}")
+ public void delDeviceLog() {
+ if (!FILE_OP_LOCK.tryLock()) {
return;
}
- List<Object> values = redisUtil.multiGet(keys);
- List<DeviceDataLog> list = new ArrayList<>();
- for (Object object : values) {
- if (object instanceof DeviceDataLog) {
- list.add((DeviceDataLog) object);
- }
- }
- if (!list.isEmpty()) {
- if ("mysql".equals(storageType)) {
- mysqlSave(keys, list);
- }else if ("file".equals(storageType)) {
- if (!FILE_OP_LOCK.tryLock()) {
- return;
- }
- try {
- fileSave(keys, list);
- } finally {
- FILE_OP_LOCK.unlock();
- }
- }else {
- log.error("鏈畾涔夌殑瀛樺偍绫诲瀷锛歿}", storageType);
- }
- }
- }
-
- private void mysqlSave(Set<String> keys, List<DeviceDataLog> list) {
- if (deviceDataLogService.saveBatch(list)) {
- redisUtil.del(keys.toArray(new String[0]));
- }
- }
-
- private void fileSave(Set<String> keys, List<DeviceDataLog> list) {
try {
- Path baseDir = Paths.get(loggingPath);
- Files.createDirectories(baseDir);
- SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
- Map<String, Map<String, List<DeviceDataLog>>> group = new HashMap<>();
- for (DeviceDataLog logItem : list) {
- String typeName = logItem.getType();
- String datePart = sdf.format(logItem.getCreateTime() == null ? new Date() : logItem.getCreateTime());
- String prefix = typeName + "_" + String.valueOf(logItem.getDeviceNo()) + "_" + datePart + "_";
- group.computeIfAbsent(datePart, k -> new HashMap<>())
- .computeIfAbsent(prefix, k -> new ArrayList<>())
- .add(logItem);
- }
- for (Map.Entry<String, Map<String, List<DeviceDataLog>>> dateEntry : group.entrySet()) {
- Path dayDir = baseDir.resolve(dateEntry.getKey());
- Files.createDirectories(dayDir);
- for (Map.Entry<String, List<DeviceDataLog>> entry : dateEntry.getValue().entrySet()) {
- String prefix = entry.getKey();
- List<DeviceDataLog> logs = entry.getValue();
- logs.sort(Comparator.comparing(DeviceDataLog::getCreateTime, Comparator.nullsLast(Date::compareTo)));
- int index = findStartIndex(dayDir, prefix);
- Path current = dayDir.resolve(prefix + index + ".log");
- if (!Files.exists(current)) {
- Files.createFile(current);
- }
- long size = Files.size(current);
- long max = 1024L * 1024L;
- for (DeviceDataLog d : logs) {
- String json = JSON.toJSONStringWithDateFormat(d, "yyyy-MM-dd HH:mm:ss.SSS", SerializerFeature.WriteDateUseDateFormat);
- byte[] line = (json + System.lineSeparator()).getBytes(StandardCharsets.UTF_8);
- if (size + line.length > max) {
- index++;
- current = dayDir.resolve(prefix + index + ".log");
- if (!Files.exists(current)) {
- Files.createFile(current);
- }
- size = 0;
- }
- Files.write(current, line, StandardOpenOption.CREATE, StandardOpenOption.APPEND);
- size += line.length;
- }
- }
- }
- redisUtil.del(keys.toArray(new String[0]));
- } catch (Exception e) {
- log.error("璁惧鏃ュ織鏂囦欢瀛樺偍澶辫触", e);
+ ensureLoggingDirectoryExists();
+ clearFileLog(resolveExpireDays());
+ } finally {
+ FILE_OP_LOCK.unlock();
}
}
- private int findStartIndex(Path baseDir, String prefix) throws Exception {
- List<Path> matched;
- try (Stream<Path> stream = Files.list(baseDir)) {
- matched = stream
- .filter(p -> {
- String n = p.getFileName().toString();
- return n.startsWith(prefix) && n.endsWith(".log");
- })
- .collect(Collectors.toList());
+ private void ensureLoggingDirectoryExistsOrThrow() {
+ Path loggingRootPath = Paths.get(loggingPath);
+ try {
+ Files.createDirectories(loggingRootPath);
+ } catch (Exception e) {
+ throw new IllegalStateException("鍒濆鍖栬澶囨棩蹇楃洰褰曞け璐�, path=" + loggingPath, e);
}
- int maxIdx = 0;
- for (Path p : matched) {
- String name = p.getFileName().toString();
- String suf = name.substring(prefix.length());
- if (!suf.isEmpty()) {
- try {
- int val = Integer.parseInt(suf.replace(".log", ""));
- if (val > maxIdx) {
- maxIdx = val;
- }
- } catch (NumberFormatException ignored) {}
- }
+ }
+
+ private void ensureLoggingDirectoryExists() {
+ try {
+ Files.createDirectories(Paths.get(loggingPath));
+ } catch (Exception e) {
+ log.warn("鍒濆鍖栬澶囨棩蹇楃洰褰曞け璐�, path={}", loggingPath, e);
}
- int candidate = maxIdx == 0 ? 1 : maxIdx;
- Path path = baseDir.resolve(prefix + candidate + ".log");
- if (Files.exists(path)) {
- long size = Files.size(path);
- if (size >= 1024L * 1024L) {
- return candidate + 1;
- }
+ }
+
+ private int resolveExpireDays() {
+ if (expireDays == null || expireDays <= 0) {
+ log.warn("deviceLogStorage.expireDays 閰嶇疆鏃犳晥锛屼娇鐢ㄩ粯璁ゅ��: {}", DEFAULT_EXPIRE_DAYS);
+ return DEFAULT_EXPIRE_DAYS;
}
- return candidate;
+ return expireDays;
}
private void clearFileLog(int days) {
@@ -196,40 +89,45 @@
if (!Files.exists(baseDir)) {
return;
}
- SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
- long cutoff = System.currentTimeMillis() - (long) days * 24 * 60 * 60 * 1000;
- List<Path> dirs;
+ LocalDate earliestReservedDay = LocalDate.now().minusDays(days - 1L);
+ List<Path> expiredDayDirs = new ArrayList<>();
try (Stream<Path> stream = Files.list(baseDir)) {
- dirs = stream.filter(Files::isDirectory).collect(Collectors.toList());
+ stream.filter(Files::isDirectory)
+ .forEach(dayDir -> collectExpiredDayDirectory(dayDir, earliestReservedDay, expiredDayDirs));
}
- for (Path dir : dirs) {
- String name = dir.getFileName().toString();
- if (name.length() == 8 && name.chars().allMatch(Character::isDigit)) {
- Date d = sdf.parse(name);
- if (d.getTime() < cutoff) {
- Files.walkFileTree(dir, new SimpleFileVisitor<Path>() {
- @Override
- public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
- try {
- Files.deleteIfExists(file);
- } catch (Exception ignored) {}
- return FileVisitResult.CONTINUE;
- }
-
- @Override
- public FileVisitResult postVisitDirectory(Path dir, java.io.IOException exc) {
- try {
- Files.deleteIfExists(dir);
- } catch (Exception ignored) {}
- return FileVisitResult.CONTINUE;
- }
- });
+ for (Path dayDir : expiredDayDirs) {
+ Files.walkFileTree(dayDir, new SimpleFileVisitor<>() {
+ @Override
+ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws java.io.IOException {
+ Files.deleteIfExists(file);
+ return FileVisitResult.CONTINUE;
}
- }
+
+ @Override
+ public FileVisitResult postVisitDirectory(Path dir, java.io.IOException exc) throws java.io.IOException {
+ Files.deleteIfExists(dir);
+ return FileVisitResult.CONTINUE;
+ }
+ });
}
} catch (Exception e) {
- log.error("璁惧鏃ュ織鏂囦欢娓呯悊澶辫触", e);
+ log.error("鍒犻櫎璁惧鏃ュ織鏂囦欢澶辫触, path={}", loggingPath, e);
}
}
+ private void collectExpiredDayDirectory(Path dayDir, LocalDate earliestReservedDay, List<Path> expiredDayDirs) {
+ LocalDate dayValue = parseDayDirectory(dayDir.getFileName().toString());
+ if (dayValue == null || !dayValue.isBefore(earliestReservedDay)) {
+ return;
+ }
+ expiredDayDirs.add(dayDir);
+ }
+
+ private LocalDate parseDayDirectory(String dayDirectoryName) {
+ try {
+ return LocalDate.parse(dayDirectoryName, DAY_FORMATTER);
+ } catch (DateTimeParseException ignored) {
+ return null;
+ }
+ }
}
--
Gitblit v1.9.1