From 9265301c1655fffdc71cca7b0e0cfab1af89afeb Mon Sep 17 00:00:00 2001
From: dengjunjie <dengjunjie@hnkhzn.com>
Date: 星期四, 16 四月 2026 19:07:48 +0800
Subject: [PATCH] 添加接口日志配置文件,优化接口日志记录方法,优化获取阻碍托生成移库任务方法
---
代码管理/WCS/WIDESEAWCS_Server/WIDESEAWCS_BasicInfoService/ApiInfoService.cs | 72 ++
代码管理/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/Filter/Log/LogCleanupService.cs | 426 +++++++++++++++++++++
代码管理/WCS/WIDESEAWCS_Server/WIDESEAWCS_Model/Models/BasicInfo/Dt_InterfaceLog.cs | 18
代码管理/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/Filter/Log/ApiLogMiddlewareNew.cs | 144 +++++++
代码管理/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/WIDESEAWCS_Server.csproj | 4
代码管理/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/Filter/Log/LoggerNew.cs | 431 +++++++++++++++++++++
代码管理/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/Program.cs | 33 +
代码管理/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/Task/RGVTaskExtend.cs | 7
代码管理/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/Filter/Log/MiddlewareHelpersNew.cs | 22 +
代码管理/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/appsettings.json | 31 +
代码管理/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/Controllers/WMS/WMSController.cs | 2
11 files changed, 1,167 insertions(+), 23 deletions(-)
diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WCS/WIDESEAWCS_Server/WIDESEAWCS_BasicInfoService/ApiInfoService.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WCS/WIDESEAWCS_Server/WIDESEAWCS_BasicInfoService/ApiInfoService.cs"
index 99a8888..57c0b3a 100644
--- "a/\344\273\243\347\240\201\347\256\241\347\220\206/WCS/WIDESEAWCS_Server/WIDESEAWCS_BasicInfoService/ApiInfoService.cs"
+++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WCS/WIDESEAWCS_Server/WIDESEAWCS_BasicInfoService/ApiInfoService.cs"
@@ -1,6 +1,7 @@
锘縰sing System;
using System.Collections.Generic;
using System.Linq;
+using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using WIDESEAWCS_Core;
@@ -36,11 +37,15 @@
{
WebResponseContent content = new WebResponseContent();
string response = string.Empty;
+ string requestHash = string.Empty;
+ string responseHash = string.Empty;
Dt_ApiInfo? apiInfo = null;
try
{
apiInfo = BaseDal.QueryFirst(x => x.ApiCode == apiCode) ?? throw new Exception($"鏈壘鍒皗remark}鎺ュ彛閰嶇疆淇℃伅锛佽妫�鏌ユ帴鍙i厤缃�");
response = HttpHelper.Post(apiInfo.ApiAddress, requestParameters);
+ requestHash = ComputeHash(requestParameters);
+ responseHash = ComputeHash(response);
if (apiInfo.Remark.Contains("鍥涘悜杞�"))
{
FOURBOTReturn fOURBOTReturn = response.DeserializeObject<FOURBOTReturn>();
@@ -70,24 +75,63 @@
{
if (isAdd && !string.IsNullOrEmpty(response) && apiInfo != null)
{
- Dt_InterfaceLog interfaceLog = new Dt_InterfaceLog()
+ #region 鏌ヨ褰撳ぉ鏄惁瀛樺湪鐩稿悓璁板綍
+ var today = DateTime.Now.Date;
+ var existingLog = _interfaceLogService.Repository.QueryFirst(x =>
+ x.ApiCode == apiCode &&
+ x.RequestParametersHash == requestHash &&
+ x.ResponseParametersHash == responseHash &&
+ x.CreateDate.Date == today);
+ if (existingLog != null)
{
- ApiCode = apiCode,
- RequestParameters = requestParameters,
- ApiAddress = apiInfo.ApiAddress,
- ApiName = apiInfo.ApiName,
- PushFrequency = 1,
- PushState = content.Status ? 1 : 2,
- Requestor = "WCS",
- Recipient = apiInfo.Remark,
- ResponseParameters = response,
- Creater = "System",
- Remark = content.Status ? remark : content.Message,
- };
- _interfaceLogService.Repository.AddData(interfaceLog);
+ existingLog.PushFrequency = existingLog.PushFrequency + 1;
+ existingLog.PushState = content.Status ? 1 : 2;
+ existingLog.ResponseParameters = response;
+ existingLog.Remark = content.Status ? remark : content.Message;
+ existingLog.Modifier = App.User?.UserName ?? "System";
+ existingLog.ModifyDate = DateTime.Now;
+ _interfaceLogService.Repository.UpdateData(existingLog);
+ }
+ #endregion
+ else
+ {
+ Dt_InterfaceLog interfaceLog = new Dt_InterfaceLog()
+ {
+ ApiCode = apiCode,
+ RequestParameters = requestParameters,
+ ApiAddress = apiInfo.ApiAddress,
+ ApiName = apiInfo.ApiName,
+ RequestParametersHash = requestHash,
+ ResponseParametersHash = responseHash,
+ PushFrequency = 1,
+ PushState = content.Status ? 1 : 2,
+ Requestor = "WCS",
+ Recipient = apiInfo.Remark,
+ ResponseParameters = response,
+ Creater = "System",
+ Remark = content.Status ? remark : content.Message,
+ };
+ _interfaceLogService.Repository.AddData(interfaceLog);
+ }
}
}
return content;
}
+
+ /// <summary>
+ /// 璁$畻瀛楃涓茬殑SHA256鍝堝笇鍊�
+ /// </summary>
+ private static string ComputeHash(string input)
+ {
+ if (string.IsNullOrEmpty(input))
+ return string.Empty;
+
+ using (SHA256 sha256 = SHA256.Create())
+ {
+ byte[] bytes = Encoding.UTF8.GetBytes(input);
+ byte[] hashBytes = sha256.ComputeHash(bytes);
+ return BitConverter.ToString(hashBytes).Replace("-", "").ToLower();
+ }
+ }
}
}
diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WCS/WIDESEAWCS_Server/WIDESEAWCS_Model/Models/BasicInfo/Dt_InterfaceLog.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WCS/WIDESEAWCS_Server/WIDESEAWCS_Model/Models/BasicInfo/Dt_InterfaceLog.cs"
index 176cd09..7d07c19 100644
--- "a/\344\273\243\347\240\201\347\256\241\347\220\206/WCS/WIDESEAWCS_Server/WIDESEAWCS_Model/Models/BasicInfo/Dt_InterfaceLog.cs"
+++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WCS/WIDESEAWCS_Server/WIDESEAWCS_Model/Models/BasicInfo/Dt_InterfaceLog.cs"
@@ -51,6 +51,12 @@
public int PushState { get; set; } = 0;
/// <summary>
+ /// 璇锋眰鏂圭敤鎴稩P
+ /// </summary>
+ [SugarColumn(IsNullable = true, Length = 20, ColumnDescription = "璇锋眰鏂圭敤鎴稩P")]
+ public string RequestorUserIP { get; set; }
+
+ /// <summary>
/// 璇锋眰鏂�
/// </summary>
[SugarColumn(IsNullable = true, Length = 50, ColumnDescription = "璇锋眰鏂�")]
@@ -63,6 +69,12 @@
public string RequestParameters { get; set; }
/// <summary>
+ /// 璇锋眰鍙傛暟鍝堝笇鍊硷紙鐢ㄤ簬绱㈠紩鍜屽幓閲嶏級
+ /// </summary>
+ [SugarColumn(IsNullable = true, Length = 64, ColumnDescription = "璇锋眰鍙傛暟鍝堝笇鍊�")]
+ public string RequestParametersHash { get; set; }
+
+ /// <summary>
/// 鎺ユ敹鏂�
/// </summary>
[SugarColumn(IsNullable = true, Length = 50, ColumnDescription = "鎺ユ敹鏂�")]
@@ -75,6 +87,12 @@
public string ResponseParameters { get; set; }
/// <summary>
+ /// 鍝嶅簲鍙傛暟鍝堝笇鍊硷紙鐢ㄤ簬绱㈠紩鍜屽幓閲嶏級
+ /// </summary>
+ [SugarColumn(IsNullable = true, Length = 64, ColumnDescription = "鍝嶅簲鍙傛暟鍝堝笇鍊�")]
+ public string ResponseParametersHash { get; set; }
+
+ /// <summary>
/// 澶囨敞
/// </summary>
[SugarColumn(IsNullable = true, Length = 100, ColumnDescription = "澶囨敞")]
diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/Controllers/WMS/WMSController.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/Controllers/WMS/WMSController.cs"
index 4476a15..999ec40 100644
--- "a/\344\273\243\347\240\201\347\256\241\347\220\206/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/Controllers/WMS/WMSController.cs"
+++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/Controllers/WMS/WMSController.cs"
@@ -71,7 +71,7 @@
}
/// <summary>
- /// 璐ㄦ缁撴灉鍙嶉
+ /// 澶栨缁撴灉鍙嶉
/// </summary>
/// <param name="iQC"></param>
/// <returns></returns>
diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/Filter/Log/ApiLogMiddlewareNew.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/Filter/Log/ApiLogMiddlewareNew.cs"
new file mode 100644
index 0000000..21d3de3
--- /dev/null
+++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/Filter/Log/ApiLogMiddlewareNew.cs"
@@ -0,0 +1,144 @@
+锘縰sing Microsoft.AspNetCore.Http;
+using Microsoft.Extensions.Logging;
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Net;
+using System.Reflection;
+using System.Text;
+using System.Text.RegularExpressions;
+using System.Threading.Tasks;
+using WIDESEAWCS_Core.Helper;
+using WIDESEAWCS_Core.LogHelper;
+
+namespace WIDESEAWCS_Core.Middlewares
+{
+ /// <summary>
+ /// 璁板綍璇锋眰鍜屽搷搴旀暟鎹�
+ /// </summary>
+ public class ApiLogMiddlewareNew
+ {
+ /// <summary>
+ ///
+ /// </summary>
+ private readonly RequestDelegate _next;
+
+ public ApiLogMiddlewareNew(RequestDelegate next, ILogger<ApiLogMiddlewareNew> logger)
+ {
+ _next = next;
+ }
+
+ //todo
+ public async Task InvokeAsync(HttpContext context)
+ {
+ if (App.ExpDateTime != null && (DateTime.Now - App.ExpDateTime.GetValueOrDefault()).TotalSeconds > 0)
+ {
+ context.Response.StatusCode = HttpStatusCode.InternalServerError.ObjToInt();
+ context.Response.ContentType = "application/json";
+
+ var json = new WebResponseContent();
+
+ json.Message = HttpStatusCode.InternalServerError.ToString();//閿欒淇℃伅
+ json.Code = 500;//500寮傚父
+
+ StreamWriter streamWriter = new StreamWriter(context.Response.Body);
+ await streamWriter.WriteAsync(json.Serialize());
+ return;
+ }
+
+ // 杩囨护锛屽彧鏈夋帴鍙�
+ if (context.Request.Path.Value?.Contains("api") ?? false)
+ {
+ context.Request.EnableBuffering();
+ Stream originalBody = context.Response.Body;
+ string requestParam = string.Empty;
+ string responseParam = string.Empty;
+ try
+ {
+ (context.RequestServices.GetService(typeof(RequestLogModel)) as RequestLogModel).RequestDate = DateTime.Now;
+ try
+ {
+ // 瀛樺偍璇锋眰鏁版嵁
+ requestParam = RequestDataLog(context);
+ context.Request.Body.Position = 0;
+ }
+ catch { }
+ using MemoryStream ms = new();
+ context.Response.Body = ms;
+
+ await _next(context);
+
+ try
+ {
+ // 瀛樺偍鍝嶅簲鏁版嵁
+ responseParam = ResponseDataLog(context.Response);
+ }
+ catch { }
+
+ ms.Position = 0;
+ await ms.CopyToAsync(originalBody);
+ #region 杩囨护鎺ュ彛
+ string path = context.Request.Path.Value;
+ if (!string.IsNullOrEmpty(path))
+ {
+ List<string> RequestPaths = new List<string>();
+ string RequestPath = AppSettings.Configuration[nameof(RequestPath)];
+ if (!string.IsNullOrEmpty(RequestPath)) RequestPaths = RequestPath.Split(',').ToList();
+ bool containsAny = RequestPaths.Any(k => path.Contains(k, StringComparison.OrdinalIgnoreCase));
+ if (!containsAny) Logger.Add(requestParam, responseParam);//璁板綍绯荤粺鏃ュ織
+ //璁板綍鎺ュ彛鏃ュ織
+ var ignoreKeywords = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "get" };
+ containsAny = RequestPaths.Where(k => !ignoreKeywords.Contains(k))
+ .Any(k => path.Contains(k, StringComparison.OrdinalIgnoreCase));
+ if (containsAny && context != null) LoggerNew.Add(requestParam, responseParam, context);
+ }
+ #endregion
+ //if (!(context.Request.Path.Value?.Contains("get") ?? true))
+ // Logger.Add(requestParam, responseParam);
+ }
+ catch (Exception ex)
+ {
+ // 璁板綍寮傚父
+
+ }
+ finally
+ {
+ context.Response.Body = originalBody;
+ }
+ }
+ else
+ {
+ await _next(context);
+ }
+ }
+
+ private string RequestDataLog(HttpContext context)
+ {
+ var request = context.Request;
+ var sr = new StreamReader(request.Body);
+
+ object obj = new
+ {
+ QueryString = request.QueryString.ToString(),
+ BodyData = sr.ReadToEndAsync().Result
+ };
+
+ string data = JsonConvert.SerializeObject(obj);
+
+ request.Body.Position = 0;
+
+ return data;
+ }
+
+ private string ResponseDataLog(HttpResponse response)
+ {
+ response.Body.Position = 0;
+ using StreamReader stream = new StreamReader(response.Body, leaveOpen: true);
+ string body = stream.ReadToEnd();
+ response.Body.Position = 0;
+ return body;
+ }
+ }
+}
diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/Filter/Log/LogCleanupService.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/Filter/Log/LogCleanupService.cs"
new file mode 100644
index 0000000..002b48b
--- /dev/null
+++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/Filter/Log/LogCleanupService.cs"
@@ -0,0 +1,426 @@
+锘縰sing Microsoft.Extensions.Hosting;
+using SqlSugar;
+using System;
+using System.IO;
+using System.Threading;
+using System.Threading.Tasks;
+using WIDESEAWCS_Core.DB;
+using WIDESEAWCS_Core.Seed;
+using WIDESEAWCS_Model.Models;
+
+namespace WIDESEAWCS_Core.LogHelper
+{
+ /// <summary>
+ /// 鏃ュ織鏁版嵁娓呯悊鏈嶅姟
+ /// </summary>
+ public class LogCleanupService : IHostedService, IDisposable
+ {
+ private Timer _cleanupTimer;
+ private bool _isDisposed = false;
+ private readonly object _lockObject = new object();
+
+ /// <summary>
+ /// 鏁版嵁淇濈暀澶╂暟锛堥粯璁�90澶╋級
+ /// </summary>
+ public int RetentionDays { get; set; } = 90;
+
+ /// <summary>
+ /// 娓呯悊闂撮殧锛堝皬鏃讹紝榛樿24灏忔椂锛�
+ /// </summary>
+ public int CleanupIntervalHours { get; set; } = 24;
+
+ /// <summary>
+ /// 娓呯悊鎵ц鏃堕棿锛堝皬鏃讹紝0-23锛岄粯璁ゅ噷鏅�2鐐癸級
+ /// </summary>
+ public int CleanupHour { get; set; } = 2;
+
+ /// <summary>
+ /// 鏄惁鍚敤褰掓。
+ /// </summary>
+ public bool EnableArchive { get; set; } = false;
+
+ /// <summary>
+ /// 鏄惁鍚敤鑷姩娓呯悊
+ /// </summary>
+ public bool EnableAutoCleanup { get; set; } = true;
+
+ /// <summary>
+ /// 鏃ュ織鏂囦欢淇濈暀澶╂暟
+ /// </summary>
+ public int LogRetentionDays { get; set; } = 30;
+ /// <summary>
+ /// 鏃ュ織鏂囦欢璺緞
+ /// </summary>
+ private string LogFilePath => Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Logs", "LogCleanup", $"Cleanup_{DateTime.Now:yyyyMMdd}.log");
+
+ public Task StartAsync(CancellationToken cancellationToken)
+ {
+ if (EnableAutoCleanup)
+ {
+ // 纭繚鏃ュ織鐩綍瀛樺湪
+ EnsureLogDirectoryExists();
+
+ // 璁$畻鍒颁笅涓�涓竻鐞嗘椂闂寸殑闂撮殧
+ var now = DateTime.Now;
+ var nextCleanupTime = DateTime.Today.AddHours(CleanupHour);
+
+ if (now > nextCleanupTime)
+ {
+ nextCleanupTime = nextCleanupTime.AddDays(1);
+ }
+
+ var timeToFirstCleanup = nextCleanupTime - now;
+
+ // 璁剧疆瀹氭椂鍣紝鍦ㄦ寚瀹氭椂闂存墽琛屾竻鐞�
+ _cleanupTimer = new Timer(CleanupCallback, null,
+ timeToFirstCleanup,
+ TimeSpan.FromHours(CleanupIntervalHours));
+
+ WriteLog($"鏃ュ織娓呯悊鏈嶅姟宸插惎鍔紝棣栨娓呯悊鏃堕棿: {nextCleanupTime:yyyy-MM-dd HH:mm:ss}");
+ }
+
+ return Task.CompletedTask;
+ }
+
+ /// <summary>
+ /// 纭繚鏃ュ織鐩綍瀛樺湪
+ /// </summary>
+ private void EnsureLogDirectoryExists()
+ {
+ try
+ {
+ string logDirectory = Path.GetDirectoryName(LogFilePath);
+ if (!Directory.Exists(logDirectory))
+ {
+ Directory.CreateDirectory(logDirectory);
+ }
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine($"鍒涘缓鏃ュ織鐩綍澶辫触: {ex.Message}");
+ }
+ }
+
+ /// <summary>
+ /// 鍐欏叆鏃ュ織鍒版枃浠�
+ /// </summary>
+ private void WriteLog(string message, bool isError = false)
+ {
+ try
+ {
+ lock (_lockObject)
+ {
+ EnsureLogDirectoryExists();
+ string logMessage = $"[{DateTime.Now:yyyy-MM-dd HH:mm:ss}] {(isError ? "[ERROR]" : "[INFO]")} {message}";
+
+ // 鍐欏叆鏂囦欢
+ File.AppendAllText(LogFilePath, logMessage + Environment.NewLine);
+
+ // 鍚屾椂杈撳嚭鍒版帶鍒跺彴锛堝彲閫夛紝渚夸簬璋冭瘯锛�
+ Console.WriteLine(logMessage);
+
+ // 鏃ュ織鏂囦欢杩囧ぇ鏃惰嚜鍔ㄦ竻鐞嗭紙淇濈暀鏈�杩�30澶╃殑鏃ュ織鏂囦欢锛�
+ AutoCleanupLogFiles();
+ }
+ }
+ catch (Exception ex)
+ {
+ // 濡傛灉鏂囦欢鏃ュ織澶辫触锛岃嚦灏戣緭鍑哄埌鎺у埗鍙�
+ Console.WriteLine($"鍐欏叆鏃ュ織鏂囦欢澶辫触: {ex.Message}");
+ Console.WriteLine($"[{DateTime.Now:yyyy-MM-dd HH:mm:ss}] {message}");
+ }
+ }
+
+ /// <summary>
+ /// 鑷姩娓呯悊杩囨湡鐨勬棩蹇楁枃浠讹紙淇濈暀30澶╋級
+ /// </summary>
+ private void AutoCleanupLogFiles()
+ {
+ try
+ {
+ string logDirectory = Path.GetDirectoryName(LogFilePath);
+ if (Directory.Exists(logDirectory))
+ {
+ var files = Directory.GetFiles(logDirectory, "Cleanup_*.log");
+ DateTime cutoffDate = DateTime.Now.AddDays(-30);
+
+ foreach (var file in files)
+ {
+ try
+ {
+ // 浠庢枃浠跺悕涓彁鍙栨棩鏈�
+ string fileName = Path.GetFileNameWithoutExtension(file);
+ if (fileName.StartsWith("Cleanup_"))
+ {
+ string dateStr = fileName.Replace("Cleanup_", "");
+ if (DateTime.TryParseExact(dateStr, "yyyyMMdd", null, System.Globalization.DateTimeStyles.None, out DateTime fileDate))
+ {
+ if (fileDate < cutoffDate)
+ {
+ File.Delete(file);
+ WriteLog($"鍒犻櫎杩囨湡鏃ュ織鏂囦欢: {Path.GetFileName(file)}");
+ }
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine($"鍒犻櫎杩囨湡鏃ュ織鏂囦欢澶辫触 {file}: {ex.Message}");
+ }
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine($"娓呯悊鏃ュ織鏂囦欢澶辫触: {ex.Message}");
+ }
+ }
+
+ private void CleanupCallback(object state)
+ {
+ Task.Run(() => CleanupAsync());
+ }
+
+ /// <summary>
+ /// 鎵ц娓呯悊
+ /// </summary>
+ public async Task CleanupAsync()
+ {
+ try
+ {
+ WriteLog($"寮�濮嬫竻鐞� {RetentionDays} 澶╁墠鐨勬棩蹇楁暟鎹�");
+
+ using (SqlSugarClient sugarClient = new SqlSugarClient(new ConnectionConfig()
+ {
+ ConnectionString = DBContext.GetMainConnectionDb().Connection,
+ IsAutoCloseConnection = true,
+ DbType = DBContext.DbType,
+ }))
+ {
+ DateTime cutoffDate = DateTime.Now.AddDays(-RetentionDays);
+
+ WriteLog($"鎴鏃ユ湡: {cutoffDate:yyyy-MM-dd HH:mm:ss}");
+
+ if (EnableArchive)
+ {
+ // 鍏堝綊妗e啀鍒犻櫎
+ await ArchiveDataAsync(sugarClient, cutoffDate);
+ }
+
+ // 鍒犻櫎鍘嗗彶鏁版嵁
+ int deletedCount = await sugarClient.Deleteable<Dt_InterfaceLog>()
+ .Where(x => x.CreateDate < cutoffDate)
+ .ExecuteCommandAsync();
+
+ WriteLog($"娓呯悊瀹屾垚锛屽叡鍒犻櫎 {deletedCount} 鏉¤褰�");
+
+ // 鍙�夛細璁板綍娓呯悊鏃ュ織鍒版暟鎹簱
+ await LogCleanupResult(sugarClient, deletedCount, cutoffDate);
+ }
+ }
+ catch (Exception ex)
+ {
+ WriteLog($"娓呯悊澶辫触: {ex.Message}", true);
+ WriteLog($"璇︾粏閿欒: {ex.ToString()}", true);
+ }
+ }
+
+ private async Task ArchiveDataAsync(SqlSugarClient sugarClient, DateTime cutoffDate)
+ {
+ try
+ {
+ string archiveTableName = $"Dt_InterfaceLog_Archive_{DateTime.Now:yyyyMM}";
+
+ WriteLog($"寮�濮嬪綊妗f暟鎹埌琛�: {archiveTableName}");
+
+ // 鍒涘缓褰掓。琛�
+ string createTableSql = $@"
+ IF NOT EXISTS (SELECT * FROM sysobjects WHERE name='{archiveTableName}' AND xtype='U')
+ BEGIN
+ SELECT * INTO {archiveTableName} FROM Dt_InterfaceLog WHERE 1=0
+ ALTER TABLE {archiveTableName} ADD ArchiveDate datetime DEFAULT GETDATE()
+ END";
+ await sugarClient.Ado.ExecuteCommandAsync(createTableSql);
+
+ // 褰掓。鏁版嵁
+ string archiveSql = $@"
+ INSERT INTO {archiveTableName} (Id, ApiCode, ApiName, ApiAddress, PushFrequency,
+ PushState, Requestor, RequestParameters, RequestParametersHash, Recipient,
+ ResponseParameters, ResponseParametersHash, Remark, CreateTime, ArchiveDate)
+ SELECT Id, ApiCode, ApiName, ApiAddress, PushFrequency, PushState,
+ Requestor, RequestParameters, RequestParametersHash, Recipient,
+ ResponseParameters, ResponseParametersHash, Remark, CreateTime, GETDATE()
+ FROM Dt_InterfaceLog
+ WHERE CreateTime < @CutoffDate";
+
+ int archivedCount = await sugarClient.Ado.ExecuteCommandAsync(archiveSql,
+ new { CutoffDate = cutoffDate });
+
+ WriteLog($"褰掓。瀹屾垚锛屽叡褰掓。 {archivedCount} 鏉¤褰曞埌 {archiveTableName}");
+ }
+ catch (Exception ex)
+ {
+ WriteLog($"褰掓。澶辫触: {ex.Message}", true);
+ }
+ }
+
+ private async Task LogCleanupResult(SqlSugarClient sugarClient, int deletedCount, DateTime cutoffDate)
+ {
+ try
+ {
+ // 鍒涘缓娓呯悊鏃ュ織琛紙濡傛灉涓嶅瓨鍦級
+ string createLogTableSql = @"
+ IF NOT EXISTS (SELECT * FROM sysobjects WHERE name='LogCleanupHistory' AND xtype='U')
+ BEGIN
+ CREATE TABLE LogCleanupHistory (
+ Id INT IDENTITY(1,1) PRIMARY KEY,
+ TableName NVARCHAR(100),
+ DeletedCount INT,
+ CutoffDate DATETIME,
+ CleanupTime DATETIME DEFAULT GETDATE()
+ )
+ END";
+ await sugarClient.Ado.ExecuteCommandAsync(createLogTableSql);
+
+ // 璁板綍娓呯悊鏃ュ織
+ string insertLogSql = @"
+ INSERT INTO LogCleanupHistory (TableName, DeletedCount, CutoffDate, CleanupTime)
+ VALUES ('Dt_InterfaceLog', @DeletedCount, @CutoffDate, GETDATE())";
+
+ await sugarClient.Ado.ExecuteCommandAsync(insertLogSql,
+ new { DeletedCount = deletedCount, CutoffDate = cutoffDate });
+
+ WriteLog($"娓呯悊璁板綍宸插啓鍏ユ暟鎹簱鏃ュ織琛�");
+ }
+ catch (Exception ex)
+ {
+ WriteLog($"鍐欏叆鏁版嵁搴撴棩蹇楀け璐�: {ex.Message}", true);
+ }
+ }
+
+ /// <summary>
+ /// 鎵嬪姩鎵ц娓呯悊
+ /// </summary>
+ public async Task<int> ManualCleanup(int days = 90)
+ {
+ try
+ {
+ WriteLog($"鎵嬪姩娓呯悊寮�濮嬶紝鍒犻櫎瓒呰繃 {days} 澶╃殑鏁版嵁");
+
+ using (SqlSugarClient sugarClient = new SqlSugarClient(new ConnectionConfig()
+ {
+ ConnectionString = DBContext.GetMainConnectionDb().Connection,
+ IsAutoCloseConnection = true,
+ DbType = DBContext.DbType,
+ }))
+ {
+ DateTime cutoffDate = DateTime.Now.AddDays(-days);
+ int deletedCount = await sugarClient.Deleteable<Dt_InterfaceLog>()
+ .Where(x => x.CreateDate < cutoffDate)
+ .ExecuteCommandAsync();
+
+ WriteLog($"鎵嬪姩娓呯悊瀹屾垚锛屽垹闄� {deletedCount} 鏉¤褰�");
+ return deletedCount;
+ }
+ }
+ catch (Exception ex)
+ {
+ WriteLog($"鎵嬪姩娓呯悊澶辫触: {ex.Message}", true);
+ return 0;
+ }
+ }
+
+ /// <summary>
+ /// 鑾峰彇娓呯悊缁熻淇℃伅
+ /// </summary>
+ public async Task<CleanupStatistics> GetStatistics()
+ {
+ try
+ {
+ using (SqlSugarClient sugarClient = new SqlSugarClient(new ConnectionConfig()
+ {
+ ConnectionString = DBContext.GetMainConnectionDb().Connection,
+ IsAutoCloseConnection = true,
+ DbType = DBContext.DbType,
+ }))
+ {
+ var totalCount = await sugarClient.Queryable<Dt_InterfaceLog>().CountAsync();
+ var oldestLog = await sugarClient.Queryable<Dt_InterfaceLog>()
+ .OrderBy(x => x.CreateDate)
+ .FirstAsync();
+ var newestLog = await sugarClient.Queryable<Dt_InterfaceLog>()
+ .OrderBy(x => x.CreateDate, OrderByType.Desc)
+ .FirstAsync();
+
+ return new CleanupStatistics
+ {
+ TotalCount = totalCount,
+ OldestLogTime = oldestLog?.CreateDate,
+ NewestLogTime = newestLog?.CreateDate,
+ RetentionDays = RetentionDays,
+ LastCleanupTime = GetLastCleanupTime(),
+ LogFilePath = LogFilePath
+ };
+ }
+ }
+ catch (Exception ex)
+ {
+ WriteLog($"鑾峰彇缁熻淇℃伅澶辫触: {ex.Message}", true);
+ return null;
+ }
+ }
+
+ private DateTime? GetLastCleanupTime()
+ {
+ try
+ {
+ string logDirectory = Path.GetDirectoryName(LogFilePath);
+ if (Directory.Exists(logDirectory))
+ {
+ var latestLogFile = Directory.GetFiles(logDirectory, "Cleanup_*.log")
+ .OrderByDescending(f => f)
+ .FirstOrDefault();
+
+ if (latestLogFile != null && File.Exists(latestLogFile))
+ {
+ return File.GetLastWriteTime(latestLogFile);
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine($"鑾峰彇涓婃娓呯悊鏃堕棿澶辫触: {ex.Message}");
+ }
+ return null;
+ }
+
+ public Task StopAsync(CancellationToken cancellationToken)
+ {
+ _cleanupTimer?.Dispose();
+ WriteLog("鏃ュ織娓呯悊鏈嶅姟宸插仠姝�");
+ return Task.CompletedTask;
+ }
+
+ public void Dispose()
+ {
+ if (!_isDisposed)
+ {
+ _cleanupTimer?.Dispose();
+ _isDisposed = true;
+ }
+ }
+ }
+
+ /// <summary>
+ /// 娓呯悊缁熻淇℃伅
+ /// </summary>
+ public class CleanupStatistics
+ {
+ public int TotalCount { get; set; }
+ public DateTime? OldestLogTime { get; set; }
+ public DateTime? NewestLogTime { get; set; }
+ public int RetentionDays { get; set; }
+ public DateTime? LastCleanupTime { get; set; }
+ public string LogFilePath { get; set; }
+ }
+}
\ No newline at end of file
diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/Filter/Log/LoggerNew.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/Filter/Log/LoggerNew.cs"
new file mode 100644
index 0000000..bd6abe2
--- /dev/null
+++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/Filter/Log/LoggerNew.cs"
@@ -0,0 +1,431 @@
+锘縰sing SqlSugar;
+using System.Collections.Concurrent;
+using System.Text;
+using WIDESEAWCS_Core.HttpContextUser;
+using WIDESEAWCS_Core.Seed;
+using WIDESEAWCS_Model.Models;
+using System.Security.Cryptography;
+using WIDESEAWCS_Core.Helper;
+using Newtonsoft.Json.Linq;
+using WIDESEAWCS_DTO.RGV.FOURBOT;
+using WIDESEAWCS_DTO.WMS;
+using WIDESEAWCS_DTO;
+
+namespace WIDESEAWCS_Core.LogHelper
+{
+ public static class LoggerNew
+ {
+ // 鐢ㄤ簬缂撳瓨褰撳ぉ宸插瓨鍦ㄧ殑鏃ュ織锛坘ey: 鏃ユ湡+ApiCode+璇锋眰鍝堝笇+鍝嶅簲鍝堝笇锛�
+ private static ConcurrentDictionary<string, Dt_InterfaceLog> _cacheLogs = new ConcurrentDictionary<string, Dt_InterfaceLog>();
+ // 闃熷垪鐢ㄤ簬瀛樺偍闇�瑕佹柊澧炴垨鏇存柊鐨勬棩蹇�
+ public static ConcurrentQueue<Dt_InterfaceLog> loggerQueueData = new ConcurrentQueue<Dt_InterfaceLog>();
+
+ // 姣忓ぉ鍑屾櫒娓呯┖缂撳瓨
+ private static DateTime _lastClearDate = DateTime.Now.Date;
+
+ static LoggerNew()
+ {
+ Task.Run(() =>
+ {
+ StartWriteLog();
+ });
+
+ // 鍚姩涓�涓悗鍙颁换鍔★紝姣忓ぉ鍑屾櫒娓呯┖缂撳瓨
+ Task.Run(() =>
+ {
+ while (true)
+ {
+ Thread.Sleep(60000); // 姣忓垎閽熸鏌ヤ竴娆�
+ DateTime today = DateTime.Now.Date;
+ if (_lastClearDate < today)
+ {
+ _cacheLogs.Clear();
+ _lastClearDate = today;
+ Console.WriteLine($"Logger缂撳瓨宸叉竻绌猴紝鏃ユ湡锛歿today:yyyy-MM-dd}");
+ }
+ }
+ });
+ }
+
+ static void StartWriteLog()
+ {
+ List<Dt_InterfaceLog> batchList = new List<Dt_InterfaceLog>();
+
+ while (true)
+ {
+ try
+ {
+ if (loggerQueueData.Count() > 0 && batchList.Count < 500)
+ {
+ DequeueToBatchList(batchList);
+ continue;
+ }
+
+ Thread.Sleep(5000);
+
+ if (batchList.Count == 0) { continue; }
+
+ SqlSugarClient sugarClient = new SqlSugarClient(new ConnectionConfig()
+ {
+ ConnectionString = DBContext.GetMainConnectionDb().Connection,
+ IsAutoCloseConnection = true,
+ DbType = DBContext.DbType,
+ });
+
+ try
+ {
+ sugarClient.BeginTran(); // 寮�鍚簨鍔�
+
+ var toInsert = new List<Dt_InterfaceLog>();
+ var toUpdate = new List<Dt_InterfaceLog>();
+
+ foreach (var log in batchList)
+ {
+ // 濡傛灉宸茬粡鏈� Id 鎴栬�� IsExisting 鏍囧織锛岀洿鎺ュ鐞�
+ if (log.Id > 0)
+ {
+ toUpdate.Add(log);
+ continue;
+ }
+
+ // 鏍规嵁鍝堝笇鍊兼煡璇㈡槸鍚﹀凡瀛樺湪
+ var existing = sugarClient.Queryable<Dt_InterfaceLog>()
+ .First(x => x.RequestParametersHash == log.RequestParametersHash
+ && x.ResponseParametersHash == log.ResponseParametersHash
+ && x.ApiCode == log.ApiCode
+ && SqlFunc.DateIsSame(x.CreateDate, DateTime.Now)); // 鍚屼竴澶�
+
+ if (existing != null)
+ {
+ // 宸插瓨鍦紝鏇存柊
+ log.Id = existing.Id;
+ log.PushFrequency = existing.PushFrequency + 1; // 鍙犲姞娆℃暟
+ log.ModifyDate = DateTime.Now;
+ toUpdate.Add(log);
+
+ // 鏇存柊缂撳瓨涓殑 Id
+ string cacheKey = GenerateCacheKey(log.ApiCode, log.RequestParametersHash, log.ResponseParametersHash);
+ if (_cacheLogs.TryGetValue(cacheKey, out var cachedLog))
+ {
+ cachedLog.Id = existing.Id;
+ }
+ }
+ else
+ {
+ // 涓嶅瓨鍦紝鏂板
+ toInsert.Add(log);
+ }
+ }
+
+ // 鎵归噺鏂板
+ if (toInsert.Any())
+ {
+ int rows = sugarClient.Fastest<Dt_InterfaceLog>().BulkCopy(toInsert);
+
+ // 鑾峰彇鏂板鏃ュ織鐨勮嚜澧濱D骞舵洿鏂扮紦瀛�
+ foreach (var insertedLog in toInsert)
+ {
+ var savedLog = sugarClient.Queryable<Dt_InterfaceLog>()
+ .First(x => x.RequestParametersHash == insertedLog.RequestParametersHash
+ && x.ResponseParametersHash == insertedLog.ResponseParametersHash);
+ if (savedLog != null)
+ {
+ string cacheKey = GenerateCacheKey(insertedLog.ApiCode,
+ insertedLog.RequestParametersHash, insertedLog.ResponseParametersHash);
+ if (_cacheLogs.TryGetValue(cacheKey, out var cachedLog))
+ {
+ cachedLog.Id = savedLog.Id;
+ }
+ }
+ }
+ }
+
+ // 鎵归噺鏇存柊鎺ㄩ�佹鏁�
+ if (toUpdate.Any())
+ {
+ foreach (var log in toUpdate)
+ {
+ sugarClient.Updateable<Dt_InterfaceLog>()
+ .SetColumns(it => new Dt_InterfaceLog
+ {
+ PushFrequency = log.PushFrequency,
+ PushState = log.PushState,
+ Remark = log.Remark,
+ //CreateDate = log.CreateDate
+ ModifyDate = log.ModifyDate
+ })
+ .Where(it => it.Id == log.Id)
+ .ExecuteCommand();
+ }
+ }
+
+ sugarClient.CommitTran(); // 鎻愪氦浜嬪姟
+ }
+ catch (Exception ex)
+ {
+ sugarClient.RollbackTran(); // 鍥炴粴浜嬪姟
+ Console.WriteLine($"澶勭悊鏃ュ織鎵规澶辫触: {ex.Message}");
+ }
+ finally
+ {
+ batchList.Clear();
+ }
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine(ex.ToString());
+ }
+ }
+ }
+
+ private static void DequeueToBatchList(List<Dt_InterfaceLog> batchList)
+ {
+ if (loggerQueueData.TryDequeue(out Dt_InterfaceLog log) && log != null)
+ {
+ batchList.Add(log);
+ }
+ }
+
+ /// <summary>
+ /// 璁$畻瀛楃涓茬殑SHA256鍝堝笇鍊�
+ /// </summary>
+ private static string ComputeHash(string input)
+ {
+ if (string.IsNullOrEmpty(input))
+ return string.Empty;
+
+ using (SHA256 sha256 = SHA256.Create())
+ {
+ byte[] bytes = Encoding.UTF8.GetBytes(input);
+ byte[] hashBytes = sha256.ComputeHash(bytes);
+ return BitConverter.ToString(hashBytes).Replace("-", "").ToLower();
+ }
+ }
+
+ /// <summary>
+ /// 鐢熸垚缂撳瓨Key
+ /// </summary>
+ private static string GenerateCacheKey(string apiCode, string requestHash, string responseHash)
+ {
+ string today = DateTime.Now.ToString("yyyy-MM-dd");
+ return $"{today}_{apiCode}_{requestHash}_{responseHash}";
+ }
+
+ /// <summary>
+ /// 鑾峰彇鎴栧垱寤烘棩蹇楋紙鐢ㄤ簬鍙犲姞鎺ㄩ�佹鏁帮級
+ /// </summary>
+ /// <param name="apiCode">缂栧彿</param>
+ /// <param name="apiName">鍚嶇О</param>
+ /// <param name="apiAddress">鍦板潃</param>
+ /// <param name="requestParameters">璇锋眰鍐呭</param>
+ /// <param name="responseParameters">鍝嶅簲鍐呭</param>
+ /// <param name="pushState">鐘舵��</param>
+ /// <param name="requestorUserIP">璇锋眰鐢ㄦ埛IP</param>
+ /// <param name="requestor">璇锋眰鏂�</param>
+ /// <param name="recipient">鎺ユ敹鏂�</param>
+ /// <param name="remark">澶囨敞</param>
+ /// <returns></returns>
+ private static Dt_InterfaceLog GetOrCreateLog(string apiCode, string apiName, string apiAddress,
+ string requestParameters, string responseParameters, int pushState,
+ string requestorUserIP, string requestor, string recipient, string remark)
+ {
+ string requestHash = ComputeHash(requestParameters);
+ string responseHash = ComputeHash(responseParameters);
+ string cacheKey = GenerateCacheKey(apiCode, requestHash, responseHash);
+
+ // 灏濊瘯浠庣紦瀛樹腑鑾峰彇
+ if (_cacheLogs.TryGetValue(cacheKey, out Dt_InterfaceLog existingLog))
+ {
+ // 瀛樺湪鐩稿悓鍙傛暟鐨勬棩蹇楋紝澧炲姞鎺ㄩ�佹鏁�
+ existingLog.PushFrequency++;
+ existingLog.PushState = pushState; // 鏇存柊鎺ㄩ�佺姸鎬�
+ existingLog.Remark = remark; // 鏇存柊澶囨敞
+ //existingLog.CreateDate = DateTime.Now; // 鏇存柊鏃堕棿
+ existingLog.ModifyDate = DateTime.Now; // 鏇存柊鏃堕棿
+
+ // 杩斿洖鐜版湁鏃ュ織锛堥渶瑕佹洿鏂版暟鎹簱锛�
+ return existingLog;
+ }
+ else
+ {
+ // 涓嶅瓨鍦紝鍒涘缓鏂版棩蹇�
+ var newLog = new Dt_InterfaceLog
+ {
+ ApiCode = apiCode,
+ ApiName = apiName,
+ ApiAddress = apiAddress,
+ PushFrequency = 1,
+ PushState = pushState,
+ RequestorUserIP = requestorUserIP,
+ Requestor = requestor,
+ RequestParameters = requestParameters,
+ RequestParametersHash = requestHash,
+ Recipient = recipient,
+ ResponseParameters = responseParameters,
+ ResponseParametersHash = responseHash,
+ Remark = remark,
+ Creater = "System",
+ CreateDate = DateTime.Now
+ };
+
+ // 鍔犲叆缂撳瓨
+ _cacheLogs.TryAdd(cacheKey, newLog);
+
+ return newLog;
+ }
+ }
+
+ /// <summary>
+ /// 娣诲姞鎺ュ彛鏃ュ織锛堝甫URL銆佽姹傚弬鏁般�佸搷搴斿弬鏁般�佸紑濮嬫椂闂达級
+ /// </summary>
+ public static void Add(string apiCode, string apiName, string apiAddress,
+ string requestParameters, string responseParameters,
+ int pushState = 0, string recipient = "", string remark = "")
+ {
+ Dt_InterfaceLog log = null;
+ try
+ {
+ // 鑾峰彇褰撳墠鐢ㄦ埛
+ IUser? user = App.User;
+
+ // 鑾峰彇鎴栧垱寤烘棩蹇楋紙鑷姩澶勭悊鍙犲姞锛�
+ log = GetOrCreateLog(apiCode, apiName, apiAddress,
+ requestParameters, responseParameters, pushState,
+ "", user?.UserName ?? "", recipient, remark);
+ }
+ catch (Exception exception)
+ {
+ // 濡傛灉鍙戠敓寮傚父锛屽垱寤哄熀纭�鏃ュ織瀵硅薄
+ log = log ?? new Dt_InterfaceLog
+ {
+ ApiCode = apiCode,
+ ApiName = apiName,
+ ApiAddress = apiAddress,
+ PushFrequency = 1,
+ PushState = pushState,
+ RequestParameters = requestParameters,
+ ResponseParameters = responseParameters,
+ Creater = "System",
+ Remark = $"璁板綍鏃ュ織鏃跺彂鐢熷紓甯革細{exception.Message}"
+ };
+ }
+
+ // 娣诲姞绯荤粺鏃ュ織
+ loggerQueueData.Enqueue(log);
+ }
+
+ /// <summary>
+ /// 娣诲姞鎺ュ彛鏃ュ織锛堜粠HttpContext鑷姩鑾峰彇淇℃伅锛�
+ /// </summary>
+ /// <param name="requestParameters">璇锋眰鍐呭</param>
+ /// <param name="responseParameters">鍝嶅簲鍐呭</param>
+ /// <param name="apiCode">鎺ュ彛缂栧彿</param>
+ /// <param name="apiName">鎺ュ彛鍚嶇О</param>
+ /// <param name="pushState">鎺ㄩ�佺姸鎬�</param>
+ /// <param name="recipient">鎺ユ敹鏂�</param>
+ /// <param name="remark">澶囨敞</param>
+ public static void Add(string requestParameters, string responseParameters, HttpContext context, string apiCode = "", string apiName = "", int pushState = 0, string recipient = "WCS", string remark = "")
+ {
+ Dt_InterfaceLog log = null;
+ try
+ {
+ // 濡傛灉璇锋眰鏂规硶涓篛PTIONS锛屽垯杩斿洖
+ if (context.Request.Method == "OPTIONS") return;
+
+ #region 鏁版嵁杞崲
+
+ // 瑙f瀽澶栧眰 JSON
+ JObject outerObj = JObject.Parse(requestParameters);
+
+ // 鑾峰彇 BodyData 鐨勫�硷紙瀹冩槸涓�涓瓧绗︿覆锛�
+ requestParameters = outerObj["BodyData"]?.ToString() ?? requestParameters;
+
+ // 鏋勫缓瀹屾暣鐨勬帴鍙e湴鍧�
+ string apiAddress = context.Request.Scheme + "://" + context.Request.Host + context.Request.PathBase + context.Request.Path;
+ // 鑾峰彇瀹㈡埛绔疘P
+ string clientIP = GetClientIP(context)?.Replace("::ffff:", "") ?? "";
+ string requestor = "";//璇锋眰鏂�
+ if (apiAddress.Contains("/api/WMS"))
+ {
+ requestor = "WMS";//绉掍紭
+ var wMSReturn = responseParameters.DeserializeObject<WMSReturn>();
+ pushState = wMSReturn.code == 0 ? 1 : 2;
+ }
+ else if (apiAddress.Contains("/api/KHAGV"))
+ {
+ requestor = "娴峰悍AGV";
+ var hIKROBOTReturn = responseParameters.DeserializeObject<HIKROBOTReturn>();
+ pushState = hIKROBOTReturn.code == "SUCCESS" ? 1 : 2;
+ }
+ else if (apiAddress.Contains("/api/KLS"))
+ {
+ requestor = "鍑箰澹獳GV";
+ ReturnGALAXIS returnGALAXIS = responseParameters.DeserializeObject<ReturnGALAXIS>();
+ pushState = returnGALAXIS.returnStatus == 0 ? 1 : 2;
+ }
+ else if (apiAddress.Contains("/api/RGV"))
+ {
+ requestor = "鍥涘悜绌挎杞�";//鏃疯娌冲浘
+ FOURBOTReturn fOURBOTReturn = responseParameters.DeserializeObject<FOURBOTReturn>();
+ pushState = fOURBOTReturn.returnCode == 0 ? 1 : 2;
+ }
+ apiCode = apiAddress.Split("/").Last();
+ apiName = AppSettings.Configuration.GetValue($"{requestor}:{apiCode}", apiCode);
+ #endregion
+
+ // 鑾峰彇鎴栧垱寤烘棩蹇楋紙鑷姩澶勭悊鍙犲姞锛�
+ log = GetOrCreateLog(apiCode, apiName, apiAddress,
+ requestParameters, responseParameters, pushState,
+ clientIP, requestor, recipient, remark);
+ }
+ catch (Exception exception)
+ {
+ // 濡傛灉鍙戠敓寮傚父锛屽垱寤哄熀纭�鏃ュ織瀵硅薄
+ log = log ?? new Dt_InterfaceLog
+ {
+ ApiCode = apiCode,
+ ApiName = apiName,
+ PushFrequency = 1,
+ PushState = pushState,
+ RequestParameters = requestParameters,
+ ResponseParameters = responseParameters,
+ Creater = "System",
+ Remark = $"璁板綍鏃ュ織鏃跺彂鐢熷紓甯革細{exception.Message}"
+ };
+ }
+
+ // 娣诲姞绯荤粺鏃ュ織
+ loggerQueueData.Enqueue(log);
+ }
+
+ /// <summary>
+ /// 鎵嬪姩澧炲姞鎺ㄩ�佹鏁帮紙鐢ㄤ簬閲嶈瘯鍦烘櫙锛�
+ /// </summary>
+ public static void IncrementPushCount(string apiCode, string requestParameters, string responseParameters)
+ {
+ string requestHash = ComputeHash(requestParameters);
+ string responseHash = ComputeHash(responseParameters);
+ string cacheKey = GenerateCacheKey(apiCode, requestHash, responseHash);
+
+ if (_cacheLogs.TryGetValue(cacheKey, out Dt_InterfaceLog existingLog))
+ {
+ existingLog.PushFrequency++;
+ loggerQueueData.Enqueue(existingLog);
+ }
+ }
+
+ public static string GetClientIP(HttpContext context)
+ {
+ // 鑾峰彇璇锋眰澶翠腑鐨刋-Forwarded-For瀛楁锛屽苟灏嗗叾杞崲涓哄瓧绗︿覆
+ var ip = context.Request.Headers["X-Forwarded-For"].ObjToString();
+ // 濡傛灉X-Forwarded-For瀛楁涓虹┖锛屽垯鑾峰彇杩滅▼IP鍦板潃
+ if (string.IsNullOrEmpty(ip))
+ {
+ ip = context.Connection.RemoteIpAddress.ObjToString();
+ }
+
+ // 杩斿洖IP鍦板潃
+ return ip;
+ }
+ }
+}
\ No newline at end of file
diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/Filter/Log/MiddlewareHelpersNew.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/Filter/Log/MiddlewareHelpersNew.cs"
new file mode 100644
index 0000000..c81600b
--- /dev/null
+++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/Filter/Log/MiddlewareHelpersNew.cs"
@@ -0,0 +1,22 @@
+锘縰sing Microsoft.AspNetCore.Builder;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace WIDESEAWCS_Core.Middlewares
+{
+ public static class MiddlewareHelpersNew
+ {
+ /// <summary>
+ /// 璇锋眰鍝嶅簲涓棿浠�
+ /// </summary>
+ /// <param name="app"></param>
+ /// <returns></returns>
+ public static IApplicationBuilder UseApiLogMiddlewareNew(this IApplicationBuilder app)
+ {
+ return app.UseMiddleware<ApiLogMiddlewareNew>();
+ }
+ }
+}
diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/Program.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/Program.cs"
index 75d3af8..8dfbad9 100644
--- "a/\344\273\243\347\240\201\347\256\241\347\220\206/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/Program.cs"
+++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/Program.cs"
@@ -18,6 +18,7 @@
using WIDESEAWCS_Core.Extensions;
using WIDESEAWCS_Core.Filter;
using WIDESEAWCS_Core.Helper;
+using WIDESEAWCS_Core.LogHelper;
using WIDESEAWCS_Core.Middlewares;
using WIDESEAWCS_QuartzJob;
using WIDESEAWCS_QuartzJob.QuartzExtensions;
@@ -50,6 +51,25 @@
builder.Services.AddHostedService<SeedDataHostedService>();//初始化数据库
builder.Services.AddDbSetup();//Db 启动服务
+
+#region 添加日志清理服务
+var cleanupRetentionDays = builder.Configuration.GetValue<int>("LogCleanup:RetentionDays", 90);
+var cleanupHour = builder.Configuration.GetValue<int>("LogCleanup:CleanupHour", 2);
+var enableAutoCleanup = builder.Configuration.GetValue<bool>("LogCleanup:EnableAutoCleanup", true);
+var enableArchive = builder.Configuration.GetValue<bool>("LogCleanup:EnableArchive", false);
+var logRetentionDays = builder.Configuration.GetValue<int>("LogCleanup:LogRetentionDays", 30);
+
+builder.Services.AddSingleton(sp => new LogCleanupService
+{
+ RetentionDays = cleanupRetentionDays,
+ CleanupHour = cleanupHour,
+ EnableAutoCleanup = enableAutoCleanup,
+ EnableArchive = enableArchive,
+ LogRetentionDays= logRetentionDays,
+ CleanupIntervalHours = 24
+});
+builder.Services.AddHostedService(sp => sp.GetRequiredService<LogCleanupService>());
+#endregion
//builder.Services.AddScoped<QuartzJobCreateDataTabel>();//任务调度 注入创建QuartzJob数据库表类
//builder.Services.AddHostedService<QuartzJobDataTableHostedService>();//任务调度 映射QuartzJob数据库表
@@ -123,7 +143,8 @@
app.UseSwaggerMiddle(() => Assembly.GetExecutingAssembly().GetManifestResourceStream("WIDESEAWCS_Server.index.html") ?? throw new Exception("未找到WIDESEAWCS_Server.index.html文件"));
app.UseIpLimitMiddle();
-app.UseApiLogMiddleware();
+//app.UseApiLogMiddleware();
+app.UseApiLogMiddlewareNew();
app.UseCors(AppSettings.Get(new string[] { "Cors", "PolicyName" }));
@@ -148,4 +169,14 @@
app.MapControllers();
+#region 应用启动时立即清理一次
+//Task.Run(async () =>
+//{
+// // 等待应用完全启动
+// await Task.Delay(30000);
+// var cleanupService = app.Services.GetRequiredService<LogCleanupService>();
+// await cleanupService.ManualCleanup(90);
+//});
+#endregion
+
app.Run();
diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/WIDESEAWCS_Server.csproj" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/WIDESEAWCS_Server.csproj"
index 87ccba2..c164b98 100644
--- "a/\344\273\243\347\240\201\347\256\241\347\220\206/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/WIDESEAWCS_Server.csproj"
+++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/WIDESEAWCS_Server.csproj"
@@ -76,8 +76,4 @@
</Content>
</ItemGroup>
- <ItemGroup>
- <Folder Include="Log\" />
- </ItemGroup>
-
</Project>
diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/appsettings.json" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/appsettings.json"
index 0541498..13f9b2e 100644
--- "a/\344\273\243\347\240\201\347\256\241\347\220\206/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/appsettings.json"
+++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/appsettings.json"
@@ -17,6 +17,7 @@
//5.PostgreSQL
"DBType": "SqlServer",
//杩炴帴瀛楃涓�
+ //"ConnectionString": "Data Source=172.16.161.20;Initial Catalog=WIDESEAWCS_GP;User ID=sa;Password=P@ssw0rd;Integrated Security=False;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False",
"ConnectionString": "Data Source=.;Initial Catalog=WIDESEAWCS_GP;User ID=sa;Password=P@ssw0rd;Integrated Security=False;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False",
//璺ㄥ煙
"Cors": {
@@ -26,15 +27,39 @@
// 娉ㄦ剰锛宧ttp://127.0.0.1:1818 鍜� http://localhost:1818 鏄笉涓�鏍风殑
"IPs": "http://127.0.0.1:8080,http://localhost:8080"
},
+ "LogCleanup": { //鎺ュ彛鏃ュ織娓呯悊閰嶇疆
+ "RetentionDays": 90, // 鏁版嵁淇濈暀澶╂暟
+ "CleanupHour": 2, // 娓呯悊鎵ц鏃堕棿锛堝皬鏃讹紝0-23锛�
+ "EnableAutoCleanup": true, // 鏄惁鍚敤鑷姩娓呯悊
+ "EnableArchive": true, // 鏄惁鍚敤褰掓。锛堝綊妗e埌鍘嗗彶琛級
+ "LogRetentionDays": 30 // 鏃ュ織鏂囦欢淇濈暀澶╂暟
+ },
"ApiLogIgnore": "", //璁板綍鏃ュ織鏃讹紝蹇界暐鐨凙PI鍚嶇О锛屽涓敤閫楀彿鍒嗛殧锛岄厤缃殑涓嶈褰曞埌鏁版嵁搴撲腑
"ApiName": "WIDESEAWCS",
"ExpMinutes": 120,
+ "RequestPath": "GET,WMS,RGV,KHAGV,KLSAGV", //,
+ ///鎺ュ彛璇存槑锛氭帴鍙f棩蹇楄褰曚娇鐢�
+ "WMS": {
+ "ReceiveTask": "WMS涓嬪彂浠诲姟",
+ "ContainerRequest": "瀹瑰櫒娴佸姩璇锋眰",
+ "UpOrDownContainer": "骞冲簱璐т綅涓婁笅鏋跺鍣�",
+ "CancelWMSTask": "WMS鍙栨秷浠诲姟",
+ "IQCResult": "澶栨缁撴灉鍙嶉",
+ "UpdateArea": "淇敼搴撲綅鍒嗗尯",
+ "UpdateTaskGrade": "WMS淇敼浠诲姟浼樺厛绾�",
+ "QueryStation": "鍖哄煙搴撲綅淇℃伅鏌ヨ",
+ "UpLocationStatus": "鏇存柊浠撳簱搴撲綅鐘舵��"
+ },
+ "娴峰悍AGV": { "UpdateTaskStatus": "娴峰悍AGV浠诲姟鐘舵�佹洿鏂�" },
+ "鍑箰澹獳GV": { "UpdateTaskStatus": "鍑箰澹獳GV浠诲姟鐘舵�佹洿鏂�" },
+ "鍥涘悜绌挎杞�": { "UpdateTaskStatus": "鍥涘悜绌挎杞︿换鍔$姸鎬佹洿鏂�" },
+ ///鎺ュ彛璇存槑
"QuartzJobAutoStart": true,
"DBSeedEnable": false,
"QuartzDBSeedEnable": false,
- "LogDeubgEnable": true, //鏄惁璁板綍璋冭瘯鏃ュ織
- "PrintSql": true, //鎵撳嵃SQL璇彞
- "LogAOPEnable": true, //鏄惁璁板綍AOP鏃ュ織
+ "LogDeubgEnable": false, //鏄惁璁板綍璋冭瘯鏃ュ織
+ "PrintSql": false, //鎵撳嵃SQL璇彞
+ "LogAOPEnable": false, //鏄惁璁板綍AOP鏃ュ織
"WebSocketEnable": true, //鏄惁寮�鍚疻ebSocket鏈嶅姟
"WebSocketPort": 9296 //WebSocket鏈嶅姟绔彛
}
diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/Task/RGVTaskExtend.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/Task/RGVTaskExtend.cs"
index a695aa8..aff1ab6 100644
--- "a/\344\273\243\347\240\201\347\256\241\347\220\206/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/Task/RGVTaskExtend.cs"
+++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/Task/RGVTaskExtend.cs"
@@ -528,6 +528,13 @@
try
{
List<Dt_RGVLocationInfo> rGVLocationInfos = _rGVLocationInfoService.Repository.QueryData(x => blockPods.Contains(x.PalletCode));
+ var palletCodes = rGVLocationInfos.Select(x => x.PalletCode).ToList();
+ // 鑾峰彇 blockPods 涓瓨鍦ㄤ絾 palletCodes 涓笉瀛樺湪鐨勬墭鐩樼爜
+ var missingPalletCodes = blockPods.Except(palletCodes).ToList();
+ if (missingPalletCodes.Any())
+ {
+ throw new Exception($"鏈壘鍒颁互涓嬮樆纰嶆墭璐т綅淇℃伅锛歿string.Join(",", missingPalletCodes)}");
+ }
var Items = _rGVLocationInfoService.GetMoveFreeLocationInfo(rGVLocationInfos);
List<Dt_Task> tasks = Items.Item1;
--
Gitblit v1.9.3