gpt4 book ai didi

.net - 我们如何使用ElasticClient(NEST)提取登录到Elasticsearch的Serilog .ForContext()对象?

转载 作者:行者123 更新时间:2023-12-02 23:54:05 28 4
gpt4 key购买 nike

我们正在寻求使用ELK堆栈更好地集中,组织和搜索日志。当前,我们正在登录数据库表,并且我们有一个EventLog POCO,它捕获填充这些行所需的字段。我们将数据输入到Elasticsearch的第一步是简单地通过Serilog记录事件,如下所示:

EventLog eventLog = ...;
log.ForContext("EventLog", eventLog, true).Write(eventLog.EventMessage);

这将产生一个Serilog“logevent”类型的文档,其中的“字段”包含我们的自定义结构,并为我们提供了大多数所需信息:
{
"_index": "logstash-2019.03.14",
"_type": "logevent",
"_id": "p_amfGkBaphWeJXGjjSW",
"_version": 1,
"_score": null,
"_source": {
"@timestamp": "2019-03-14T09:41:21.6924251-05:00",
"level": "Information",
"messageTemplate": "blah",
"message": "blah",
"fields": {
"EventLog": {
"_typeTag": "EventLog",
"EventMessage": "blah",
"EventId": 3112,
...

Kibana允许我们对自定义结构中的字段的日志进行临时搜索,我们已经很高兴了。

现在,我们想以编程方式搜索日志,我们正在寻找NEST,但是我们还无法确定正确的方法。 ElasticClient.Search<T>似乎是我们需要的,我们不确定 T是什么,也不知道NEST如何解释搜索条件或返回的数据。

我们尝试的是:
client.Search<EventLog>();   // returns zero results
client.Search<Serilog.Events.LogEvent>(); // throws: Error converting string to Serilog.Events.MessageTemplate
client.Search<EventLog>(s => s.Type("logevent")); // returns results!, but the EventLog objects are all empty (properties all have default values)

似乎唯一可以联系我们的电话是:
client.Search<Object>(s => s.Type("logevent")); // returns the raw JSON source of each log entry

因此,我们觉得这里缺少一些简单而基本的东西。 NEST文档都基于直接索引到Elasticsearch中的 Project类型,但是我们需要做些什么才能能够提取和查询我们使用Serilog的 ForContext添加到日志中的自定义结构?

更新:似乎我们可能需要构造一组单独的POCO,以复制Serilog事件的结构,例如:
        private class DummyFields
{
public EventLog EventLog { get; set; }
}

private class Dummy
{
public DummyFields Fields { get; set; }
}


在NEST中查询 Dummy确实确实使我们能够访问我们的内部结构,但是似乎应该有一个更好的方法来执行此操作...

更新2:
我们可以仅实现POCO来匹配查询响应,但是现在看来嵌套结构中的字段匹配还存在其他问题:
client.Search<Dummy>(s => s
.AllTypes()
.Query(q => q
.Match(t => t
.Field(f => f.Message).Query("blah"); // returns some results

client.Search<Dummy>(s => s
.AllTypes()
.Query(q => q
.Match(t => t
.Field(f => f.Fields.EventLog.EventMessage).Query("blah"); // returns zero results

为什么第二个查询没有“看到”我们的嵌套事件消息?

更新3:

奇怪的是,这也起作用:
client.Search<Dummy>(s => s
.AllTypes()
.Query(q => q
.Match(t => t
.Field(f => new Field("fields.EventLog.EventMessage")).Query("blah");

因此,看起来NEST与嵌套字段的类型安全版本不匹配。我们显然不希望这里不必依靠魔术弦...

更新4:

我在ES中启用查询日志记录,发现文字查询和表达式查询之间存在大小写差异。文字查询(具有PascalCased属性)被ES视作Pascal装入并查找文档,而类型安全表达式则转换为camelCase(“fields.eventLog.eventMessage”),并且不匹配任何内容。果然,如果我使用文字驼峰式字段路径查询,我什么也得不到。

如何告诉NEST使用正确的区分大小写?

最佳答案

发送到Elasticsearch的原始JSON文档包含在搜索响应中每个匹配的_source属性内

{
"@timestamp": "2019-03-14T09:41:21.6924251-05:00",
"level": "Information",
"messageTemplate": "blah",
"message": "blah",
"fields": {
"EventLog": {
"_typeTag": "EventLog",

我相信您尝试获取的 "EventLog"在JSON路径 "fields.EventLog"处,因此,任何映射到此且将JSON反序列化的CLR POCO都必须符合此结构,就像上面的 Dummy类型所做的。

您可以采用两种方法来更改此设置:
  • "EventLog"序列化为_source中的整个JSON文档。然后,您可以将其直接映射到您的"EventLog"类型。
  • 实现一个自定义序列化程序,该序列化程序仅将"fields.EventLog"反序列化为给定的EventLog POCO类型。您可以使用 JsonNetSerializer 做到这一点,并为JsonConverter类型实现自定义EventLog。但是,这样做有两个复杂之处:首先,这只能用作读取模型,因为当希望再次进行序列化时,生成的JSON将仅是EventLog的JSON,其次,与NEST使用的内部序列化程序相比,使用JsonNetSerializer具有性能开销。
  • 关于.net - 我们如何使用ElasticClient(NEST)提取登录到Elasticsearch的Serilog .ForContext()对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55170126/

    28 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com