You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

524 lines
26 KiB

using Hangfire;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
2 weeks ago
using Microsoft.AspNetCore.Identity.Data;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
3 weeks ago
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
2 weeks ago
using Microsoft.Extensions.Logging;
using OfficeOpenXml.FormulaParsing.Excel.Functions.DateTime;
using OfficeOpenXml.FormulaParsing.Excel.Functions.Text;
using Omu.ValueInjecter;
3 weeks ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
3 weeks ago
using System.Linq;
2 weeks ago
using System.Net.Http.Json;
using System.Security.Policy;
3 weeks ago
using System.Text;
2 weeks ago
using System.Text.Encodings.Web;
using System.Text.Json;
using System.Text.Json.Serialization;
3 weeks ago
using System.Threading.Channels;
using System.Threading.Tasks;
using TaskManager.Contracts.Dtos;
3 weeks ago
using TaskManager.Entity;
using TaskManager.EntityFramework;
2 weeks ago
using Wood.Entity;
using Wood.Service.Controllers;
2 weeks ago
using Wood.Service.SystemManage;
3 weeks ago
2 weeks ago
namespace TaskManager.Controllers
3 weeks ago
{
2 weeks ago
public class LogConsumerService : BackgroundService
3 weeks ago
{
2 weeks ago
private readonly ChannelReader<TaskLog> _logReader;
private readonly ILogger<LogConsumerService> _logger;
private const int BatchSize = 100; // 批量写入大小
3 weeks ago
private readonly string _logDirectory;
2 weeks ago
private readonly IServiceProvider _serviceProvider;
3 weeks ago
2 weeks ago
public LogConsumerService(
LogController logService,
ILogger<LogConsumerService> logger, IServiceProvider serviceProvider)
3 weeks ago
{
2 weeks ago
_logReader = logService.GetLogReader();
_logger = logger;
_serviceProvider = serviceProvider; ;
_logDirectory = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "CustomLogs"); // 使用更安全的路径获取方式
3 weeks ago
EnsureDirectoryExists(_logDirectory);
2 weeks ago
}
3 weeks ago
2 weeks ago
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
3 weeks ago
{
2 weeks ago
_logger.LogInformation("日志消费服务已启动");
3 weeks ago
2 weeks ago
// 批量处理日志,减少数据库写入次数
while (!stoppingToken.IsCancellationRequested &&
await _logReader.WaitToReadAsync(stoppingToken))
{
try
{
var logs = new List<TaskLog>();
int count = 0;
// 读取一批日志
while (_logReader.TryRead(out var log) && count < BatchSize)
{
logs.Add(log);
count++;
}
if (logs.Any())
{
using var scope = _serviceProvider.CreateScope();
var db = scope.ServiceProvider.GetRequiredService<JobDbContext>();
List<TaskLog> logsToSave = new List<TaskLog>();
foreach (var log in logs)
{
if (!string.IsNullOrEmpty(log.Remark) && log.Type=="请求")
2 weeks ago
{
log.Path = WriteLogToFile(log.Remark);
}
2 weeks ago
log.Remark = string.Empty;
logsToSave.Add(log);
}
//foreach (var log in logsToSave)
//{
// switch (log.TaskName)
// {
// case "来料检验数据":
// //RecurringJob.AddOrUpdate<SupplierProMaterialStockService>(
// // task.TaskName,
// // x => ((IDoExecute)x).ExecuteAsync(url, path, task.TaskName, client, pagesize),
// // task.Corn,
// // TimeZoneInfo.Local
// //);
// break;
// case "排产数据":
// //RecurringJob.AddOrUpdate<CherySupplierProSchedulingService>(
// // task.TaskName,
// // x => ((IDoExecute)x).ExecuteAsync(url, path, task.TaskName, client, pagesize),
// // task.Corn,
// // TimeZoneInfo.Local
// //);
// break;
// case "供应商基础信息":
// //RecurringJob.AddOrUpdate<CherySupplierInfoService>(
// // task.TaskName,
// // x => ((IDoExecute)x).ExecuteAsync(url, path, task.TaskName, client, pagesize),
// // task.Corn,
// // TimeZoneInfo.Local
// //);
// break;
// case "人员资质信息":
// //RecurringJob.AddOrUpdate<CherySupplierEmployeeService>(
// // task.TaskName,
// // x => ((IDoExecute)x).ExecuteAsync(url, path, task.TaskName, client, pagesize),
// // task.Corn,
// // TimeZoneInfo.Local
// //);
// break;
// case "BOM主数据":
// //RecurringJob.AddOrUpdate<CherySupplierBomService>(
// // task.TaskName,
// // x => ((IDoExecute)x).ExecuteAsync(url, path, task.TaskName, client, pagesize),
// // task.Corn,
// // TimeZoneInfo.Local
// //);
// break;
// case "过程控制项质量数据":
// //RecurringJob.AddOrUpdate<CherySupplierProCpsService>(
// // task.TaskName,
// // x => ((IDoExecute)x).ExecuteAsync(url, path, task.TaskName, client, pagesize),
// // task.Corn,
// // TimeZoneInfo.Local
// //);
// break;
// case "生产过程数据":
// //RecurringJob.AddOrUpdate<CherySupplierProDataService>(
// // task.TaskName,
// // x => ((IDoExecute)x).ExecuteAsync(url, path, task.TaskName, client, pagesize),
// // task.Corn,
// // TimeZoneInfo.Local
// //);
// break;
// case "产品一次合格率":
// //RecurringJob.AddOrUpdate<CherySupplierProFirstPassyieldService>(
// // task.TaskName,
// // x => ((IDoExecute)x).ExecuteAsync(url, path, task.TaskName, client, pagesize),
// // task.Corn,
// // TimeZoneInfo.Local
// //);
// break;
// case "工位一次合格率":
// //RecurringJob.AddOrUpdate<CherySupplierProStationFirstPassyieldService>(
// // task.TaskName,
// // x => ((IDoExecute)x).ExecuteAsync(url, path, task.TaskName, client, pagesize),
// // task.Corn,
// // TimeZoneInfo.Local
// //);
// break;
// case "缺陷业务数据":
// //RecurringJob.AddOrUpdate<CherySupplierProFlawService>(
// // task.TaskName,
// // x => ((IDoExecute)x).ExecuteAsync(url, path, task.TaskName, client, pagesize),
// // task.Corn,
// // TimeZoneInfo.Local
// //);
// break;
// case "环境业务数据":
// //RecurringJob.AddOrUpdate<CherySupplierProEnvironmentService>(
// // task.TaskName,
// // x => ((IDoExecute)x).ExecuteAsync(url, path, task.TaskName, client, pagesize),
// // task.Corn,
// // TimeZoneInfo.Local
// //);
// break;
// case "设备OEE达成率":
// //RecurringJob.AddOrUpdate<CherySupplierProOeeAchievementRateService>(
// // task.TaskName,
// // x => ((IDoExecute)x).ExecuteAsync(url, path, task.TaskName, client, pagesize),
// // task.Corn,
// // TimeZoneInfo.Local
// //);
// break;
// case "OEE时间明细":
// //RecurringJob.AddOrUpdate<CherySupplierProOeeTimeDetailsService>(
// // task.TaskName,
// // x => ((IDoExecute)x).ExecuteAsync(url, path, task.TaskName, client, pagesize),
// // task.Corn,
// // TimeZoneInfo.Local
// //);
// break;
// case "物料主数据":
// //RecurringJob.AddOrUpdate<CherySupplierProMaterialDataService>(
// // task.TaskName,
// // x => ((IDoExecute)x).ExecuteAsync(url, path, task.TaskName, client, pagesize),
// // task.Corn,
// // TimeZoneInfo.Local
// //);
// break;
// case "附件类数据":
// //RecurringJob.AddOrUpdate<CherySupplierProAttachmentDataService>(
// // task.TaskName,
// // x => ((IDoExecute)x).ExecuteAsync(url, path, task.TaskName, client, pagesize),
// // task.Corn,
// // TimeZoneInfo.Local
// //);
// break;
// case "工艺装备":
// //RecurringJob.AddOrUpdate<CherySupplierProProcessEquipmentService>(
// // task.TaskName,
// // x => ((IDoExecute)x).ExecuteAsync(url, path, task.TaskName, client, pagesize),
// // task.Corn,
// // TimeZoneInfo.Local
// //);
// break;
// case "工艺":
// //RecurringJob.AddOrUpdate<CherySupplierProProcessService>(
// // task.TaskName,
// // x => ((IDoExecute)x).ExecuteAsync(url, path, task.TaskName, client, pagesize),
// // task.Corn,
// // TimeZoneInfo.Local
// //);
// break;
// case "整车月度生产计划1":
// var planlingResult1 = Response<SUPPLIER_PRO_PLANING, SUPPLIER_PRO_PLANING_DETIAL_DTO>(log.Remark, log.Version,log.TaskId,db);
// break;
// case "M+6月物料需求计划1":
// var monthResult = Response<SUPPLIER_MRP_MONTH, SUPPLIER_MRP_MONTH_DETAIL_DTO>(log.Remark, log.Version,log.TaskId,db);
// break;
// case "整车月度生产计划2":
// var planlingResult2=Response<SUPPLIER_PRO_PLANING, SUPPLIER_PRO_PLANING_DETIAL_DTO>(log.Remark,log.Version, log.TaskId, db);
// break;
// case "M+6月物料需求计划2":
// var monthResult2 = Response<SUPPLIER_MRP_MONTH, SUPPLIER_MRP_MONTH_DETAIL_DTO>(log.Remark, log.Version,log.TaskId,db);
// break;
// case "日物料需求计划":
// var dateResult2 = Response<SUPPLIER_MRP_DATE, SUPPLIER_MRP_DATE_DETAIL_DTO>(log.Remark, log.Version, log.TaskId, db);
// break;
// case "计划协议":
// var weekResult = Response<SUPPLIER_SA_WEEK, SUPPLIER_SA_WEEK_DETAIL_DTO>(log.Remark, log.Version, log.TaskId, db);
// break;
// case "采购订单":
// var poResult = Response<SUPPLIER_PO, SUPPLIER_PO_DETAIL_DTO>(log.Remark, log.Version, log.TaskId, db);
// break;
// case "过焊装未过总装":
// var GHResult = Response<SUPPLIER_PRO_HSCHEDUL, SUPPLIER_PO_DETAIL_DTO>(log.Remark, log.Version, log.TaskId, db);
// break;
// case "过涂装未过总装":
// var TSResult = Response<SUPPLIER_PRO_TSCHEDUL, SUPPLIER_PRO_TSCHEDUL_DETAIL_DTO>(log.Remark, log.Version, log.TaskId, db);
// break;
// case "排序供货":
// var CSResult = Response<SUPPLIER_PRO_CSCHEDUL, SUPPLIER_PRO_CSCHEDUL_DETAIL_DTO>(log.Remark, log.Version, log.TaskId, db);
// break;
// case "看板配送单":
// var DELResult = Response<SUPPLIER_DEL_STATE, SUPPLIER_DEL_STATE_DETAIL_DTO>(log.Remark, log.Version, log.TaskId, db);
// break;
// case "退货单":
// var ReturnResult = Response<SUPPLIER_RETURN, SUPPLIER_RETURN_DETAIL_DTO>(log.Remark, log.Version, log.TaskId, db);
// break;
// case "奇瑞RDC共享库存":
// var InvDataResult = Response<SUPPLIER_INV_DATA, SUPPLIER_INV_DATA_DETAIL_DTO>(log.Remark, log.Version, log.TaskId, db);
// break;
// case "日MRP状态监控":
// var MrpDateResult = Response<SUPPLIER_MRP_DATE, SUPPLIER_MRP_DATE_DETAIL_DTO>(log.Remark, log.Version, log.TaskId, db);
// break;
// case "日MRP预警推移":
// var WarningResult = Response<SUPPLIER_MRP_WARNING, SUPPLIER_MRP_WARNING_DETAIL_DTO>(log.Remark, log.Version, log.TaskId, db);
// break;
// case "M+6月物料需求计划风险确认":
// //RecurringJob.AddOrUpdate<CherySupplierConMmrpService>(
// // task.TaskName,
// // x => ((IDoExecute)x).ExecuteAsync(url, path, task.TaskName, client, pagesize),
// // task.Corn,
// // TimeZoneInfo.Local
// //);
// break;
// case "日物料需求计划风险确认":
// //RecurringJob.AddOrUpdate<CherySupplierConDateService>(
// // task.TaskName,
// // x => ((IDoExecute)x).ExecuteAsync(url, path, task.TaskName, client, pagesize),
// // task.Corn,
// // TimeZoneInfo.Local
// //);
// break;
// case "采购订单风险确认":
// //RecurringJob.AddOrUpdate<CherySupplierConPoService>(
// // task.TaskName,
// // x => ((IDoExecute)x).ExecuteAsync(url, path, task.TaskName, client, pagesize),
// // task.Corn,
// // TimeZoneInfo.Local
// //);
// break;
// case "供应商共享库存-上午":
// //RecurringJob.AddOrUpdate<CherySupplierSinvDataService>(
// // task.TaskName,
// // x => ((IDoExecute)x).ExecuteAsync(url, path, task.TaskName, client, pagesize),
// // task.Corn,
// // TimeZoneInfo.Local
// //);
// break;
// case "供应商共享库存-晚上":
// //RecurringJob.AddOrUpdate<CherySupplierSinvDataService>(
// // task.TaskName,
// // x => ((IDoExecute)x).ExecuteAsync(url, path, task.TaskName, client, pagesize),
// // task.Corn,
// // TimeZoneInfo.Local
// //);
// break;
// }
//}
2 weeks ago
await db.TaskLogs.AddRangeAsync(logsToSave, stoppingToken);
await db.SaveChangesAsync(stoppingToken);
_logger.LogInformation($"已写入 {logs.Count} 条日志");
}
}
catch (Exception ex)
{
_logger.LogError(ex, "日志写入数据库失败");
// 错误处理:可记录到临时文件或重试
await Task.Delay(1000, stoppingToken); // 短暂延迟后重试
}
}
3 weeks ago
}
2 weeks ago
public override async Task StopAsync(CancellationToken stoppingToken)
3 weeks ago
{
2 weeks ago
_logger.LogInformation("日志消费服务正在停止");
// 处理剩余日志
await base.StopAsync(stoppingToken);
}
private void EnsureDirectoryExists(string directoryPath)
{
if (!Directory.Exists(directoryPath))
{
Directory.CreateDirectory(directoryPath);
}
}
// 修改后的日志写入方法
private string WriteLogToFile(string jsonContent)
{
//if string.IsNullOrEmpty(logMessage.RawRemark)) return null; // 必须提供JSON数据
3 weeks ago
2 weeks ago
// 创建日期目录
string dateDirectory = DateTime.Now.ToString("yyyy-MM-dd");
string fullDatePath = Path.Combine(_logDirectory, dateDirectory);
EnsureDirectoryExists(fullDatePath);
3 weeks ago
2 weeks ago
// 生成唯一文件名(时间戳+随机数)
string fileName = $"log_{DateTime.Now.Ticks}_{Random.Shared.Next(1000, 9999)}.json";
string fullPath = Path.Combine(fullDatePath, fileName);
3 weeks ago
try
{
2 weeks ago
// 写入文件(使用UTF-8无BOM格式)
File.WriteAllText(fullPath, jsonContent, new UTF8Encoding(false));
// 存储相对路径(从日志根目录开始,使用正斜杠兼容API)
return Path.Combine(dateDirectory, fileName).Replace('\\', '/');
3 weeks ago
}
catch (Exception ex)
{
2 weeks ago
Console.WriteLine($"JSON文件写入失败:{ex.Message}");
3 weeks ago
2 weeks ago
return null;
3 weeks ago
}
}
2 weeks ago
2 weeks ago
}
3 weeks ago
2 weeks ago
2 weeks ago
// 后台服务
//public class LogBackgroundService : BackgroundService
//{
// private readonly Channel<TaskLog> _logChannel;
// private readonly IServiceProvider _serviceProvider;
// private readonly string _logDirectory;
// public LogBackgroundService(IServiceProvider serviceProvider, IConfiguration configuration)
// {
// Console.WriteLine("LogService 初始化");
// _serviceProvider = serviceProvider;
// _logDirectory = configuration["Logging:Directory"] ??
// Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "CustomLogs"); // 使用更安全的路径获取方式
// EnsureDirectoryExists(_logDirectory);
// _logChannel = Channel.CreateUnbounded<TaskLog>();
// }
// public void EnqueueLog(TaskLog log)
// {
// _logChannel.Writer.TryWrite(log);
// }
// public override async Task StartAsync(CancellationToken cancellationToken)
// {
// // 服务启动前的准备工作
// // _logger.LogInformation("Worker starting up...");
// // 调用基类方法
// await base.StartAsync(cancellationToken);
// }
// public override async Task StopAsync(CancellationToken cancellationToken)
// {
// // 服务停止前的清理工作
// //_logger.LogInformation("Worker shutting down...");
// // 调用基类方法
// await base.StopAsync(cancellationToken);
// }
// public override void Dispose()
// {
// // 资源释放
// // _logger.LogInformation("Worker disposing resources");
// base.Dispose();
// }
// protected override async Task ExecuteAsync(CancellationToken stoppingToken)
// {
// Console.WriteLine("LogService 开始执行后台任务");
// using PeriodicTimer timer = new(TimeSpan.FromSeconds(10));
// // 主循环 - 使用 PeriodicTimer 等待下一个触发时间
// while (await timer.WaitForNextTickAsync(stoppingToken))
// {
// await foreach (var log in _logChannel.Reader.ReadAllAsync(stoppingToken))
// {
// try
// {
// if (!string.IsNullOrEmpty(log.Remark))
// {
// log.Path = WriteLogToFile(log.Remark);
// }
// log.Remark = string.Empty;
// using var scope = _serviceProvider.CreateScope();
// var db = scope.ServiceProvider.GetRequiredService<JobDbContext>();
// await db.TaskLogs.AddAsync(log, stoppingToken);
// await db.SaveChangesAsync(stoppingToken);
// Console.WriteLine($"日志已保存: {log.Info}");
// }
// catch (Exception ex)
// {
// Console.WriteLine($"日志处理失败: {ex.Message}");
// }
// }
// }
// Console.WriteLine("LogService 后台任务已停止");
// }
// private void EnsureDirectoryExists(string directoryPath)
// {
// if (!Directory.Exists(directoryPath))
// {
// Directory.CreateDirectory(directoryPath);
// }
// }
// // 修改后的日志写入方法
// private string WriteLogToFile(string jsonContent)
// {
// //if string.IsNullOrEmpty(logMessage.RawRemark)) return null; // 必须提供JSON数据
// // 创建日期目录
// string dateDirectory = DateTime.Now.ToString("yyyy-MM-dd");
// string fullDatePath = Path.Combine(_logDirectory, dateDirectory);
// EnsureDirectoryExists(fullDatePath);
// // 生成唯一文件名(时间戳+随机数)
// string fileName = $"log_{DateTime.Now.Ticks}_{Random.Shared.Next(1000, 9999)}.json";
// string fullPath = Path.Combine(fullDatePath, fileName);
// try
// {
// // 写入文件(使用UTF-8无BOM格式)
// File.WriteAllText(fullPath, jsonContent, new UTF8Encoding(false));
// // 存储相对路径(从日志根目录开始,使用正斜杠兼容API)
// return Path.Combine(dateDirectory, fileName).Replace('\\', '/');
// }
// catch (Exception ex)
// {
// Console.WriteLine($"JSON文件写入失败:{ex.Message}");
// return null;
// }
// }
//}
2 weeks ago
2 weeks ago
}
2 weeks ago
3 weeks ago