简体   繁体   English

获取 SignalR 连接启动错误堆栈

[英]Getting SignalR connection startup error stack

How can I get the full stack of an exception that's happening in an otherwise functioning Web application during SignalR connection setup?如何在 SignalR 连接设置期间获取其他功能正常的 Web 应用程序中发生的异常的完整堆栈?

Background背景

I'm part of a team maintaining a Web application with C# clients that uses an extremely basic SignalR setup (version 2.2) to effectively deliver push notifications about progress during long-running server processes.我是维护带有 C# 客户端的 Web 应用程序的团队的一员,该应用程序使用极其基本的 SignalR 设置(版本 2.2)在长时间运行的服务器进程期间有效地提供有关进度的推送通知。 Like, out-of-the-box,就像,开箱即用,

app.MapSignalR();
HubConnection connection = new HubConnection(_applicationConfiguration.ApiBaseUri + "/signalr");
await connection.Start();

basic.基本的。 Some of our clients run on remoting services and periodically run into an issue where the other functions of the Web application work fine, but the client code that calls connection.Start() returns a 500 internal server error with no further information.我们的一些客户端在远程服务上运行,并定期遇到 Web 应用程序的其他功能正常工作的问题,但调用connection.Start()的客户端代码返回 500 内部服务器错误,没有进一步的信息。 They can address it by refreshing the remote connection but this is less than ideal, so I'm trying to get some information about where in the connection setup process this error is happening.他们可以通过刷新远程连接来解决它,但这不太理想,所以我试图获取一些有关连接设置过程中发生此错误的位置的信息。

Problem问题

Following the information about setting up error handling for SignalR on MSDN , I've tried to simulate the problem by inserting the following pipeline module into the GlobalHost.HubPipeline : 继有关设置错误处理SignalR MSDN上的信息,我试图模拟通过插入下面的管道模块插入问题GlobalHost.HubPipeline

public class HubErrorHandlingModule : HubPipelineModule
  {
    public override Func<IHub, Task> BuildConnect(Func<IHub, Task> connect)
    {
      throw new InvalidOperationException("Testing Connection Exceptions");
    }

    protected override void OnIncomingError(ExceptionContext exceptionContext, 
      IHubIncomingInvokerContext invokerContext)
    {
      // some logging happens here
      base.OnIncomingError(exceptionContext, invokerContext);
    }
  }

and it kind of works, in that I can see the exception get thrown in the pipeline code, and my test C# client is also seeing a 500 internal server error with no further information.它有点工作,因为我可以看到在管道代码中抛出异常,并且我的测试 C# 客户端也看到 500 内部服务器错误,没有更多信息。

But it also kind of doesn't work, in that I've dropped in breakpoints and the OnIncomingError code is never hit.但它也有点不起作用,因为我已经放弃了断点并且 OnIncomingError 代码从未被命中。 That sort of makes sense, since it's not code in any Hub method that's causing the exception, but I don't know where this exception is happening;这样说是有道理的,因为它不是导致异常的任何 Hub 方法中的代码,但我不知道这个异常发生在哪里; it could be anywhere during the client call to connection.Start .它可以在客户端调用connection.Start期间的任何位置。

I've also tried passing in an alternate HubConfiguration with EnableDetailedErrors = true but that doesn't seem to improve anything.我也尝试过使用EnableDetailedErrors = true传入备用HubConfiguration但这似乎没有任何改善。

It doesn't really matter where I get the full stack trace, since I control both the server and the client code, but in order to understand their problem I need to see the full trace somewhere .从哪里获得完整的堆栈跟踪并不重要,因为我同时控制服务器和客户端代码,但是为了理解他们的问题,我需要在某处查看完整的跟踪。

What I've Tried And Why It Doesn't Work我尝试过的方法以及为什么它不起作用

app.MapSignalR(new HubConfiguration { EnableDetailedErrors = true });

I think this is meant to show detailed errors from Hub processing, not connection handshaking?我认为这是为了显示Hub处理中的详细错误,而不是连接握手? Supposedly it's meant to send a message tagged as an error that might be traced by the connection even if it's never bubbled up to any consumer.据说它的目的是发送一条标记为错误的消息,即使它从未冒泡给任何消费者,也可能会被连接跟踪。 Unfortunately...很遗憾...

var writer = new StreamWriter("C:\\Logs\\ClientLog.txt");
writer.AutoFlush = true;
connection.TraceLevel = TraceLevels.All;
connection.TraceWriter = writer;

This does trace successful communication to the SignalR backend, once I remove the deliberate pipeline error.一旦我删除了故意的管道错误,这会跟踪到 SignalR 后端的成功通信。 But when I set it back up, all I see is a failed attempt to establish the connection and a 500 internal server error.但是当我重新设置它时,我看到的只是建立连接的失败尝试和 500 内部服务器错误。 No trace.没有踪迹。

<system.diagnostics>
  <sharedListeners ... >
  <switches ...>
  <sources ...>
  <trace autoflush="true" />
</system.diagnostics>

Set up both after the MSDN trace details and this commentary on GitHub . 在 MSDN 跟踪详细信息GitHub 上的此评论之后进行设置。 Neither set of details works.两组细节都不起作用。 As I play around by moving the pipeline exception to different pipeline events, I can sometimes see a stack trace show up in the SignalR.HubDispatcher source mentioned only in the GitHub details, but it happens when I throw the exception after the connection's been established and what arrives at the client side is a different error than just a 500 internal server error, so that's probably happening too late to be whatever's going wrong at the client installation.当我将管道异常移动到不同的管道事件时,我有时会看到仅在 GitHub 详细信息中提到的 SignalR.HubDispatcher 源中显示堆栈跟踪,但是当我在建立连接后抛出异常时会发生这种情况,并且到达客户端的是一个不同的错误,而不仅仅是 500 个内部服务器错误,所以这可能发生得太晚了,以至于客户端安装出了什么问题。

In my case I have to put the SignalR.cs in my root path .在我的情况下,我必须将 SignalR.cs 放在我的根路径中

在此处输入图片说明

Then in the view I include the script:然后在视图中包含脚本:

<script src="~/signalr/hubs"></script>

This is what my SignalR.cs looks like:这是我的 SignalR.cs 的样子:

public class NotificationHub : Hub
{
    public void SendUpdateNotification(string message)
    {
        // message = "show" / "hide"
        if (message.Equals("show"))
            Config._MaintenanceMode = true;
        else
            Config._MaintenanceMode = false;

        // Call the broadcastUpdate method to update clients.
        Clients.All.broadcastUpdate(message);
    }
}

To handle errors that SignalR raises, you can add a handler for the error event on the connection object要处理 SignalR 引发的错误,您可以为连接对象上的错误事件添加处理程序

connection.Error += ex => Console.WriteLine("SignalR error: {0}", ex.StackTrace);

To handle errors from method invocations, wrap the code in a try-catch block.要处理来自方法调用的错误,请将代码包装在 try-catch 块中。

HubConnection connection = new HubConnection(_applicationConfiguration.ApiBaseUri + "/signalr");
try
{   
    await connection.Start(); 
}
catch (Exception ex)
{
    Console.WriteLine("Error " + ex);
}

To enable detailed error messages for troubleshooting purposes,要启用详细的错误消息以进行故障排除,

var hubConfiguration = new HubConfiguration();
hubConfiguration.EnableDetailedErrors = true;
App.MapSignalR(hubConfiguration);

In your code the hub pipeline module I do not see you are logging/printing the error在您的代码中,集线器管道模块我没有看到您正在记录/打印错误

Console.WriteLine("Exception " + exceptionContext.Error.Message);
base.OnIncomingError(exceptionContext, invokerContext);

and now hook up the custom HubPipelineModule we've created, this is achieved in the startup class现在连接我们创建的自定义 HubPipelineModule,这是在启动类中实现的

public partial class Startup
{
    public void Configuration(IAppBuilder app)
    {
        GlobalHost.HubPipeline.AddModule(new HubErrorHandlingModule());

        app.MapSignalR();
    }
}

References:参考:

SignalR Notify user about disconnections SignalR 通知用户断开连接
SingalR How to Handle Errors SingalR 如何处理错误
SignalR 500 Internal Server Error SignalR 500 内部服务器错误

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM