You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Serilog Elasticsearch接收器出现404及400错误求助

排查Serilog Elasticsearch接收器的404+400错误

我来帮你拆解这个问题——创建日志器时先出现两次404、再两次400,核心问题基本都和索引模板的读取/创建流程有关,咱们一步步来排查:

先搞懂错误链的逻辑

首先,Serilog Elasticsearch接收器默认会先检查ES中是否存在名为serilog-events-template的索引模板:

  • 第一次404:说明ES里根本没有这个模板
  • 紧接着接收器会尝试自动创建这个模板,但请求被ES拒绝(返回400),重试一次还是失败,所以又出现一次400

常见原因和解决办法

1. ES版本与接收器版本不兼容

这是最常见的坑!不同ES版本对索引模板的格式要求差异很大,比如:

  • ES 7.x移除了模板中的_doc类型字段,ES 8.x又对索引设置的格式做了调整
  • 如果你的ES是8.x,但Serilog.Sinks.Elasticsearch还停留在7.x或更早版本,接收器生成的模板格式完全不符合ES 8.x的要求,必然返回400

解决:

  • 查看你的ES版本(执行GET /),然后升级Serilog.Sinks.Elasticsearch到对应兼容的版本(比如ES 8.x对应接收器v8.0+)
  • 如果暂时不想升级接收器,可以手动创建符合ES版本的模板,然后禁用自动注册:
    _perfElasticLogger = new LoggerConfiguration()
      .WriteTo.Elasticsearch(new ElasticsearchSinkOptions(new Uri("http://{ip}:{port}"))
      {
        AutoRegisterTemplate = false, // 关闭自动创建模板
        IndexFormat = "serilog-{yyyyMMdd}" // 确保索引格式匹配你手动创建的模板模式
      })
      .CreateLogger();
    

2. ES用户权限不足

如果你的ES开启了安全验证,用于写入日志的用户可能没有manage_index_templates权限:

  • 404:用户没有权限读取模板列表,所以返回“找不到”(实际是权限不足的伪装)
  • 400:用户没有权限创建模板,或者创建时因为权限问题导致请求被拦截(部分ES环境会把权限错误返回成400)

解决:

  • 给用户添加manage_index_templatescreate_index权限,比如在Kibana Dev Tools执行:
    PUT /_security/role/serilog-writer
    {
      "cluster": ["manage_index_templates"],
      "indices": [
        {
          "names": ["serilog-*"],
          "privileges": ["create_index", "write", "read"]
        }
      ]
    }
    
  • 然后把这个角色分配给你的日志用户

3. 模板名称或索引格式不匹配

如果你修改过接收器的模板名称或索引格式,可能导致:

  • 接收器检查的模板名(默认serilog-events-template)和你手动创建的不一致,返回404
  • 索引格式包含ES不允许的字符(比如大写字母、空格),导致创建模板时格式错误返回400

解决:

  • 检查接收器配置中的TemplateNameIndexFormat,确保模板名称正确,索引格式只包含小写字母、-_.
  • 用curl手动验证模板是否存在:
    curl -X GET http://{ip}:{port}/_template/serilog-events-template
    

4. 获取详细错误信息定位根因

如果上面的方法都没解决,建议捕获ES返回的详细错误响应,这能直接告诉你400的具体原因:

  • 在接收器配置中添加FailureCallback
    _perfElasticLogger = new LoggerConfiguration()
      .WriteTo.Elasticsearch(new ElasticsearchSinkOptions(new Uri("http://{ip}:{port}"))
      {
        FailureCallback = e => Console.WriteLine($"Failed to send log: {e.Message}, Response: {e.ResponseBody}")
      })
      .CreateLogger();
    
  • 运行程序后,控制台会输出ES返回的错误详情(比如“映射字段type不合法”“索引设置格式错误”),根据提示调整模板或配置

手动创建兼容的模板示例(以ES 8.x为例)

如果需要手动创建模板,在Kibana Dev Tools执行以下请求:

PUT /_template/serilog-events-template
{
  "index_patterns": ["serilog-*"],
  "settings": {
    "number_of_shards": 1,
    "number_of_replicas": 0
  },
  "mappings": {
    "properties": {
      "@timestamp": { "type": "date" },
      "level": { "type": "keyword" },
      "message": { "type": "text" },
      "messageTemplate": { "type": "text" },
      "fields": { "type": "object", "dynamic": true },
      "renderedMessage": { "type": "text" }
    }
  }
}

内容的提问来源于stack exchange,提问作者Maverick Meerkat

火山引擎 最新活动