init
This commit is contained in:
227
day02/src/com/inmind/student/杨靖宇/LogAnalyzer.java
Normal file
227
day02/src/com/inmind/student/杨靖宇/LogAnalyzer.java
Normal file
@@ -0,0 +1,227 @@
|
||||
package com.inmind.student.杨靖宇;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.Socket;
|
||||
import java.util.*;
|
||||
import java.net.*;
|
||||
|
||||
|
||||
public class LogAnalyzer {
|
||||
private static final String LOG_DIR = "D:\\io_test";
|
||||
private static final String SERVER_HOST = "localhost";
|
||||
private static final int SERVER_PORT = 8080;
|
||||
|
||||
private final List<Log> logs = Collections.synchronizedList(new ArrayList<>());
|
||||
private final List<Thread> threads = new ArrayList<>();
|
||||
|
||||
public static void main(String[] args) {
|
||||
LogAnalyzer analyzer = new LogAnalyzer();
|
||||
try {
|
||||
analyzer.analyze();
|
||||
} catch (FileNotFoundException e) {
|
||||
System.err.println("[错误] 日志目录不存在: " + e.getMessage());
|
||||
} catch (Exception e) {
|
||||
System.err.println("[错误] 分析过程中出现异常: " + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void analyze() throws FileNotFoundException {
|
||||
// 1. 检查并创建日志目录
|
||||
ensureLogDirectoryExists();
|
||||
|
||||
// 2. 读取日志文件
|
||||
readLogFiles();
|
||||
|
||||
// 3. 等待所有线程完成
|
||||
waitForThreads();
|
||||
|
||||
if (logs.isEmpty()) {
|
||||
System.out.println("[提示] 没有解析到任何有效日志");
|
||||
return;
|
||||
}
|
||||
|
||||
// 4. 统计日志数据
|
||||
Map<String, Integer> levelStats = countByLevel();
|
||||
Map<String, Integer> moduleErrorStats = countModuleErrors();
|
||||
List<Log> earliestLogs = getEarliestLogs(3);
|
||||
|
||||
// 5. 上报统计结果
|
||||
reportToServer(levelStats, moduleErrorStats, earliestLogs);
|
||||
}
|
||||
|
||||
private void ensureLogDirectoryExists() throws FileNotFoundException {
|
||||
File logDir = new File(LOG_DIR);
|
||||
if (!logDir.exists()) {
|
||||
System.out.println("[提示] 日志目录不存在,尝试创建...");
|
||||
if (!logDir.mkdirs()) {
|
||||
throw new FileNotFoundException("无法创建日志目录: " + LOG_DIR);
|
||||
}
|
||||
System.out.println("[成功] 已创建日志目录: " + LOG_DIR);
|
||||
}
|
||||
}
|
||||
|
||||
private void readLogFiles() throws FileNotFoundException {
|
||||
File logDir = new File(LOG_DIR);
|
||||
File[] logFiles = logDir.listFiles((dir, name) -> name.endsWith(".log"));
|
||||
|
||||
if (logFiles == null || logFiles.length == 0) {
|
||||
System.out.println("[提示] 目录中没有找到.log文件");
|
||||
return;
|
||||
}
|
||||
|
||||
System.out.printf("[信息] 找到 %d 个日志文件\n", logFiles.length);
|
||||
|
||||
for (File file : logFiles) {
|
||||
Thread thread = new Thread(() -> parseLogFile(file));
|
||||
threads.add(thread);
|
||||
thread.start();
|
||||
}
|
||||
}
|
||||
|
||||
private void waitForThreads() {
|
||||
for (Thread thread : threads) {
|
||||
try {
|
||||
thread.join();
|
||||
} catch (InterruptedException e) {
|
||||
System.err.println("[警告] 线程等待被中断");
|
||||
Thread.currentThread().interrupt();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void parseLogFile(File file) {
|
||||
System.out.printf("[信息] 开始解析文件: %s\n", file.getName());
|
||||
|
||||
try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
|
||||
String line;
|
||||
int lineNum = 0;
|
||||
int successCount = 0;
|
||||
|
||||
while ((line = reader.readLine()) != null) {
|
||||
lineNum++;
|
||||
try {
|
||||
Log log = parseLogLine(line);
|
||||
logs.add(log);
|
||||
successCount++;
|
||||
} catch (NumberFormatException e) {
|
||||
System.err.printf("[警告] %s 第 %d 行: 时间戳格式错误\n",
|
||||
file.getName(), lineNum);
|
||||
} catch (IllegalArgumentException e) {
|
||||
System.err.printf("[警告] %s 第 %d 行: 日志格式错误\n",
|
||||
file.getName(), lineNum);
|
||||
}
|
||||
}
|
||||
|
||||
System.out.printf("[成功] 文件 %s 解析完成: 总行数 %d, 成功 %d, 失败 %d\n",
|
||||
file.getName(), lineNum, successCount, lineNum - successCount);
|
||||
} catch (FileNotFoundException e) {
|
||||
System.err.printf("[错误] 文件不存在: %s\n", file.getPath());
|
||||
} catch (IOException e) {
|
||||
System.err.printf("[错误] 读取文件 %s 失败: %s\n", file.getName(), e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private Log parseLogLine(String line) throws IllegalArgumentException, NumberFormatException {
|
||||
String[] parts = line.split(",", 4);
|
||||
if (parts.length != 4) {
|
||||
throw new IllegalArgumentException("需要4个字段但找到" + parts.length);
|
||||
}
|
||||
|
||||
long timestamp = Long.parseLong(parts[0].trim());
|
||||
return new Log(timestamp, parts[1].trim(), parts[2].trim(), parts[3].trim());
|
||||
}
|
||||
|
||||
private Map<String, Integer> countByLevel() {
|
||||
Map<String, Integer> stats = new HashMap<>();
|
||||
synchronized (logs) {
|
||||
for (Log log : logs) {
|
||||
stats.merge(log.getLevel(), 1, Integer::sum);
|
||||
}
|
||||
}
|
||||
return stats;
|
||||
}
|
||||
|
||||
private Map<String, Integer> countModuleErrors() {
|
||||
Map<String, Integer> stats = new HashMap<>();
|
||||
synchronized (logs) {
|
||||
for (Log log : logs) {
|
||||
if ("ERROR".equals(log.getLevel())) {
|
||||
stats.merge(log.getModule(), 1, Integer::sum);
|
||||
}
|
||||
}
|
||||
}
|
||||
return stats;
|
||||
}
|
||||
|
||||
private List<Log> getEarliestLogs(int count) {
|
||||
List<Log> copy;
|
||||
synchronized (logs) {
|
||||
copy = new ArrayList<>(logs);
|
||||
}
|
||||
|
||||
if (copy.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
copy.sort(Comparator.comparingLong(Log::getTimestamp));
|
||||
return new ArrayList<>(copy.subList(0, Math.min(count, copy.size())));
|
||||
}
|
||||
|
||||
private void reportToServer(Map<String, Integer> levelStats,
|
||||
Map<String, Integer> moduleErrorStats,
|
||||
List<Log> earliestLogs) {
|
||||
final int maxRetries = 3;
|
||||
int attempt = 0;
|
||||
|
||||
while (attempt < maxRetries) {
|
||||
attempt++;
|
||||
try (Socket socket = new Socket()) {
|
||||
// 设置连接和读取超时
|
||||
socket.connect(new InetSocketAddress(SERVER_HOST, SERVER_PORT), 5000);
|
||||
socket.setSoTimeout(10000);
|
||||
|
||||
try (ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
|
||||
ObjectInputStream ois = new ObjectInputStream(socket.getInputStream())) {
|
||||
|
||||
// 确保发送的是可序列化的ArrayList
|
||||
oos.writeObject(new HashMap<>(levelStats));
|
||||
oos.writeObject(new HashMap<>(moduleErrorStats));
|
||||
oos.writeObject(new ArrayList<>(earliestLogs));
|
||||
oos.flush();
|
||||
|
||||
String response = (String) ois.readObject();
|
||||
System.out.println("[成功] 服务器响应: " + response);
|
||||
return;
|
||||
}
|
||||
} catch (ConnectException e) {
|
||||
System.err.printf("[错误] 连接失败(尝试 %d/%d): %s\n",
|
||||
attempt, maxRetries, e.getMessage());
|
||||
if (attempt >= maxRetries) {
|
||||
System.err.println("[错误] 达到最大重试次数,放弃连接");
|
||||
} else {
|
||||
try {
|
||||
Thread.sleep(1000 * attempt);
|
||||
} catch (InterruptedException ie) {
|
||||
Thread.currentThread().interrupt();
|
||||
return;
|
||||
}
|
||||
}
|
||||
} catch (SocketTimeoutException e) {
|
||||
System.err.println("[错误] 连接或读取超时");
|
||||
} catch (EOFException e) {
|
||||
System.err.println("[错误] 连接意外中断");
|
||||
} catch (UnknownHostException e) {
|
||||
System.err.println("[错误] 未知主机: " + SERVER_HOST);
|
||||
break;
|
||||
} catch (IOException e) {
|
||||
System.err.println("[错误] 通信错误: " + e.getMessage());
|
||||
break;
|
||||
} catch (ClassNotFoundException e) {
|
||||
System.err.println("[错误] 协议错误: 收到未知响应类型");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user