WebAPI+SignalR实现实时日志监测

在最近的一篇博文中描述了使用NLog记录WebAPI的调用日志,但是也发现在实际使用中由诸多不便。日志只有在生成后才能查看,能否在接口调用的同时就看到呢?结合使用SignalR可以实现这种可能。

本文会在之前的两篇文章基础上进行讲解:
WebAPI+NLog实现日志输出
WebAPI集成SignalR


思路

第三方程序调用API接口时会触发日志跟踪,如果在此时将日志内容通过SignalR广播出去,并由一个Web页面接收显示,那么就能实现接口调用的实时监听。

这里写图片描述

实现

改造SignalR

首先我们希望能够为日志监听单独开辟一条“通道”,以便不受到其他通道的影响。同时考虑到日志消息的发送是“广播”,与Client无关,所以采用持久连接PersistentConnection来做这件事情。
添加我们的日志广播通道LogTracer.cs,并继承于PersistentConnection:

    public class LogTracer : PersistentConnection
    {
        //protected override Task OnConnected(IRequest request, string connectionId)
        //{
        //    return Connection.Send(connectionId, "Welcome!");
        //}

        //protected override Task OnReceived(IRequest request, string connectionId, string data)
        //{
        //    return Connection.Broadcast(data);
        //}
    }

这个类不需要添加任何代码,要做的仅仅是在Startup类中对它进行配置。

这里写图片描述

这样一条专为日志广播的通道就建好了。

改造NLog日志类

在之前的文章WebAPI+NLog实现接口日志输出中,日志的写入是在AppLog类中完成的,我们只需要在日志写入前或写入后将日志内容广播出去就行了。
在AppLog中引入上一步创建的持久连接:

//持久连接--日志监听
private static IPersistentConnectionContext connectContext = GlobalHost.ConnectionManager.GetConnectionContext<Hubs.LogTracer>();

在日志内容被写入文件之前,将其通过持久连接广播出去(添加在函数Log中):
这里写图片描述

页面展示

显示实时日志的页面实质上就是SignalR的Web客户端。
在项目中添加一个MVC控制器LogController,同时在Views目录下会创建Log目录以及Index.cshtml。
为Index.cshtml添加js引用:

    <script src="~/Scripts/jquery-1.10.2.min.js"></script>

    <script src="~/Scripts/jquery.signalR-2.2.1.js"></script>

定义持久连接代理以及连接、断开的方法:

            var listener = $.connection('/LogTracer');
            //开启连接
            function startConnection() {
                //stopConnection();
                listener.start().fail(function () {
                    $('#_messageList').append('<li>监听启动失败!</li>');
                }).done(function () {
                    $('#_messageList').append('<li>监听已启动...</li>');
                });
                listener.received(function (message) {

                    $('#_messageList').append('<li>' + message + '</li>');

                });
            }

            //断开连接
            function stopConnection() {
                if(listener!=null){
                    listener.stop();
                }
            };

页面全部代码如下:

@{
    ViewBag.Title = "系统日志";
}
<h2>实时日志</h2>
<p>
    @Html.ActionLink("历史日志","History")
</p>
<div>
    <input type="button" id="_start" value="开始监听" />
    <input type="button" id="_stop" value="停止监听" />
    <input type="button" id="_clear" value="清空记录" />
</div>
<div>
    <ul id="_messageList"></ul>
</div>

@section scripts{
    <script src="~/Scripts/jquery-1.10.2.min.js"></script>

    <script src="~/Scripts/jquery.signalR-2.2.1.js"></script>
    <script>

        //隐藏
        $("#tbLog").hide();

        $(function () {
            var startBtn = $('#_start');
            var stopBtn = $('#_stop');
            var listener = $.connection('/LogTracer');

            enable(stopBtn, false);
            enable(startBtn, true);

            //启动
            startBtn.click(function () {
                startConnection();
                enable(stopBtn, true);
                enable(startBtn, false);
            });

            //停止
            stopBtn.click(function () {
                stopConnection();
                enable(startBtn, true);
                enable(stopBtn, false);
                $('#_messageList').append('<li>监听已停止...</li>');
            });

            //清空列表
            $('#_clear').click(function () {
                $('#_messageList').children().remove();

            });

            //开启连接
            function startConnection() {
                //stopConnection();
                listener.start().fail(function () {
                    $('#_messageList').append('<li>监听启动失败!</li>');
                }).done(function () {
                    $('#_messageList').append('<li>监听已启动...</li>');
                });
                listener.received(function (message) {

                    $('#_messageList').append('<li>' + message + '</li>');

                });
            }

            //断开连接
            function stopConnection() {
                if(listener!=null){
                    listener.stop();
                }
            };

            //按钮切换
            function enable(button,enabled) {
                if (enabled) {
                    button.removeAttr("disabled");
                }
                else {

    button.attr("disabled", "disabled");

  }

            }

        });



    </script>
}

效果

完成上述改造后,运行项目,在系统日志页面启动日志监听,当API接口被调用时,就可以实时监测了。效果如下:

这里写图片描述

另外又增加了一个历史日志的查询界面(日志文件保存在指定目录下,读取文件内容展示在界面上即可),效果如下:

这里写图片描述


通过这次思考及实现,发现将不同的技术点融合后会有许多不错的结果,期待后面能发现更多有趣的事情。

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值