Compare commits

..

2 Commits

Author SHA1 Message Date
huangxianguo e20129a4c1 集成Serilog日志框架 2024-09-09 11:52:15 +08:00
huangxianguo 4dd680b0dc 完善故障记录和上传图片的接口 2024-09-09 11:06:21 +08:00
11 changed files with 231 additions and 42 deletions

View File

@ -0,0 +1,60 @@
using Serilog;
using Serilog.Core;
using Serilog.Events;
namespace MasstransferCommon.Config;
/// <summary>
/// 日志配置类
/// </summary>
public class LogConfiguration
{
/// <summary>
/// 获取日志配置对象
/// </summary>
/// <returns></returns>
public static Logger GetLogger()
{
// 日志输出目录
var basePath = AppDomain.CurrentDomain.BaseDirectory;
return new LoggerConfiguration()
.MinimumLevel.Debug()
.Enrich.FromLogContext()
.WriteTo.Logger(
l =>
l.Filter.ByIncludingOnly(e => e.Level == LogEventLevel.Debug)
.WriteTo.File(
Path.Combine(basePath, "logs", "debug", "debug-.log"),
rollingInterval: RollingInterval.Hour,
retainedFileCountLimit: 24
)
)
.WriteTo.Logger(
l => l.Filter.ByIncludingOnly(e => e.Level == LogEventLevel.Information)
.WriteTo.File(
Path.Combine(basePath, "logs", "info", "info-.log"),
rollingInterval: RollingInterval.Hour,
retainedFileCountLimit: 72
)
)
.WriteTo.Logger(
l => l.Filter.ByIncludingOnly(e => e.Level == LogEventLevel.Warning)
.WriteTo.File(
Path.Combine(basePath, "logs", "warning", "warning-.log"),
rollingInterval: RollingInterval.Day,
retainedFileCountLimit: 30
)
)
.WriteTo.Logger(
l => l.Filter.ByIncludingOnly(e => e.Level == LogEventLevel.Error)
.WriteTo.File(
Path.Combine(basePath, "logs", "error", "error-.log"),
rollingInterval: RollingInterval.Day,
retainedFileCountLimit: 90
)
)
.WriteTo.Console()
.CreateLogger();
}
}

View File

@ -12,6 +12,11 @@
<PackageReference Include="Microsoft.EntityFrameworkCore.Abstractions" Version="7.0.15" /> <PackageReference Include="Microsoft.EntityFrameworkCore.Abstractions" Version="7.0.15" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3"/> <PackageReference Include="Newtonsoft.Json" Version="13.0.3"/>
<PackageReference Include="Quartz" Version="3.10.0" /> <PackageReference Include="Quartz" Version="3.10.0" />
<PackageReference Include="Serilog.Enrichers.Environment" Version="3.0.1" />
<PackageReference Include="Serilog.Extensions.Logging" Version="3.1.0" />
<PackageReference Include="Serilog.Extensions.Logging.File" Version="3.0.1-dev-00077" />
<PackageReference Include="Serilog.Sinks.Console" Version="6.0.0" />
<PackageReference Include="Serilog.Sinks.RollingFile" Version="3.3.1-dev-00771" />
<PackageReference Include="sqlite-net-sqlcipher" Version="1.9.172" /> <PackageReference Include="sqlite-net-sqlcipher" Version="1.9.172" />
<PackageReference Include="System.Management" Version="8.0.0"/> <PackageReference Include="System.Management" Version="8.0.0"/>
<PackageReference Include="Serilog" Version="4.0.0"/> <PackageReference Include="Serilog" Version="4.0.0"/>

View File

@ -0,0 +1,8 @@
namespace MasstransferCommon.Model.Enum;
public enum ExceptionLevel : int
{
NORMAL,
WARN,
ERROR,
}

View File

@ -0,0 +1,36 @@
using MasstransferCommon.Model.Constant;
using MasstransferCommunicate.Mqtt.Client;
using MasstransferExporter.DataExporter.Model;
using MasstransferInfrastructure.Database.Sqlite;
namespace MasstransferExporter.DataExporter;
public class FaultRecordService
{
private static readonly SqliteHelper Db = SqliteHelper.GetInstance();
/// <summary>
/// 每5分钟上传一次故障数据
/// </summary>
public static async Task FaultRecordDataExporter()
{
var endTime = DateTime.Now;
var startTime = endTime.AddMinutes(-30);
// 查询5分钟内的故障记录
var sql = "SELECT * FROM fault_records WHERE update_time >= ? AND update_time <= ?";
var records = Db.Query<FaultRecord>(sql, startTime, endTime);
foreach (var record in records)
{
var dto = new FaultRecordDTO()
{
ErrorCode = record.FaultCode,
Timestamp = record.UpdateTime,
Status = record.Solved ? 0 : 1
};
await MessageQueueHelper.Publish(Topics.ReportFaultRecord, dto);
}
}
}

View File

@ -0,0 +1,43 @@
using System.ComponentModel;
using MasstransferCommon.Model.Entity;
using MasstransferCommon.Model.Enum;
using SQLite;
namespace MasstransferExporter.DataExporter.Model;
/// <summary>
/// 故障记录
/// </summary>
[Table("fault_records"), Description("故障记录")]
public class FaultRecord : Entity
{
[Column("source"), Description("故障来源")]
public string? Source { get; set; }
[Column("fault_code"), Description("故障编码")]
public string? FaultCode { get; set; }
[Column("fault_desc"), Description("故障描述")]
public string? FaultDesc { get; set; }
[Column("fault_time"), Description("故障时间")]
public DateTime FaultTime { get; set; }
[Column("fault_level"), Description("故障级别")]
public ExceptionLevel Level { get; set; }
[Column("fault_message"), Description("故障信息")]
public string? FaultMessage { get; set; }
[Column("solved"), Description("是否已处理")]
public bool Solved { get; set; }
[Column("solved_time"), Description("处理时间")]
public DateTime? SolvedTime { get; set; }
[Column("solved_by_user_id"), Description("处理人Id")]
public string? SolvedByUserId { get; set; }
[Column("solved_by_user_name"), Description("处理人名称")]
public string? SolvedByUserName { get; set; }
}

View File

@ -0,0 +1,25 @@
using Newtonsoft.Json;
namespace MasstransferExporter.DataExporter.Model;
/// <summary>
/// 上报的故障信息
/// </summary>
public class FaultRecordDTO
{
/// <summary>
/// 错误码
/// </summary>
[JsonProperty("errorCode")]
public string? ErrorCode { get; set; }
[JsonProperty("timestamp")] public DateTime Timestamp { get; set; }
/// <summary>
/// 故障状态项
/// 0解除故障
/// 1发生故障
/// </summary>
[JsonProperty("status")]
public int Status { get; set; }
}

View File

@ -181,7 +181,7 @@ public class ImageService : Instant
{ {
var yesterday = DateTime.Today.AddDays(-2); var yesterday = DateTime.Today.AddDays(-2);
await ImageExporter(yesterday, false); await ImageExporter(new DateTime(2024, 9, 9), false);
} }
/// <summary> /// <summary>
@ -205,47 +205,52 @@ public class ImageService : Instant
var dirInfo = new DirectoryInfo(dir); var dirInfo = new DirectoryInfo(dir);
// 文件保存路径的规则是 {user BasePath}/masstransfer/images/{batchCode}/{yyyyMMdd}/wafer/{waferCode}/{timestamp}.bmp var batchCodes = dirInfo.GetDirectories();
var files = dirInfo.GetDirectories().Where(d => d.CreationTime.Date == dateTime); foreach (var batchCode in batchCodes)
foreach (var batchDir in files)
{ {
if (isThumbnail) // 文件保存路径的规则是 {user BasePath}/masstransfer/images/{batchCode}/{yyyyMMdd}/wafer/{waferCode}/{timestamp}.bmp
var dates = batchCode.GetDirectories().Where(d => d.CreationTime.Date == dateTime);
foreach (var dateDir in dates)
{ {
// 对图片进行压缩 if (isThumbnail)
GenerateThumbnail(batchDir);
}
var types = batchDir.GetDirectories();
foreach (var type in types)
{
var codeDirs = type.GetDirectories();
foreach (var codeDir in codeDirs)
{ {
var images = codeDir.GetFiles(); // 对图片进行压缩
GenerateThumbnail(dateDir);
}
images = isThumbnail var types = dateDir.GetDirectories();
? images.Where(x => x.Name.EndsWith("_thumbnail.bmp")).ToArray() foreach (var type in types)
: images.Where(x => !x.Name.EndsWith("_thumbnail.bmp")).ToArray(); {
var codeDirs = type.GetDirectories();
foreach (var image in images) foreach (var codeDir in codeDirs)
{ {
var fileName = $"{Constants.SN}/{codeDir.Name}/{batchDir.Name}/{type.Name}/{image.Name}"; var images = codeDir.GetFiles();
var path = image.FullName; images = isThumbnail
? images.Where(x => x.Name.EndsWith("_thumbnail.bmp")).ToArray()
: images.Where(x => !x.Name.EndsWith("_thumbnail.bmp")).ToArray();
await Minio.UploadFileAsync(bucket, fileName, path); foreach (var image in images)
{
var fileName =
$"{Constants.SN}/{codeDir.Name}/{batchCode.Name}/{type.Name}/{image.Name}";
var path = image.FullName;
await Minio.UploadFileAsync(bucket, fileName, path);
}
var data = new ImageExportData()
{
BatchNumber = batchCode.Name,
BizNumber = codeDir.Name,
ImageType = type.Name,
PicType = isThumbnail ? "thumbnail" : "raw"
};
// 上传完成后发布通知
await MessageQueueHelper.Publish(Topics.ImageUpload, data);
} }
var data = new ImageExportData()
{
BatchNumber = batchDir.Name,
BizNumber = codeDir.Name,
ImageType = type.Name,
PicType = isThumbnail ? "thumbnail" : "raw"
};
// 上传完成后发布通知
await MessageQueueHelper.Publish(Topics.ImageUpload, data);
} }
} }
} }

View File

@ -13,6 +13,7 @@
<PackageReference Include="M2Mqtt" Version="4.3.0" /> <PackageReference Include="M2Mqtt" Version="4.3.0" />
<PackageReference Include="MQTTnet.Extensions.ManagedClient" Version="4.3.6.1152" /> <PackageReference Include="MQTTnet.Extensions.ManagedClient" Version="4.3.6.1152" />
<PackageReference Include="Serilog" Version="4.0.0" /> <PackageReference Include="Serilog" Version="4.0.0" />
<PackageReference Include="Serilog.Extensions.Logging.File" Version="3.0.1-dev-00077" />
<PackageReference Include="Serilog.Sinks.Console" Version="6.0.0" /> <PackageReference Include="Serilog.Sinks.Console" Version="6.0.0" />
<PackageReference Include="System.Diagnostics.Process" Version="4.3.0" /> <PackageReference Include="System.Diagnostics.Process" Version="4.3.0" />
<PackageReference Include="System.Drawing.Common" Version="6.0.0" /> <PackageReference Include="System.Drawing.Common" Version="6.0.0" />

View File

@ -1,12 +1,11 @@
using MasstransferCommon.Events; using MasstransferCommon.Config;
using MasstransferCommon.Events;
using MasstransferCommon.Model.Entity; using MasstransferCommon.Model.Entity;
using MasstransferCommon.Scheduler;
using MasstransferCommunicate.Mqtt.Client; using MasstransferCommunicate.Mqtt.Client;
using MasstransferCommunicate.Process.Client;
using MasstransferExporter.DataExporter;
using MasstransferExporter.Init; using MasstransferExporter.Init;
using MasstransferInfrastructure.Database.Sqlite; using MasstransferInfrastructure.Database.Sqlite;
using MasstransferInfrastructure.Mqtt.Model; using MasstransferInfrastructure.Mqtt.Model;
using Serilog;
namespace MasstransferExporter; namespace MasstransferExporter;
@ -19,6 +18,10 @@ class Program
// 进行初始化调用 // 进行初始化调用
InstantUtil.Init(); InstantUtil.Init();
Log.Logger = LogConfiguration.GetLogger();
Log.Error("Masstransfer Exporter Startup");
var mqttParams = Db.Query<MqttParams>("select * from mqtt_params").FirstOrDefault(); var mqttParams = Db.Query<MqttParams>("select * from mqtt_params").FirstOrDefault();
// 启动mqtt连接 // 启动mqtt连接
@ -35,11 +38,11 @@ class Program
// 启动完成后,广播启动通知 // 启动完成后,广播启动通知
EventBus<bool>.Publish(EventType.StartUp, true); EventBus<bool>.Publish(EventType.StartUp, true);
DelayScheduler.Delay(async () => await FormulaService.FormulaDataExporter(), // DelayScheduler.Delay(async () => ImageService.ImageExporter(),
TimeSpan.FromSeconds(5)); // TimeSpan.FromSeconds(5));
// 启动与主程序的通信 // 启动与主程序的通信
ProcessHelper.Init(); // ProcessHelper.Init();
// SystemStatExporter.Collect(); // SystemStatExporter.Collect();

View File

@ -18,6 +18,7 @@
<PackageReference Include="MQTTnet" Version="4.3.6.1152"/> <PackageReference Include="MQTTnet" Version="4.3.6.1152"/>
<PackageReference Include="Serilog" Version="4.0.0"/> <PackageReference Include="Serilog" Version="4.0.0"/>
<PackageReference Include="Microsoft.Data.Sqlite" Version="9.0.0-preview.2.24128.4"/> <PackageReference Include="Microsoft.Data.Sqlite" Version="9.0.0-preview.2.24128.4"/>
<PackageReference Include="Serilog.Extensions.Logging.File" Version="3.0.1-dev-00077" />
<PackageReference Include="sqlite-net" Version="1.6.292"/> <PackageReference Include="sqlite-net" Version="1.6.292"/>
<PackageReference Include="sqlite-net-sqlcipher" Version="1.9.172"/> <PackageReference Include="sqlite-net-sqlcipher" Version="1.9.172"/>
<PackageReference Include="Stateless" Version="5.15.0"/> <PackageReference Include="Stateless" Version="5.15.0"/>

View File

@ -63,12 +63,14 @@ public class MinioHelper
await _client.MakeBucketAsync(new MakeBucketArgs().WithBucket(bucketName)); await _client.MakeBucketAsync(new MakeBucketArgs().WithBucket(bucketName));
} }
Console.WriteLine($"正在上传文件: {fileName} 到 bucket: {bucketName}");
await _client.PutObjectAsync(new PutObjectArgs() await _client.PutObjectAsync(new PutObjectArgs()
.WithBucket(bucketName) .WithBucket(bucketName)
.WithObject(fileName) .WithObject(fileName)
.WithFileName(filePath)); .WithFileName(filePath));
Console.WriteLine("文件上传成功"); Console.WriteLine($"文件 {fileName} 上传成功");
return $"{bucketName}/{fileName}"; return $"{bucketName}/{fileName}";
} }