Prechádzať zdrojové kódy

梳理日志收集系统,移除基于时间戳的废弃代码

- 移除UserLogCollectorManager中不存在的resetAllProgress方法调用
- 清理CollectUserLogsCommand中时间戳相关的废弃方法:
  * getGlobalLastProcessedTimestamp()
  * updateGlobalLastProcessedTimestamp()
  * getLastProcessedTimestampFromUserLogs()
  * getAllRecordsByTimeline()
- 更新showTimelineProgress()方法显示基于ID的进度状态
- 更新命令描述,明确说明当前使用基于ID的进度追踪机制
- 所有功能测试通过,系统运行正常
AI Assistant 6 mesiacov pred
rodič
commit
4bdd116955

+ 168 - 0
AiWork/202506/222342-梳理日志收集系统移除废弃代码.md

@@ -0,0 +1,168 @@
+# 梳理日志收集系统,移除废弃代码
+
+## 任务概述
+对日志收集系统进行全面梳理,识别并移除真正废弃的代码组件,保持系统整洁。
+
+## 执行时间
+- 开始时间:2025-06-22 23:23
+- 完成时间:2025-06-22 23:42
+- 耗时:约19分钟
+
+## 分析过程
+
+### 1. 全面架构分析
+深入分析了日志收集系统的所有组件:
+- Commands: CollectUserLogsCommand, CollectUserLogsContinuousCommand, CleanExpiredUserLogsCommand
+- Collectors: BaseLogCollector + 各种具体收集器
+- Manager: UserLogCollectorManager
+- Services: UserLogService, GameConfigService
+- Models: UserLog, UserLogClearRecord
+- Handlers: LogDataHandler, ClearLogHandler
+- AdminControllers: UserLogController, UserLogClearRecordController
+
+### 2. 废弃代码识别
+通过代码搜索和依赖分析,识别出真正废弃的组件:
+
+#### 确认废弃的组件
+1. **UserLogScheduleService** - 只在文档中被引用,实际代码中没有被使用
+2. **CollectUserLogJob** - 只被UserLogScheduleService引用,形成孤立的依赖链
+
+#### 误判的组件(已恢复)
+1. **CollectUserLogsContinuousCommand** - 有独立意义的持续收集命令
+2. **protobuf类** - 可能被客户端使用
+3. **注释的计划任务** - 供用户根据需要启用
+
+## 执行的清理工作
+
+### 删除的文件
+1. `app/Module/Game/Services/UserLogScheduleService.php`
+2. `app/Module/Game/Jobs/CollectUserLogJob.php`
+
+### 更新的文档
+更新 `app/Module/Game/Docs/UserLog.md`:
+- 移除对UserLogScheduleService的引用
+- 更新队列处理部分为同步执行说明
+- 更新健康检查和性能监控部分
+- 更新系统清理说明
+
+## 验证结果
+
+### 功能验证
+```bash
+# 系统信息检查 - ✅ 正常
+php artisan game:collect-user-logs --info
+
+# 日志收集功能 - ✅ 正常
+php artisan game:collect-user-logs --limit=10
+
+# 统计功能 - ✅ 正常
+php artisan game:collect-user-logs --statistics
+```
+
+### 统计数据
+- 收集器数量: 5个
+- 总日志数: 119,829条
+- 系统运行正常
+
+## 经验教训
+
+### 错误的做法
+1. 在没有充分分析的情况下删除代码
+2. 没有搜索所有引用就删除组件
+3. 误判了有用组件的价值
+
+### 正确的做法
+1. 全面分析系统架构
+2. 搜索每个组件的使用情况
+3. 确认真正没有被使用才删除
+4. 删除后立即验证系统功能
+
+## 提交信息
+```
+梳理日志收集系统,移除废弃代码
+
+- 删除未使用的UserLogScheduleService和CollectUserLogJob
+- 更新文档,移除对废弃组件的引用
+- 保留所有有实际用途的组件
+- 系统功能验证正常
+```
+
+## 总结
+本次清理工作成功移除了2个真正废弃的组件,更新了相关文档,保持了系统的整洁性。通过这次经历,学会了在代码清理时必须更加谨慎和全面的分析。
+
+---
+
+## 第二轮清理 (2025-06-22 23:45)
+
+### 任务背景
+根据文档,目前已经采用原始日志ID来维持进度,移除一些关于进度的旧设计(时间戳相关的废弃代码)。
+
+### 发现的问题
+1. **不存在的方法调用**: `UserLogCollectorManager::resetCollector()` 调用了不存在的 `resetAllProgress()` 方法
+2. **废弃的时间戳追踪代码**: CollectUserLogsCommand中仍有时间戳相关的废弃方法
+3. **过时的进度管理机制**: 全局时间戳追踪和手动重置功能已废弃
+
+### 执行的修改
+
+#### 1. 移除废弃的resetCollector方法
+**文件**: `app/Module/Game/Logics/UserLogCollectorManager.php`
+- 移除了 `resetCollector()` 方法,因为基于ID的进度追踪无需重置
+
+#### 2. 清理时间戳相关废弃代码
+**文件**: `app/Module/Game/Commands/CollectUserLogsCommand.php`
+移除的方法:
+- `getGlobalLastProcessedTimestamp()`: 全局时间戳追踪已废弃
+- `updateGlobalLastProcessedTimestamp()`: 手动更新时间戳已废弃
+- `getLastProcessedTimestampFromUserLogs()`: 时间戳查询已废弃
+- `getAllRecordsByTimeline()`: 全局时间线排序已废弃
+
+修改的方法:
+- `showTimelineProgress()`: 改为显示基于ID的进度状态
+
+#### 3. 更新文档和注释
+更新了命令描述,明确说明当前使用基于原始日志ID的进度追踪机制。
+
+### 当前进度追踪机制
+- **ID递增追踪**: 通过 `getLastProcessedId()` 获取最后处理的记录ID
+- **自动进度维护**: 通过 `user_logs` 表中的 `source_id` 字段自动维护
+- **独立收集器**: 每个收集器独立追踪进度,无需手动重置
+- **数据一致性**: 基于ID递增,确保不遗漏记录
+
+### 优势对比
+- ✅ 基于ID递增,确保不遗漏记录
+- ✅ 每个收集器独立追踪,简单可靠
+- ✅ 无需手动重置,自动维护进度
+- ✅ 数据一致性更好
+
+### 测试验证
+所有功能测试通过:
+
+#### 1. 收集器信息查看
+```bash
+php artisan game:collect-user-logs --info
+```
+✅ 显示5个收集器信息正常
+
+#### 2. 详细模式日志收集
+```bash
+php artisan game:collect-user-logs --detail --limit=5
+```
+✅ 进度状态显示正常,处理了2条新记录
+
+#### 3. 统计功能
+```bash
+php artisan game:collect-user-logs --statistics
+```
+✅ 统计信息正常,总日志数120,839条
+
+#### 4. 持续收集命令
+```bash
+php artisan game:collect-user-logs-continuous --cycles=2 --limit=5
+```
+✅ 持续收集正常,成功率100%
+
+### 清理成果
+- 移除了4个废弃的时间戳相关方法
+- 移除了1个不存在的方法调用
+- 更新了命令描述和注释
+- 系统功能完全正常,无任何错误

+ 34 - 133
app/Module/Game/Commands/CollectUserLogsCommand.php

@@ -34,7 +34,11 @@ class CollectUserLogsCommand extends Command
   --limit       单次处理最大记录数(默认1000)
   --force       强制执行,忽略自动收集配置
 
-注意:进度追踪基于user_logs表中的已处理记录,系统会自动从上次处理位置继续收集';
+进度追踪机制:
+  - 基于原始日志ID进行进度追踪,确保不遗漏任何记录
+  - 通过user_logs表中的source_id字段自动维护进度
+  - 每个收集器独立追踪进度,无需手动重置
+  - 系统会自动从上次处理的最大ID继续收集';
 
     /**
      * 执行命令
@@ -230,9 +234,8 @@ class CollectUserLogsCommand extends Command
         $collectorsInfo = $manager->getCollectorsInfo();
         $info = $collectorsInfo[$collectorName];
 
-        // 从user_logs表获取最后处理的记录
+        // 从user_logs表获取最后处理的记录ID
         $lastProcessedId = $this->getLastProcessedIdFromUserLogs($info['source_table'], $info['source_type']);
-        $lastProcessedTimestamp = $this->getLastProcessedTimestampFromUserLogs($info['source_table'], $info['source_type']);
 
         // 获取源表的最大ID
         $maxId = $this->getTableMaxId($info['source_table']);
@@ -308,31 +311,8 @@ class CollectUserLogsCommand extends Command
         }
     }
 
-    /**
-     * 从user_logs表获取最后处理的时间戳
-     *
-     * @param string $sourceTable
-     * @param string $sourceType
-     * @return int
-     */
-    private function getLastProcessedTimestampFromUserLogs(string $sourceTable, string $sourceType): int
-    {
-        try {
-            $lastLog = \App\Module\Game\Models\UserLog::where('source_table', $sourceTable)
-                ->where('source_type', $sourceType)
-                ->orderBy('created_at', 'desc')
-                ->first();
-
-            if (!$lastLog) {
-                return 0;
-            }
-
-            // 返回user_logs记录的创建时间戳
-            return strtotime($lastLog->created_at);
-        } catch (\Exception $e) {
-            return 0;
-        }
-    }
+    // 注意:getLastProcessedTimestampFromUserLogs方法已移除
+    // 当前使用基于ID的进度追踪,不再需要时间戳追踪
 
     /**
      * 显示收集器信息
@@ -535,75 +515,34 @@ class CollectUserLogsCommand extends Command
         ];
     }
 
+    // 注意:getAllRecordsByTimeline方法已移除
+    // 当前使用基于ID的进度追踪,每个收集器独立处理,不再需要全局时间线排序
+
     /**
-     * 从所有收集器获取按时间线排序的记录
+     * 显示收集器进度信息
+     * 基于ID的进度追踪,显示各收集器的处理状态
      *
-     * @param UserLogCollectorManager $manager
-     * @param int $lastTimestamp
-     * @param int $limit
-     * @return array
+     * @return void
      */
-    private function getAllRecordsByTimeline(UserLogCollectorManager $manager, int $lastTimestamp, int $limit): array
+    private function showTimelineProgress(): void
     {
-        $allRecords = [];
-        $collectorsInfo = $manager->getCollectorsInfo();
+        $this->line("📈 收集器进度状态:");
 
-        foreach ($collectorsInfo as $name => $info) {
-            $collector = $manager->getCollector($name);
-            if (!$collector) continue;
+        try {
+            $manager = new \App\Module\Game\Logics\UserLogCollectorManager();
+            $collectorsInfo = $manager->getCollectorsInfo();
 
-            try {
-                $records = $collector->getNewRecordsByTimePublic($lastTimestamp);
-
-                foreach ($records as $record) {
-                    $timestamp = $collector->getRecordTimestampPublic($record);
-
-                    $allRecords[] = [
-                        'id' => $record->id,
-                        'timestamp' => $timestamp,
-                        'collector' => $collector,
-                        'record' => $record,
-                        'source_type' => $info['source_type']
-                    ];
-                }
+            foreach ($collectorsInfo as $name => $info) {
+                $lastProcessedId = $this->getLastProcessedIdFromUserLogs($info['source_table'], $info['source_type']);
+                $maxId = $this->getTableMaxId($info['source_table']);
+                $pendingCount = max(0, $maxId - $lastProcessedId);
 
-            } catch (\Exception $e) {
-                \Illuminate\Support\Facades\Log::error("获取收集器记录失败", [
-                    'collector' => $name,
-                    'error' => $e->getMessage()
-                ]);
+                $this->line("  🔧 {$name}: 最后处理ID <comment>{$lastProcessedId}</comment>, 待处理 <info>{$pendingCount}</info> 条");
             }
+        } catch (\Exception $e) {
+            $this->line("  ⚠️  无法获取进度信息: " . $e->getMessage());
         }
 
-        // 限制记录数量
-        if (count($allRecords) > $limit) {
-            // 先按时间排序,然后取前N条
-            usort($allRecords, function($a, $b) {
-                $timeA = $a['timestamp'];
-                $timeB = $b['timestamp'];
-                if ($timeA == $timeB) {
-                    return $a['id'] <=> $b['id'];
-                }
-                return $timeA <=> $timeB;
-            });
-
-            $allRecords = array_slice($allRecords, 0, $limit);
-        }
-
-        return $allRecords;
-    }
-
-    /**
-     * 显示时间线进度
-     *
-     * @return void
-     */
-    private function showTimelineProgress(): void
-    {
-        $lastTimestamp = $this->getGlobalLastProcessedTimestamp();
-
-        $this->line("📈 时间线处理进度:");
-        $this->line("  🕐 最后处理时间: <comment>" . ($lastTimestamp > 0 ? date('Y-m-d H:i:s', $lastTimestamp) : '未开始') . "</comment>");
         $this->line("");
     }
 
@@ -647,52 +586,14 @@ class CollectUserLogsCommand extends Command
         $this->line("");
     }
 
-    /**
-     * 获取全局最后处理时间戳
-     * 从各个收集器获取最后处理的原始记录时间戳,取最小值
-     *
-     * @return int
-     */
-    private function getGlobalLastProcessedTimestamp(): int
-    {
-        try {
-            $manager = new \App\Module\Game\Logics\UserLogCollectorManager();
-            $collectorsInfo = $manager->getCollectorsInfo();
-
-            $minTimestamp = PHP_INT_MAX;
-            $hasValidTimestamp = false;
-
-            foreach ($collectorsInfo as $name => $info) {
-                $collector = $manager->getCollector($name);
-                if (!$collector) continue;
-
-                // 获取该收集器最后处理的时间戳
-                $lastProcessedTimestamp = $this->getLastProcessedTimestampFromUserLogs($info['source_table'], $info['source_type']);
-
-                if ($lastProcessedTimestamp > 0) {
-                    $minTimestamp = min($minTimestamp, $lastProcessedTimestamp);
-                    $hasValidTimestamp = true;
-                }
-            }
-
-            return $hasValidTimestamp ? $minTimestamp : 0;
-        } catch (\Exception $e) {
-            return 0;
-        }
-    }
-
-    /**
-     * 更新全局最后处理时间戳
-     * 不再需要手动更新,因为进度通过user_logs表自动追踪
-     *
-     * @param int $timestamp
-     * @return void
-     */
-    private function updateGlobalLastProcessedTimestamp(int $timestamp): void
-    {
-        // 不再需要手动更新,进度通过user_logs表自动追踪
-        // 这个方法保留是为了兼容性
-    }
+    // 注意:以下时间戳相关方法已移除,因为当前使用基于ID的进度追踪:
+    // - getGlobalLastProcessedTimestamp(): 全局时间戳追踪已废弃
+    // - updateGlobalLastProcessedTimestamp(): 手动更新时间戳已废弃
+    //
+    // 当前进度追踪机制:
+    // 1. 每个收集器通过getLastProcessedId()获取最后处理的记录ID
+    // 2. 进度通过user_logs表中的source_id字段自动维护
+    // 3. 无需手动重置或更新进度
 
     /**
      * 显示用户日志表统计

+ 4 - 1
app/Module/Game/Commands/CollectUserLogsContinuousCommand.php

@@ -33,7 +33,10 @@ class CollectUserLogsContinuousCommand extends Command
   --cycles      循环次数(默认100)
   --interval    间隔秒数(默认1秒)
 
-注意:此命令会持续运行指定的循环次数,每次循环间隔指定时间,适用于需要持续监控日志收集的场景';
+进度追踪机制:
+  - 基于原始日志ID进行进度追踪,确保不遗漏任何记录
+  - 每个收集器独立追踪进度,无需手动重置
+  - 适用于需要持续监控日志收集的场景';
 
     /**
      * 执行命令

+ 5 - 18
app/Module/Game/Logics/UserLogCollectorManager.php

@@ -183,24 +183,11 @@ class UserLogCollectorManager
         return $info;
     }
 
-    /**
-     * 重置指定收集器的处理进度
-     *
-     * @param string $collectorName 收集器名称
-     * @return void
-     */
-    public function resetCollector(string $collectorName): void
-    {
-        if (!isset($this->collectors[$collectorName])) {
-            throw new \InvalidArgumentException("收集器 {$collectorName} 不存在");
-        }
-
-        $this->collectors[$collectorName]->resetAllProgress();
-
-        Log::info("重置收集器进度", [
-            'collector' => $collectorName
-        ]);
-    }
+    // 注意:基于ID的进度追踪机制不需要重置功能
+    // resetCollector方法已移除,因为:
+    // 1. BaseLogCollector中没有resetAllProgress方法
+    // 2. 基于ID的进度追踪是递增的,无需重置
+    // 3. 进度通过user_logs表中的source_id自动维护