NetCore微服务实战体系:日志管理
一. 起始
进入NetCore时代,日志的使用有了很大的变化,因为跨平台以及虚拟化技术的使用,日志不能够再像Framework的方式直接记录在文本,文本其实也可以,但是日志的管理以及查看都不太方便。Linux都是指令化,对于开发来说并不友好。
后来Exceptionless进入了视线,选择这个组件的原因很简单,可视化、数据统计、实时性以及对于.net开发人员相当友好。在当前网络上,有很多关于Exceptionless的使用文档,但是个人觉得并不友好,在使用上并不方便。
在微软体系中,Microsoft.Extesions.Logging是官方日志框架,它允许我们自己去实现ILoggerProvider / ILogging,那么根据这两者得特性,由此开发了组件 Overt.Core.Logging
二. 组件Overt.Core.Logging
https://github.com/overtly/logging
三. 简单介绍使用
1. Nuget包引用
- Nuget版本:V 1.0.4.1
- 框架支持: NetStandard 2.0
Install-Package Overt.Core.Logging -Version 1.0.4.1
2. 配置信息
- NetCore配置案例 appsettings.json
{
"Exceptionless": {
"ServerUrl": "http://exless.g.lan", // 私有化域名(Exceptionless私有化的文档网上很多)
"ApiKey": "ugGFmeeriaj1BG12itWWURfiJjwqiyi2o71ll4mm", // 项目Key 如何创建网上文档也很多
"Tags": "Local" // 日志所属项目环境
}
}
3. 具体使用
(1)服务注入
- Web服务使用
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{// Logging
app.AddExlessLogging(); }
- IHost 普通服务使用
static void Main(string[] args)
{
var host = new HostBuilder()
.UseConsoleLifetime() //使用控制台生命周期
.ConfigureAppConfiguration((context, configuration) =>
{
configuration
.AddJsonFile("appsettings.json", optional: true)
.AddEnvironmentVariables();
})
.ConfigureLogging(logger =>
{ })
.ConfigureServices(ConfigureServices)
.Build(); host.Services.AddExlessLogging();
ThreadPool.SetMinThreads(100, 100); AppDomain.CurrentDomain.UnhandledException += (sender, e) =>
{
var logFactory = host.Services.GetService<ILoggerFactory>();
var logger = logFactory.CreateLogger<Program>();
logger.LogError(e.ExceptionObject as Exception, $"UnhandledException");
}; host.Run();
}
(2)日志使用
using Microsoft.Extensions.Logging; private readonly ILogger _logger; public Test(ILogger<Test> logger)
{
_logger = logger;
} _logger.LogInformation("你好");
4. 源码详解
(1)实现ILogger
using Exceptionless;
using Microsoft.Extensions.Logging;
using System; namespace Overt.Core.Logging
{
/// <summary>
/// Logger实现
/// </summary>
public class ExlessLogger : ILogger
{
private readonly string _categoryName;
public ExlessLogger(string categoryName)
{
_categoryName = categoryName;
} /// <summary>
///
/// </summary>
/// <typeparam name="TState"></typeparam>
/// <param name="state"></param>
/// <returns></returns>
public IDisposable BeginScope<TState>(TState state)
{
return new NoopDisposable();
} /// <summary>
/// 是否可用
/// </summary>
/// <param name="logLevel"></param>
/// <returns></returns>
public bool IsEnabled(LogLevel logLevel)
{
return true;
} /// <summary>
/// 记录日志
/// </summary>
/// <typeparam name="TState"></typeparam>
/// <param name="logLevel"></param>
/// <param name="eventId"></param>
/// <param name="state"></param>
/// <param name="exception"></param>
/// <param name="formatter"></param>
public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
{
try
{
var message = formatter(state, exception);
var source = $"{_categoryName}";
var exlessLogLevel = Exceptionless.Logging.LogLevel.Trace;
switch (logLevel)
{
case LogLevel.Trace:
exlessLogLevel = Exceptionless.Logging.LogLevel.Trace;
break;
case LogLevel.Information:
exlessLogLevel = Exceptionless.Logging.LogLevel.Info;
break;
case LogLevel.Warning:
exlessLogLevel = Exceptionless.Logging.LogLevel.Warn;
break;
case LogLevel.Error:
exlessLogLevel = Exceptionless.Logging.LogLevel.Error;
break;
case LogLevel.Critical:
exlessLogLevel = Exceptionless.Logging.LogLevel.Fatal;
break;
default:
exlessLogLevel = Exceptionless.Logging.LogLevel.Debug;
break;
}
var eventBuilder = ExceptionlessClient.Default
.CreateLog(message, exlessLogLevel)
.SetSource(source)
.SetException(exception); if (eventId != null)
eventBuilder.SetProperty("Event", $"{eventId.ToString()}"); var serverAndPoint = LoggingUtility.GetAddressIP();
if (!string.IsNullOrEmpty(serverAndPoint))
eventBuilder.SetProperty("ServerEndPoint", serverAndPoint); eventBuilder.Submit();
}
catch { }
} private class NoopDisposable : IDisposable
{
public void Dispose()
{
}
}
}
}
(2)实现ILoggerProvider
using Microsoft.Extensions.Logging; namespace Overt.Core.Logging
{
/// <summary>
/// LoggerProvider
/// </summary>
public class ExlessLoggerProvider : ILoggerProvider
{
/// <summary>
/// Contructor
/// </summary>
/// <param name="categoryName"></param>
/// <returns></returns>
public ILogger CreateLogger(string categoryName)
{
return new ExlessLogger(categoryName);
} /// <summary>
///
/// </summary>
public void Dispose()
{
}
}
}
(3)依赖注入
using Exceptionless;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using NLog.Extensions.Logging;
using Overt.Core.Logging;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq; namespace Microsoft.Extensions.DependencyInjection
{
public static class ServiceCollectionExtensions
{ #region ExLess
/// <summary>
/// 注入
/// </summary>
/// <param name="loggingBuilder"></param>
/// <param name="configFile"></param>
public static void AddExlessLogging(this IServiceProvider provider)
{
var configuration = provider.GetService<IConfiguration>();
var loggerFactory = provider.GetService<ILoggerFactory>(); var client = ExceptionlessClient.Default;
client.InitExlessTags(configuration);
client.Configuration.ReadFromConfiguration(configuration);
client.Configuration.ReadFromEnvironmentalVariables();
client.Configuration.UseInMemoryStorage();
client.Startup(); loggerFactory.AddProvider(new ExlessLoggerProvider());
} /// <summary>
/// 注入
/// </summary>
/// <param name="loggingBuilder"></param>
/// <param name="configFile"></param>
public static void AddExlessLogging(this IApplicationBuilder app)
{
var provider = app.ApplicationServices;
var configuration = provider.GetService<IConfiguration>();
var loggerFactory = provider.GetService<ILoggerFactory>(); app.UseExceptionless(configuration);
var client = ExceptionlessClient.Default;
client.InitExlessTags(configuration);
client.Configuration.UseInMemoryStorage(); loggerFactory.AddProvider(new ExlessLoggerProvider());
} /// <summary>
/// tags
/// </summary>
/// <param name="client"></param>
/// <param name="configuration"></param>
private static void InitExlessTags(this ExceptionlessClient client, IConfiguration configuration)
{
var tags = configuration?["Exceptionless:Tags"]?.Split(",", StringSplitOptions.RemoveEmptyEntries)?.ToList();
foreach (var tag in tags ?? new List<string>())
{
client.Configuration.DefaultTags.Add(tag);
}
}
#endregion
}
}
5. 最终效果
可实时查看日志信息
NetCore微服务实战体系:日志管理的更多相关文章
- ASP.NET Core微服务实战系列
希望给你3-5分钟的碎片化学习,可能是坐地铁.等公交,积少成多,水滴石穿,码字辛苦,如果你吃了蛋觉得味道不错,希望点个赞,谢谢关注. 前言 这里记录的是个人奋斗和成长的地方,该篇只是一个系列目录和构想 ...
- 微服务实战(二):使用API Gateway - DockOne.io
原文:微服务实战(二):使用API Gateway - DockOne.io [编者的话]本系列的第一篇介绍了微服务架构模式.它讨论了采用微服务的优点和缺点,除了一些复杂的微服务,这种模式还是复杂应用 ...
- 微服务实战(一):微服务架构的优势与不足 - DockOne.io
原文:微服务实战(一):微服务架构的优势与不足 - DockOne.io [编者的话]本文来自Nginx官方博客,是微服务系列文章的第一篇,主要探讨了传统的单体式应用的不足,以及微服务架构的优势与挑战 ...
- Spring Cloud 微服务实战笔记
Spring Cloud 微服务实战笔记 微服务知识 传统开发所有业务逻辑都在一个应用中, 开发,测试,部署随着需求增加会不断为单个项目增加不同业务模块:前端展现也不局限于html视图模板的形式,后端 ...
- .Net微服务实战之可观测性
系列文章 .Net微服务实战之技术选型篇 .Net微服务实战之技术架构分层篇 .Net微服务实战之DevOps篇 .Net微服务实战之负载均衡(上) .Net微服务实战之CI/CD .Net微服务实战 ...
- go-zero微服务实战系列(三、API定义和表结构设计)
前两篇文章分别介绍了本系列文章的背景以及根据业务职能对商城系统做了服务的拆分,其中每个服务又可分为如下三类: api服务 - BFF层,对外提供HTTP接口 rpc服务 - 内部依赖的微服务,实现单一 ...
- 微服务实战(三):落地微服务架构到直销系统(构建基于RabbitMq的消息总线)
从前面文章可以看出,消息总线是EDA(事件驱动架构)与微服务架构的核心部件,没有消息总线,就无法很好的实现微服务之间的解耦与通讯.通常我们可以利用现有成熟的消息代理产品或云平台提供的消息服务来构建自己 ...
- 微服务实战(二):使用API Gateway
微服务实战(一):微服务架构的优势与不足 微服务实战(二):使用API Gateway 微服务实战(三):深入微服务架构的进程间通信 微服务实战(四):服务发现的可行方案以及实践案例 微服务实践(五) ...
- Spring Cloud微服务实战阅读笔记(一) 基础知识
本文系<Spring Cloud微服务实战>作者:翟永超,一书的阅读笔记. 一:基础知识 1:什么是微服务架构 是一种架构设计风格,主旨是将一个原本独立的系统拆分成多个小型服务 ...
随机推荐
- CentOS7(Linux)源码安装MySQL5.7.X
介绍 软件应用最重要的就是数据库了,可是还有小伙伴不会在Linux上安装MySQL数据库,今天就来讲讲如何在CentOS7环境使用源码进行安装MySQL5.7.X. MySQL官网下载链接:https ...
- 开发过程中遇到的-npm加载进node_modules里的文件怎么修改
来源:https://juejin.im/post/5ec381215188256d776342cd https://mp.weixin.qq.com/s?__biz=MzUzNjk5MTE1OQ== ...
- rabbit rpm地址
rabbitmq 官方源: https://dl.bintray.com/rabbitmq/rpm/rabbitmq-server/ erlang 清华源(包含erlang所有版本): https:/ ...
- ubuntu 下添加环境变量
ubuntu 下添加环境变量 方法1: 第一种临时设置,用 export 指令,如在$PATH中增加JAVA文件夹: $export PATH=$PATH:/usr/local/lib/jdk1.6. ...
- Hive 常见面试题(一)
面试题: hive 内部表和外部表的区别? hive 是如何实现分区的? Hive 有哪些方式保存元数据,各有哪些优缺点? hive中order by.distribute by.sort by和cl ...
- Less 预处理笔记
1. less 简介 1. less是CSS的预编译器,可以扩展CSS语言(当然也兼容CSS),可以定义变量.混合.函数等等,让CSS代码更易维护和扩展 2. less与传统写法相比: less后缀为 ...
- 重温Java Web的技术细节
目录 一.背景 二.请求与响应 2.1.Http请求 2.2.Http响应 三.ServletConfig 3.1 测试ServletConfig参数 四.ServletContext 4.1 测试S ...
- 现在的市场对 C++ 的需求大吗?
分享 大师助手 先说结论:需求还是很大,但是没有什么初级程序员能干的岗位. 游戏引擎,存储,推荐引擎,infra,各种各样的性能敏感场景.这些都是C++的刚需场景,别的语言基本替代不了的.除了pin ...
- 招新裁老,两面派互联网大厂,培训三个月,就拿15K,凭什么?
看到一位朋友在发帖子求问:亲身经历,(如有谎言我名字倒过来写)一个大学同学18年毕业的.在兰州一个二本学的兽医农牧,毕业难找工作,去深圳一个机构培训了三个月吧,然后就去做大数据 算法了,然后又去做ja ...
- e3mall商城的归纳总结8之solr集群、activemq的搭建和使用
由于本节内容比较分散,因此专门为这两个技术进行开展了帖子. solr集群的搭建 solr集群solrJ的测试 activemq的搭建 activemq的使用 引入activemq.jar包 我们先来说 ...