65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 SignalR 2.0 流式传输日志

starIconstarIconstarIconstarIconstarIcon

5.00/5 (6投票s)

2014年4月14日

CPOL

4分钟阅读

viewsIcon

34497

downloadIcon

1222

实现 NLog 日志记录和 SignalR。

引言

有时你需要从你的网站读取在线日志流,但你并不总是有 FTP 访问权限来访问日志文件,或者有 Visual Studio 来附加到进程并读取调试输出。

在本文中,我们将使用 SignalR 和 NLog 将日志事件发送到 Web 浏览器。

背景

在很多情况下,你需要在线访问你的日志。在我的例子中,我有一个 webservice,它启动长时间运行的后台进程。此进程在进行时生成日志事件。我没有处理进度报告,而是决定扩展我的日志记录系统并将日志发送到浏览器。

SignalR 是一个 ASP.NET 框架,可以轻松开发实时 Web 应用程序。 SignalR 支持 WebSockets,但如果不支持 WebSockets,则会回退到其他兼容技术。 对我们来说重要的是它允许服务器将内容推送到连接的客户端/浏览器。

NLog 是 .NET 的日志记录平台。 它支持数十个日志目标(文件、事件日志、数据库、电子邮件等)。 最重要的是,任何开发人员都可以编写自定义目标。 它也部分兼容 Log4Net。

此示例使用使用 SignalR 实现日志流的最简单方法。

使用代码

服务器部分

通过 SignalR 2.0 添加日志记录是一个简单的过程。 唯一的要求是 .NET 4.5。 更改代码以使用 SignalR 1.0 将允许你使用 .NET 4.0。 附加的代码使用 Web Forms,但 SignalR 和 NLog 都可以与 MVC 一起使用,作为网站和 Web 应用程序。

首先,你需要添加 SignalR 和 NLog nuget 包。 这是一个简单且自动的步骤。 然后你需要添加 SignalR 启动类。 这设置了 SignalR 管道所需的所有配置。

[assembly: OwinStartup(typeof(SignalRStartup))]
public class SignalRStartup
{
    public void Configuration(IAppBuilder app)
    {
        app.MapSignalR();
    }
} 

SignalR 使用所谓的 HUB 向客户端提供服务。 日志记录是一个单向过程,因此我们只需要将数据从服务器传输到客户端,而不是反过来。 为了更容易调试,有一个 Hello 方法,稍后可以更改该方法以实现(取消)订阅特定日志级别。

public class SignalRTargetHub : Hub
{
    public void Hello()
    {
        this.Clients.Caller.logEvent(
            DateTime.UtcNow.ToLongTimeString(),
            "info",
            "SignalR connected");
    } 

    static IHubContext signalRHub;
    public static void Send(string longdate, string logLevel, String message)
    {
        if (signalRHub == null)
        {
            signalRHub = GlobalHost.ConnectionManager.GetHubContext<SignalRTargetHub>();
        }
        if (signalRHub != null)
        {
            signalRHub.Clients.All.logEvent(longdate, logLevel, message);
        }
    }
}

NLog 支持开箱即用的 MethodCallTarget。 这允许我们将数据从日志记录系统传递回我们的代码。 此目标可以使用任意数量的参数调用任何静态方法。 在我们的例子中,被调用的方法是 SignalRTargetHub.Send(longdate, logLevel, message)。 我们不能简单地创建 SignalRTargetHub 的新实例,但我们必须在 ConnectionManager 中找到上下文。 该上下文可用于将数据发送到连接的客户端。 如果找到上下文,我们会在所有连接的客户端上调用 javascript logEvent 函数。

Hello 方法仅用于更轻松的调试。 一旦客户端连接,浏览器就会调用 Hello 方法,服务器会使用字符串“SignalR 已连接”进行响应(调用调用者的 javascript 方法)。 这不是必需的,但稍后可以扩展并用于客户端注册。

客户端部分

唯一剩下的部分是客户端/浏览器的代码。 SignalR 自动生成 javascript 对象以访问 hub 方法。 此自动生成的 javascript 可以从 /signalr/hubs 下载。

<script src="/Scripts/jquery-1.6.4.min.js"></script>
<script src="/Scripts/jquery.signalR-2.0.3.min.js"></script>
<script src="/signalr/hubs"></script>
<script>
    $(function () {
        var logTable = $("#logTable");

        var nlog = $.connection.signalRTargetHub;

        nlog.client.logEvent = function (datetime, logLevel, message) {
            var tr = $("<tr>");
            tr.append($("<td>").text(datetime));
            tr.append($("<td>").text(logLevel));
            tr.append($("<td style='white-space: pre;'>").text(message));
            logTable.append(tr);
        };

        $.connection.hub.start().done(function () {
            nlog.server.hello();
        });
    });
</script>
<table id="logTable">
</table> 

请注意 logEvent 函数定义。 每当 ASP.NET 调用方法 signalRHub.Clients.All.logEvent 时,都会从服务器调用此函数。

测试它

我们将向 global.asax 添加错误处理方法。 此方法将记录所有应用程序错误(例如,对不存在的网页的请求)

void Application_Error(object sender, EventArgs e)
    {
        Exception lastException = Server.GetLastError();
        NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
        logger.Fatal("Request: '{0}'\n Exception:{1}", HttpContext.Current.Request.Url, lastException);
    } 

现在我们可以加载 Log.aspx 网页并将第二个请求发送到一些随机页面。 在第一行,你将看到来自 Hello 方法的响应 - “SignalR 已连接”。

.

总结所有步骤

  • 将 SignalR nuget 包添加到你的项目 (Microsoft.AspNet.SignalR)
  • 添加 NLog nuget 包
  • 添加 SignalRStartup.cs
  • 添加 SignalRTargetHub.cs
  • 更新你的 web.config (nlogconfigSections)
  • 添加 Log.aspx 页面
  • 添加 global.asax

Hub 方法 Hello 不是必需的。它只是将第一个记录返回到你的网页。 你可以使用它来扩展你的 hub - 例如,允许用户仅注册某些级别的日志记录 - 检查 SignalR 对组的支持 - http://www.asp.net/signalr/overview/signalr-20/hubs-api/working-with-groups

要考虑的未来任务

© . All rights reserved.