NLog自定義Target之MQTT

NLog是.Net中最流行的日志記錄開源項目(之一),它靈活免費開源

官方支持文件網絡(TCP、UDP)、數據庫控制臺等輸出

社區支持ElasticSeq等日志平臺輸出

實時日志需求

在工業物聯網等特定場景下需要實時獲取日志信息

工業物聯網領域常用的是mqtt協議

那我們就使用NLog?自定義一個Target,將日志輸出到MqttServer

Web通過Mqtt(websocket)實時獲取日志,而不是傳統的通過WebApi輪詢日志

f9520f2213ed1c70cd33680cbdc6c6cc.gif

NLog自定義Target

  1. 官方文檔介紹了如何自定義Target,可以獲取到一串日志消息,無法獲取結構化消息

  2. 需要使用自定義Field來完成這部分工作

///?<summary>
///?Additional?field?details
///?</summary>
[NLogConfigurationItem]
public?class?Field
{///?<summary>///?Name?of?additional?field///?</summary>[RequiredParameter]public?string?Name?{?get;?set;?}///?<summary>///?Value?with?NLog?<see?cref="NLog.Layouts.Layout"/>?rendering?support///?</summary>[RequiredParameter]public?Layout?Layout?{?get;?set;?}///?<summary>///?Custom?type?conversion?from?default?string?to?other?type///?</summary>///?<remarks>///?<see?cref="System.Object"/>?can?be?used?if?the?<see?cref="Layout"/>?renders?JSON///?</remarks>public?Type?LayoutType?{?get;?set;?}?=?typeof(string);///?<inheritdoc?/>public?override?string?ToString(){return?$"Name:?{Name},?LayoutType:?{LayoutType},?Layout:?{Layout}";}
}
  1. 重寫Write方法

protected?override?void?Write(LogEventInfo?logEvent)
{//default?fieldsDictionary<string,?object>?logDictionary?=?new(){{?"timestamp",?logEvent.TimeStamp?},{?"level",?logEvent.Level.Name?},{?"message",?RenderLogEvent(Layout,?logEvent)?}};//customer?fields//這里都處理為字符串了,有優化空間foreach?(var?field?in?Fields){var?renderedField?=?RenderLogEvent(field.Layout,?logEvent);if?(string.IsNullOrWhiteSpace(renderedField))continue;logDictionary[field.Name]?=?renderedField;}SendTheMessage2MqttBroker(JsonConvert.SerializeObject(logDictionary));
}

使用

下面將使用Nlog.Target.MQTT,演示通過web實時查看應用程序的日志

  1. 創建WebApi項目

  2. 引用NLog.Target.MQTT

003663326f0a3049cf73cb7ae5e34ac4.png

  1. 配置文件

<extensions><add?assembly="NLog.Web.AspNetCore"/><!--<add?assembly="NLog.Targets.MQTT"/>--><add?assembly="NLog.Targets.MQTT"/>
</extensions>
<!--?the?targets?to?write?to?-->
<targets><!--?MQTT?Target??--><target?xsi:type="MQTT"?name="mqtt"?host="localhost"?port="1883"?username="UserName"??password="Password"?topic="log"layout="${longdate}|${event-properties:item=EventId_Id:whenEmpty=0}|${level:uppercase=true}|${logger}|${message}?${exception:format=tostring}|url:?${aspnet-request-url}|action:?${aspnet-mvc-action}|${callsite}"?><field?name="machine"?layout="${machinename}"?/><field?name="processid"?layout="${processid}"?/><field?name="threadname"?layout="${threadname}"?/><field?name="logger"?layout="${logger}"?/><field?name="callsite"?layout="${callsite-linenumber}"?/><field?name="url"?layout="${aspnet-request-url}"?/><field?name="action"?layout="${aspnet-mvc-action}"?/><field?name="level"?layout="${level:uppercase=true}"?/><field?name="message"?layout="${message}"?/><field?name="exception"?layout="${exception:format=toString}"?/></target>
</targets>
<!--?rules?to?map?from?logger?name?to?target?-->
<rules><logger?name="*"?minlevel="Trace"?writeTo="mqtt"?/>
</rules>
  1. 配置MQTTServer和NLog

//?...
//?NLog:?Setup?NLog?for?Dependency?injection
builder.Logging.ClearProviders();
builder.Logging.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Trace);
builder.Host.UseNLog();//AddHostedMqttServer
builder.Services.AddHostedMqttServer(mqttServer?=>{mqttServer.WithoutDefaultEndpoint();}).AddMqttConnectionHandler().AddConnections();//Config?Port
builder.WebHost.UseKestrel(option?=>
{option.ListenAnyIP(1883,?l?=>?l.UseMqtt());option.ListenAnyIP(80);
});
var?app?=?builder.Build();//?...
//UseStaticFiles?html?js?etc.
app.UseStaticFiles();
app.UseRouting();//Websocket?Mqtt
app.UseEndpoints(endpoints?=>
{//MqttServerWebSocketendpoints.MapConnectionHandler<MqttConnectionHandler>("/mqtt",?options?=>{options.WebSockets.SubProtocolSelector?=?MqttSubProtocolSelector.SelectSubProtocol;});
});
//?...
  1. Web連接MqttServer

//?...????
<script?src="./jquery.min.js"></script>
<script?src="./mqtt.min.js"></script>
<script?src="./vue.js"></script>
//?...var?client?=?mqtt.connect('ws://'?+?window.location.host?+?'/mqtt',?options);
client.on('connect',function()?{client.subscribe('log',function(err)?{if?(!err)?{console.log("subed!");}?else?{alert("subed?error!");}});});
client.on('message',function(topic,?message)?{if?(topic?===?'log')?{if?(app.logs.length?>?50)app.logs.length?=?0;app.logs.unshift($.parseJSON(message.toString()));}});
//?...
  1. 輸出日志

//?...??
_logger.LogDebug("LogDebug!");
_logger.LogError(new?Exception("Exception?Message!"),?"LogError!");//new?thread?output?log?after?500ms
Thread?thread?=?new?Thread(ThreadProc);
thread.Name?=?"My?Thread";
thread.Start();
//?...
  1. 實時查看日志 訪問/index.html

604f30ca44d884e5298808c0a617b89e.png

8. 也可以通過Mqtt客戶端訂閱日志?

0e794d921b253c073c53c50bd768ef13.png

源碼及相關鏈接

[1]?Githubhttps://github.com/iioter/NLog.Targets.MQTT

[2]?Giteehttps://gitee.com/iioter/NLog.Targets.MQTT

[3]??IoTGateway-Doc:http://iotgateway.net/blog/NLog

[4]?NLog自定義Target:https://github.com/NLog/NLog/wiki/How-to-write-a-custom-target

感興趣可以關注我

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/285781.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/285781.shtml
英文地址,請注明出處:http://en.pswp.cn/news/285781.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

2016-1-27

2019獨角獸企業重金招聘Python工程師標準>>> 1.前端的三大技能:1.1.描述網頁內容html 1.2.描述網頁樣式css 1.3.描述網頁行為js2.html和jsp區別在于靜態和動態..bootsharp是目前比較火爆的css..angular是目前比較火爆的js.3.單點登陸(SSO):登陸一次就可以訪問所有相…

【ArcGIS風暴】ArcGIS生成GlobeLand30土地利用數據集中國區域行列號shp格式對照圖(附shp下載)

效果預覽: 本文主要講述了在ArcGIS中生成GlobeLand中國區域對照行列號的shp格式矢量數據,用途在于將自己的研究區跟行列號矢量圖層直接疊加顯示,快速找出自己所需要的圖幅號,便于快速下載數據。同時為了方便使用,本文提供了對照圖的下載。 文章目錄 1. 創建文件數據庫2. 創…

Android 節操視頻播放器jiecaovideoplayer自定義播放音頻使用:屏蔽全屏按鈕,增加倒計時,當前時間/總時間

一、屏蔽全屏按鈕 找到JCVideoPlayerStandard.java文件中的代碼&#xff1a; private void fixAudio() {if (SrcType.equalsIgnoreCase("Audio")) {//如果是音頻&#xff0c;始終顯示coverImageView//thumbImageView.setVisibility(View.VISIBLE);coverImageView.se…

Android之Dialog提示Unable to add window -- token is not valid; is your activity running?

1、問題 Dialog奔潰提示Unable to add window -- token android.os.BinderProxy@b251dbc is not valid; is your activity running? 2、解決辦法 傳遞context到dialog的時候,要記得先判斷狀態是不是isFinishing或者isDestroyed狀態,這個時候就不要再去show相關的dialog了,…

nagios監控haproxy(借助腳本)

nagios監控haproxy&#xff08;借助腳本&#xff09; 修改后的腳本如下&#xff08;需添加指示燈的狀態&#xff09; # vi haproxy.sh #!/bin/bash Portnetstat -ntpl | grep haproxy | awk -F[:" "] {print $5} if [ $Port "1080" ];then echo "OK …

一、Qt初嘗試,做一個QT計算器《QT 入門到實戰》

學習目標 了解 qt 的基本信息了解 qt 的下載及安裝了解創建一個基本 qt 項目的流程了解信號與槽通過示例了解信號與槽的設置與編寫了解控件添加的方式了解控件如何使用代碼獲取其文本了解控件如何使用代碼設置其文本使用 connect 自定義信號與槽了解使用樣式修飾控件外觀了解使…

VS C#語言獲取輸入名稱的漢語拼音簡拼碼和全拼碼完整案例教程

結果預覽: 擴展閱讀: SQL語言獲取拼音碼:SQL Server編寫函數獲取漢字的拼音碼(簡拼) 文章目錄 1. 拼音碼類編寫2. 界面設計3. 前端調用4. 結果展示1. 拼音碼類編寫 打開Visual Studio,新建一個Winform項目,再添加一個類文件,命名為PYM。 鍵入如下代碼: using Syst…

iOS duplicate symbol for architecture arm64 解決辦法

導致這個問題的原因有多種&#xff1a; 1.重復定義了const常量。 2.多個第三方庫同時用到了某個函數庫。 暫時列舉這幾種&#xff0c;以后遇到了其他原因再加。轉載于:https://www.cnblogs.com/zhanglinfeng/p/5987077.html

WPF 實現星空效果

本文經原作者授權以原創方式二次分享&#xff0c;歡迎轉載、分享。原文作者&#xff1a;普通的地球人原文地址&#xff1a;https://www.cnblogs.com/tsliwei/p/6282183.htmlGithub地址&#xff1a;https://github.com/WPFDevelopersOrg/WPFDevelopers效果前陣子看到ay的蜘蛛網效…

data類型的Url的格式

data類型的Url的格式 一、data類型的簡介 所謂"data"類型的Url格式&#xff0c;是在RFC2397中提出的&#xff0c;目的對于一些“小”的數據&#xff0c;可以在網頁中直接嵌入&#xff0c;而不是從外部文件載入。例如對于img這個Tag&#xff0c;哪怕 這個圖片非常非…

C語言試題八十之統計單詞個數

??個人主頁:個人主頁 ??系列專欄:C語言試題200例目錄 ??推薦一款刷算法、筆試、面經、拿大公司offer神器 ?? 點擊跳轉進入網站 ?作者簡介:大家好,我是碼莎拉蒂,CSDN博客專家(全站排名Top 50),阿里云博客專家、51CTO博客專家、華為云享專家 1、題目 終端輸入一…

SSIS 執行變量中的腳步輸出列順序與SQL查詢列順序不同

這個問題是朋友遇到的&#xff0c;做一個SSIS的程序將數據導入到txt。然后再用Oracle的工具導入到Oracle。但是在SSIS中執行變量腳步的時候&#xff0c;發現輸出的列名稱跟查詢的列名稱完全不同。比如Schema_id在查詢的第三列&#xff0c;但是輸出的時候到了第6列。 如圖&#…

【ArcGIS風暴】ArcGIS自定義坐標系統案例教程---以阿爾伯斯投影(Albers)為例

在實際工作中,經常需要進行矢量數據或柵格數據的投影轉換工作,但有時候ArcGIS中恰恰沒有我們需要的坐標系,此時,就需要我們自定義坐標系。本文以阿爾伯斯投影(Albers)為例,講解自定義投影的一般過程及注意事項。 文章目錄 1. 確定投影名稱2. 選擇投影坐標系及修改參數4.…

C語言試題八十一之利用遞歸函數調用方式,將所輸入的5個字符,相反順序打印

??個人主頁:個人主頁 ??系列專欄:C語言試題200例目錄 ??推薦一款刷算法、筆試、面經、拿大公司offer神器 ?? 點擊跳轉進入網站 ?作者簡介:大家好,我是碼莎拉蒂,CSDN博客專家(全站排名Top 50),阿里云博客專家、51CTO博客專家、華為云享專家 1、題目 利用遞歸函…

Unity5 GI與PBS渲染從用法到著色代碼

本文主要介紹Untiy5以后的GI&#xff0c;PBS&#xff0c;以及光源探頭&#xff0c;反射探頭的用法以及在著色器代碼中如何發揮作用&#xff0c;GI是如何影響渲染的&#xff0c;主要分成三個部分&#xff0c;最開始說明PBS需要的材質與相應概念&#xff0c;二是Unity 里相應GI的…

Web前端筆試面試題匯總(轉自github)

前言 本文總結了一些優質的前端面試題&#xff08;多數源于網絡&#xff09;&#xff0c;初學者閱后也要用心鉆研其中的原理&#xff0c;重要知識需要系統學習&#xff0c;透徹學習&#xff0c;形成自己的知識鏈。萬不可投機取巧&#xff0c;只求面試過關是錯誤的&#xff01; …

Blazor University (31)表單 —— 驗證

原文鏈接&#xff1a;https://blazor-university.com/forms/validation/驗證源代碼[1]DataAnnotationsValidator 是 Blazor 中的標準驗證器類型。在 EditForm 組件中添加此組件將啟用基于 System.ComponentModel.DataAnnotations.ValidationAttribute 的 .NET 屬性的表單驗證。…

CSDN,CNBLOGS博客文章一鍵轉載插件 終于更新了!

之前&#xff0c;Shawn Chou等朋友一直建議插件支持cnblogs文章轉載&#xff0c;但一直沒時間修改插件&#xff0c;今天晚上抽時間將插件進行了升級&#xff0c;可以支持 CSDN,CNBLOGS博客文章的一鍵轉載。時間倉促&#xff0c;難免有各種問題&#xff0c;歡迎提出建議&#xf…

ROS2_Control官方資料+運動控制

Getting Started — ROS2_Control: Rolling Dec 2023 documentation Getting Started Edit on GitHub Youre reading the documentation for a development version. For the latest released version, please have a look at Iron. Getting Started? Installation? Binar…

三、教你搞懂漸變堆疊面積圖《手把手教你 ECharts 數據可視化詳解》

注&#xff1a;本系列教程需要對應 JavaScript 、html、css 基礎&#xff0c;否則將會導致閱讀時困難&#xff0c;本教程將會從 ECharts 的官方示例出發&#xff0c;詳解每一個示例實現&#xff0c;從中學習 ECharts 。 ECharts 官方示例&#xff1a;https://echarts.apache.o…