refactor: 移除 stats 统计功能
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -11,7 +11,6 @@
|
|||||||
| `parse` | 解析日志文件到本地库 | log → local.db |
|
| `parse` | 解析日志文件到本地库 | log → local.db |
|
||||||
| `aggregate` | 从本地库汇总生成发布库 | local.db → release.db |
|
| `aggregate` | 从本地库汇总生成发布库 | local.db → release.db |
|
||||||
| `export` | 导出发布库到 CSV | release.db → CSV |
|
| `export` | 导出发布库到 CSV | release.db → CSV |
|
||||||
| `stats` | 查询本地库统计信息 | 只读 local.db |
|
|
||||||
| `clean` | 清理本地库数据(软删除) | 只写 local.db |
|
| `clean` | 清理本地库数据(软删除) | 只写 local.db |
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -60,26 +59,7 @@ dotnet run export --type qfod --format csv
|
|||||||
dotnet run export --format json --type qfod
|
dotnet run export --format json --type qfod
|
||||||
```
|
```
|
||||||
|
|
||||||
### 2.4 stats
|
### 2.4 clean
|
||||||
|
|
||||||
```bash
|
|
||||||
# 查看整体统计
|
|
||||||
dotnet run stats --summary
|
|
||||||
|
|
||||||
# 按 FOD 类型统计
|
|
||||||
dotnet run stats --by-fod-type
|
|
||||||
|
|
||||||
# 按面板统计
|
|
||||||
dotnet run stats --by-panel
|
|
||||||
|
|
||||||
# 按硬件版本统计
|
|
||||||
dotnet run stats --by-hardware
|
|
||||||
|
|
||||||
# 按 RX 类型统计
|
|
||||||
dotnet run stats --by-rx-type
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2.5 clean
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# 清理指定场景
|
# 清理指定场景
|
||||||
@@ -97,13 +77,10 @@ dotnet run clean --all --confirm
|
|||||||
# 1. 解析日志
|
# 1. 解析日志
|
||||||
dotnet run parse --dir ./data/test_input --recursive
|
dotnet run parse --dir ./data/test_input --recursive
|
||||||
|
|
||||||
# 2. 查看统计
|
# 2. 汇总生成发布库
|
||||||
dotnet run stats --summary
|
|
||||||
|
|
||||||
# 3. 汇总生成发布库
|
|
||||||
dotnet run aggregate
|
dotnet run aggregate
|
||||||
|
|
||||||
# 4. 导出正式 CSV
|
# 3. 导出正式 CSV
|
||||||
dotnet run export --output ./data/output
|
dotnet run export --output ./data/output
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ log 文件
|
|||||||
│ Application Layer │
|
│ Application Layer │
|
||||||
│ ┌───────────────┐ ┌──────────────┐ ┌────────────┐ ┌──────────────┐ │
|
│ ┌───────────────┐ ┌──────────────┐ ┌────────────┐ ┌──────────────┐ │
|
||||||
│ │ LocalIngestion│ │ Publishing │ │ Exporting │ │Administration│ │
|
│ │ LocalIngestion│ │ Publishing │ │ Exporting │ │Administration│ │
|
||||||
│ │ ParseService │ │AggregationSvc│ │ExportSvc │ │ StatsService │ │
|
│ │ ParseService │ │AggregationSvc│ │ExportSvc │ │ CleanService │ │
|
||||||
│ │ ScenarioSvc │ │ThresholdCalc │ │ │ │ CleanService │ │
|
│ │ ScenarioSvc │ │ThresholdCalc │ │ │ │ CleanService │ │
|
||||||
│ │ DimensionSvc │ │ │ │ │ │ │ │
|
│ │ DimensionSvc │ │ │ │ │ │ │ │
|
||||||
│ └───────────────┘ └──────────────┘ └────────────┘ └──────────────┘ │
|
│ └───────────────┘ └──────────────┘ └────────────┘ └──────────────┘ │
|
||||||
@@ -92,7 +92,6 @@ src/
|
|||||||
│ ├── Commands/ # 命令实现
|
│ ├── Commands/ # 命令实现
|
||||||
│ │ ├── ParseCommand.cs
|
│ │ ├── ParseCommand.cs
|
||||||
│ │ ├── AggregateCommand.cs
|
│ │ ├── AggregateCommand.cs
|
||||||
│ │ ├── StatsCommand.cs
|
|
||||||
│ │ ├── ExportCommand.cs
|
│ │ ├── ExportCommand.cs
|
||||||
│ │ └── CleanCommand.cs
|
│ │ └── CleanCommand.cs
|
||||||
│ ├── Program.cs
|
│ ├── Program.cs
|
||||||
@@ -115,7 +114,6 @@ src/
|
|||||||
│ ├── Exporting/ # 导出
|
│ ├── Exporting/ # 导出
|
||||||
│ │ └── ExportService.cs
|
│ │ └── ExportService.cs
|
||||||
│ └── Administration/ # 管理
|
│ └── Administration/ # 管理
|
||||||
│ ├── StatsService.cs
|
|
||||||
│ └── CleanService.cs
|
│ └── CleanService.cs
|
||||||
├── Domain/ # 领域实体
|
├── Domain/ # 领域实体
|
||||||
│ └── Models/
|
│ └── Models/
|
||||||
|
|||||||
@@ -58,7 +58,6 @@
|
|||||||
|
|
||||||
| 类 | 职责 |
|
| 类 | 职责 |
|
||||||
|----|------|
|
|----|------|
|
||||||
| `StatsService` | 本地库统计查询 |
|
|
||||||
| `CleanService` | 软删除管理 |
|
| `CleanService` | 软删除管理 |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|||||||
@@ -1,142 +0,0 @@
|
|||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using Microsoft.Extensions.Logging;
|
|
||||||
using Gpulse.WCT.DataAnalyzer.Core.Infrastructure.LocalData;
|
|
||||||
using Gpulse.WCT.DataAnalyzer.Core.Domain.Local;
|
|
||||||
|
|
||||||
namespace Gpulse.WCT.DataAnalyzer.Core.Application;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 统计查询服务 - 使用数据库端聚合优化内存效率
|
|
||||||
/// </summary>
|
|
||||||
public class StatsService
|
|
||||||
{
|
|
||||||
private readonly WctMinerDbContext _context;
|
|
||||||
private readonly ILogger<StatsService> _logger;
|
|
||||||
|
|
||||||
public StatsService(WctMinerDbContext context, ILogger<StatsService> logger)
|
|
||||||
{
|
|
||||||
_context = context;
|
|
||||||
_logger = logger;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 获取整体统计摘要(并行查询优化)
|
|
||||||
/// </summary>
|
|
||||||
public async Task<StatsSummary> GetSummaryAsync()
|
|
||||||
{
|
|
||||||
// 使用 Task.WhenAll 并行执行多个查询
|
|
||||||
var tasks = new[]
|
|
||||||
{
|
|
||||||
_context.TestScenarios.CountAsync(),
|
|
||||||
_context.QfodRecords.CountAsync(),
|
|
||||||
_context.PlossRecords.CountAsync(),
|
|
||||||
_context.TxPanels.CountAsync(),
|
|
||||||
_context.TxHardwares.CountAsync(),
|
|
||||||
_context.TxSoftwares.CountAsync(),
|
|
||||||
_context.RxTypes.CountAsync()
|
|
||||||
};
|
|
||||||
|
|
||||||
var results = await Task.WhenAll(tasks);
|
|
||||||
|
|
||||||
var summary = new StatsSummary(
|
|
||||||
results[0], results[1], results[2],
|
|
||||||
results[3], results[4], results[5], results[6]
|
|
||||||
);
|
|
||||||
|
|
||||||
_logger.LogDebug("统计摘要: Scenarios={ScenarioCount}, Qfod={QfodCount}, Ploss={PlossCount}",
|
|
||||||
summary.ScenarioCount, summary.QfodCount, summary.PlossCount);
|
|
||||||
|
|
||||||
return summary;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 按FOD类型统计Qfod记录(数据库端聚合)
|
|
||||||
/// </summary>
|
|
||||||
public async Task<List<FodTypeStats>> GetStatsByFodTypeAsync()
|
|
||||||
{
|
|
||||||
// 使用数据库端 GroupBy
|
|
||||||
var stats = await _context.QfodRecords
|
|
||||||
.GroupBy(r => r.FodType)
|
|
||||||
.Select(g => new FodTypeStats(g.Key, g.Count()))
|
|
||||||
.OrderBy(s => s.FodType)
|
|
||||||
.ToListAsync();
|
|
||||||
|
|
||||||
_logger.LogDebug("按 FOD 类型统计完成: {Count} 种类型", stats.Count);
|
|
||||||
return stats;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 按面板类型统计(数据库端聚合 - 使用维度表反向统计)
|
|
||||||
/// </summary>
|
|
||||||
public async Task<List<DimensionStats>> GetStatsByPanelAsync()
|
|
||||||
{
|
|
||||||
// 方式: 使用维度表反向统计(更高效)
|
|
||||||
var stats = await _context.TxPanels
|
|
||||||
.Select(p => new DimensionStats(
|
|
||||||
p.Name,
|
|
||||||
p.TestScenarios.Count()
|
|
||||||
))
|
|
||||||
.OrderByDescending(s => s.Count)
|
|
||||||
.ToListAsync();
|
|
||||||
|
|
||||||
_logger.LogDebug("按面板类型统计完成: {Count} 种面板", stats.Count);
|
|
||||||
return stats;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 按硬件版本统计(数据库端聚合)
|
|
||||||
/// </summary>
|
|
||||||
public async Task<List<DimensionStats>> GetStatsByHardwareAsync()
|
|
||||||
{
|
|
||||||
var stats = await _context.TxHardwares
|
|
||||||
.Select(h => new DimensionStats(
|
|
||||||
h.Version,
|
|
||||||
h.TestScenarios.Count()
|
|
||||||
))
|
|
||||||
.OrderByDescending(s => s.Count)
|
|
||||||
.ToListAsync();
|
|
||||||
|
|
||||||
_logger.LogDebug("按硬件版本统计完成: {Count} 种版本", stats.Count);
|
|
||||||
return stats;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 按RX类型统计(数据库端聚合)
|
|
||||||
/// </summary>
|
|
||||||
public async Task<List<DimensionStats>> GetStatsByRxTypeAsync()
|
|
||||||
{
|
|
||||||
var stats = await _context.RxTypes
|
|
||||||
.Select(r => new DimensionStats(
|
|
||||||
r.Name,
|
|
||||||
r.TestScenarios.Count()
|
|
||||||
))
|
|
||||||
.OrderByDescending(s => s.Count)
|
|
||||||
.ToListAsync();
|
|
||||||
|
|
||||||
_logger.LogDebug("按 RX 类型统计完成: {Count} 种类型", stats.Count);
|
|
||||||
return stats;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 整体统计摘要
|
|
||||||
/// </summary>
|
|
||||||
public record StatsSummary(
|
|
||||||
int ScenarioCount,
|
|
||||||
int QfodCount,
|
|
||||||
int PlossCount,
|
|
||||||
int PanelCount,
|
|
||||||
int HardwareCount,
|
|
||||||
int SoftwareCount,
|
|
||||||
int RxTypeCount
|
|
||||||
);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// FOD类型统计
|
|
||||||
/// </summary>
|
|
||||||
public record FodTypeStats(byte FodType, int Count);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 维度统计
|
|
||||||
/// </summary>
|
|
||||||
public record DimensionStats(string Name, int Count);
|
|
||||||
@@ -54,7 +54,6 @@ public static class ServiceCollectionExtensions
|
|||||||
services.AddScoped<DimensionService>();
|
services.AddScoped<DimensionService>();
|
||||||
services.AddScoped<ScenarioService>();
|
services.AddScoped<ScenarioService>();
|
||||||
services.AddScoped<ParseService>();
|
services.AddScoped<ParseService>();
|
||||||
services.AddScoped<StatsService>();
|
|
||||||
services.AddScoped<ExportService>();
|
services.AddScoped<ExportService>();
|
||||||
services.AddScoped<CleanService>();
|
services.AddScoped<CleanService>();
|
||||||
services.AddScoped<AggregationService>();
|
services.AddScoped<AggregationService>();
|
||||||
|
|||||||
@@ -1,112 +0,0 @@
|
|||||||
using System.CommandLine;
|
|
||||||
using Gpulse.WCT.DataAnalyzer.Core.Application;
|
|
||||||
|
|
||||||
namespace Gpulse.WCT.DataAnalyzer.Commands;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 统计查询命令
|
|
||||||
/// </summary>
|
|
||||||
public class StatsCommand : Command
|
|
||||||
{
|
|
||||||
public StatsCommand(StatsService statsService)
|
|
||||||
: base("stats", "Query statistics from database")
|
|
||||||
{
|
|
||||||
var summaryOption = new Option<bool>(
|
|
||||||
"--summary",
|
|
||||||
() => false,
|
|
||||||
"Show overall statistics summary"
|
|
||||||
);
|
|
||||||
|
|
||||||
var byFodTypeOption = new Option<bool>(
|
|
||||||
"--by-fod-type",
|
|
||||||
() => false,
|
|
||||||
"Show statistics by FOD type"
|
|
||||||
);
|
|
||||||
|
|
||||||
var byPanelOption = new Option<bool>(
|
|
||||||
"--by-panel",
|
|
||||||
() => false,
|
|
||||||
"Show statistics by TX panel"
|
|
||||||
);
|
|
||||||
|
|
||||||
var byHardwareOption = new Option<bool>(
|
|
||||||
"--by-hardware",
|
|
||||||
() => false,
|
|
||||||
"Show statistics by TX hardware version"
|
|
||||||
);
|
|
||||||
|
|
||||||
var byRxTypeOption = new Option<bool>(
|
|
||||||
"--by-rx-type",
|
|
||||||
() => false,
|
|
||||||
"Show statistics by RX type"
|
|
||||||
);
|
|
||||||
|
|
||||||
AddOption(summaryOption);
|
|
||||||
AddOption(byFodTypeOption);
|
|
||||||
AddOption(byPanelOption);
|
|
||||||
AddOption(byHardwareOption);
|
|
||||||
AddOption(byRxTypeOption);
|
|
||||||
|
|
||||||
this.SetHandler(async (summary, byFodType, byPanel, byHardware, byRxType) =>
|
|
||||||
{
|
|
||||||
// 如果没有指定任何选项,默认显示摘要
|
|
||||||
if (!summary && !byFodType && !byPanel && !byHardware && !byRxType)
|
|
||||||
{
|
|
||||||
summary = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (summary)
|
|
||||||
{
|
|
||||||
var s = await statsService.GetSummaryAsync();
|
|
||||||
Console.WriteLine("=== Statistics Summary ===");
|
|
||||||
Console.WriteLine($" Scenarios: {s.ScenarioCount}");
|
|
||||||
Console.WriteLine($" Qfod Records: {s.QfodCount}");
|
|
||||||
Console.WriteLine($" Ploss Records: {s.PlossCount}");
|
|
||||||
Console.WriteLine($" TX Panels: {s.PanelCount}");
|
|
||||||
Console.WriteLine($" TX Hardware: {s.HardwareCount}");
|
|
||||||
Console.WriteLine($" TX Software: {s.SoftwareCount}");
|
|
||||||
Console.WriteLine($" RX Types: {s.RxTypeCount}");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (byFodType)
|
|
||||||
{
|
|
||||||
Console.WriteLine("\n=== By FOD Type ===");
|
|
||||||
var stats = await statsService.GetStatsByFodTypeAsync();
|
|
||||||
foreach (var s in stats)
|
|
||||||
{
|
|
||||||
Console.WriteLine($" FOD Type {s.FodType}: {s.Count}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (byPanel)
|
|
||||||
{
|
|
||||||
Console.WriteLine("\n=== By TX Panel ===");
|
|
||||||
var stats = await statsService.GetStatsByPanelAsync();
|
|
||||||
foreach (var s in stats)
|
|
||||||
{
|
|
||||||
Console.WriteLine($" {s.Name}: {s.Count}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (byHardware)
|
|
||||||
{
|
|
||||||
Console.WriteLine("\n=== By TX Hardware ===");
|
|
||||||
var stats = await statsService.GetStatsByHardwareAsync();
|
|
||||||
foreach (var s in stats)
|
|
||||||
{
|
|
||||||
Console.WriteLine($" {s.Name}: {s.Count}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (byRxType)
|
|
||||||
{
|
|
||||||
Console.WriteLine("\n=== By RX Type ===");
|
|
||||||
var stats = await statsService.GetStatsByRxTypeAsync();
|
|
||||||
foreach (var s in stats)
|
|
||||||
{
|
|
||||||
Console.WriteLine($" {s.Name}: {s.Count}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, summaryOption, byFodTypeOption, byPanelOption, byHardwareOption, byRxTypeOption);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -74,7 +74,6 @@ public class Program
|
|||||||
|
|
||||||
rootCommand.AddCommand(new ParseCommand(provider.GetRequiredService<ParseService>()));
|
rootCommand.AddCommand(new ParseCommand(provider.GetRequiredService<ParseService>()));
|
||||||
rootCommand.AddCommand(new AggregateCommand(provider.GetRequiredService<AggregationService>()));
|
rootCommand.AddCommand(new AggregateCommand(provider.GetRequiredService<AggregationService>()));
|
||||||
rootCommand.AddCommand(new StatsCommand(provider.GetRequiredService<StatsService>()));
|
|
||||||
rootCommand.AddCommand(new ExportCommand(provider.GetRequiredService<ExportService>()));
|
rootCommand.AddCommand(new ExportCommand(provider.GetRequiredService<ExportService>()));
|
||||||
rootCommand.AddCommand(new CleanCommand(provider.GetRequiredService<CleanService>()));
|
rootCommand.AddCommand(new CleanCommand(provider.GetRequiredService<CleanService>()));
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user