zoukankan      html  css  js  c++  java
  • 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:	emp
    log-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 xsi:type="JsonLayout">
            <attribute name="ProcessId" layout="${processid}" />
            <attribute name="Level" layout="${level}"/>
            <attribute name="AppDomain" layout="${appdomain}" />
            <attribute name="MachineName" layout="${machinename}" />
            <attribute name="Message" layout="${message}"/>
            <attribute name="AssemblyVersion" layout="${assembly-version}" />
            <attribute name="ProcessName" layout="${processname}" />
            <attribute name="CallSite" layout="${callsite}"/>
            <attribute name="CallSiteLinenumber" layout="${callsite-linenumber}" />
            <attribute name="ThreadId" layout="${threadid}" />
            <attribute name="Exception" layout="${exception}"/>
            <attribute name="IP" layout="${aspnet-request-ip}" />
            <attribute name="LongDate" layout="${longdate}" />
            <attribute name="StackTrace" layout="${stackTrace}"/>
          </layout>
        </target>
      </targets>
      <rules>
        <logger name="*" minlevel="Trace" writeTo="database" />
      </rules>
    </nlog>
    

    到这Nlog部分就结束了

    InfluxDB Studio查询日志内容
    在这里插入图片描述

  • 相关阅读:
    静态代码块、非静态代码块、构造函数之间的执行顺序
    Linux跨主机传输文件
    🗒 Linux 系统监控
    Mysql Mode
    Mysql 表锁行锁
    Centos 下修改时区
    Redis 解决内存过大
    Mysql 表达式
    Centos 二进制包安装Mysql5.7
    Vim 快捷键
  • 原文地址:https://www.cnblogs.com/ziqinchao/p/13096194.html
Copyright © 2011-2022 走看看