Logging
Elasticsearch:如何“拯救”無法通過映射解析的文件?
我們使用 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