'elastic'에 해당되는 글 130건

  1. 2020.04.02 [Kibana] Docker Compose 구성 하기
  2. 2020.04.02 [Elasticsearch] Docker Compose 구성 하기
  3. 2020.04.01 [Beats] Metricbeat Docker Compose 기본 구성 하기
  4. 2020.04.01 [Kibana] Docker Compose 설정 시 environment 중
  5. 2020.03.19 [Elasticsearch] 작은 팁!!
  6. 2020.02.28 [Logstash] CSV 파일 밀어 넣기
  7. 2020.02.18 [Elasticsearch] Block-Max WAND 가 뭔가요?
  8. 2020.02.14 [Elasticsearch] App Search 소개.
  9. 2019.11.07 [Logstash] 최적화 설정 정보
  10. 2019.11.06 [Logstash] logstash filter date 조금 알아보기

[Kibana] Docker Compose 구성 하기

Elastic/Kibana 2020. 4. 2. 08:28

Kibana를 Docker로 구성 하기 위한 docker-compose.yml 내용을 살펴 봅니다.

 

참고문서)

 

https://www.elastic.co/guide/en/kibana/current/docker.html

 

docker-compose.yml)

version: '2.2'
services:
  ${KIBANA-SERVICE-NAME}:
    image: docker.elastic.co/kibana/kibana:7.6.2
    container_name: ${KIBANA-SERVICE-NAME}
#    depends_on:
#      - ${ES-SERVICE-NAME}
    ports:
      - 5601:5601
    expose:
      - 5601
    environment:
      ELASTICSEARCH_HOSTS: http://host.docker.internal:9200
    networks:
      - ${NETWORK-NAME}

networks:
  ${NETWORK-NAME}:
    driver: bridge

위 설정은 host 에서 Elasticsearch 를 Standalone 으로 띄우고 Kibana 를 컨테이너로 실행 시킨 후 연동 하도록 한 것입니다.

접속은 아래와 같이 하면 됩니다.

- http://localhost:5601

 

만약, docker-compose.yml 파일 내 Elasticsearch 와 Kibana 를 모두 구성해서 띄우실 때는 아래 설정을 맞춰 주면 됩니다.

- depends_on : 섹션에서 Elasticsearch 실행 후 Kibana 가 실행 되도록 구성

- network 구성은  같은 걸 사용하도록 하고 bridge 로 설정

- kibana 에서 elasticsearch 를 찾기 위해 host.docker.internal 이 아닌 ${ES-SERVICE-NAME} 으로 변경

 

또는 다른 인스턴스에 Elasticsearch 가 구성이 되어 있다면,

- environment: 섹션에서 host.docker.internal 이 아닌 Elasticsearch가 구성된 인스턴스의 DNS나 IP로 변경

하시면 됩니다.

 

 

 

 

:

[Elasticsearch] Docker Compose 구성 하기

Elastic/Elasticsearch 2020. 4. 2. 07:49

Elasticsearch 를 Single Node 로 구성 하기 위한 docker-compose.yml 내용을 살펴 봅니다.

 

참고문서)

https://www.elastic.co/guide/en/elasticsearch/reference/current/docker.html

 

docker-compose.yml)

version: '2.2'
services:
  ${ES-SERVICE-NAME}:
    image: docker.elastic.co/elasticsearch/elasticsearch:7.6.2
    container_name: ${ES-SERVICE-NAME}
    environment:
      - node.name=${NODE-NAME}
      - cluster.name=${CLUSTER-NAME}
      - discovery.type=single-node
      - discovery.seed_hosts=${NODE-NAME}
      - path.data=/usr/share/elasticsearch/data
      - path.logs=/usr/share/elasticsearch/logs
      - bootstrap.memory_lock=true
      - http.port=9200
      - transport.port=9300
      - transport.compress=true
      - network.host=0.0.0.0
      - http.cors.enabled=false
      - http.cors.allow-origin=/https?:\/\/localhost(:[0-9]+)?/
      - gateway.expected_master_nodes=1
      - gateway.expected_data_nodes=1
      - gateway.recover_after_master_nodes=1
      - gateway.recover_after_data_nodes=1
      - action.auto_create_index=true
      - action.destructive_requires_name=true
      - cluster.routing.use_adaptive_replica_selection=true
      - xpack.monitoring.enabled=false
      - xpack.ml.enabled=false
      - http.compression=true
      - http.compression_level=3
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
    ulimits:
      memlock:
        soft: -1
        hard: -1
      nproc:
        soft: 1024000
        hard: 1024000
      nofile:
        soft: 1024000
        hard: 1024000
    sysctls:
      net.core.somaxconn: 65000
    healthcheck:
      test: ["CMD-SHELL", "curl --silent --fail localhost:9200/_cat/health || exit 1"]
      interval: 30s
      timeout: 30s
      retries: 3
    restart: always
    volumes:
      - ${NAMED-VOLUME-DATA}:/usr/share/elasticsearch/data:rw
      - ${NAMED-VOLUME-LOG}:/usr/share/elasticsearch/logs:rw
#      - ${FULL-PATH-DATA}:/usr/share/elasticsearch/data:rw
#      - ${FULL-PATH-LOG}:/usr/share/elasticsearch/logs:rw
    ports:
      - 9200:9200
      - 9300:9300
    expose:
      - 9200
      - 9300
    networks:
      - ${NETWORK-NAME}

volumes:
  ${NAMED-VOLUME-DATA}:
    driver: local
  ${NAMED-VOLUME-LOG}:
    driver: local

networks:
  ${NETWORK-NAME}:
    driver: bridge

 

Single Node 로 구성 하기 위해 중요한 설정은

- environment: 섹션에서 discovery.type=single-node 

입니다.

 

만약, Clustering 구성을 하고 싶다면 위 설정을 제거 하고 아래 세개 설정을 작성 하시면 됩니다.

- cluster.initial_master_nodes=# node 들의 private ip 를 등록 합니다.
- discovery.seed_hosts=# node 들의 private ip 를 등록 합니다.

- network.publish_host=# 컨테이너가 떠 있는 host 의 private ip 를 등록 합니다.

 

path.data 에 대한 구성을 복수로 하고 싶으실 경우

- volumes: 섹션에서 named volume 을 여러개 설정 하시거나

- bind mount 설정을 구성 하셔서 

적용 하시면 됩니다.

 

위 docker-compose.yml 을 기준으로 single node 구성과 cluster 구성을 모두 하실 수 있습니다.

 

  • ${....} 는 변수명 입니다.
    • 본인의 환경에 맞춰 작명(?) 하셔서 변경 하시면 됩니다.
:

[Beats] Metricbeat Docker Compose 기본 구성 하기

Elastic/Beats 2020. 4. 1. 20:38

대부분 올라온 예제가 docker-compose.yml 내 ELKB 구성을 한방에 해서 사용을 하게 되어 있는데,

하고 싶은건 metricbeat 만 컨테이너 기반으로 올려서 agent 형태로 사용하고 다른 노드에서 실행 되고 있는

- Elasticsearch 와

- Kibana 로

통신 하게 하고 싶어서 기록해 봅니다.

 

특별한 내용은 전혀 없습니다.

 

참고문서)

https://www.elastic.co/guide/en/beats/metricbeat/current/running-on-docker.html

 

docker-compose.yml)

version: "3.7"
services:
  metricbeat:
    image: docker.elastic.co/beats/metricbeat:7.6.2
    user: root
    environment:
      - ELASTICSEARCH_HOSTS=http://host.docker.internal:9200
      - KIBANA_HOST=http://host.docker.internal:5601
    network_mode: "host"
    ports:
      - 9200:9200
      - 5601:5601

 

$ docker-compose up -d

 

위 구성은 host 장비에 Elasticsearch 와 Kibana 가 실행 되고 있고,

Metricbeat 를 컨테이너로 실행 시키고 host 장비를 모니터링 하기 위한 구성입니다.

즉, Metricbeat 를 컨테이너 기반의 Agent 로 사용 하는 거라고 보면 될 것 같습니다.

 

관련 문서는 아래 참고 하세요.

https://www.elastic.co/guide/en/beats/metricbeat/current/running-on-docker.html#monitoring-host

 

:

[Kibana] Docker Compose 설정 시 environment 중

Elastic/Kibana 2020. 4. 1. 09:47

kibana docker compose 에서 아래 변수가 어떤 값을 참조 하는지 확인 하시기 바랍니다.

 

참고 문서)

https://www.elastic.co/guide/en/kibana/current/docker.html

environment:
    ELASTICSEARCH_URL: http://${SERVICE-NAME}:9200
    ELASTICSEARCH_HOSTS: http://${SERVICE-NAME}:9200
또는
    ELASTICSEARCH_URL: http://${CONTAINER-NAME}:9200
    ELASTICSEARCH_HOSTS: http://${CONTAINER-NAME}:9200

단일 노드에 Elasticsearch 와 Kibana 두 개의 컨테이너를 띄울 때 Kibana 에서는 Elasticsearch 의 Service 명 또는 Container 명으로 Elasticsearch 를 찾습니다.

:

[Elasticsearch] 작은 팁!!

Elastic/Elasticsearch 2020. 3. 19. 20:15

Elasticsearch 를 사용 하다 보면 Maximum 값에 대한 궁금증이 생길 때가 있습니다.

지나가다 또 기억 못할 까봐 적어 봅니다.

 

1. Shard 하나가 가질 수 있는 최대 Document/Term 의 수는 대략 21억개 입니다.

Elasticsearch 에서 Shard 는 Lucene 기준에 Segments 에 해당 합니다.

공식 문서에는 아래와 같이 나와 있습니다.

https://lucene.apache.org/core/8_4_1/index.html

https://lucene.apache.org/core/8_4_1/core/org/apache/lucene/codecs/lucene84/package-summary.html#Limitations

Lucene uses a Java int to refer to document numbers, 
and the index file format uses an Int32 on-disk to store document numbers. 
This is a limitation of both the index file format and 
the current implementation. 
Eventually these should be replaced with either UInt64 values, 
or better yet, VInt values which have no limit.

 

그래서 == 2,147,483,647

 

2. Shard  1개의 크기는 너무 작아도 너무 커도 안됩니다.

실시간 서비스를 위한 용도로는 ~ 10GB

백오피스 운영을 위한 용도로는 ~ 50GB (그러나 Aggregation 질의가 많고 검색 범위가 넓을 경우 20GB 정도로 사용하세요.)

정답은 없으며, 다양한 환경에 따라 적절히 구성해서 사용을 하셔야 합니다.

 

3. Document 1개의 크기는 최대 2GB 까지 입니다.

그러나 이렇게 까지 사용 하시라고 절대 저는 추천 하지 않습니다.

 

:

[Logstash] CSV 파일 밀어 넣기

Elastic/Logstash 2020. 2. 28. 18:35

전에 그냥 문서 링크만 걸었었는데 혹시 샘플 코드가 필요 하신 분들도 있을 수 있어서 기록해 봅니다.

 

[config/logstash-csv.conf]

input {
  file {
      path => ["/Users/henryjeong/Works/poc/elastic/data/*.csv"]
      start_position => "beginning"
  }
}

filter {
    csv {
        separator => ","
        columns => ["title", "cat1", "cat2", "cat3", "area", "sigungu", "description"]
    }

    mutate { rename => ["title", "tt"] }
}

output {
  elasticsearch {
    hosts => ["http://localhost:9200"]
    index => "csv-%{+YYYY.MM.dd}"
  }
}

[*.csv]

title,cat1,cat2,cat3,area,sigungu,description
엄마손충무김밥,음식,음식점,한식,경상남도,통영시,"KBS ""1박2일"" 욕지도 복불복에 추천된 충무김밥집이다."
평창동의 봄,음식,음식점,한식,서울,종로구,"평창동의 명소, 평창동 언덕마을에 유럽풍의 아름다운 음식점 & 카페. 1층에는 커피는 물론 계절빙수, 단팥죽, 호박죽, 허브티를 파는 카페, 2층에는 식당이 있다. 2층 식당에서는 평창동 봄만의 특별한 한정식 코스 요리와 웰빙 삼계탕 등의 음식을  선보이고 있다. 3층은 최대 40명수용의 연회룸이 있고, 갤러리 전시와 건강교실도 운영하고 있다. "

음봉가든,음식,음식점,한식,경기도,가평군,"음봉가든 (구, 진짜네집)은 자연산 민물고기만을 고집하는 50년 전통의 진정한 매운탕전문점이다. 주재료로 쓰이고 있는 메기 및 쏘가리, 빠가사리
등은 주인이 직접 낚아 올린 물고기로 매우 신선하며 매운탕 역시 얼큰하고 개운하다. 또한 집앞에서 직접 재배하고 키우는 야채와 채소는 매운탕의 국물맛을 더욱 맛나게 해준다."

대자골토속음식,음식,음식점,한식,경기도,고양시,경기 북부지방에선 국수나 수제비를 넣어 국물을 넉넉하게 만든 음식을 '털레기'라 하는데 이곳은 '미꾸라지털레기'를 주메뉴로 하는 30여년
내력의 경기 북부지방 대표향토음식점이다. 주인이 직접 야채와 채소를 재배하는데 고춧가루까지도 직접 재배한 것을 사용한다고하니 그 사명감이 대단하다 할 수 있겠다. 통미꾸라지매운탕의 옛맛을 찾는 사람이라면 꼭 한번은 들려봐야 전통 맛집이다.

장수촌,음식,음식점,한식,경기도,광명시,"부드러운 닭고기 육질에 구수한 누룽지가 함께 하는 '누룽지삼계탕'. 거기다 잘 익은 김치 한 점 더 한다면 그 어떤 맛도 부러울 것이 없다. 식사메뉴인 '누룽지삼계탕'과 '쟁반막국수', 안주메뉴인 골뱅이무침 메뉴가 전부인 '장수촌'은 경기도 광명의 대표맛집으로 토종닭 선별부터 양념 재료 하나 하나까지 일일이 주인이 직접 선별하는 그 정성과 끈기가 맛의 비결이라 할 수 있겠다."
청기와뼈다귀해장국,음식,음식점,한식,경기도,부천시,"부천 사람이라면 모르는 이 없을 정도로 유명한 집이다. 돼지고기와 국물에서 냄새가 안나 여성이나 어린이들 특히 어르신들 보양식으로
도 입소문이 난 곳인데, 부재료 보다는 뼈다귀로 양을 채우는 그 푸짐함 또한 그 소문이 자자하다. 양질의 돼지 뼈에 사골 국물과 우거지를 넣어 맛을 낸 뼈다귀 해장국. 그 맛을 제대로 만날 수 있는 대표적인 음식점이다. "

일번지,음식,음식점,한식,경기도,성남시,닭요리의 으뜸이라 해도 과언이 아닌 '남한산성 닭죽촌민속마을' 에서 남한산성 등산후 가장 많이 찾는 집 중에 한 집이다. 특히 이집은 닭백숙 이외에 '닭도가니'로도 유명한데 이집의 '도가니'는 소의 도가니를 뜻 하는 것이 아니라 장독대의 '독'에서 유래된 말로 '독'에 밥과 닭과 여러보약재를 넣어 만드는 것으로 그 맛과 영양면에서 닭요리 중에 최고라 할 수 있겠다.

장금이,음식,음식점,한식,경기도,시흥시,"경기도 시흥의 지역특산물 중의 하나가 바로 '연'이다. 연은 수련과에 속하는 다년생 수생식물로 뿌리채소로는 드물게 다량의 비타민과 무기질을 함유하고 있어 최근 건강식 식품원료로 각광받고 있으나 그 효능에 비해 다양한 조리방법이 개발되어 있지 않아 흔히 '연'하면 '연근' 반찬 이외엔 생각나는 것이 없는데, 물왕동 연요리전문점 '장금이'를 찾으면 그렇지 않음을 직접 확인 할 수 있다. 흔치 않은 색다른 한정식을 원한다면 한 번쯤은 꼭 한 번 들러 연밥정식과 연잎수육을 맛 봐야 할 곳이다. "

안성마춤갤러리,음식,음식점,한식,경기도,안성시,경기도 안성의 농산물 브랜드 '안성마춤'을 내세워 만든 고품격 갤러리풍 식당으로 각종 공연과 작품전시회 감상과 동시에 농협에서 직접 운영하는 특등급 안성한우를 맞볼 수 있는 곳으로 유명한 집이다. 특히 안성마춤한우 중에 10%만 생산된다는 슈프림급 한우는 늦어도 하루 전에는 꼭 예약을 해야 그 맛을 볼 수 있다 하여 그 희소성에 더더욱 인기가 높다.

언덕너머매운탕,음식,음식점,한식,경기도,연천군,민물고기 중에 살이 탱탱하고 쫄깃한 맛으로 매운탕 재료 중에 으뜸이라 불리우는 '쏘가리'를 메인메뉴로 자랑하는 이집의 '쏘가리매운탕'은
임진강에서 직접 잡아올린 자연 그대로의 그 담백하고 칼칼한 맛이 일품이라 할 수 있다.

보기 좋으라고 개행을 추가 했습니다.

실제 개행 없이 들어 있습니다.

위 데이터는 공공데이터에서 제가 추려 온 데이터 입니다.

 

위 데이터에서는 Datatype 에 대한 변환을 고민 하지 않아도 되지만 필요한 경우가 있을 수도 있습니다.

공식문서)

https://www.elastic.co/guide/en/logstash/current/plugins-filters-csv.html#plugins-filters-csv-convert

 

convert

  • Value type is hash
  • Default value is {}

Define a set of datatype conversions to be applied to columns. Possible conversions are integer, float, date, date_time, boolean

Example:

    filter {
      csv {
        convert => {
          "column1" => "integer"
          "column2" => "boolean"
        }
      }
    }

keyword 나 text 는 지원 하지 않으며 지원하는 datatype 은 integer, float, date, date_time, boolean 입니다.

 

csv 파일을 밀어 넣을 때 주의 하셔야 하는 점은)

- input 에서 codec 으로 csv 를 지정 하시게 되면 column 명 지정이 원하는 데로 되지 않습니다.

- filter 에서 처리를 하셔야 정상적으로 column 명이 field 명으로 들어 가게 됩니다.

- input codec csv 와 filter 모두 설정 안하게 되면 그냥 message field 에 row 단위로 들어 가게 됩니다.

 

mutate { rename => ["title", "tt"] }

- 이건 뭔지 딱 보셔도 아시겠죠?

- column 명을 title 에서 tt 로 변경 해서 field 로 생성 되게 됩니다.

 

:

[Elasticsearch] Block-Max WAND 가 뭔가요?

Elastic/Elasticsearch 2020. 2. 18. 14:48

Top N 개에 대한 문서를 검색 하기 위한 성능 개선 제안으로 2012년에 처음 이슈화 되었던 것 같습니다.

처음에 저도 WAND 가 뭐지?? 했었는데요.

 

기억력이 나빠서 자꾸 잊어버리네요.

 

Weak and = Weak AND = WAND 이렇게 됩니다.

즉, Elasticsearch 에서는 minimum_should_match 라는 개념이 들어가 있다는 것인데,

정확도가 떨어지지 않는다고 합니다.

어찌되었든,  WAND와 유사 개념이라고 보시면 이해 하기 쉬우실 것 같습니다.

 

근데 앞에 보시면 Block-Max 라고 붙어 있죠.

이걸 또 초간단하게 설명 하면 문서를 특정 블럭단위로 묶으고 그 안에서의 Max Score 를 기록해 두는 방식 입니다.

이렇게 해서 문서 스캔 범위를 줄이게 되어 성능성 이득을 볼 수 있는 내용이라고 보시면 될 것 같습니다.

 

뭐 문서랑 알고리즘을 잘 읽어 보시면 더 심오한 내용이 있으나 쉽게 접근하는 것도 중요하다고 생각 하기 때문에 이렇게 정리 하도록 하겠습니다.

 

자세한 내용이 궁금하신 분은 아래 문서 보시면 됩니다.

http://engineering.nyu.edu/~suel/papers/bmw.pdf

bmw.pdf
0.32MB

 

 

더불어 Elastic 공홈에 올라온 관련 글 링크 입니다.

https://www.elastic.co/blog/elasticsearch-7-6-0-released
https://www.elastic.co/blog/faster-retrieval-of-top-hits-in-elasticsearch-with-block-max-wand
https://www.elastic.co/blog/index-sorting-elasticsearch-6-0

 

여기서 추가적으로 나오는 기법들이  

 

- Early Termination

이건 탐색 할 때 특정 조건에 맞춰 전체를 스캔 하지 않고 중간에 멈추고 스캔한 문서를 대상으로 리턴 하는 방식입니다.

- Document At A Time

문서에 대한 포인트 탐색 으로 보시면 될 것 같고 성능이 우수 합니다.

- Term At A Time

색인어에 대한 탐색을 하는 것으로 별도의 데이터구조에 따른 병목이 발생 할 수 있습니다.

 

등이 있습니다.

 

최종 정리를 하면,

1. Top N 개에 대해서 빠르게 조회를 한다.

2. 정확도가 떨어지지 않는다.

3. 그러므로 고민 하지 말고 최신 Elasticsearch 를 사용 하면 알아서 성능적 향상을 가져 올 수 있으니 사용 하시면 된다

는 이야기 였습니다.

 

:

[Elasticsearch] App Search 소개.

Elastic/Elasticsearch 2020. 2. 14. 15:44

굉장히 좋은 제품인데 ㅎㅎ 아직 잘 모르시는 분들이 많으신 것 같아서 제가 소개해 보려고 합니다.

이미 Elastic 공홈에는 올라가 있습니다.

 

관련 글)

https://www.elastic.co/kr/blog/automation-through-search-analytics-with-elastic-app-search

https://www.elastic.co/kr/blog/elastic-app-search-now-available-on-elasticsearch-service

https://swiftype.com/documentation/app-search/getting-started

 

기본적으로는 elastic 사가 swiftype 이라는 회사를 합병 하면서 관련 제품이 enable 되었다고 보시면 됩니다.

제 기억에는  샌프란시스코에서 했던 2번째 Elastic{On} 에서 소개가 되었던 것 같습니다.

 

기본 통신 방식은 (글로 작성 하기 때문에 전달이 잘 안될 수도 있으니 양해 바랍니다.)

 

Elasticsearch Cluster <-----> App Search <-----> App Search API <-----> Your Application

 

보셔서 아시겠지만 App Search API 를 이용하기 때문에 기존에 Elasticsearch Cluster 로 질의 하기 위한 별도 API Gateway 나 WAS 를 구현 하셨던 분들은 더 이상 구현 하지 않으셔도 됩니다.

더불어 검색을 통한 사용자 행동로그 역시 요구사항에 따라 다를 수 있지만, App Search 에서 자동으로 수집, 분석을 다 해줍니다.

 

엄청나게 편리 하겠죠!!

 

이 제품을 잘 활용 하시면 실제 구축 시간 절약이 가능하고, 검색관련 전문 지식이 없으셔도 검색 서비스를 잘 운영 할 수 있습니다.

 

한번 시도해 보시죠)

https://www.elastic.co/app-search

https://www.elastic.co/downloads/app-search

https://www.elastic.co/downloads/elasticsearch

 

위에서 말씀 드렸듯이 기본 Elasticsearch 가 설치 되어 있어야 합니다.

다운로드 페이지 보시면 기본 설치 과정에 대한 내용이 있으니 참고 하셔서 좋은 경험해 보시길 바랍니다.

:

[Logstash] 최적화 설정 정보

Elastic/Logstash 2019. 11. 7. 15:00

공식 문서에 잘 나와 있습니다.

https://www.elastic.co/guide/en/logstash/current/tuning-logstash.html

https://www.elastic.co/guide/en/logstash/current/performance-tuning.html

 

기본적으로 아래 두 개 설정만 잘 세팅 하셔도 성능 뽑아 낼 수 있습니다.

 

pipeline.workers)

이 설정 값은 그냥 기본으로 Core 수 만큼 잡아 주고 시작 하시면 됩니다.

 

pipeline.batch.size)

Worker thread 가 한 번에 처리 하기 위한 이벤트의 크기 입니다.
최적 크기는 직접 구하셔야 합니다.

결국 Elasticsearch 로 Bulk Request 를 보내기 위한 최적의 크기로 설정 한다고 보시면 됩니다.

 

이외 더 봐주시면 좋은 건

- CPU

- MEM

- I/O (Disk, Network)

- JVM Heap

:

[Logstash] logstash filter date 조금 알아보기

Elastic/Logstash 2019. 11. 6. 14:34

문의가 들어 왔습니다.

여러 필드에 대해서 date format 이 다른데 어떻게 적용을 해야 하나요?

 

그래서 소스코드를 열어 보고 아래와 같이 해보라고 했습니다.

date {
...
}

date {
...
}

결국 date {...} 를 필드 별로 선언을 해주면 되는 내용입니다.

 

공식 문서)

https://www.elastic.co/guide/en/logstash/current/plugins-filters-date.html

 

Common Options)

https://www.elastic.co/guide/en/logstash/current/plugins-filters-date.html#plugins-filters-date-common-options

 

Date Filter Configuration Options)

Setting

Input type

Required

locale

string

No

match

array

No

tag_on_failure

array

No

target

string

No

timezone

string

No

전체 옵션이 필수가 아니긴 합니다.

그래도 꼭 아셔야 하는 설정은 match, target 입니다.

 

- match 의 첫 번째 값은 field 명이고, 그 이후는 format 들이 되겠습니다.

(공식 문서에 잘 나와 있습니다.)

 

An array with field name first, and format patterns following, [ field, formats... ]

If your time field has multiple possible formats, you can do this:

 

match => [ "logdate", 

    "MMM dd yyyy HH:mm:ss", 

    "MMM d yyyy HH:mm:ss", 

    "ISO8601" ]

 

- target 은 지정을 하지 않게 되면 기본 @timestamp 필드로 설정이 됩니다. 변경 하고자 하면 target 에 원하시는 field name 을 넣으시면 됩니다.

 

예제)

date {
    match => ["time" , "yyyy-MM-dd'T'HH:mm:ssZ", "yyyy-MM-dd'T'HH:mm:ss.SSSZ"]
    target => "@timestamp"
}

date {
    match => ["localtime" , "yyyy-MM-dd HH:mm:ssZ"]
    target => "time"
}

DateFilter.java)

더보기
/*
 * Licensed to Elasticsearch under one or more contributor
 * license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright
 * ownership. Elasticsearch licenses this file to you under
 * the Apache License, Version 2.0 (the "License"); you may
 * not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package org.logstash.filters;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.joda.time.Instant;
import org.logstash.Event;
import org.logstash.ext.JrubyEventExtLibrary.RubyEvent;
import org.logstash.filters.parser.CasualISO8601Parser;
import org.logstash.filters.parser.JodaParser;
import org.logstash.filters.parser.TimestampParser;
import org.logstash.filters.parser.TimestampParserFactory;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class DateFilter {
  private static Logger logger = LogManager.getLogger();
  private final String sourceField;
  private final String[] tagOnFailure;
  private RubyResultHandler successHandler;
  private RubyResultHandler failureHandler;
  private final List<ParserExecutor> executors = new ArrayList<>();
  private final ResultSetter setter;

  public interface RubyResultHandler {
    void handle(RubyEvent event);
  }

  public DateFilter(String sourceField, String targetField, List<String> tagOnFailure, RubyResultHandler successHandler, RubyResultHandler failureHandler) {
    this(sourceField, targetField, tagOnFailure);
    this.successHandler = successHandler;
    this.failureHandler = failureHandler;
  }

  public DateFilter(String sourceField, String targetField, List<String> tagOnFailure) {
    this.sourceField = sourceField;
    this.tagOnFailure = tagOnFailure.toArray(new String[0]);
    if (targetField.equals("@timestamp")) {
      this.setter = new TimestampSetter();
    } else {
      this.setter = new FieldSetter(targetField);
    }
  }

  public void acceptFilterConfig(String format, String locale, String timezone) {
    TimestampParser parser = TimestampParserFactory.makeParser(format, locale, timezone);
    logger.debug("Date filter with format={}, locale={}, timezone={} built as {}", format, locale, timezone, parser.getClass().getName());
    if (parser instanceof JodaParser || parser instanceof CasualISO8601Parser) {
      executors.add(new TextParserExecutor(parser, timezone));
    } else {
      executors.add(new NumericParserExecutor(parser));
    }
  }

 public List<RubyEvent> receive(List<RubyEvent> rubyEvents) {
    for (RubyEvent rubyEvent : rubyEvents) {
      Event event = rubyEvent.getEvent();

      switch (executeParsers(event)) {
        case FIELD_VALUE_IS_NULL_OR_FIELD_NOT_PRESENT:
        case IGNORED:
          continue;
        case SUCCESS:
          if (successHandler != null) {
            successHandler.handle(rubyEvent);
          }
          break;
        case FAIL: // fall through
        default:
          for (String t : tagOnFailure) {
            event.tag(t);
          }
          if (failureHandler != null) {
            failureHandler.handle(rubyEvent);
          }
      }
    }
    return rubyEvents;
  }

  public ParseExecutionResult executeParsers(Event event) {
    Object input = event.getField(sourceField);
    if (event.isCancelled()) { return ParseExecutionResult.IGNORED; }
    if (input == null) { return ParseExecutionResult.FIELD_VALUE_IS_NULL_OR_FIELD_NOT_PRESENT; }

    for (ParserExecutor executor : executors) {
      try {
        Instant instant = executor.execute(input, event);
        setter.set(event, instant);
        return ParseExecutionResult.SUCCESS;
      } catch (IllegalArgumentException | IOException e) {
        // do nothing, try next ParserExecutor
      }
    }
    return ParseExecutionResult.FAIL;
  }
}

 

: