[翻译] 使用ElasticSearch,Kibana,ASP.NET Core和Docker可视化数据

原文地址:http://www.dotnetcurry.com/aspnet/1354/elastic-search-kibana-in-docker-dotnet-core-appjavascript

想要轻松地经过许多不一样的方式查询数据,甚至是从未预料到的方式?想要以多种方式可视化日志?同时支持基于时间、文本和其余类型的即时过滤器?
借助于 Elastic stack 的卓越性能和可扩展方式的优势,咱们将经过两个示例轻松实现。html

本文由 DNC Magazine for Developers and Architects 发布。 从这里下载此杂志[PDF] 或 免费订阅本杂志 下载全部之前和当前的版本版本。java

在这篇文章中,我将介绍流行的搜索引擎 Elasticsearch,其配套的可视化应用 Kibana,并展现如何对.NET核心能够轻松地与 Elastic stack 整合在一块。git


Elasticsearch和.Net Core


咱们将开始探索 Elasticsearch 的 REST API ,经过索引和查询某些数据。接着,咱们将使用Elasticsearch官方的 .Net API 完成相似的练习。一旦熟悉 Elasticsearch 及其 API 后,咱们将使用 .Net Core 建立一个日志模块,并将数据发送到 Elasticsearch 。Kibana紧随其中,以有趣的方式可视化 Elasticsearch 的索引数据。
我迫切但愿你会认为这篇文章十分有趣,而且想要了解更多关于Elastic的强大之处。github

本文假设您已经了解 C#和 REST API 的基本知识。使用 Visual Studio,Postman 和 Docker 等工具,但您能够轻松使用 VS Code 和 Fiddler 等替代方案。docker

Elasticsearch - 简介

Elasticsearch 做为核心的部分,是一个具备强大索引功能的文档存储库,而且能够经过 REST API 来搜索数据。它使用 Java 编写,基于 Apache Lucene,尽管这些细节隐藏在 API 中。
经过被索引的字段,能够用许多不一样的聚合方式找到任何被存储(索引)的文档。
可是,ElasticSearch不只仅只提供对这些被索引文档的强大搜索功能。
快速、分布式、水平扩展,支持实时文档存储和分析,支持数百台服务器和 PB 级索引数据。同时做为 Elastic stack (aka ELK) 的核心,提供了诸如 LogStash、Kibana 和更多的强大应用。
Kibana 是 Elasticsearch 中专门提供强有力的可视化查询Web应用程序。使用Kibana,能很是简单地为 Elasticsearch 中索引的数据建立查询、图表和仪表盘。
Elasticsearch开放了一个 REST API,你会发现许多文档示例是 HTTP 调用,你能够尝试使用 curl 或 postman 等工具。固然,这个 API 的客户端已经用许多不一样的语言编写,包括.Net、Java、Python、Ruby和JavaScript等。
若是你想阅读更多,Elasticsearch 官方网站 多是最好的地方。数据库

Docker是在本地运行的最简方式

在这篇文章中,咱们须要先链接到一个 Elasticsearch (和后面的Kibana)的服务器。若是您已经有一个在本地运行或可使用的服务器,那很好。不然须要先搭建一个服务器。
您能够选择在您的本地机器或可使用的 VM 或服务器中下载和安装 Elasticsearch 和 Kibana 。不过,建议您使用最简单最纯粹的方式,使用Docker 搭建 Elasticsearch 和 Kibana 。
您能够直接运行如下命令,获取包含Elasticsearch和Kibana的容器。apache

docker run -it --rm -p 9200:9200 -p 5601:5601 --name esk nshou/elasticsearch-kibana
  • -it 表示以交互模式启动容器,并附加到终端。
  • --rm 表示从终端退出后,容器将被移除。
  • -p 将容器中的端口映射到主机中的端口
  • --name 给容器一个名称,当您不使用的状况下能够用 --rm 手动中止/删除
  • nshou/elasticsearch-kibana 是 Docker Hub中的一个镜像的名称,已经有人帮你准备好了Elasticsearch和Kibana
  • 若是你喜欢在后台运行的话,你可使用参数-d 代替 --it --rm,而且手动中止/删除容器。

在同一个容器中运行多个应用程序,就像咱们如今这种作法,很是适用本文,但不是推荐用于生产容器!windows

您应该意识到,一旦你删除容器,你的数据就会消失(一旦你使用-rm选项就删除它了)。虽然有利于本地实验,但在实际环境中,若是您不想丢失数据,请参照 "data container" 模式。api

Docker是一个很棒的工具,我鼓励你更多地了解它,特别是若是你想作更重要的事情,而不只仅是跟随本文,在本地快速搭建 Elasticsearch 服务器。在以前的文章 Building DockNetFiddle using Docker and .NET Core 中已经对 .NET Core 搭配 Docker 有很好的介绍。

只需打开 http://localhost:9200 和 http://localhost:5600 ,检查Elasticsearch 和 Kibana 是否均可以使用。(若是您使用docker toolbox,请使用托管Docker的虚拟机ip替换localhost,您能够在命令行中运行 docker-machine env default )。


在docker中运行 Elasticsearch

kibana也准备好了

在 Elasticsearch 中索引和查询

在咱们开始编写任何 .Net 代码以前,咱们先了解一下一些基本知识。先在 Elasticsearch 索引一些文档(相似于存到数据库),以便咱们对它们运行不一样的查询。

在这里,我将使用Postman向咱们的 Elasticsearch 服务器发送 HTTP 请求,但您可使用任何其余相似的工具,如 Fiddler或 curl 。

咱们要作的第一件事是请求 Elasticsearch 建立一个新的索引 (译者语:相似建立一个表) 并索引一些文档 (译者语:相似于在数据中插入数据) 。这相似于将数据存储在表/集合中,主要区别(和目的)是让 Elasticsearch 集群 (这里只是一个节点) 能够分析和搜索文档数据。
被索引的文档在 Elasticsearch 中以索引和类型进行组织。以往,被拿来和数据库表作对比,每每会使人困惑。如这篇文章所述,索引由Lucene处理,在分布式跨 分片 中,与类型紧密地联系在一块儿。
发送如下两个请求以建立索引,并在该索引中插入文档 (请记住 toolbox,若是使用docker ,请使用托管Docker的虚拟机ip而不是localhost) :

  • 建立一个名为 "default" 的新索引。
PUT localhost:9200/default
  • 在 "default" 索引中索引文档。请注意,咱们须要知道咱们存储哪一种类型的文档("product")和该文档的ID (如 1,尽管您可使用任何值,只要它是惟一的)
PUT localhost:9200/default/product/1 { "name": "Apple MacBook Pro", "description": "Latest MacBook Pro 13", "tags": ["laptops", "mac"] }

建立一个新索引

索引新文档


在咱们验证搜索功能和查询数据以前,再索引几个 "product"。尝试使用不一样的 "tags",如 "laptops"和 "laptops",并记得使用不一样的ids!
完成后,让咱们按名称排序的搜索全部被索引的文档。您可使用查询字符串或 GET/POST 一样的内容,下面两个请求是等效的:

GET http://localhost:9200/default/_search?q=*&sort=name.keyword:asc
POST http://localhost:9200/default/_search { "query": { "match_all": {} }, "sort": [ { "name.keyword": "asc" } ] }

让咱们尝试一些更有趣的东西,例如搜索 "description" 字段中含有 "latest" ,同时 "tags" 字段中含有 "laptops" 的全部文档:

POST http://localhost:9200/default/_search { "query": { "bool": { "must": [ { "match": {"description": "latest"} }, { "match": { "tags": "laptops" } } ] } }, "sort": [ { "name.keyword": "asc" } ] }

搜索结果

Kibana 可视化数据

做为介绍的最后部分,咱们将对 Kibana 的相关知识走马观花。
假设您在上一步已经索引了几个文档,经过访问 http://localhost:5601 中打开在 Docker 的 Kibana 服务器。你会注意到,Kibana 要求你提供默认的索引模式,因此必须告诉它使用的 Elasticsearch 索引:

  • 咱们在上一节中建立了一个名为 "default" 的索引,所以可使用 "default" 做为索引模式。
  • 您还须要取消 "索引包含基于时间的事件 (Index contains time-based events ) " 选项,由于咱们的文档不包含任什么时候间字段。

在 Kibana 中添加索引模式


完成后,使用左侧菜单打开 " 发现 (Discover) " 页面,您应该会看到上一节中插入的全部最新文档。尝试选择不一样的字段,在搜索栏中输入相关的字段或某个过滤器:


在 kibana 中可视化数据


最后,咱们建立一个饼图,显示 "laptops" 或 "desktops" 的销量百分比。利用以前索引的数据,在左侧菜单新建一个 "饼图 (Pie Chart)" 。
您能够在 饼图 (Pie Chart)的页面上配置。将 " Count " 做为切片的大小,并在 " buckets " 部分中选择 " split slices " 。将 " filters " 做为聚合类型,添加两个过滤器:tags ="laptop" 和 tags ="desktoptops" 。单击运行,您将看到相似于下图:


在Kibana中建立饼图


确保在搜索栏中输入包含已过滤的项目的搜索关键词,并注意到可视化图形如何变化。

Elasticsearch .Net API

在简要介绍Elasticsearch和Kibana以后,咱们来看看咱们如何用 .Net 应用程序索引和查询咱们的文档。
您可能想知道为何要这样作,而不是直接使用 HTTP API 。我能够提供几个理由,我相信你能够本身找几个:

  • 你不想直接暴露 Elasticsearch 集群
  • Elasticsearch 可能不是您的主数据库,您可能须要结合来自主数据库的结果。
  • 你但愿包含来自存储/生产服务器中的被索引文档

首先须要注意的是打开 这个文档 ,有两个官方提供的 APIs : Elasticsearch.Net 和 NEST ,都支持 .Net Core 项目。

  • Elasticsearch.Net 提供了一个用于与 Elasticsearch链接的低级API,提供构建/处理请求和响应的功能。它是 .Net 瘦客户端。
  • NEST 在 Elasticsearch.Net 之上,提供了更高级别的 API 。它能够将对象映射到请求/响应中,提供强大查询功能,将索引名称、文档类型、字段类型用于构建与 HTTP REST API 的匹配查询。

    Elasticsearch .Net API

因为我使用的是 NEST,因此第一步是建立一个新的 ASP .Net Core 应用程序,并使用 Package Manager 安装NEST。

使用Nest开始索引数据

咱们将在新的 ASP.Net Core 应用程序中完成以前手动发送 HTTP 请求的一些步骤。若是须要,请从新启Docker 容器,从而清理数据;或经过 HTTP API 和 Postman 手动删除文档/索引。
咱们首先为产品建立一个POCO模型:

public class Product { public Guid Id { get; set; } public string Name { get; set; } public string Description { get; set; } public string[] Tags { get; set; } }

接下来,咱们建立一个新的控制器 ProductController,它具备添加新的 "Product" 的方法和基于单个关键词查找 "Product" 的方法:

[Route("api/[controller]")] public class ProductController : Controller { [HttpPost] public async Task< IActionResult > Create([FromBody]Product product) { } [HttpGet("find")] public async Task< IActionResult > Find(string term) { } }

为了实现这些方法,咱们须要先链接到 Elasticsearch。这里有一个 ElasticClient 链接的正确示范。 因为该类是线程安全的,因此推荐的方法是在应用程序中使用单例模式,而不是按请求建立新的链接。

为了简洁起见,我如今将使用带有硬编码设置的私有静态变量。在 .Net Core 中使用依赖注入配置框架,或查看 Github中 的代码

能够想到的是,至少须要提供被链接的 Elasticsearch 集群的URL。固然,还有其余可选参数,用于与您的群集进行身份验证、设置超时、链接池等。

private static readonly ConnectionSettings connSettings = new ConnectionSettings(new Uri("http://localhost:9200/")); private static readonly ElasticClient elasticClient = new ElasticClient(connSettings);

创建链接后,索引文档只是简单地使用 ElasticClient 的Index/IndexAsync 方法:

[Route("api/[controller]")] public class ProductController : Controller { [HttpPost] public async Task<IActionResult> Create([FromBody]Product product) { } [HttpGet("find")] public async Task<IActionResult> Find(string term) { } }

很简单,对吧?不幸的是,若是您向Postman发送如下请求,您将看到失败。

POST http://localhost:65113/api/product { "name": "Dell XPS 13", "description": "Latest Dell XPS 13", "tags": ["laptops", "windows"] }

这是由于NEST没法肯定在索引文档时使用哪一个索引!若是您想起手动使用 HTTP API 的作法,那么须要在URL指出文档的索引、文档的类型和ID,如 localhost:9200/default/product/1

NEST可以推断文档的类型(使用类的名称),还能够默认对字段进行索引(基于字段的类型),但须要一些索引名称的帮助。您能够指定默认的索引名称,以及特定类型的特定索引名称。

connSettings = new ConnectionSettings(new Uri("http://192.168.99.100:9200/")) .DefaultIndex("default") //Optionally override the default index for specific types .MapDefaultTypeIndices(m => m .Add(typeof(Product), "default"));

进行这些更改后再试一次。您将看到 NEST 建立索引(若是还没有存在),并将文档编入索引。若是你切换到 Kibana,你也能够看到该文档。须要注意的是:

  • 从类的名称推断文档类型,如 Product
  • 在类中将Id属性推断为标识
  • 将全部公开的属性发送到 Elasticsearch

使用NEST索引的文档


在咱们查询数据以前,从新考虑建立索引的方式。
如何建立索引?
如今咱们获得一个事实,即若是这个索引不存在,也会被建立。然而映射字段的索引方式很重要,并直接定义了 Elasticsearch 如何索引和分析这些字段。这对于字符串字段尤为明显,由于在 Elasticsearch v5 中提供了两种不一样字段类型的 "Text" 和 "Keyword":

  • Text 类型的字段将会被分析和分解成单词,以便用于更高级的 Elasticsearch 搜索功能
  • 另外一方面,Keyword 字段将 "保持原样" 而不进行分析,只能经过其精确值进行搜索。

您可使用 NEST 索引映射属性来生成POCO模型:

public class Product { public Guid Id { get; set; } [Text(Name="name")] public string Name { get; set; } [Text(Name = "description")] public string Description { get; set; } [Keyword(Name = "tag")] public string[] Tags { get; set; } }

然而,咱们须要先建立索引,必须使用 ElasticClient API 手动建立和定义索引的映射。这是很是简单的,特别是若是咱们只是使用属性:

if (!elasticClient.IndexExists("default").Exists) { elasticClient.CreateIndex("default", i => i .Mappings(m => m .Map<Product>(ms => ms.AutoMap()))); }

直接向Elasticsearch发送请求(GET localhost:92000/default),并注意与咱们想要的映射是否相同。


使用NEST建立索引映射

使用Nest查询数据

如今,咱们有一个使用 NEST 对 "products" 进行索引的 ProductController 控制器。是时候,为这个控制器添加 Find action,用于使用 NEST 向 Elasticsearch 查询文档。
咱们只是用到一个字段来实现一个简单的搜索。您应该观察全部字段:

  • 映射为 "Text" 类型的字段能够被分析,您能够在 "name" / "description" 字段内搜索特定的单词
  • 映射为 "Keywords" 的字段是保持原样的,未进行分析。您只能在 "tags" 字段中彻底匹配。

NEST 提供了一个查询 Elasticsearch 的丰富 API,能够转换成标准的 HTTP API 。实现上述查询类型与使用Search/SearchAsync方法同样简单,并构建一个 SimpleQueryString 做为参数。

[HttpGet("find")] public async Task<IActionResult> Find(string term) { var res = await elasticClient.SearchAsync<Product>(x => x .Query( q => q. SimpleQueryString(qs => qs.Query(term)))); if (!res.IsValid) { throw new InvalidOperationException(res.DebugInformation); } return Json(res.Documents); }

使用PostMan测试您的新操做:


使用nest查询


正如您可能已经意识到的那样,咱们的操做行为与手动发送请求到 Elasticsearch 同样:

GET http://localhost:9200/default/_search?q=*&

在 .Net Core 中建立一个Elasticsearch日志提供程序

如今咱们了解了 NEST 的一些基础知识,让咱们尝试一些更有野心的事情。咱们已经建立了一个 ASP.Net Core 的应用程序,借助.NET Core的日志框架,实现咱们的日志提供程序,并将信息发送到Elasticsearch。
新的日志 API 在日志 (logger) 和日志提供程序 (logger provider) 方面的区别:

  • 日志 (logger) 记录信息和事件,如用于控制器中
  • 能够为应用程序添加并启用多个日志提供程序 (provider) ,并能够配置独立的记录级别和记录相应的信息/事件。

该日志框架内置了一些对事件日志、Azure 等的日志提供程序 (provider),但正如您将看到的,建立本身的并不复杂。有关详细信息,请查阅.NET Core 关于日志的官方文档
在本文的最后部分,咱们将为Elasticsearch建立一个新的日志提供程序,在咱们的应用程序中启用它,并使用Kibana来查看记录的事件。

为Elasticsearch添加一个新的日志提供程序

首先要作的是定义一个新的POCO对象,咱们将使用它做为使用NEST进行索引的文档,相似于以前建立的 "Product" 类。
这将包含有关可能发生的任何异常以及相关请求数据的记录信息、可选信息。记录请求数据将会派上用场,由于咱们能够根据具体请求查询/可视化咱们记录的事件。

public class LogEntry { public DateTime DateTime { get; set; } public EventId EventId { get; set; } [Keyword] [JsonConverter(typeof(StringEnumConverter))] public Microsoft.Extensions.Logging.LogLevel Level { get; set; } [Keyword] public string Category { get; set; } public string Message { get; set; } [Keyword] public string TraceIdentifier { get; set; } [Keyword] public string UserName { get; set; } [Keyword] public string ContentType { get; set; } [Keyword] public string Host { get; set; } [Keyword] public string Method { get; set; } [Keyword] public string Protocol { get; set; } [Keyword] public string Scheme { get; set; } public string Path { get; set; } public string PathBase { get; set; } public string QueryString { get; set; } public long? ContentLength { get; set; } public bool IsHttps { get; set; } public IRequestCookieCollection Cookies { get; set; } public IHeaderDictionary Headers { get; set; } [Keyword] public string ExceptionType { get; set; } public string ExceptionMessage { get; set; } public string Exception { get; set; } public bool HasException { get { return Exception != null; } } public string StackTrace { get; set; } }

下一步是在一个新类上实现ILogger接口。如您所想,这将须要记录的数据映射到一个新的 LogEntry 对象,并使用 ElasticClient 对其进行索引。

  • 咱们将使用IHttpContextAccessor,以便咱们能够获取当前的HttpContext并提取相关的请求属性。

在这里就不写链接到Elasticsearch并建立索引的代码,这与以前的操做,没有什么不一样。使用不一样的索引或删除上一节中索引的 "products" 。

注意: 您可使用依赖注入和配置文检查 Github 中 的配套代码。

实现的主要方法是Log <TState>,这是咱们建立一个LogEntry并用NEST进行索引:

public void Log< TState >(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func< TState, Exception, string > formatter) { if (!IsEnabled(logLevel)) return; var message = formatter(state, exception); var entry = new LogEntry { EventId = eventId, DateTime = DateTime.UtcNow, Category = _categoryName, Message = message, Level = logLevel }; var context = _httpContextAccessor.HttpContext; if (context != null) { entry.TraceIdentifier = context.TraceIdentifier; entry.UserName = context.User.Identity.Name; var request = context.Request; entry.ContentLength = request.ContentLength; entry.ContentType = request.ContentType; entry.Host = request.Host.Value; entry.IsHttps = request.IsHttps; entry.Method = request.Method; entry.Path = request.Path; entry.PathBase = request.PathBase; entry.Protocol = request.Protocol; entry.QueryString = request.QueryString.Value; entry.Scheme = request.Scheme; entry.Cookies = request.Cookies; entry.Headers = request.Headers; } if (exception != null) { entry.Exception = exception.ToString(); entry.ExceptionMessage = exception.Message; entry.ExceptionType = exception.GetType().Name; entry.StackTrace = exception.StackTrace; } elasticClient.Client.Index(entry); }

您还须要额外实现 BeginScope 和 IsEnabled 方法。

  • 为了本文的目的,忽略 BeginScope,只返回null。
  • 更新您的构造函数,以便它接收一个日志级别(LogLevel),若是接收到大于或等于构造函数中的日志级别,则实现 IsEnabled 并返回 true。

你可能会问为何须要分类?这是一个用于标识日志是哪一种类型的字符串。默认状况下,每次注入ILogger <T>的实例时,该类别默认分配为T的分类名称。例如,获取ILogger <MyController>并使用它来记录某些事件,意味着这些事件将具备 "MyController " 名称。
这可能派上用场,例如为不一样的类设置不一样的日志级别,以过滤/查询记录的事件。我相信您可能还想到更多的用法。

这个类的实现将以下所示:

public class ESLoggerProvider: ILoggerProvider { private readonly IHttpContextAccessor _httpContextAccessor; private readonly FilterLoggerSettings _filter; public ESLoggerProvider(IServiceProvider serviceProvider, FilterLoggerSettings filter = null) { _httpContextAccessor = serviceProvider.GetService<IHttpContextAccessor>(); _filter = filter ?? new FilterLoggerSettings { {"*", LogLevel.Warning} }; } public ILogger CreateLogger(string categoryName) { return new ESLogger(_httpContextAccessor, categoryName, FindLevel(categoryName)); } private LogLevel FindLevel(string categoryName) { var def = LogLevel.Warning; foreach (var s in _filter.Switches) { if (categoryName.Contains(s.Key)) return s.Value; if (s.Key == "*") def = s.Value; } return def; } public void Dispose() { } }

最后,咱们建立一个扩展方法,能够用于在启动类中注册咱们的日志提供程序:

public static class LoggerExtensions { public static ILoggerFactory AddESLogger(this ILoggerFactory factory, IServiceProvider serviceProvider, FilterLoggerSettings filter = null) { factory.AddProvider(new ESLoggerProvider(serviceProvider, filter)); return factory; } } public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) { loggerFactory.AddConsole(Configuration.GetSection("Logging")) .AddDebug() .AddESLogger(app.ApplicationServices, new FilterLoggerSettings { {"*", LogLevel.Information} }); … }

请注意我如何覆盖默认设置并按日志级别分类记录。这样,咱们能够轻松地为每一个请求索引一些事件。

在Kibana中可视化数据

如今咱们已经在Kibana中记录了事件,咱们来探索数据可视化吧!
首先,在Kibana中重建索引,此次确保选择" Index contains time-based events ( Index包含基于时间的事件 )",选择字段dateTime做为"Time-field name (时间字段名称)"。
接下来,启动您的应用程序,浏览一些页面以获取一些事件日志。还能够在某个端点随意添加抛出异常的代码,以便咱们能够看到被记录的异常数据。
在这以后,请转到Kibana的 发现 (Discover) 页面,您能够看到由 "dateTime" 字段排序的多个事件(默认状况下,数据被过滤为最近15分钟,但您能够在右上角更改):


Kibana可视化中记录的事件


试着在搜索栏中输入 "exception",并注意任何一个被分析的文本字段中包含 "exception" 的事件。而后尝试搜索特定的异常类型(记住咱们使用了一个关键字字段!)。
您还能够尝试搜索特定的URL,如以 " /Home/About "和" /Home/About" 路径的两种搜索方式 。您会注意到第一种状况包括引用者是 "/Home/About" 的事件,而第二种状况则只能正确返回路径为 "/Home/About" 的事件。
一旦你熟悉了数据,以及如何查询数据,那么能够用数据建立一些有趣的图形。
首先,咱们将建立一个图表,显示每分钟记录的异常数。

  • 转到Kibana的 可视化 (Visualize) 页面,并建立一个新的 垂直条形图 (Vertical bar chart) 。
  • 选择Y轴做为计数,X轴上为日期的直方图。
  • 将间隔设置为每分钟,最后在搜索框中添加一个过滤器 "hasException:true" 。

一个很棒的图表,显示每分钟记录的异常数目:


每分钟记录的异常数目


接下来,显示每一个 category 随时间记录的消息数量,限于前5个 category :

  • 转到Kibana的 可视化 (Visualize) 页面,并建立一个新的 线型图 (Line chart) 。
  • 再次选择Y轴做为计数,X轴上为日期的直方图,选择dateTime做为字段,间隔为每分钟。
  • 如今添加一个 sub-bucket 并选择 "split lines" 。使用 "significant terms" 做为聚合,category 为字段,单位为5个。

这将绘制相似于如下的图表:


随着时间的推移


尝试在搜索框中添加一些过滤器,并查看它对结果的影响。
最后,咱们添加另外一个图表,咱们将看到前五个出现最多的消息和前五个 categories 的消息。

  • 转到Kibana的 可视化 (Visualize) 页面,并建立一个新的 饼图 (Pie chart) 。
  • 像以前同样,选择Y轴的计数
  • 如今,将 "Terms" 做为聚合,将 "category" 做为字段,数量做为单位,限制前五个,画出图表。
  • 而后将 "Terms" 做为聚合来分割切片,"message.keyword" 做为字段,数量做为单位,限制前五个。
    一旦你有了这些设置,你会看到一个相似于这个图表:

每一个 category 中最多见的消息


花时间观察下数据(百分比,message/category 显示在图表元素上)。例如,您将观察到由
DeveloperExceptionPageMiddleware类记录的异常。

结论

Elasticsearch是一个强大的数据索引和查询平台。虽然它自己至关使人印象深入,但与其余应用程序(如Kibana)相结合,能够很好地分析、报告和可视化数据。只要您开始使用,只是走马观花都能的到非凡的结果。
对于 .Net 和 .Net Core,Elasticsearch 官方的 API 已经覆盖,由于它们支持 .Net Standard 1.3和更高版本(他们仍然在为1.1提供支持)。
正如咱们已经看到的,在 ASP.Net Core 项目中使用这个 API 是很方便的,咱们能够轻松地将其 REST API 做为存储,以及在应用程序中做为日志提供程序。
最后但并不是不重要的一点,我但愿您使用Docker。尝试使用 Elasticsearch,同时思考Docker能够为您和您的团队作些什么。

下载本文的所有源代码(Github)。

相关文章
相关标签/搜索