.net core+seq实现日志中心 电脑版发表于:2022/1/5 14:58 >[TOC] ### 为什么需要日志中心 日志是编写程序常用的功能。在我们排查问题的时候日志是非常有用的。我们的每个服务都在不停的生产日志。但是实施微服务后,如果按照传统的写本地文件的日志方案,就会面临跟修改配置一样的麻烦。不同的日志分散在各个服务器、容器内,这种情况下查日志简直无法忍受。 日志中心就是为了解决了这个问题。所有的服务通过接口发送日志到聚合服务,再由聚合服务进行统一存储,并且提供统一的查询、分析的能力。 日志聚合组件业界有 ELK、Exceptionless、Seq 等 ### 分布式日志收集框架Seq介绍 Seq 是一款使用现代化技术构建的结构化日志存储,查询,分析工具。比起 ELK 这种组合要轻量级许多。只需要一个安装包就具有数据存储,查询,图表分析功能。它对 windows 友好,直接提供了安装包。当然也可以使用 docker 来部署。Seq 对于单个用户是免费的,这对于一些小团队并没有什么问题。Seq 一个比较强大的功能是提供了类似 Sql 语句的数据查询及处理能力,使得用户可以直接写 Select from 来得到自己想要的数据。 官网:https://docs.datalust.co/docs - Seq支持主流的编程语言,尤其对.NET非常友好 支持的日志框架有:ASP.NET Core , Serilog ,使用NLog,使用log4net,当然还支持其他语言以及其他的一些方式,比如RabbitMQ、GELF、Windows事件等等 - 丰富的事件格式 以结构化形式记录上文信息与应用程序事件,支持消息模板将文本数据与结构话数据无缝连接。下图中所有属性都是由使用者自定义的。 - 支持筛选语法和SQL查询,非常简单和灵活 多种查询方式 -支持以SQL表达式查询,以及C#中的,==,!=,<,<=,内置StartsWith(),EndsWith(),IndexOf() 和Contains(),并支持文本全文检索。 - 支持仪表盘,可以自行创建和编辑图表  - 支持安装插件,插件可以使用.NET进行编写 - 支持发送邮件(通过插件) - 支持团队操作 - 提供命令行客户端 - 支持健康检查(通过插件) - 支持收集Docker日志 - 支持收集K8s日志 - 支持自定义警报和Webhook ### 安装Seq docker安装: ``` docker run --name seq -e ACCEPT_EULA=Y -p 8900:80 -p 5341:5341 datalust/seq ``` 使用 docker run 运行一个实例。8900 绑定容器的 80 端口,该端口是 web 管理界面的入口。5341 绑定容器的 5341 端口,该端口是日志写入时候真正的端口。 -e的作用是指定容器内的环境变量。dockerfile中使用ENV指令指定环境变量  **安装好后我们就可以使用ip : 8090去访问了** 如果能出现页面说明我们访问成功了!  上面是菜单,可以切换白天和晚上的不同风格  <br/> ### 账户管理 需要设置账户信息,不然可以直接不用登录就能访问不安全 Seq提供内置用户名和密码、OpenID连接和Azure Active Directory身份验证。Windows服务器上支持Active Directory身份验证。为第一个管理员设置身份验证后,您可以创建和配置其他用户帐户。 如果失去对Seq的管理访问权,可以从Seq命令行重置密码。  您使用的是免费个人许可证,允许一个人使用Seq。要与您的团队共享SEQ,请购买多用户许可证或请求试用。感谢您在Seq的朋友! ### API Keys 配置 可以用来区分项目,不同服务配置一个API Keys在进行日志查询的时候也方便查询 **找到API Keys点击进去** <img src="https://img.tnblog.net/arcimg/aojiancc2/9412d6af8e52498bbc3964f79abfaefb.png" width = "500" alt="图片名称" align=center /> 点击添加: <img src="https://img.tnblog.net/arcimg/aojiancc2/38e262fc44204b42a05df0867bd35995.png" width = "500" alt="图片名称" align=center /> **然后填写title信息(一般填写服务名这些)。选择具有的权限。还有日志等级什么的**  日志等级可以不写,默认就是最低等级 **还可以自定义一些属性,这些属性会附加到每个日志记录上。** 比如我们这里为 member_center 这个 apikey 自定义一个 app = PruductAPIService 的属性。后面做日志查询的时候可以直接使用app = PruductAPIService查询。 <img src="https://img.tnblog.net/arcimg/aojiancc2/73d68f32925a4fd58e9b9730f70ff01c.png" width = "500" alt="图片名称" align=center /> **然后填写好了之后点击存储即可。** 存储成功之后可以看到API Key Token。后面集成NLOG的时候可以根据这个Token来区分日志  注意复制令牌存储下来,关闭此对话框后,将无法再次检索它。 ### NLog 输出到 Seq 如果nlog使用不会可以参考:https://www.tnblog.net/aojiancc2/article/details/6861 下载seq依赖 ``` Install-Package NLog.Targets.Seq ``` 或者 ``` <PackageReference Include="NLog.Targets.Seq" Version="2.1.0" /> ``` 修改nlog配置文件,增加一个输出到seq的target ``` <?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" > <extensions> <add assembly="NLog.Targets.Seq"/> </extensions> <targets> <target xsi:type="File" name="f" fileName="${basedir}/logs/nlog-my2-${shortdate}.log" layout="${longdate} ${uppercase:${level}} ${message}" /> <target xsi:type="File" name="f2" fileName="${basedir}/logs/nlog-cs-${shortdate}.log" layout="${longdate} ${uppercase:${level}} ${message}" /> <!--输出目标配置:配置Seq为输出类型--> <target name="seq" xsi:type="BufferingWrapper" bufferSize="1000" flushTimeout="2000" > <target xsi:type="Seq" serverUrl="http://seqip地址:8900" apiKey="你的apikey"> <property name="ThreadId" value="${threadid}" as="number" /> <property name="stacktrace" value="${onexception:inner=${stacktrace}}"/> </target> </target> </targets> <rules> <logger name="*" minlevel="Debug" writeTo="f" /> <logger name="*" minlevel="Trace" writeTo="f2" /> <!--设定了一个日志等级为Trace, 最终指向了一个seq名称的目标 --> <logger name="*" minlevel="Trace" writeTo="seq" /> </rules> </nlog> ``` 上面的输出配置有线程id,stacktrace信息。我们还可以配置更多的信息比如机器名、ip地址、URL、环境变量等属性。 ``` <property name="MachineName" value="${machinename}" /> <property name="Environment" value="Development" /> <!--https://github.com/NLog/NLog/wiki/Logger-Layout-Renderer--> <property name="Logger" value="${logger}" /> <!--https://github.com/NLog/NLog/wiki/AspNet-Request-IP-Layout-Renderer--> <property name="IP" value="${aspnet-request-ip}" /> <!--https://github.com/NLog/NLog/wiki/AspNetRequest-Url-Layout-Renderer--> <property name="Url" value="${aspnet-request-url:IncludeHost=true:IncludePort=true:IncludeQueryString=true:IncludeScheme=true}" /> <property name="Code" value="${aspnet-response-statuscode}" /> ``` 输出日志: ``` public IActionResult Index() { var Logger = NLog.LogManager.GetCurrentClassLogger(); Logger.Info("普通信息日志-----------"); Logger.Debug("调试日志-----------"); Logger.Error("错误日志-----------"); Logger.Fatal("异常日志-----------"); Logger.Warn("警告日志-----------"); Logger.Trace("跟踪日志-----------"); return View(); } ``` 然后在Seq查看: <img src="https://img.tnblog.net/arcimg/aojiancc2/278837da2251473891a6150c92ba868e.png" width = "500" alt="图片名称" align=center /> 当然也可以使用.net core自带的日志输出到nlog: ``` private readonly ILogger<HomeController> _logger; public HomeController(ILogger<HomeController> logger) { _logger = logger; } public IActionResult Index() { _logger.LogInformation("自带log测试_普通信息日志"); _logger.LogDebug("自带log测试_调试日志"); _logger.LogError("自带log测试_错误日志"); _logger.LogWarning("自带log测试_警告日志"); _logger.LogTrace("自带log测试_跟踪日志"); return View(); } ``` 日志的输出可以在seq里边查看: <img src="https://img.tnblog.net/arcimg/aojiancc2/70c697734b5049cb8a01599a05770a29.png" width = "700" alt="图片名称" align=center /> 而且使用自带的日志输出的内容详情就更多一点,还会包含控制器,Action这些信息: <img src="https://img.tnblog.net/arcimg/aojiancc2/ff253e40fd0049d7b3ee68b179b72b4b.png" width = "700" alt="图片名称" align=center /> 比如要过滤掉某些日志,或者只想查看某些日志可以配置日志级别,比如 ``` <logger name="*" level="Debug,Warn,Trace,Error,Fatal" writeTo="seq" /> ``` **如果要跳过微软的日志只显示我们自己的日志,这样就行** 不然日志会太多了,当然如果觉得多无所谓也没关系 ``` <?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" > <extensions> <add assembly="NLog.Targets.Seq"/> </extensions> <targets> <!--输出目标配置:配置Seq为输出类型--> <target name="seq" xsi:type="BufferingWrapper" bufferSize="1000" flushTimeout="2000" > <target xsi:type="Seq" serverUrl="http://xx.yy.zz:8900/" apiKey="apiKey"> <property name="ThreadId" value="${threadid}" as="number" /> <property name="stacktrace" value="${onexception:inner=${stacktrace}}"/> <property name="Environment" value="Development" /> <property name="IP" value="${aspnet-request-ip}" /> </target> </target> <target xsi:type="Null" name="blackhole" /> </targets> <rules> <!--跳过微软的日志只显示我们自己的日志--> <logger name="Microsoft.*" maxlevel="Warning" final="true" /> <logger name="*" levels="Debug,Warn,Information,Trace,Error,Fatal" writeTo="seq" /> </rules> </nlog> ``` 详细的使用说明可以参考: https://www.tnblog.net/aojiancc2/article/details/6884 ### 查询日志 每天的日志可能会很庞大,而且我们会把各个服务的日志都统一汇总过来,所以方便查询就显得很重要了,seq的查询很方便,可以像使用sql语句一样查询。 tn3> 全匹配查询 查询日志级别为Error的日志:@Level = 'Error' <img src="https://img.tnblog.net/arcimg/aojiancc2/d84e2bf3d5fd45a5b9c84dadd0be389d.png" width = "500" align=center /> 注意大小写问题,@Level = 'error'与@level = 'Error'都是查询不出来的 <img src="https://img.tnblog.net/arcimg/aojiancc2/5d241c770c014322a925287f0739dc3f.png" width = "500" style='margin-bottom:5px' /> 查询app等于test Service的日志:app = 'test Service' <img src="https://img.tnblog.net/arcimg/aojiancc2/62da62df1c3d41aaa0366ddc1eef3746.png" width = "700" align=center /> tn4> 模糊查询 查询日志消息里带有警告关键字的内容:@Message like '%警告%' <img src="https://img.tnblog.net/arcimg/aojiancc2/e572c3af02a247d5bc0fc69f641d245f.png" width = "500" align=center /> 官方查询文档:https://docs.datalust.co/docs/the-seq-query-language ### 图表分析功能  tn2>自定义图表 待续 ### 保留一定范围的日志 比如保留一个月 待续