Merge branch 'master' of http://115.159.85.185:8098/r/RuiShengZhiNeng/GaoPuLiTiKu
| | |
| | | using System; |
| | | using System.Collections.Generic; |
| | | using System.Linq; |
| | | using System.Security.Cryptography; |
| | | using System.Text; |
| | | using System.Threading.Tasks; |
| | | using WIDESEAWCS_Core; |
| | |
| | | { |
| | | 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}æ¥å£é
置信æ¯ï¼è¯·æ£æ¥æ¥å£é
ç½®"); |
| | | response = HttpHelper.Post(apiInfo.ApiAddress, requestParameters); |
| | | requestHash = ComputeHash(requestParameters); |
| | | responseHash = ComputeHash(response); |
| | | if (apiInfo.Remark.Contains("åå车")) |
| | | { |
| | | FOURBOTReturn fOURBOTReturn = response.DeserializeObject<FOURBOTReturn>(); |
| | |
| | | { |
| | | 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(); |
| | | } |
| | | } |
| | | } |
| | | } |
| | |
| | | public int PushState { get; set; } = 0; |
| | | |
| | | /// <summary> |
| | | /// è¯·æ±æ¹ç¨æ·IP |
| | | /// </summary> |
| | | [SugarColumn(IsNullable = true, Length = 20, ColumnDescription = "è¯·æ±æ¹ç¨æ·IP")] |
| | | public string RequestorUserIP { get; set; } |
| | | |
| | | /// <summary> |
| | | /// è¯·æ±æ¹ |
| | | /// </summary> |
| | | [SugarColumn(IsNullable = true, Length = 50, ColumnDescription = "è¯·æ±æ¹")] |
| | |
| | | public string ResponseParameters { get; set; } |
| | | |
| | | /// <summary> |
| | | /// 请æ±åæ°åå¸å¼ï¼ç¨äºç´¢å¼åå»éï¼ |
| | | /// </summary> |
| | | [SugarColumn(IsNullable = true, Length = 64, ColumnDescription = "请æ±åæ°åå¸å¼")] |
| | | public string RequestParametersHash { get; set; } |
| | | |
| | | /// <summary> |
| | | /// ååºåæ°åå¸å¼ï¼ç¨äºç´¢å¼åå»éï¼ |
| | | /// </summary> |
| | | [SugarColumn(IsNullable = true, Length = 64, ColumnDescription = "ååºåæ°åå¸å¼")] |
| | | public string ResponseParametersHash { get; set; } |
| | | |
| | | /// <summary> |
| | | /// 夿³¨ |
| | | /// </summary> |
| | | [SugarColumn(IsNullable = true, Length = 100, ColumnDescription = "夿³¨")] |
| | |
| | | } |
| | | |
| | | /// <summary> |
| | | /// è´¨æ£ç»æåé¦ |
| | | /// 夿£ç»æåé¦ |
| | | /// </summary> |
| | | /// <param name="iQC"></param> |
| | | /// <returns></returns> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | using 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; |
| | | } |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | using 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) |
| | | { |
| | | // å
彿¡£åå é¤ |
| | | 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($"å¼å§å½æ¡£æ°æ®å°è¡¨: {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; } |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | using 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 |
| | | { |
| | | // ç¨äºç¼åå½å¤©å·²åå¨çæ¥å¿ï¼key: æ¥æ+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); |
| | | |
| | | // è·åæ°å¢æ¥å¿çèªå¢IDå¹¶æ´æ°ç¼å |
| | | 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 |
| | | { |
| | | // å¦æè¯·æ±æ¹æ³ä¸ºOPTIONSï¼åè¿å |
| | | if (context.Request.Method == "OPTIONS") return; |
| | | |
| | | #region æ°æ®è½¬æ¢ |
| | | |
| | | // è§£æå¤å± JSON |
| | | JObject outerObj = JObject.Parse(requestParameters); |
| | | |
| | | // è·å BodyData çå¼ï¼å®æ¯ä¸ä¸ªåç¬¦ä¸²ï¼ |
| | | requestParameters = outerObj["BodyData"]?.ToString() ?? requestParameters; |
| | | |
| | | // æå»ºå®æ´çæ¥å£å°å |
| | | string apiAddress = context.Request.Scheme + "://" + context.Request.Host + context.Request.PathBase + context.Request.Path; |
| | | // è·å客æ·ç«¯IP |
| | | 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 = "å¯ä¹å£«AGV"; |
| | | 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) |
| | | { |
| | | // è·å请æ±å¤´ä¸çX-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; |
| | | } |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | using 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>(); |
| | | } |
| | | } |
| | | } |
| | |
| | | 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; |
| | |
| | | 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æ°æ®åºè¡¨ |
| | |
| | | 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" })); |
| | | |
| | |
| | | |
| | | app.MapControllers(); |
| | | |
| | | #region åºç¨å¯å¨æ¶ç«å³æ¸
ç䏿¬¡ |
| | | //Task.Run(async () => |
| | | //{ |
| | | // // çå¾
åºç¨å®å
¨å¯å¨ |
| | | // await Task.Delay(30000); |
| | | // var cleanupService = app.Services.GetRequiredService<LogCleanupService>(); |
| | | // await cleanupService.ManualCleanup(90); |
| | | //}); |
| | | #endregion |
| | | |
| | | app.Run(); |
| | |
| | | </Content> |
| | | </ItemGroup> |
| | | |
| | | <ItemGroup> |
| | | <Folder Include="Log\" /> |
| | | </ItemGroup> |
| | | |
| | | </Project> |
| | |
| | | //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": { |
| | |
| | | // 注æï¼http://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, // æ¯å¦å¯ç¨å½æ¡£ï¼å½æ¡£å°åå²è¡¨ï¼ |
| | | "LogRetentionDays": 30 // æ¥å¿æä»¶ä¿çå¤©æ° |
| | | }, |
| | | "ApiLogIgnore": "", //è®°å½æ¥å¿æ¶ï¼å¿½ç¥çAPIåç§°ï¼å¤ä¸ªç¨éå·åéï¼é
ç½®çä¸è®°å½å°æ°æ®åºä¸ |
| | | "ApiName": "WIDESEAWCS", |
| | | "ExpMinutes": 120, |
| | | "RequestPath": "GET,WMS,RGV,KHAGV,KLSAGV", //, |
| | | ///æ¥å£è¯´æï¼æ¥å£æ¥å¿è®°å½ä½¿ç¨ |
| | | "WMS": { |
| | | "ReceiveTask": "WMSä¸åä»»å¡", |
| | | "ContainerRequest": "容卿µå¨è¯·æ±", |
| | | "UpOrDownContainer": "å¹³åºè´§ä½ä¸ä¸æ¶å®¹å¨", |
| | | "CancelWMSTask": "WMSåæ¶ä»»å¡", |
| | | "IQCResult": "夿£ç»æåé¦", |
| | | "UpdateArea": "ä¿®æ¹åºä½ååº", |
| | | "UpdateTaskGrade": "WMSä¿®æ¹ä»»å¡ä¼å
级", |
| | | "QueryStation": "åºååºä½ä¿¡æ¯æ¥è¯¢", |
| | | "UpLocationStatus": "æ´æ°ä»åºåºä½ç¶æ" |
| | | }, |
| | | "海康AGV": { "UpdateTaskStatus": "海康AGVä»»å¡ç¶ææ´æ°" }, |
| | | "å¯ä¹å£«AGV": { "UpdateTaskStatus": "å¯ä¹å£«AGVä»»å¡ç¶ææ´æ°" }, |
| | | "ååç©¿æ¢è½¦": { "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, //æ¯å¦å¼å¯WebSocketæå¡ |
| | | "WebSocketPort": 9296 //WebSocketæå¡ç«¯å£ |
| | | } |
| | |
| | | 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; |