Logging

Elasticsearch:如何“拯救”無法通過映射解析的文件?

  • November 19, 2019

我們使用 ElasticSearch 來儲存和檢查來自我們基礎設施的日誌。其中一些日誌是法律要求的,我們不能失去任何日誌。

我們已經在沒有任何映射的情況下解析日誌很長一段時間了。這使得它們大多無法用於搜尋和/或繪圖。例如,一些整數欄位已被自動辨識為文本,因此我們無法在直方圖中聚合它們。

我們想引入模板和映射,這將解決新索引的問題。

但是,我們注意到擁有映射也為解析失敗打開了大門。如果一個欄位被定義為整數,但突然得到一個非整數值,那麼解析將失敗,文件將被拒絕。

這些文件有什麼地方去和/或有什麼方法可以保存它們以供以後檢查?

下面的 Python 腳本適用於本地 ES 實例。

#!/usr/bin/env python3

import requests
import JSON
from typing import Any, Dict


ES_HOST = "http://localhost:9200"


def es_request(method: str, path: str, data: Dict[str, Any]) -> None:
   response = requests.request(method, f"{ES_HOST}{path}", json=data)

   if response.status_code != 200:
       print(response.content)


es_request('put', '/_template/my_template', {
   "index_patterns": ["my_index"],
   "mappings": {
       "properties": {
           "some_integer": { "type": "integer" }
       }
   }
})

# This is fine
es_request('put', '/my_index/_doc/1', {
   'some_integer': 42
})

# This will be rejected by ES, as it doesn't match the mapping.
# But how can I save it?
es_request('put', '/my_index/_doc/2', {
   'some_integer': 'hello world'
})

執行腳本會出現以下錯誤:

{
   "error": {
       "root_cause": [
           {
               "type": "mapper_parsing_exception",
               "reason":"failed to parse field [some_integer] of type [integer] in document with id '2'. Preview of field's value: 'hello world'"
           }
       ],
       "type": "mapper_parsing_exception",
       "reason":"failed to parse field [some_integer] of type [integer] in document with id '2'. Preview of field's value: 'hello world'",
       "caused_by": {
           "type": "number_format_exception",
           "reason": "For input string: \"hello world\""
       }
   },
   "status": 400
}

然後文件失去了,或者看起來是這樣。我可以在某處設置一個選項,將文件自動保存在其他地方,一種死信隊列嗎?

**tl;dr:**我們需要映射,但不能因為解析錯誤而失去日誌行。我們可以自動將不適合映射的文件保存到其他地方嗎?

事實證明,它就像允許“格式錯誤”的屬性一樣簡單。有兩種方法可以做到這一點。在整個索引上:

PUT /_template/ignore_malformed_attributes
{
 "index_patterns": ["my_index"],
 "settings": {
     "index.mapping.ignore_malformed": true
 }
}

或每個屬性(參見此處的範例:https ://www.elastic.co/guide/en/elasticsearch/reference/current/ignore-malformed.html )

PUT my_index
{
 "mappings": {
   "properties": {
     "number_one": {
       "type": "integer",
       "ignore_malformed": true
     },
     "number_two": {
       "type": "integer"
     }
   }
 }
}

# Will work
PUT my_index/_doc/1
{
 "text":       "Some text value",
 "number_one": "foo" 
}

# Will be rejected
PUT my_index/_doc/2
{
 "text":       "Some text value",
 "number_two": "foo" 
}

請注意,您還可以更改現有索引的屬性,但您需要先關閉它:

POST my_existing_index/_close
PUT my_existing_index/_settings
{
 "index.mapping.ignore_malformed": false
}
POST my_existing_index/_open

注意:在刷新索引模式之前,類型更改不會在 kibana 中可見。然後,您將遇到類型沖突,這需要您重新索引數據以再次搜尋它……真是太痛苦了。

POST _reindex
{
 "source": {
   "index": "my_index"
 },
 "dest": {
   "index": "my_new_index"
 }
}

https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-reindex.html

引用自:https://serverfault.com/questions/978150