Generic SignalR logger hub and writer, doc updates

Introduced generic `AcLoggerSignalRHub<TLogger, TLogItem>` and `AcSignaRClientLogItemWriter<TLogItem>` for flexible log item wire types (AcBinary/JSON). Updated writer to accept protocol options and enforce feedback-loop prevention. Improved documentation to clarify generic usage, protocol selection, and migration. Added TODOs for protocol-diagnostic logger and log noise reduction. Refactored exception handling and signatures for generics; updated issue/TODO tracking and enhanced code comments.
This commit is contained in:
Loretta 2026-07-13 08:38:17 +02:00
parent 2bb9e3a77e
commit a6bd024d17
6 changed files with 91 additions and 16 deletions

File diff suppressed because one or more lines are too long

View File

@ -1,13 +1,27 @@
using AyCode.Core.Consts; using AyCode.Core.Consts;
using AyCode.Core.Loggers; using AyCode.Core.Loggers;
using AyCode.Entities.Server.LogItems; using AyCode.Entities.Server.LogItems;
using Castle.Core.Logging;
using Microsoft.AspNetCore.SignalR; using Microsoft.AspNetCore.SignalR;
namespace AyCode.Services.Server.SignalRs; namespace AyCode.Services.Server.SignalRs;
public class AcLoggerSignalRHub<TLogger>(TLogger logger) : Hub where TLogger : IAcLoggerBase /// <summary>
/// Back-compat: az eredeti egy-generikusos alak a szerver-oldali <see cref="AcLogItem"/> wire-típussal —
/// a nem-generikus (JSON-os) <c>AcSignaRClientLogItemWriter</c> kliensek párja.
/// </summary>
public class AcLoggerSignalRHub<TLogger>(TLogger logger) : AcLoggerSignalRHub<TLogger, AcLogItem>(logger)
where TLogger : IAcLoggerBase;
/// <summary>
/// Kliens-log fogadó hub, generikus wire-típussal. A <typeparamref name="TLogItem"/>-nek meg kell egyeznie
/// a kliens-oldali <c>AcSignaRClientLogItemWriter&lt;TLogItem&gt;</c> típusparaméterével — a SignalR erre a
/// paraméter-típusra deserializál (AcBinary-nál a generált serializere fut, polymorph-dispatch nélkül).
/// </summary>
public class AcLoggerSignalRHub<TLogger, TLogItem>(TLogger logger) : Hub
where TLogger : IAcLoggerBase
where TLogItem : class, IAcLogItemClient
{ {
private TLogger _logger = logger; private TLogger _logger = logger;
@ -25,7 +39,7 @@ public class AcLoggerSignalRHub<TLogger>(TLogger logger) : Hub where TLogger : I
await base.OnDisconnectedAsync(exception); await base.OnDisconnectedAsync(exception);
} }
public void AddLogItem(AcLogItem? logItem) public void AddLogItem(TLogItem? logItem)
{ {
try try
{ {
@ -47,7 +61,8 @@ public class AcLoggerSignalRHub<TLogger>(TLogger logger) : Hub where TLogger : I
} }
catch (Exception ex) catch (Exception ex)
{ {
Console.WriteLine($@"ERROR!!! {nameof(AcLoggerSignalRHub<TLogger>)}->AddLogItem; ex: {ex.Message}{AcEnv.NL}{AcEnv.NL}{ex}"); Console.WriteLine($@"ERROR!!! {nameof(AcLoggerSignalRHub<TLogger, TLogItem>)}->AddLogItem; ex: {ex.Message}{AcEnv.NL}{AcEnv.NL}{ex}");
} }
} }
} }

View File

@ -1,13 +1,33 @@
using AyCode.Core.Enums; using AyCode.Core.Enums;
using AyCode.Core.Helpers; using AyCode.Core.Helpers;
using AyCode.Core.Loggers; using AyCode.Core.Loggers;
using AyCode.Entities; using AyCode.Entities;
using AyCode.Entities.LogItems; using AyCode.Entities.LogItems;
using AyCode.Services.SignalRs;
using Microsoft.AspNetCore.SignalR.Client; using Microsoft.AspNetCore.SignalR.Client;
namespace AyCode.Services.Loggers namespace AyCode.Services.Loggers
{ {
public class AcSignaRClientLogItemWriter : AcLogItemWriterBase<AcLogItemClient>, IAcLogWriterClientBase /// <summary>
/// Nem-generikus, JSON-protokollos alak — back-compat a meglévő fogyasztóknak
/// (wire-típus: AcLogItemClient; a szerver-oldali párja az AcLoggerSignalRHub&lt;TLogger&gt; shim).
/// </summary>
public class AcSignaRClientLogItemWriter : AcSignaRClientLogItemWriter<AcLogItemClient>
{
public AcSignaRClientLogItemWriter(string fullHubName, AppType appType = AppType.Web, LogLevel logLevel = LogLevel.Detail, string? categoryName = null)
: base(fullHubName, appType, logLevel, categoryName)
{ }
}
/// <summary>
/// SignalR log-item feltöltő writer, generikus wire-típussal. A <typeparamref name="TLogItem"/>-et az
/// alkalmazás adja (pl. FruitBank: FbLogItem [AcBinarySerializable] — így a csatorna AcBinary-protokollal mehet;
/// a generált serializer az app rétegében él, az AyCode.Entities generator-mentes marad).
/// Az opcionális acBinaryProtocolOptions-szel a kapcsolat az AcBinary protokollt használja;
/// enélkül a SignalR default JSON-ja megy (back-compat).
/// </summary>
public class AcSignaRClientLogItemWriter<TLogItem> : AcLogItemWriterBase<TLogItem>, IAcLogWriterClientBase
where TLogItem : class, IAcLogItemClient
{ {
private readonly HubConnection _hubConnection; private readonly HubConnection _hubConnection;
private readonly string _fullHubName; private readonly string _fullHubName;
@ -19,14 +39,20 @@ namespace AyCode.Services.Loggers
private bool _connectedReported; private bool _connectedReported;
private long _droppedCount; private long _droppedCount;
public AcSignaRClientLogItemWriter(string fullHubName, AppType appType = AppType.Web, LogLevel logLevel = LogLevel.Detail, string? categoryName = null) : base(appType, logLevel, categoryName) public AcSignaRClientLogItemWriter(string fullHubName, AppType appType = AppType.Web, LogLevel logLevel = LogLevel.Detail, string? categoryName = null, AcBinaryHubProtocolOptions? acBinaryProtocolOptions = null) : base(appType, logLevel, categoryName)
{ {
_fullHubName = fullHubName; _fullHubName = fullHubName;
_hubConnection = new HubConnectionBuilder() // VISSZACSATOLÁS-VÉDELEM: erre a builderre TILOS app-loggert kötni (AddAcDefaults / ConfigureLogging) —
.WithUrl(fullHubName) // a protokoll saját logja a feltöltőn át újra ide érkezne (log → sorosítás → log → … robbanó hurok).
// AcBinary-nál ezért a hívó az opciókban EXPLICIT süket loggert adjon (pl. NullLogger.Instance),
// hogy az AddAcBinaryProtocol ??= DI-fallbackje se tölthesse fel.
var hubBuilder = new HubConnectionBuilder().WithUrl(fullHubName);
if (acBinaryProtocolOptions != null) hubBuilder.AddAcBinaryProtocol(acBinaryProtocolOptions);
_hubConnection = hubBuilder
//.WithAutomaticReconnect() //.WithAutomaticReconnect()
//.AddMessagePackProtocol(options => options.SerializerOptions = MessagePackSerializerOptions.Standard.WithSecurity(MessagePackSecurity.UntrustedData))
.Build(); .Build();
StartConnection().Forget(); StartConnection().Forget();
@ -67,7 +93,7 @@ namespace AyCode.Services.Loggers
public override void Write(AppType appType, LogLevel logLevel, string? logText, string? callerMemberName, string? categoryName, string? errorType, string? exMessage) public override void Write(AppType appType, LogLevel logLevel, string? logText, string? callerMemberName, string? categoryName, string? errorType, string? exMessage)
=> WriteLogItem(CreateLogItem(DateTime.UtcNow, appType, Environment.CurrentManagedThreadId, logLevel, logText, callerMemberName, categoryName, errorType, exMessage)); => WriteLogItem(CreateLogItem(DateTime.UtcNow, appType, Environment.CurrentManagedThreadId, logLevel, logText, callerMemberName, categoryName, errorType, exMessage));
protected override async void WriteLogItemCallback(AcLogItemClient logItem) protected override async void WriteLogItemCallback(TLogItem logItem)
{ {
// Teljes try/catch: async void — egy StartAsync/SendAsync-kivétel különben kezeletlenül szökne el. // Teljes try/catch: async void — egy StartAsync/SendAsync-kivétel különben kezeletlenül szökne el.
try try
@ -117,4 +143,6 @@ namespace AyCode.Services.Loggers
_droppedCount = 0; _droppedCount = 0;
} }
} }
} }

File diff suppressed because one or more lines are too long

View File

@ -89,7 +89,7 @@ See `SIGNALR_TODO.md#accore-sig-t-m5l6`.
### Related ### Related
- `../../../AyCode.Core/docs/LOGGING/LOGGING_ISSUES.md#accore-log-i-m4c9` (sibling gap — same plugin, logger setup) - `../../../AyCode.Core/docs/LOGGING/LOGGING_ISSUES.md#accore-log-i-m4c9` (sibling gap — same plugin, logger setup)
- `ACCORE-SIG-I-K6F1` (client-side equivalent — `HubConnectionBuilder.Services` inner DI isolation forces a different workaround) - `ACCORE-SIG-I-K6F1` (client-side equivalent — `HubConnectionBuilder.Services` inner DI isolation forces a different workaround)
- Plugin doc drift: `Nop.Plugin.Misc.AIPlugin/docs/SIGNALR/README.md:22` documents `services.AddSingleton<IHubProtocol>(new AcBinaryHubProtocol())` — the actual code uses `.AddAcBinaryProtocol(opts => {...})`. Doc needs a rewrite. - Plugin doc drift: `Nop.Plugin.Misc.AIPlugin/docs/SIGNALR/README.md:22` documents `services.AddSingleton<IHubProtocol>(new AcBinaryHubProtocol())` — the actual code uses `.AddAcBinaryProtocol(opts => {...})`. **Resolved 2026-07-13** — plugin-README rewritten (AddAcBinaryProtocol; json+acbinary side-by-side registration; hub list corrected).
## Client-side Setup & DI ## Client-side Setup & DI

View File

@ -8,6 +8,17 @@
--- ---
## ACCORE-SBP-T-T5R2: Per-üzenet diagnosztikai sorok átsorolása Trace szintre
**Priority:** P2 · **Type:** Behaviour / zajcsökkentés · **Related:** `../../../AyCode.Core/docs/LOGGING/LOGGING_TODO.md#accore-log-t-d7s3`
**Probléma:** a protokoll soronkénti diagnosztikája túl magas szinten logol — `Serialize/Deserialize start/end` = **Info**, `WriteArgument`/`ReadSingleArgument`/`ReadArguments`/`ParseInvocation`/`TryParseMessage` = **Debug/Trace**. Következmény: a szerver-konzolt elárasztja (a loggerHub-on MINDEN felküldött log-item ~8 protokoll-sort termel; az fbHub-forgalom ugyanígy), és egy leendő kliens-oldali protokoll-diagnosztika (ACCORE-LOG-T-D7S3) default szinten spammelne.
**Megoldás:** a per-üzenet sorok `LogTrace`-re; hiba/anomália marad Warning/Error. A `Serialize end totalSentSize=…` jellegű összegző sorok szintje mérlegelendő (Debug-on hagyva olcsó forgalmi áttekintést adnak).
**Ellenőrzendő:** az MS→AyCode szint-megfeleltetés az `AddAcLogger` hídban — a konzol-kimenet alapján MS `Trace` jelenleg Ac `Detail(0)`-ra képződik (a TryParseMessage-sorok `[Detail]`-lel jelennek meg), az Ac-enumban pedig `Detail(0) < Trace(5)`, tehát egy Detail-szintű writer a Trace-t IS átengedi. A „csend default szinten" célhoz a fogyasztó loggerek Debug(10)+ szintje és/vagy a mapping tisztázása kell.
**Érintett:** `AcBinaryHubProtocol` `Log*` segédmetódusai + `DebugLogArgument`.
## ACCORE-SBP-T-Y2R8: Per-message protocol mode selection ## ACCORE-SBP-T-Y2R8: Per-message protocol mode selection
**Priority:** P2 · **Type:** Feature **Priority:** P2 · **Type:** Feature