使用ElasticSearch,Kibana,ASP.NET Core和Docker可视化数据
原文地址:http://www.dotnetcurry.com/aspnet/1354/elastic-search-kibana-in-docker-dotnet-core-app
想要輕松地通過許多不同的方式查詢數據,甚至是從未預料到的方式?想要以多種方式可視化日志?同時支持基于時間、文本和其他類型的即時過濾器?
借助于?Elastic?stack 的卓越性能和可擴展方式的優點,我們將通過兩個示例輕松實現。
本文由?DNC Magazine for Developers and Architects?發布。?從這里下載此雜志[PDF] 或?免費訂閱本雜志?下載所有以前和當前的版本版本。
在這篇文章中,我將介紹流行的搜索引擎 Elasticsearch,其配套的可視化應用 Kibana,并展示如何對.NET核心可以輕松地與 Elastic stack 整合在一塊。
Elasticsearch和.Net Core
我們將開始探索 Elasticsearch 的 REST API ,通過索引和查詢某些數據。接著,我們將使用Elasticsearch官方的 .Net API 完成類似的練習。一旦熟悉 Elasticsearch 及其 API 后,我們將使用 .Net Core 創建一個日志模塊,并將數據發送到 Elasticsearch 。Kibana緊隨其中,以有趣的方式可視化 Elasticsearch 的索引數據。
我迫切希望你會認為這篇文章十分有趣,并且想要了解更多關于Elastic的強大之處。
本文假設您已經了解 C#和 REST API 的基本知識。使用 Visual Studio,Postman 和 Docker 等工具,但您可以輕松使用 VS Code 和 Fiddler 等替代方案。
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的容器。
-it 表示以交互模式啟動容器,并附加到終端。
--rm 表示從終端退出后,容器將被移除。
-p 將容器中的端口映射到主機中的端口
--name 給容器一個名稱,當您不使用的情況下可以用 --rm 手動停止/刪除
nshou/elasticsearch-kibana 是?Docker Hub中的一個鏡像的名稱,已經有人幫你準備好了Elasticsearch和Kibana
如果你喜歡在后臺運行的話,你可以使用參數-d 代替 --it --rm,并且手動停止/刪除容器。
在同一個容器中運行多個應用程序,就像我們現在這種做法,非常適用本文,但不是推薦用于生產容器!
您應該意識到,一旦你刪除容器,你的數據就會消失(一旦你使用-rm選項就刪除它了)。雖然有利于本地實驗,但在實際環境中,如果您不想丟失數據,請參照 "data container" 模式。
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" 的新索引。
在 "default" 索引中索引文檔。請注意,我們需要知道我們存儲哪種類型的文檔("product")和該文檔的ID (如 1,盡管您可以使用任何值,只要它是唯一的)
創建一個新索引
索引新文檔
在我們驗證搜索功能和查詢數據之前,再索引幾個 "product"。嘗試使用不同的 "tags",如 "laptops"和 "laptops",并記得使用不同的ids!
完成后,讓我們按名稱排序的搜索所有被索引的文檔。您可以使用查詢字符串或 GET/POST 同樣的內容,下面兩個請求是等效的:
讓我們嘗試一些更有趣的東西,例如搜索 "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模型:
接下來,我們創建一個新的控制器 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 一樣:
在 .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" 類。
這將包含有關可能發生的任何異常以及相關請求數據的記錄信息、可選信息。記錄請求數據將會派上用場,因為我們可以根據具體請求查詢/可視化我們記錄的事件。
下一步是在一個新類上實現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可以為您和您的團隊做些什么。
相關文章:?
使用Elasticsearch 與 NEST 庫 構建 .NET 企業級搜索
配置高性能ElasticSearch集群的9個小貼士
免費開源分布式系統日志收集框架 Exceptionless
ExceptionLess新玩法 — 記日志
原文地址:http://www.cnblogs.com/chenug/p/6681891.html
.NET社區新聞,深度好文,微信中搜索dotNET跨平臺或掃描二維碼關注
總結
以上是生活随笔為你收集整理的使用ElasticSearch,Kibana,ASP.NET Core和Docker可视化数据的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: .NET Framework 4.7发布
- 下一篇: 如何在多个项目中分离Asp.Net Co