【问题标题】:Serilog Elasicsearch Sink - custom index template mapping is ignoredSerilog Elasicsearch Sink - 自定义索引模板映射被忽略
【发布时间】:2021-01-18 02:21:12
【问题描述】:

我在 ASP.NET Core 3.1 中使用 Serilog elasticsearch sink(版本 8.4.1,elastic 7.8.0),配置如下:

{
  "Serilog": {
    "MinimumLevel": {
      "Default": "Information",
      "Override": {
        "Serilog.AspNetCore": "Information"
      }
    },
    "Enrich": [ "FromLogContext" ],
    "WriteTo": [
      {
        "Name": "Logger",
        "Args": {
          "configureLogger": {
            "Filter": [
              {
                "Name": "ByIncludingOnly",
                "Args": {
                  "expression": "SourceContext = 'Serilog.AspNetCore.RequestLoggingMiddleware'"
                }
              }
            ],
            "WriteTo": [
              {
                "Name": "Elasticsearch",
                "Args": {
                  "nodeUris": "http://localhost:9200",
                  "indexFormat": "request-logs-{0:yyyy.MM.dd}",
                  "period": 1,
                  "connectionTimeout": 5,
                  "typeName":  "_doc",
                  "inlineFields": true,
                  "restrictToMinimumLevel": "Information"
                }
              }
            ]
          }
        }
      }
    ]
  }
}

我正在使用 Serilog.AspNetCore 的 RequestLogging

app.UseSerilogRequestLogging();

并使用需要对 GeoSpatial 和 IP 属性进行特殊映射的对象来丰富自定义中间件中的 IDiagnosticContext

HttpDiagnostics diagnostics = new HttpDiagnostics
{
  Host = host.ToString(),
  IsHttps = isHttps,
  LocalIp = localIpAddress,
  LocalPort = localPort,
  Protocol = protocol,
  RemoteIp = remoteIpAddress,
  RemotePort = remotePort,
  RequestContentLength = requestContentLength,
  RequestContentType = requestContentType,
  Scheme = scheme,
  UserAgent = userAgent,
  ResponseContentLength = responseContentLength,
  ResponseContentType = responseContentType
};

this.diagnosticContext.Set("Http", diagnostics, true);

我最终在 logevent 中正确映射字段的方法是:使用我的自定义 Object 重新建模 LogEvent 类型,并使用 NEST 客户端为索引模板创建映射。

ElasticClient client = new ElasticClient(new Uri(settings.Uri));
PutIndexTemplateResponse response = client.Indices.PutTemplate(
  settings.Name,
  p => p.IndexPatterns(settings.IndexPattern)
        .Settings(s => s.DefaultPipeline("geoip"))
        .Map<SerilogDiagnosticsLogEvent>(m => m.AutoMap()));

索引模板映射创建正确

{
  "_doc": {
    "properties": {
      "traceId": {
        "fields": {
          "keyword": {
            "ignore_above": 256,
            "type": "keyword"
          }
        },
        "type": "text"
      },
      "level": {
        "fields": {
          "keyword": {
            "ignore_above": 256,
            "type": "keyword"
          }
        },
        "type": "text"
      },
      "requestMethod": {
        "fields": {
          "keyword": {
            "ignore_above": 256,
            "type": "keyword"
          }
        },
        "type": "text"
      },
      "message": {
        "fields": {
          "keyword": {
            "ignore_above": 256,
            "type": "keyword"
          }
        },
        "type": "text"
      },
      "sourceContext": {
        "fields": {
          "keyword": {
            "ignore_above": 256,
            "type": "keyword"
          }
        },
        "type": "text"
      },
      "parentId": {
        "fields": {
          "keyword": {
            "ignore_above": 256,
            "type": "keyword"
          }
        },
        "type": "text"
      },
      "elapsed": {
        "type": "double"
      },
      "spanId": {
        "fields": {
          "keyword": {
            "ignore_above": 256,
            "type": "keyword"
          }
        },
        "type": "text"
      },
      "@timestamp": {
        "type": "date"
      },
      "requestId": {
        "fields": {
          "keyword": {
            "ignore_above": 256,
            "type": "keyword"
          }
        },
        "type": "text"
      },
      "http": {
        "type": "object",
        "properties": {
          "responseContentLength": {
            "type": "long"
          },
          "requestContentLength": {
            "type": "long"
          },
          "geoIp": {
            "type": "object",
            "properties": {
              "cityName": {
                "fields": {
                  "keyword": {
                    "ignore_above": 256,
                    "type": "keyword"
                  }
                },
                "type": "text"
              },
              "countryIsoCode": {
                "fields": {
                  "keyword": {
                    "ignore_above": 256,
                    "type": "keyword"
                  }
                },
                "type": "text"
              },
              "regionName": {
                "fields": {
                  "keyword": {
                    "ignore_above": 256,
                    "type": "keyword"
                  }
                },
                "type": "text"
              },
              "location": {
                "type": "geo_point"
              },
              "continentName": {
                "fields": {
                  "keyword": {
                    "ignore_above": 256,
                    "type": "keyword"
                  }
                },
                "type": "text"
              }
            }
          },
          "remoteIp": {
            "type": "ip"
          },
          "localPort": {
            "type": "integer"
          },
          "scheme": {
            "fields": {
              "keyword": {
                "ignore_above": 256,
                "type": "keyword"
              }
            },
            "type": "text"
          },
          "remotePort": {
            "type": "integer"
          },
          "userAgent": {
            "fields": {
              "keyword": {
                "ignore_above": 256,
                "type": "keyword"
              }
            },
            "type": "text"
          },
          "protocol": {
            "fields": {
              "keyword": {
                "ignore_above": 256,
                "type": "keyword"
              }
            },
            "type": "text"
          },
          "responseContentType": {
            "fields": {
              "keyword": {
                "ignore_above": 256,
                "type": "keyword"
              }
            },
            "type": "text"
          },
          "host": {
            "fields": {
              "keyword": {
                "ignore_above": 256,
                "type": "keyword"
              }
            },
            "type": "text"
          },
          "isHttps": {
            "type": "boolean"
          },
          "localIp": {
            "type": "ip"
          },
          "requestContentType": {
            "fields": {
              "keyword": {
                "ignore_above": 256,
                "type": "keyword"
              }
            },
            "type": "text"
          }
        }
      },
      "connectionId": {
        "fields": {
          "keyword": {
            "ignore_above": 256,
            "type": "keyword"
          }
        },
        "type": "text"
      },
      "messageTemplate": {
        "fields": {
          "keyword": {
            "ignore_above": 256,
            "type": "keyword"
          }
        },
        "type": "text"
      },
      "requestPath": {
        "fields": {
          "keyword": {
            "ignore_above": 256,
            "type": "keyword"
          }
        },
        "type": "text"
      },
      "statusCode": {
        "type": "integer"
      }
    }
  }
}

所以现在我期望 Serilog 索引的文档使用我创建的索引模板的映射。但实际发生的是,创建的索引没有使用模板中的正确映射。因此 IP 字段被索引为字符串,这导致 GeoIp 管道无法处理这些字段。

现在我问自己:我的配置有问题吗? Serilog 是否总是使用他们的映射索引日志事件?如何将正确的映射应用到日志事件中的自定义属性?

【问题讨论】:

    标签: serilog elasticsearch-net


    【解决方案1】:

    所以正如这个 Github 问题 https://github.com/serilog/serilog-sinks-elasticsearch/issues/366 中所述...

    原来使用 NEST 客户端创建的索引模板映射是使用驼峰式命名的属性名称,而 LogEvent 上的自定义属性是 pascal-case,这触发了弹性搜索的动态映射并导致重复的映射条目.

    编辑

    您可以通过使用映射属性注释模型的属性并将名称设置为 pascal-case 来解决此问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-14
      • 1970-01-01
      • 2021-11-28
      • 2019-03-24
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多