日志补全

This commit is contained in:
2026-01-16 15:17:23 +08:00
parent fd6a82eb4e
commit 0b374121f3
17 changed files with 52 additions and 30 deletions

View File

@@ -15,7 +15,7 @@ public class FrameConsumer : IDisposable
{ {
#region --- (Private Resources & States) --- #region --- (Private Resources & States) ---
private static ILogger _sysLog = Log.ForContext("SourceContext", LogModules.Core); private ILogger _sysLog = Log.ForContext("SourceContext", LogModules.Core);
/// <summary> 帧缓冲队列容量1仅存储最新一帧保证零延迟渲染 </summary> /// <summary> 帧缓冲队列容量1仅存储最新一帧保证零延迟渲染 </summary>
/// <remarks> BlockingCollection 封装线程安全操作GetConsumingEnumerable 支持取消令牌 </remarks> /// <remarks> BlockingCollection 封装线程安全操作GetConsumingEnumerable 支持取消令牌 </remarks>

View File

@@ -11,7 +11,7 @@ public class CameraManager : IDisposable, IAsyncDisposable
{ {
#region --- 1. (Fields & States) --- #region --- 1. (Fields & States) ---
private static ILogger _sysLog = Log.ForContext("SourceContext", LogModules.Core); private ILogger _sysLog = Log.ForContext("SourceContext", LogModules.Core);
/// <summary> 全局设备实例池线程安全Key = 设备唯一标识 </summary> /// <summary> 全局设备实例池线程安全Key = 设备唯一标识 </summary>
private readonly ConcurrentDictionary<long, BaseVideoSource> _cameraPool = new(); private readonly ConcurrentDictionary<long, BaseVideoSource> _cameraPool = new();

View File

@@ -15,7 +15,7 @@ public class ProcessingPipeline
{ {
#region --- (Private Resources & States) --- #region --- (Private Resources & States) ---
private static ILogger _sysLog = Log.ForContext("SourceContext", LogModules.Core); private ILogger _sysLog = Log.ForContext("SourceContext", LogModules.Core);
/// <summary> 任务队列(有界通道):存储待处理的帧任务 </summary> /// <summary> 任务队列(有界通道):存储待处理的帧任务 </summary>
private readonly Channel<ProcessingTask> _queue; private readonly Channel<ProcessingTask> _queue;

View File

@@ -15,7 +15,7 @@ public class CameraCoordinator
{ {
#region --- (Private Resources & Configurations) --- #region --- (Private Resources & Configurations) ---
private static ILogger _sysLog = Log.ForContext("SourceContext", LogModules.Core); private ILogger _sysLog = Log.ForContext("SourceContext", LogModules.Core);
/// <summary> 已注册的相机设备集合(线程安全,支持并发添加与遍历) </summary> /// <summary> 已注册的相机设备集合(线程安全,支持并发添加与遍历) </summary>
private readonly ConcurrentBag<BaseVideoSource> _cameras = new(); private readonly ConcurrentBag<BaseVideoSource> _cameras = new();

View File

@@ -11,7 +11,7 @@ namespace SHH.CameraSdk;
/// </summary> /// </summary>
public class FrameController public class FrameController
{ {
private static ILogger _sysLog = Log.ForContext("SourceContext", LogModules.Core); private ILogger _sysLog = Log.ForContext("SourceContext", LogModules.Core);
// 需求字典 // 需求字典
private readonly ConcurrentDictionary<string, FrameRequirement> _requirements = new(); private readonly ConcurrentDictionary<string, FrameRequirement> _requirements = new();

View File

@@ -19,7 +19,7 @@ namespace SHH.CameraSdk
{ {
#region --- --- #region --- ---
private static ILogger _sysLog = Log.ForContext("SourceContext", LogModules.Core); private ILogger _sysLog = Log.ForContext("SourceContext", LogModules.Core);
/// <summary> Worker 线程池,负责具体的帧处理任务 </summary> /// <summary> Worker 线程池,负责具体的帧处理任务 </summary>
protected readonly List<TWorker> _workers = new List<TWorker>(); protected readonly List<TWorker> _workers = new List<TWorker>();
@@ -165,7 +165,7 @@ namespace SHH.CameraSdk
{ {
#region --- --- #region --- ---
private static ILogger _gRpcLog = Log.ForContext("SourceContext", LogModules.gRpc); private ILogger _gRpcLog = Log.ForContext("SourceContext", LogModules.gRpc);
/// <summary> 线程内任务队列容量限制100防止内存溢出 </summary> /// <summary> 线程内任务队列容量限制100防止内存溢出 </summary>
private readonly BlockingCollection<(long DeviceId, SmartFrame Frame, FrameDecision Decision)> _taskQueue = new BlockingCollection<(long, SmartFrame, FrameDecision)>(100); private readonly BlockingCollection<(long DeviceId, SmartFrame Frame, FrameDecision Decision)> _taskQueue = new BlockingCollection<(long, SmartFrame, FrameDecision)>(100);

View File

@@ -20,7 +20,7 @@ namespace SHH.CameraSdk
{ {
#region --- --- #region --- ---
private static ILogger _sysLog = Log.ForContext("SourceContext", LogModules.Core); private ILogger _sysLog = Log.ForContext("SourceContext", LogModules.Core);
/// <summary> /// <summary>
/// 单个窗口的上下文信息载体 /// 单个窗口的上下文信息载体

View File

@@ -9,7 +9,7 @@ namespace SHH.CameraSdk;
/// </summary> /// </summary>
public class ProcessingConfigManager public class ProcessingConfigManager
{ {
private static ILogger _sysLog = Log.ForContext("SourceContext", LogModules.Core); private ILogger _sysLog = Log.ForContext("SourceContext", LogModules.Core);
// 内存字典Key=设备ID, Value=配置对象 // 内存字典Key=设备ID, Value=配置对象
private readonly ConcurrentDictionary<long, ProcessingOptions> _configs = new(); private readonly ConcurrentDictionary<long, ProcessingOptions> _configs = new();

View File

@@ -1,4 +1,6 @@
namespace SHH.CameraSdk; using Serilog;
namespace SHH.CameraSdk;
/// <summary> /// <summary>
/// [架构基类] 工业级视频源抽象核心 (V3.3.4 严格匹配版) /// [架构基类] 工业级视频源抽象核心 (V3.3.4 严格匹配版)
@@ -39,6 +41,8 @@ public abstract class BaseVideoSource : IVideoSource, IAsyncDisposable, IDeviceC
} }
} }
protected abstract ILogger _sdkLog { get; }
#region --- 1. (Core Config & Locks) --- #region --- 1. (Core Config & Locks) ---
/// <summary> /// <summary>

View File

@@ -20,7 +20,8 @@ public class HikVideoSource : BaseVideoSource,
#region --- (Global Resources) --- #region --- (Global Resources) ---
// 日志实例 // 日志实例
private static ILogger _sdkLog = Log.ForContext("SourceContext", LogModules.HikVisionSdk); protected override ILogger _sdkLog => Log.ForContext("SourceContext", LogModules.HikVisionSdk);
// 静态路由表 // 静态路由表
private static readonly ConcurrentDictionary<int, HikVideoSource> _instances = new(); private static readonly ConcurrentDictionary<int, HikVideoSource> _instances = new();
// 全局异常回调 // 全局异常回调
@@ -108,7 +109,7 @@ public class HikVideoSource : BaseVideoSource,
if (!HikSdkManager.Initialize()) if (!HikSdkManager.Initialize())
{ {
_sdkLog.Error("HikVision Sdk 初始化失败."); _sdkLog.Error("[SDK] HikVision Sdk 初始化失败.");
throw new CameraException(CameraErrorCode.SdkNotInitialized, "HikVision Sdk 初始化失败.", DeviceBrand.HikVision); throw new CameraException(CameraErrorCode.SdkNotInitialized, "HikVision Sdk 初始化失败.", DeviceBrand.HikVision);
} }
@@ -117,8 +118,8 @@ public class HikVideoSource : BaseVideoSource,
HikNativeMethods.NET_DVR_SetExceptionCallBack_V30(0, IntPtr.Zero, _globalExceptionCallback, IntPtr.Zero); HikNativeMethods.NET_DVR_SetExceptionCallBack_V30(0, IntPtr.Zero, _globalExceptionCallback, IntPtr.Zero);
// [审计] 记录登录动作 // [审计] 记录登录动作
AddAuditLog($"Hik 正在执行登录 => ID:{_config.Id} IP:{_config.IpAddress} Port:{_config.Port} Name:{_config.Name}"); _sdkLog.Information($"[SDK] Hik 正在执行登录 => ID:{_config.Id} IP:{_config.IpAddress} Port:{_config.Port} Name:{_config.Name}");
_sdkLog.Information($"Hik 正在执行登录 => ID:{_config.Id} IP:{_config.IpAddress} Port:{_config.Port} Name:{_config.Name}"); AddAuditLog($"[SDK] Hik 正在执行登录 => ID:{_config.Id} IP:{_config.IpAddress} Port:{_config.Port} Name:{_config.Name}");
var devInfo = new HikNativeMethods.NET_DEVICEINFO_V30(); var devInfo = new HikNativeMethods.NET_DEVICEINFO_V30();
int newUserId = HikNativeMethods.NET_DVR_Login_V30( int newUserId = HikNativeMethods.NET_DVR_Login_V30(
@@ -138,7 +139,9 @@ public class HikVideoSource : BaseVideoSource,
} }
_instances.TryAdd(_userId, this); _instances.TryAdd(_userId, this);
AddAuditLog($"物理登录成功 (UserID: {_userId})");
_sdkLog.Information($"[SDK] Hik 登录成功 => ID:{_config.Id} IP:{_config.IpAddress} Port:{_config.Port} Name:{_config.Name}, UserID: {_userId}");
AddAuditLog($"[SDK] Hik 登录成功 => ID:{_config.Id} IP:{_config.IpAddress} Port:{_config.Port} Name:{_config.Name}, UserID: {_userId}");
// 开启取流 // 开启取流
if (!StartRealPlay()) if (!StartRealPlay())
@@ -147,11 +150,13 @@ public class HikVideoSource : BaseVideoSource,
throw new CameraException(HikErrorMapper.Map(err), $"预览失败: {err}", DeviceBrand.HikVision, (int)err); throw new CameraException(HikErrorMapper.Map(err), $"预览失败: {err}", DeviceBrand.HikVision, (int)err);
} }
AddAuditLog($"网络取流成功 (StreamType: {_config.StreamType})"); _sdkLog.Debug($"[SDK] Hik 网络取流成功 => ID:{_config.Id} IP:{_config.IpAddress} Port:{_config.Port} Name:{_config.Name}, UserID: {_userId}");
AddAuditLog($"[SDK] Hik 网络取流成功 => ID:{_config.Id} IP:{_config.IpAddress} Port:{_config.Port} Name:{_config.Name}, UserID: {_userId}");
} }
catch (Exception ex) catch (Exception ex)
{ {
AddAuditLog($"启动异常: {ex.Message}"); _sdkLog.Error($"[SDK] Hik 启动异常. => ID:{_config.Id} IP:{_config.IpAddress} Port:{_config.Port} Name:{_config.Name}, UserID: {_userId}");
AddAuditLog($"[SDK] Hik 启动异常. => ID:{_config.Id} IP:{_config.IpAddress} Port:{_config.Port} Name:{_config.Name}, UserID: {_userId}");
CleanupSync(); CleanupSync();
throw; throw;
} }
@@ -161,9 +166,14 @@ public class HikVideoSource : BaseVideoSource,
protected override async Task OnStopAsync() protected override async Task OnStopAsync()
{ {
Interlocked.Increment(ref _connectionEpoch); Interlocked.Increment(ref _connectionEpoch);
AddAuditLog("正在执行停止流程...");
_sdkLog.Debug($"[SDK] Hik 正在执行停止流程. => ID:{_config.Id} IP:{_config.IpAddress} Port:{_config.Port} Name:{_config.Name}, UserID: {_userId}");
AddAuditLog($"[SDK] Hik 正在执行停止流程. => ID:{_config.Id} IP:{_config.IpAddress} Port:{_config.Port} Name:{_config.Name}, UserID: {_userId}");
await Task.Run(() => CleanupSync()); await Task.Run(() => CleanupSync());
AddAuditLog("设备已停止");
_sdkLog.Information($"[SDK] Hik 设备已停止. => ID:{_config.Id} IP:{_config.IpAddress} Port:{_config.Port} Name:{_config.Name}, UserID: {_userId}");
AddAuditLog($"[SDK] Hik 设备已停止. => ID:{_config.Id} IP:{_config.IpAddress} Port:{_config.Port} Name:{_config.Name}, UserID: {_userId}");
} }
private void CleanupSync() private void CleanupSync()
@@ -218,6 +228,8 @@ public class HikVideoSource : BaseVideoSource,
if (options.StreamType.HasValue) if (options.StreamType.HasValue)
{ {
int targetStream = options.StreamType.Value; int targetStream = options.StreamType.Value;
_sdkLog.Debug($"[SDK] Hik 收到码流切换请求. => ID:{_config.Id} IP:{_config.IpAddress} Port:{_config.Port} Name:{_config.Name}, UserID: {_userId}, 播放句柄:{_realPlayHandle}");
AddAuditLog($"收到码流切换请求: {targetStream},开始执行热切换..."); AddAuditLog($"收到码流切换请求: {targetStream},开始执行热切换...");
lock (_initLock) lock (_initLock)
@@ -244,12 +256,14 @@ public class HikVideoSource : BaseVideoSource,
// D. 重新开启预览 // D. 重新开启预览
if (StartRealPlay()) if (StartRealPlay())
{ {
AddAuditLog($"码流热切换成功 (当前: {(_config.StreamType == 0 ? "" : "")}码流)"); _sdkLog.Information($"[SDK] Hik 码流热切换成功. => 当前: {(_config.StreamType == 0 ? "" : "")}码流), ID:{_config.Id} IP:{_config.IpAddress} Port:{_config.Port} Name:{_config.Name}, UserID: {_userId}, 播放句柄:{_realPlayHandle}");
AddAuditLog($"[SDK] Hik 码流热切换成功. => 当前: {(_config.StreamType == 0 ? "" : "")}码流), ID:{_config.Id} IP:{_config.IpAddress} Port:{_config.Port} Name:{_config.Name}, UserID: {_userId}, 播放句柄:{_realPlayHandle}");
} }
else else
{ {
uint err = HikNativeMethods.NET_DVR_GetLastError(); uint err = HikNativeMethods.NET_DVR_GetLastError();
AddAuditLog($"码流切换失败: {err}"); _sdkLog.Information($"[SDK] Hik 码流切换失败. => Err:{err}, ID:{_config.Id} IP:{_config.IpAddress} Port:{_config.Port} Name:{_config.Name}, UserID: {_userId}, 播放句柄:{_realPlayHandle}");
AddAuditLog($"[SDK] Hik 码流切换失败. => Err:{err}, ID:{_config.Id} IP:{_config.IpAddress} Port:{_config.Port} Name:{_config.Name}, UserID: {_userId}, 播放句柄:{_realPlayHandle}");
} }
} }
} }
@@ -258,7 +272,8 @@ public class HikVideoSource : BaseVideoSource,
if (options.RenderHandle.HasValue) if (options.RenderHandle.HasValue)
{ {
// 如果是硬解码模式,可以在这里调用 PlayM4_Play(port, newHandle) // 如果是硬解码模式,可以在这里调用 PlayM4_Play(port, newHandle)
AddAuditLog($"收到新句柄绑定请求: {options.RenderHandle}"); _sdkLog.Information($"[SDK] Hik 收到新句柄绑定请求, 新句柄:{options.RenderHandle}. => ID:{_config.Id} IP:{_config.IpAddress} Port:{_config.Port} Name:{_config.Name}, UserID: {_userId}, 播放句柄:{_realPlayHandle}");
AddAuditLog($"[SDK] Hik 收到新句柄绑定请求, 新句柄:{options.RenderHandle}. => ID:{_config.Id} IP:{_config.IpAddress} Port:{_config.Port} Name:{_config.Name}, UserID: {_userId}, 播放句柄:{_realPlayHandle}");
} }
} }
@@ -425,7 +440,10 @@ public class HikVideoSource : BaseVideoSource,
{ {
if (_instances.TryGetValue(lUserID, out var instance)) if (_instances.TryGetValue(lUserID, out var instance))
{ {
instance.AddAuditLog($"SDK报警异常: 0x{dwType:X}"); // 写入审计 Log.ForContext("SourceContext", LogModules.HikVisionSdk)
.Error($"Hik SDK 报警异常: 0x{dwType:X}, UserId: {lUserID} ");
instance.AddAuditLog($"SDK报警 User:{pUser} 异常: 0x{dwType:X}, UserId: {lUserID}"); // 写入审计
instance.ReportError(new CameraException( instance.ReportError(new CameraException(
CameraErrorCode.NetworkUnreachable, CameraErrorCode.NetworkUnreachable,
$"SDK全局异常: 0x{dwType:X}", $"SDK全局异常: 0x{dwType:X}",

View File

@@ -11,7 +11,7 @@ namespace SHH.CameraService;
/// </summary> /// </summary>
public class CommandDispatcher public class CommandDispatcher
{ {
private static ILogger _gRpcLog = Log.ForContext("SourceContext", LogModules.gRpc); private ILogger _gRpcLog = Log.ForContext("SourceContext", LogModules.gRpc);
private readonly Dictionary<string, ICommandHandler> _handlers; private readonly Dictionary<string, ICommandHandler> _handlers;
/// <summary> /// <summary>

View File

@@ -14,7 +14,7 @@ public class ParentProcessSentinel : BackgroundService
{ {
private readonly ServiceConfig _config; private readonly ServiceConfig _config;
private readonly IHostApplicationLifetime _lifetime; private readonly IHostApplicationLifetime _lifetime;
private static ILogger _sysLog = Log.ForContext("SourceContext", LogModules.Core); private ILogger _sysLog = Log.ForContext("SourceContext", LogModules.Core);
/// <summary> /// <summary>
/// 使用统一的结构化日志记录器SourceContext 设置为 Core 模块 /// 使用统一的结构化日志记录器SourceContext 设置为 Core 模块

View File

@@ -11,7 +11,7 @@ namespace SHH.CameraService;
/// </summary> /// </summary>
public class DeviceConfigHandler : ICommandHandler public class DeviceConfigHandler : ICommandHandler
{ {
private static ILogger _sysLog = Log.ForContext("SourceContext", LogModules.Core); private ILogger _sysLog = Log.ForContext("SourceContext", LogModules.Core);
private readonly CameraManager _cameraManager; private readonly CameraManager _cameraManager;

View File

@@ -16,7 +16,7 @@ namespace SHH.CameraService;
/// </summary> /// </summary>
public class DeviceStatusHandler : BackgroundService public class DeviceStatusHandler : BackgroundService
{ {
private static ILogger _gRpcLog = Log.ForContext("SourceContext", LogModules.gRpc); private ILogger _gRpcLog = Log.ForContext("SourceContext", LogModules.gRpc);
private readonly CameraManager _manager; private readonly CameraManager _manager;
private readonly ServiceConfig _config; private readonly ServiceConfig _config;

View File

@@ -11,7 +11,7 @@ namespace SHH.CameraService
/// </summary> /// </summary>
public class RemoveCameraHandler : ICommandHandler public class RemoveCameraHandler : ICommandHandler
{ {
private static ILogger _sysLog = Log.ForContext("SourceContext", LogModules.Core); private ILogger _sysLog = Log.ForContext("SourceContext", LogModules.Core);
private readonly CameraManager _cameraManager; private readonly CameraManager _cameraManager;

View File

@@ -15,7 +15,7 @@ namespace SHH.CameraService;
/// </summary> /// </summary>
public class ImageMonitorController : BackgroundService public class ImageMonitorController : BackgroundService
{ {
private static ILogger _sysLog = Log.ForContext("SourceContext", LogModules.Core); private ILogger _sysLog = Log.ForContext("SourceContext", LogModules.Core);
// 注入所有注册的目标(云端、大屏等),实现动态分发 // 注入所有注册的目标(云端、大屏等),实现动态分发
private readonly IEnumerable<StreamTarget> _targets; private readonly IEnumerable<StreamTarget> _targets;

View File

@@ -13,7 +13,7 @@ namespace SHH.CameraService;
/// </summary> /// </summary>
public class GrpcSenderWorker : BackgroundService public class GrpcSenderWorker : BackgroundService
{ {
private static ILogger _gRpcLog = Log.ForContext("SourceContext", LogModules.gRpc); private ILogger _gRpcLog = Log.ForContext("SourceContext", LogModules.gRpc);
private readonly StreamTarget _target; private readonly StreamTarget _target;
private readonly string _grpcUrl; private readonly string _grpcUrl;