我正在努力将 SignalR 集成到 AspNetCore 项目正在使用的错误/异常日志记录包中。
日志记录包提供了两种记录错误的方法:
ICustomLogger
接口,然后调用_customLogger.LogError(...)
IApplicationBuilder.UseExceptionHandler
自动通过已注册的异常处理程序来构造自定义记录器的实例,然后调用与上面类似的 .LogError(...)
为了测试此功能,我在使用此包的项目中创建了 3 个端点:
/UnhandledException
:
internal static async Task TestUnhandledException()
{
//caught by the exception handler mentioned above
//logs the error and a message is received in the in the front-end by signal r
//no issues
throw new NotImplementedException();
}
/SendMessage
:
public static async Task SendSignalRMessage(IHubContext<CustomLogger.SignalR.EventHub> hubContext)
{
//uses the dependency-injected event hub from package
//does not call any functions from CustomLogger
//no issues
await hubContext.Clients.All.SendAsync("NewEvent", "Hello");
}
/ExplicitTest
:
internal static async Task Test(ICustomLogger logger)
{
//relies on injected CustomLogger receiving an injected IHubContext<EventHub>
//performs logging successfully but signalr message is not received in front-end
//issues!
var a = await logger.LogEventAsync(LogLevel.Info, "Manual event", "Is this message sent?");
}
EventHub
通过以下方式在使用项目的Program.cs中注册:
app.UseEndpoints(ep => ep.MapHub<EventHub>("/Events"));
自定义日志记录包包括:
public class CustomLogger
{
private readonly IHubContext<EventHub> hubContext;
public EventLogger(IOptionsSnapshot<LoggerSettings> settings, IHubContext<EventHub> hubContext)
{
this.hubContext = hubContext;
}
//Snip boring code that does actual logging
private async Task SendEventAsync(Event evt)
{
if (this.hubContext == null)
{
await this.LogEventAsync(LogLevel.Warning, "Configuration Error", "SignalR hub context is null");
return;
}
var eventData = new NewEvent
{
EventId = evt.EventId,
TimeStamp = evt.TimeStamp,
Message = evt.Message,
};
try
{
await this.hubContext.Clients.All.SendAsync(MessageType.NewEvent, eventData);
}
catch (Exception ex)
{
await this.LogExceptionAsync(LogLevel.Warning, ex);
}
}
}
如您所见,调用函数来手动记录数据(在非工作的 /ExplicitTest 端点中)需要依赖项包中的依赖项注入
ICustomLogger
,其构造函数需要依赖项注入 IHubContext<EventHub>
。包内的实际日志记录将成功运行,并且在暂停调试器时,我可以看到注入的 ICustomLogger
有一个 IHubContext
和 1 个活动连接。尝试向连接的客户端发送消息时似乎没有抛出异常,但未收到消息。
以下:
isc.AddDbContext<AppDbContext>(options =>
{
var connection = new SqliteConnection("DataSource=:memory:");
connection.Open();
options.UseSqlite(connection);
});
将导致多次创建新连接,并且默认情况下 SQLite 内存中不共享。有多种选项可以解决此问题,例如只需将连接创建移到 lambda 之外:
var connection = new SqliteConnection("DataSource=:memory:");
connection.Open();
isc.AddDbContext<AppDbContext>(options =>
{
options.UseSqlite(connection);
});