You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
haoliang-net/tools/ErrorSimulation/Program.cs

113 lines
5.6 KiB
C#

using System;
using System.Linq;
using System.Net.Http;
using Dapper;
using MySqlConnector;
const string BizConn = "Server=localhost;Database=cnc_business;Uid=root;Pwd=root;Charset=utf8mb4;SslMode=None;";
const string LogConn = "Server=localhost;Database=cnc_log;Uid=root;Pwd=root;Charset=utf8mb4;SslMode=None;";
int pass = 0, fail = 0;
void Assert(string name, bool cond, string detail = "")
{
if (cond) { Console.WriteLine($" ✅ {name} {detail}"); pass++; }
else { Console.WriteLine($" ❌ {name} {detail}"); fail++; }
}
Console.WriteLine("===== 错误模拟验证 =====\n");
// ====== 测试1: HTTP请求失败 ======
Console.WriteLine("--- 测试1: HTTP请求失败 → log_collect_raw + 本地日志 ---");
try
{
using var http = new HttpClient();
http.DefaultRequestHeaders.Add("X-Api-Key", "collector_api_key_2026");
http.PostAsync("http://localhost:5800/api/collector/refresh", null).Wait();
Console.WriteLine(" 已触发配置刷新(将重新采集)");
System.Threading.Thread.Sleep(40000); // 等两个采集周期
using var c = new MySqlConnection(LogConn);
var err = c.QueryFirstOrDefault<(long Id, string Msg, DateTime T)>(
"SELECT id, error_message, request_time FROM log_collect_raw WHERE is_success=0 AND error_message IS NOT NULL AND error_message!='' ORDER BY id DESC LIMIT 1");
bool hasRec = err.Id > 0;
bool notVague = err.Msg != "发生一个或多个错误。" && !(err.Msg??"").StartsWith("发生一个或多个错误");
bool hasType = (err.Msg??"").Contains("Exception") || (err.Msg??"").Contains("Error");
Assert("失败记录存在", hasRec);
Assert("非模糊消息(不是'发生一个或多个错误')", notVague);
Assert("包含异常类型名", hasType);
if (hasRec) Console.WriteLine($" 错误: {err.Msg?.Substring(0, Math.Min(200, err.Msg.Length))}");
Assert("本地日志文件存在", System.IO.File.Exists(@"C:\CncCollector\logs\collector.log"));
Assert("错误日志文件存在", System.IO.File.Exists(@"C:\CncCollector\logs\collector_error.log"));
}
catch (Exception ex) { Assert("测试1执行", false, ex.Message); }
// ====== 测试2: JSON解析失败 ======
Console.WriteLine("\n--- 测试2: JSON解析失败 → log_collect_raw ---");
try
{
using var c = new MySqlConnection(LogConn);
var before = c.ExecuteScalar<long>("SELECT COUNT(*) FROM log_collect_raw WHERE error_message LIKE '%[JsonReaderException]%'");
// 写一条模拟JSON解析失败的记录
c.Execute(@"INSERT INTO log_collect_raw (collect_address_id,request_time,response_time,response_duration,is_success,status_code,raw_json,error_message,created_at)
VALUES (1,NOW(),NOW(),50,0,NULL,'{broken json',@E,NOW())",
new { E = "[JsonReaderException] 无效的JSON格式: Unexpected character ← [ParseAndSave异常] JSON解析失败" });
var after = c.ExecuteScalar<long>("SELECT COUNT(*) FROM log_collect_raw WHERE error_message LIKE '%[JsonReaderException]%'");
Assert("JSON解析失败已记录", after > before);
// 清理
c.Execute("DELETE FROM log_collect_raw WHERE error_message LIKE '%[JsonReaderException]%'");
}
catch (Exception ex) { Assert("测试2执行", false, ex.Message); }
// ====== 测试3: ProductionTracker失败 → cnc_alert ======
Console.WriteLine("\n--- 测试3: ProductionTracker失败 → cnc_alert ---");
try
{
using var c = new MySqlConnection(BizConn);
var before = c.ExecuteScalar<long>("SELECT COUNT(*) FROM cnc_alert WHERE alert_type='production_error'");
c.Execute(@"INSERT INTO cnc_alert (alert_type,title,detail,is_resolved,created_at)
VALUES ('production_error','产量跟踪处理异常(模拟)','机床999产量跟踪失败: MySqlException: Connection timeout',0,NOW())");
var after = c.ExecuteScalar<long>("SELECT COUNT(*) FROM cnc_alert WHERE alert_type='production_error'");
Assert("产量跟踪告警已创建", after > before);
var alert = c.QueryFirstOrDefault<(string T, string D)>(
"SELECT title, detail FROM cnc_alert WHERE title LIKE '%模拟%' ORDER BY id DESC LIMIT 1");
Assert("告警标题含'产量跟踪'", alert.T.Contains("产量跟踪"));
Assert("告警详情非空", !string.IsNullOrEmpty(alert.D));
Console.WriteLine($" 告警: {alert.T}: {alert.D}");
c.Execute("DELETE FROM cnc_alert WHERE title LIKE '%模拟%'");
}
catch (Exception ex) { Assert("测试3执行", false, ex.Message); }
// ====== 测试4: DailySummaryJob失败 → cnc_alert ======
Console.WriteLine("\n--- 测试4: DailySummaryJob失败 → cnc_alert ---");
try
{
using var c = new MySqlConnection(BizConn);
var before = c.ExecuteScalar<long>("SELECT COUNT(*) FROM cnc_alert WHERE alert_type='summary_error'");
c.Execute(@"INSERT INTO cnc_alert (alert_type,title,detail,is_resolved,created_at)
VALUES ('summary_error','日终汇总失败(模拟-2026-05-07)','MySqlException: Connection timeout during daily summary transaction',0,NOW())");
var after = c.ExecuteScalar<long>("SELECT COUNT(*) FROM cnc_alert WHERE alert_type='summary_error'");
Assert("日终汇总告警已创建", after > before);
var alert = c.QueryFirstOrDefault<(string T, string D)>(
"SELECT title, detail FROM cnc_alert WHERE title LIKE '%模拟%' ORDER BY id DESC LIMIT 1");
Assert("告警标题含'日终汇总'", alert.T.Contains("日终汇总"));
Console.WriteLine($" 告警: {alert.T}: {alert.D}");
c.Execute("DELETE FROM cnc_alert WHERE title LIKE '%模拟%'");
}
catch (Exception ex) { Assert("测试4执行", false, ex.Message); }
Console.WriteLine($"\n===== 结果: {pass}通过, {fail}失败 =====");