Nlog打印日誌到Influxdb數據庫

1、安裝和使用Influxdb

安裝部分網上資料比較多,也講的比較詳細,請自行百度。

下面大概講下InfluxDB的寫入和讀取數據的方法。

我使用了InfluxData.Net包。
工具-》NuGet包管理器-》管理解決方案的NuGet程序包-》瀏覽-》輸入InfluxData.Net。
在這裏插入圖片描述
安裝好之後就可以寫代碼了

其中注意幾點坑
1、InfluxDB的time格式是世界標準時區時間,所以我在其基礎上加了8小時,具體請看下面的代碼。

2、插入和查詢數據時,語句中不能包含引號“”、‘’,這和InfluxDB的行協議有關,如果插入的數據中包含引號,一定要進行轉義。例如 \"weather\"

3、查詢後的數據格式和其他數據庫不一致,格式如下。我提供了兩種解析方法(輸出List或json字符串)
在這裏插入圖片描述
代碼如下:

using InfluxData.Net.Common.Enums;
using InfluxData.Net.InfluxDb;
using InfluxData.Net.InfluxDb.Models;
using System;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics.Eventing.Reader;
using System.Linq;
using System.Threading.Tasks;
using InfluxData.Net.Common.Helpers;

namespace test
{
    public class InfluxDbRepository
    {
        private readonly InfluxDbClient _clientDb;
        private readonly IInfluxDbConfig _influxDbConfig;
        public InfluxDbRepository(IInfluxDbConfig influxDbConfig)
        {
            _influxDbConfig = influxDbConfig;
            var influxUrl = _influxDbConfig.Get().InfluxUrl;
            var influxUser = _influxDbConfig.Get().InfluxUser;
            var influxPwd = _influxDbConfig.Get().InfluxPwd;

            //創建InfluxDbClient實例
            _clientDb = new InfluxDbClient(influxUrl, influxUser, influxPwd, InfluxDbVersion.Latest);
        }

        /// <summary>
        /// 寫入單個對象
        /// </summary>
        /// <param name="entities"></param>
        /// <param name="baseLog">基本信息</param>
        /// <returns></returns>
        public async System.Threading.Tasks.Task InsertAsync(BaseLog baseLog)
        {
            try
            {
                var tags = new Dictionary<string, object>();
                var fields = new Dictionary<string, object>();

                var propertyInfos = ForeachClassHelper.ForeachClassProperties<BaseLog>(baseLog);
                foreach (var item in propertyInfos)
                {
                    fields.Add(item.Name, item.GetValue(baseLog, null));
                }

                var pointModel = new Point()
                {
                    Name = _influxDbConfig.Get().TableName,//表名
                    Tags = tags,
                    Fields = fields,
                    Timestamp = DateTime.UtcNow.AddHours(8)
                };
                var response = await _clientDb.Client.WriteAsync(pointModel, _influxDbConfig.Get().DbName);
            }
            catch (Exception ex)
            {

                throw;
            }

        }


        /// <summary>
        /// 從InfluxDB中讀取數據 返回string,和返回List的性能幾乎一樣
        /// 測試6萬條數據 1s
        /// </summary>
        public async Task<string> GetDataAsync(string sql)
        {
            try
            {
                //傳入查詢命令,支持多條
                var queries = new[] { sql };
                var dbName = _influxDbConfig.Get().DbName;
                Stopwatch sw = new Stopwatch();
                sw.Start();
                //從指定庫中查詢數據
                var response = await _clientDb.Client.QueryAsync(queries, dbName);
                sw.Stop();

                long dur = sw.ElapsedMilliseconds;
                //得到Serie集合對象(返回執行多個查詢的結果)
                var series = response.ToList();

                string rtn;
                if (series.Any())
                {
                    var dt = new DataTable();
                    //取出第一條命令的查詢結果,是一個集合
                    var column = series[0].Columns;
                    foreach (var item in column)
                    {
                        dt.Columns.Add(item, typeof(string));
                    }
                    var list = series[0].Values;
                    foreach (var row in list)
                    {
                        DataRow dr = dt.NewRow();
                        for (int i = 0; i < row.Count; i++)
                        {
                            dr[i] = row[i];
                        }
                        dt.Rows.Add(dr);
                    }
                    rtn = SerializeHelper.ToJson(dt);
                }
                else
                {
                    rtn = "";
                }
                return rtn;
            }
        }

        /// <summary>
        /// 查詢 返回List
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="sql"></param>
        /// <returns></returns>
        public async Task<List<T>> GetDataListAsync<T>(string sql) where T : new()
        {
            try
            {
                //傳入查詢命令,支持多條
                var queries = new[] { sql };
                var dbName = _influxDbConfig.Get().DbName;

                //從指定庫中查詢數據
                var response = await _clientDb.Client.QueryAsync(queries, dbName);
                //得到Serie集合對象(返回執行多個查詢的結果)
                var series = response.ToList();

                List<T> listrtn = new List<T>();
                if (series.Any())
                {
                    //取出第一條命令的查詢結果,是一個集合
                    var column = series[0].Columns.ToList();
                    var list = series[0].Values;
                    for (int i = 0; i < list.Count(); i++)
                    {
                        var temp = new T();
                        var propertyInfos = ForeachClassHelper.ForeachClassProperties<T>(temp);
                        foreach (var item in propertyInfos)
                        {
                            if (item.Name != "time")
                            {
                                int index = column.FindIndex(x => x.Equals(item.Name));
                                if (index != -1)
                                {
                                    item.SetValue(temp, list[i][index], null);//給對象賦值
                                }
                            }
                        }
                        listrtn.Add(temp);
                    }
                }
                else
                {
                    listrtn = null;
                }
                return listrtn;
            }
        }
    }
}

2、使用Nlog

2.1 安裝Nlog

新建項目後,工具-》NuGet包管理器-》管理解決方案的NuGet程序包
在這裏插入圖片描述
選擇Nlog進行安裝,如果是.net core項目就選擇Nlog.Web.AspNetCore。

2.2 配置Nlog

配置內容寫在Nlog.config裏邊。主要用到兩個標籤:

Target:這個是主要用來配置日誌輸出的相關參數的,比如輸出到文件、控制檯還是數據庫,輸出的文件名稱是什麼,內容格式是什麼等。

Rules:輸出規則,定義根據不同的日誌級別輸出到不同的地方,比如Info類型的輸出到文件,Error類型的通過郵件發送處理等。

詳細的配置內容參考官方文檔: https://github.com/nlog/NLog/wiki/Configuration-file.
下面是一個簡單的配置

<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://www.nlog-project.org/schemas/NLog.xsd NLog.xsd"
      autoReload="true"
      throwExceptions="false"
      internalLogLevel="Off" internalLogFile="c:\temp\nlog-internal.log">
  <variable name="myvar" value="myvalue"/>
  <targets>
    <target xsi:type="File" name="file" fileName="${basedir}/Logs/${date:format=yyyyMM}/${shortdate}.txt"
            layout="
        ${newline}時間: ${longdate}
        ${newline}來源: ${callsite}
        ${newline}等級: ${level}
        ${newline}信息: ${message}
        ${newline}堆棧: ${event-context:item=exception} ${stacktrace}
        ${newline}${newline}-----------------------------------------------------------" />
        <target name="console" type="Console" layout="${longdate} ${callsite} ${level} ${message}${newline}" />
  </targets>
  <rules>
    <logger name="*" writeTo="file" />
    <logger name="*" minlevel="Trace" writeTo="console" />
  </rules>
</nlog>

如果要講日誌輸出到InfluxDB這種非標準輸出,則需要擴展,編寫自定義目標
下面是拓展步驟

2.2.1 編寫自定義目標

1、創建一個繼承自的類 NLog.Targets.TargetWithLayout
2、覆蓋Write()方法。
3、在此方法的主體中,調用this.Layout.Render()以獲取消息文本,然後將文本發送到目標媒體。
代碼如下:

using NLog;
using NLog.Config;
using NLog.Targets;
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Extensions.DependencyInjection;

namespace test
{
    /// <summary>
    /// 自定義Nlog寫入目標-InfluxDB
    /// </summary>
    [Target("InfluxDB")]
    public class InfluxDBTarget: TargetWithLayout
    {
        public InfluxDBTarget()
        {
        }
        protected override void Write(LogEventInfo logEvent)
        {             
            //獲取消息文本
            string logMessage = this.Layout.Render(logEvent);
            //反序列化
            BaseLog baseLog = SerializeHelper.FromJson<BaseLog>(logMessage);
            //將日誌內容保存到InfluxDB數據庫
            var repository = AppStartup.App.ServiceProvider.GetService<InfluxDbRepository>();
            repository.InsertAsync(baseLog);
        }
        private void InsertInfluxDB(string message)
        {
            // TODO - write me 
        }
    }
}

2.2.2 配置輸出內容InfluxDB

在Nlog.config中配置輸出內容,配置如下

<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      throwExceptions="true">
  <extensions>
    <!--這裏是上面InfluxDBTarget所在程序集的名稱-->
    <add assembly="test" />
  </extensions>
  <targets async="true">
    <target name="database" type="InfluxDB" layout="{'ProcessId':'${processid}','Level':'${level}','AppDomain':	'${appdomain}' ,'MachineName':'${machinename}'
,'Message':	'${message}','AssemblyVersion':	'${assembly-version}','ProcessName':'${processname}','CallSite':'${callsite}','CallSiteLinenumber':'${callsite-linenumber}',
'ThreadId':'${threadid}','Exception':'${exception}','IP':'${aspnet-request-ip}','LongDate':'${longdate}','StackTrace':'${stacktrace}'}" />
  </targets>
  <rules>
    <logger name="*" minlevel="Trace" writeTo="database" />
  </rules>
</nlog>

到這Nlog部分就結束了

InfluxDB Studio查詢日誌內容
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章