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"); + } + /// /// 转发请求到采集服务 ///