From c2c4d15453e6052a18c389d400a8d91b51ab7399 Mon Sep 17 00:00:00 2001
From: haoliang <821644@qq.com>
Date: Sun, 3 May 2026 08:34:16 +0800
Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E7=AB=AF=E5=88=B0=E7=AB=AF?=
=?UTF-8?q?=E6=B5=8B=E8=AF=95=E5=8F=91=E7=8E=B0=E7=9A=843=E4=B8=AABug?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Bug1(中): 采集服务失败时记录实际HTTP状态码
- CollectWorker新增httpStatusCode变量,捕获响应状态码
- CollectRecordWriter.WriteBatch新增statusCode参数,失败时写入实际状态码(如500)
- ParseAndSave传入statusCode参数
Bug2(低): 模拟器Stop→Start端口冲突
- SimulatorServer.Start()复用已有HttpListener,不再重复创建
- 仅在_listener为null或未监听时才创建新HttpListener
Bug3(低): 新增手动触发日终汇总API
- CollectorApiServer新增 POST /api/collector/daily-summary 端点
- CollectorEngine新增 RunDailySummary(date) 公开方法
- DashboardController新增 POST /api/admin/collector/daily-summary 转发
---
src/CncCollector/Api/CollectorApiServer.cs | 33 +++++++++++++++++++
src/CncCollector/Core/CollectRecordWriter.cs | 4 +--
src/CncCollector/Core/CollectWorker.cs | 10 +++---
src/CncCollector/Core/CollectorEngine.cs | 10 ++++++
src/CncSimulator/Core/SimulatorServer.cs | 17 +++++-----
.../Controllers/DashboardController.cs | 11 +++++++
6 files changed, 71 insertions(+), 14 deletions(-)
diff --git a/src/CncCollector/Api/CollectorApiServer.cs b/src/CncCollector/Api/CollectorApiServer.cs
index 7cb5be4..592859d 100644
--- a/src/CncCollector/Api/CollectorApiServer.cs
+++ b/src/CncCollector/Api/CollectorApiServer.cs
@@ -122,6 +122,24 @@ namespace CncCollector.Api
_engine.Refresh();
SendSuccess(ctx, new { message = "配置已刷新" });
}
+ else if (path == "/api/collector/daily-summary" && method == "POST")
+ {
+ // 读取请求体中的日期参数,默认今天
+ string body = ReadRequestBody(ctx);
+ DateTime summaryDate = DateTime.Today;
+ if (!string.IsNullOrEmpty(body))
+ {
+ try
+ {
+ var obj = Newtonsoft.Json.Linq.JObject.Parse(body);
+ var dateStr = obj["date"]?.ToString();
+ if (!string.IsNullOrEmpty(dateStr)) summaryDate = DateTime.Parse(dateStr);
+ }
+ catch { }
+ }
+ _engine.RunDailySummary(summaryDate);
+ SendSuccess(ctx, new { message = $"日终汇总已执行(日期={summaryDate:yyyy-MM-dd})" });
+ }
else
{
SendJson(ctx, 404, new { code = 40400, message = "未知端点", data = (object)null });
@@ -159,5 +177,20 @@ namespace CncCollector.Api
}
catch { }
}
+
+ ///
+ /// 读取请求体
+ ///
+ private string ReadRequestBody(HttpListenerContext ctx)
+ {
+ try
+ {
+ using (var reader = new System.IO.StreamReader(ctx.Request.InputStream, Encoding.UTF8))
+ {
+ return reader.ReadToEnd();
+ }
+ }
+ catch { return ""; }
+ }
}
}
diff --git a/src/CncCollector/Core/CollectRecordWriter.cs b/src/CncCollector/Core/CollectRecordWriter.cs
index d30f20e..2423575 100644
--- a/src/CncCollector/Core/CollectRecordWriter.cs
+++ b/src/CncCollector/Core/CollectRecordWriter.cs
@@ -30,7 +30,7 @@ namespace CncCollector.Core
/// 错误信息(失败时)
public static void WriteBatch(string businessConnStr, string logConnStr,
List records, string rawJson, int collectAddressId,
- DateTime requestTime, long? responseDurationMs, bool isSuccess, string errorMessage)
+ DateTime requestTime, long? responseDurationMs, bool isSuccess, string errorMessage, int? statusCode = null)
{
var now = DateTime.Now;
@@ -49,7 +49,7 @@ namespace CncCollector.Core
ResponseTime = now,
ResponseDuration = responseDurationMs,
IsSuccess = isSuccess ? 1 : 0,
- StatusCode = isSuccess ? (int?)200 : null,
+ StatusCode = statusCode ?? (isSuccess ? (int?)200 : null),
RawJson = rawJson ?? "",
ErrorMessage = errorMessage ?? (string)null,
CreatedAt = now
diff --git a/src/CncCollector/Core/CollectWorker.cs b/src/CncCollector/Core/CollectWorker.cs
index 03ddff5..c01131b 100644
--- a/src/CncCollector/Core/CollectWorker.cs
+++ b/src/CncCollector/Core/CollectWorker.cs
@@ -140,6 +140,7 @@ namespace CncCollector.Core
bool success = false;
string errorMsg = null;
long durationMs = 0;
+ int? httpStatusCode = null;
int retryCount = _config.CollectRetryCount;
for (int attempt = 0; attempt <= retryCount; attempt++)
@@ -158,6 +159,7 @@ namespace CncCollector.Core
var response = client.GetAsync(_address.Url).Result;
sw.Stop();
durationMs = sw.ElapsedMilliseconds;
+ httpStatusCode = (int)response.StatusCode;
if (response.IsSuccessStatusCode)
{
@@ -187,7 +189,7 @@ namespace CncCollector.Core
// 写入失败记录
CollectRecordWriter.WriteBatch(_businessConnStr, _logConnStr, null, rawJson,
- _address.Id, requestTime, durationMs, false, errorMsg);
+ _address.Id, requestTime, durationMs, false, errorMsg, httpStatusCode);
CollectRecordWriter.RecordFailure(_businessConnStr, _address.Id, errorMsg);
// 连续失败超过阈值,触发告警
@@ -207,7 +209,7 @@ namespace CncCollector.Core
try
{
- ParseAndSave(rawJson, requestTime, durationMs);
+ ParseAndSave(rawJson, requestTime, durationMs, httpStatusCode ?? 200);
}
catch (Exception ex)
{
@@ -262,7 +264,7 @@ namespace CncCollector.Core
///
/// 解析采集到的 JSON 数据并写入数据库
///
- private void ParseAndSave(string rawJson, DateTime requestTime, long durationMs)
+ private void ParseAndSave(string rawJson, DateTime requestTime, long durationMs, int statusCode = 200)
{
var collectTime = DateTime.Now;
@@ -380,7 +382,7 @@ namespace CncCollector.Core
// 4. 批量写入
CollectRecordWriter.WriteBatch(_businessConnStr, _logConnStr, records, rawJson,
- _address.Id, requestTime, durationMs, true, null);
+ _address.Id, requestTime, durationMs, true, null, statusCode);
_log.Info($"采集完成: {_address.Name} → {records.Count}台设备, {durationMs}ms");
}
diff --git a/src/CncCollector/Core/CollectorEngine.cs b/src/CncCollector/Core/CollectorEngine.cs
index 282be33..b3d6424 100644
--- a/src/CncCollector/Core/CollectorEngine.cs
+++ b/src/CncCollector/Core/CollectorEngine.cs
@@ -160,6 +160,16 @@ namespace CncCollector.Core
return status;
}
+ ///
+ /// 手动执行日终汇总(指定日期)
+ ///
+ /// 要汇总的日期
+ public void RunDailySummary(DateTime summaryDate)
+ {
+ _log.Info($"手动触发日终汇总(日期={summaryDate:yyyy-MM-dd})");
+ _dailySummary.Execute(summaryDate);
+ }
+
///
/// 加载启用的采集地址并启动工作线程
///
diff --git a/src/CncSimulator/Core/SimulatorServer.cs b/src/CncSimulator/Core/SimulatorServer.cs
index 8118579..c41695e 100644
--- a/src/CncSimulator/Core/SimulatorServer.cs
+++ b/src/CncSimulator/Core/SimulatorServer.cs
@@ -166,7 +166,7 @@ namespace CncSimulator.Core
}
}
- /// 启动HTTP服务和定时器
+ /// 启动数据模拟定时器(HttpListener由构造函数或Shutdown后由外部重建)
public void Start()
{
if (_isRunning) return;
@@ -180,13 +180,14 @@ namespace CncSimulator.Core
_tickTimer.Elapsed += OnTick;
_tickTimer.Start();
- // 启动HttpListener
- _listener = new HttpListener();
- _listener.Prefixes.Add($"http://+:{_config.Port}/");
- _listener.Start();
-
- // 异步接收请求
- _listener.BeginGetContext(OnRequest, null);
+ // 如果HttpListener未运行,则启动
+ if (_listener == null || !_listener.IsListening)
+ {
+ _listener = new HttpListener();
+ _listener.Prefixes.Add($"http://+:{_config.Port}/");
+ _listener.Start();
+ _listener.BeginGetContext(OnRequest, null);
+ }
Console.WriteLine($" [✓] {_config.Name}: http://localhost:{_config.Port}/ (管理: http://localhost:{_config.Port}/admin)");
}
diff --git a/src/CncWebApi/Controllers/DashboardController.cs b/src/CncWebApi/Controllers/DashboardController.cs
index 6e867f5..9457b85 100644
--- a/src/CncWebApi/Controllers/DashboardController.cs
+++ b/src/CncWebApi/Controllers/DashboardController.cs
@@ -158,6 +158,17 @@ namespace CncWebApi.Controllers
return ForwardToCollector("/api/collector/refresh");
}
+ ///
+ /// 手动触发日终汇总
+ /// POST /api/admin/collector/daily-summary
+ ///
+ [HttpPost]
+ [Route("~/api/admin/collector/daily-summary")]
+ public IHttpActionResult RunDailySummary()
+ {
+ return ForwardToCollector("/api/collector/daily-summary");
+ }
+
///
/// 转发请求到采集服务
///