97

ASP.NET Core 日志收集(log4net+Kafka+ELK)

 5 years ago
source link: http://beckjin.com/2018/12/02/aspnet-log4net-kafka-elk/?amp%3Butm_medium=referral
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

在开发环境中,记录日志这件事情常常被忽视,因为我们有强大的 IDE ,可以调试,可以断点,问题出现后一般都能很快解决。但在生产环境,异常一旦发生,如果不能重现,又没有提前做好日志记录,就会非常被动,问题的定位也可能需要花很多时间,问题最终也是不了了之。给对方的回复也许是这样的: 可能你的网络那个时间点有问题

日志当然不只是为了定位问题,实际我们还可以通过日志进行一系列的分析,通过分析结果我们可以获得很多有效信息。这篇文章将介绍如何在 .NET Core 项目中使用 log4net 进行日志收集,虽然是 log4net ,但其他 log4xxx 也类似,毕竟 Kafka + ELK 这一套和语言无关。

在使用 log4net 前,我们需要先搭建好 Kafka 和 ELK 环境,之前的文章介绍过 ELK + Filebeat 搭建日志系统Elasticsearch 集群Kafka 集群 ,这里会将使用 Kafka 作日志存储,实际情况完全可以 log4net + Filebeat + ELK 、log4net + Redis + ELK 等组合。Kafka、Redis 、Filebeat 都有其自身的特点,根据项目情况选择一种适合的方案即可。

26FjQrq.png!web

以下 Kafka 和 ELK 的测试环境将基于 Windows 的非集群模式,集群模式请参考上面的文章。

基础环境搭建

下载 ELK ( 当前最新 6.5.1 ), Kafka ( Binary downloads ) 、 Zookeeper 最新版本,下载后分别解压。每个服务的配置文件这里不详细介绍了,使用默认配置即可。

iyeIj2b.png!web

ELK

Elasticsearch

在 elasticsearch-6.5.1 目录下,运行启动命令:

bin\elasticsearch

启动成功后,可通过 http://localhost:9200 查看 Elasticsearch 的一些基本信息。

uAJZnqR.png!web

Logstash

将 logstash-6.5.1\config 目录下的 logstash-sample.conf 重命名为 logstash.conf,内容暂替换为:

# 输入
input { 
  # 标准输入(命令行输入)
  stdin { }  
}

# 输出
output {
  # 标准输出
  stdout { codec => rubydebug }
}

运行启动命令:

bin\logstash -f config\logstash.conf

启动成功后,在当前的启动窗口中输入测试消息:hi ,马上会返回输出一段 Json 格式的数据,message 为输入的内容,其他字段是内置的。

YNRRjyJ.png!web

Kibana

在 kibana-6.5.1-windows-x86_64 目录下,运行启动命令:

bin\kibana

启动成功后,通过 http://localhost:5601 访问 Kibana UI,Kibana 默认配置的 Elasticsearch 地址是 http://localhost:9200,所以 Kibana 启动之前,确保 Elasticsearch 已启动,不然会提示 Elasticsearch 状态不正常。

Zookeeper

将 zookeeper-3.4.13\conf 目录下的 zoo_sample.cfg 重命名为 zoo.cfg,运行启动命令:

bin\zkServer

Kafka

在 kafka_2.12-2.1.0 目录下,运行启动命令:

.\bin\windows\kafka-server-start.bat .\config\server.properties

Zookeeper 默认访问地址是 localhost:2181,Kafka 启动后默认的 zookeeper.connect=localhost:2181,Kafka 强依赖于 Zookeeper ,所以必须先启动 Zookeeper。

通过以上步骤,完成了 Kafka 和 ELK 单实例的环境搭建。

项目搭建

  1. 创建一个基于 .NET Core 的 WebApi 项目;
  2. Nuget 安装 Microsoft.Extensions.Logging.Log4Net.AspNetCore;
  3. 启动文件中注入 Log4Net;

    public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
    	WebHost.CreateDefaultBuilder(args)
    	.ConfigureLogging((logging) =>
    	{
    		// 过滤掉 System 和 Microsoft 开头的命名空间下的组件产生的警告级别以下的日志
    		logging.AddFilter("System", LogLevel.Warning);
    		logging.AddFilter("Microsoft", LogLevel.Warning);
    		logging.AddLog4Net();
    	})
    	.UseStartup<Startup>();
    
  4. 根目录下添加 log4net.config,设置为 “如果较新则复制”;

log4net 提供了多种内置的 appender,配置使用哪种 appender,就会以对应 appender 的实现方式来记录日志。以下例子使用了 FileAppender,日志的格式由 layout 设定,追加的方式写入 Logs/log-file.log。

<?xml version="1.0" encoding="utf-8" ?>
<log4net>
  <appender name="FileAppender" type="log4net.Appender.FileAppender">
	<file value="Logs/log-file.log" />
	<appendToFile value="true" />
	<layout type="log4net.Layout.PatternLayout">
	  <conversionPattern value="%date [%thread] %-5level %logger - %message%newline" />
	</layout>
  </appender>
  <root>
	<level value="ALL"/>
	<appender-ref ref="FileAppender" />
  </root>
</log4net>

appender 支持自定义,只要符合 appender 定义规则即可,这里我开发了一个将日志写入 Kafka 的 Nuget 包, log4net.Kafka.Core ,安装后在 log4net.config 添加 KafkaAppender 配置即可。 log4net.Kafka.Core 源码 在 github 上 ,可以 Fork 自行修改。

<?xml version="1.0" encoding="utf-8" ?>
<log4net>
  <appender name="KafkaAppender" type="log4net.Kafka.Core.KafkaAppender, log4net.Kafka.Core">
    <KafkaSettings>
      <broker value="127.0.0.1:9092" />
      <topic value="api-log" />
    </KafkaSettings>
    <layout type="log4net.Kafka.Core.KafkaLogLayout,log4net.Kafka.Core" >
      <appid value="api-test" />
    </layout>
  </appender>
  <root>
    <level value="ALL"/>
    <appender-ref ref="KafkaAppender" />
  </root>
</log4net>

broker: Kafka 服务地址,集群可使用,分割;

topic:日志对应的 Topic 名称;

appid:服务唯一标识,辅助识别日志来源;

KafkaAppender 日志写入 Kafka Topic 的格式如下:

{
	"host_name": "Beck",
	"logger_name": "WebApi.Controllers.ValuesController",
	"log_timestamp": 1543745129111,
	"level": "INFO",
	"message": "自定义的日志内容",
	"app_id": "api-test",
	"exception": null
}

接下来我们需要修改 Logstash 的配置文件,之前 Logstash 的 input 设置的是标准输入,现在需要改成 Kafka 输入( 可以理解为 Logstash 是 Kafka 的消费端, 将消费 api-log 这个 Topic ),输出改到 Elasticsearch, 这里使用 app_id 作为索引名称,使得每个服务的日志相互独立,便于后续查看。修改后的 logstash.conf 如下:

# 输入
input { 
  kafka {
   codec => "json"
   bootstrap_servers => "localhost:9092"
   topics => ["api-log"] 
   auto_offset_reset => "earliest"
  }
}

filter {
  date {
    # 时间戳转换
    match => [ "log_timestamp" , "UNIX_MS" ]
  }
}

# 输出
output {
  # 输出到 Elasticsearch
  elasticsearch {
    # Elasticsearch 地址
    hosts => ["localhost:9200"] 
    # Elasticsearch 索引名
    index => "logstash-%{app_id}"
  }
}

在 ValuesController 修改代码进行测试:

public class ValuesController : ControllerBase
{
	private readonly ILogger _logger;

	public ValuesController(ILogger<ValuesController> logger)
	{
		_logger = logger;
	}

	[HttpGet]
	public ActionResult<IEnumerable<string>> Get()
	{
		_logger.LogInformation("request api/values");
		_logger.LogError(new Exception("出错啦!!!"), "request api/values");
		return new string[] { "value1", "value2" };
	}
}

接口调用完成后,可以通过 Kibana 查看到索引 logstash-api-test 的日志信息。

7BB7bmF.png!web

目前 log4net.Kafka.Core 封装的并不完善,后面会继续优化。

参考链接


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK