'date'에 해당되는 글 5건

  1. 2022.11.21 [Elasticsearch] Date Type 사용 시
  2. 2021.10.06 [Elasticsearch] Date Format & Logback Timestamp Format
  3. 2019.11.06 [Logstash] logstash filter date 조금 알아보기
  4. 2016.10.18 [Range Query] datetime query 작성 예제.
  5. 2015.12.09 [Elasticsearch - The Definitive Guide] Ranges

[Elasticsearch] Date Type 사용 시

Elastic/Elasticsearch 2022. 11. 21. 21:59

Elastic Stack 에서 Date Field Type 사용 시 내용을 인지 하고 사용 하셔야 데이터에 대해서 기대한 결과를 얻을 수 있습니다.

 

우선, Elasticsearch 는 기본 UTC 시간을 사용 합니다.

색인 되는 Date 값은 모두 UTC 로 저장 된다고 보시면 됩니다.

또한 기본 질의 시 사용 하는 값도 UTC 입니다.

 

하지만, Kibana 를 사용 하다 보면 UTC 에 대한 사용이 불편해서 브라우저 TZ 설정이나 사용자 정의 TZ 설정으로 Date 값을 사용 할 때가 있습니다.

이때 주의 해야 할 점은 실제 색인된 데이터에 대한 변형이나 조작이 있는게 아닌 Client 단에서 TZ 설정에 따른 질의 시 Date 값 변환이나 화면에서의 조작을 한다는 것을 알아야 합니다.

 

아래 설명은 그냥 저 혼자 기억하기 위해서 풀어 쓴걸 올려 둔 내용 입니다.

- kibana 에서는 실제 색인된 date 유형의 값에 대한 tz 설정으로 화면에서 변환 된 정보로 보여 주는 것이며,
실제 질의는 utc 데이터로 질의가 이루어 집니다.
  ㄴ 결국 query dsl 작성 시 utc 기준으로 작성이 되어야 하기 때문에
     본인이 속한 tz 값을 계산 해서 질의 값에 반영이 되어야 합니다.
  ㄴ 단순 tz 설정만 하고 현재 속한 tz 값 기준으로 질의를 작성 하게 되면
     KST 기준으로는 미래에 대한 datetime 값으로 질의를 하게 되어 데이터가 존재 하지 않을 수 있습니다.

  QueryDSL UTC 값 변환을 위한 TZ 설정과 값은 아래와 같이 해야 동작 합니다.
    KST 기준으로 오전 11시 보다 큰 값으로 질의 하고자 할 때 Elasticsearch 는 UTC 기준으로
    오전 2시 보다 큰 값으로 질의가 되어야 합니다.
      "time_zone": "+09:00",
      "gte": "2022-11-18T11:00:00.000"
      to
      "gte": "2022-11-18T02:00:00.000"
    와 같이 실제 Elasticsearch 에 저장 되는 UTC 값으로 변환 되어 질의하게 됩니다.
    아래와 같이 설정 되면 동작 하지 않습니다.
      "time_zone": "+09:00",
      "gte": "2022-11-18T11:00:00.000Z"
    Z 가 들어 가게 되면 TZ 설정이 적용 무시 되고 값 자체를 UTC 값으로 질의 하게 됩니다.

Z 는 java.time 아래 클래스 관련 설명이 되어 있습니다. (소스코드 참고하세요.)

:

[Elasticsearch] Date Format & Logback Timestamp Format

Elastic/Elasticsearch 2021. 10. 6. 12:18

Elasticsearch 에서 data field 를 이용해서 range 질의를 하기 위해서는 format 을 잘 맞춰 줘야 합니다.

Springboot 로 개발 한 WAS 에서 로그를 JSON 으로 찍으면서 timestamp 값에 대한 format 기 위한 설정에 대해서 기록 합니다.

 

참고문서)

https://www.elastic.co/guide/en/elasticsearch/reference/current/date.html
https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-range-query.html
http://logback.qos.ch/manual/layouts.html

 

Logback Timestamp Format & JSON 설정)

https://jjeong.tistory.com/1570

  <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
    <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
      <layout class="ch.qos.logback.contrib.json.classic.JsonLayout">
        <timestampFormat>yyyy-MM-dd'T'HH:mm:ss.SSS'Z'</timestampFormat>
        <timestampFormatTimezoneId>Asia/Seoul</timestampFormatTimezoneId>
        <appendLineSeparator>true</appendLineSeparator>
        <jsonFormatter class="ch.qos.logback.contrib.jackson.JacksonJsonFormatter">
          <prettyPrint>true</prettyPrint>
        </jsonFormatter>
      </layout>
    </encoder>
  </appender>

 

Timestamp Formet Index)

{
  "mappings": {
    "properties": {
      "timestamp": {
        "type":   "date",
        "format": "strict_date_optional_time||epoch_millis",
        "ignore_malformed": true
      }
    }
  }
}

위 foramt 설정은 별도로 하지 않아도 기본 설정 됩니다.

 

Document Put)

{
    "timestamp" : "2021-10-06T11:33:46.855Z"
}

Range Query )

[Case 1]
{
    "query": {
        "range" : {
            "ts": {
                "gte": "2021-10-06T11:33:36.000Z",
                "lte": "2021-10-06T11:34:38.000Z"
            }
        }
    }
}

[Case 2]
{
    "query": {
        "range" : {
            "ts": {
                "gte": "2021-10-06 11:33:36.000",
                "lte": "2021-10-06 11:34:38.000",
                "format": "yyyy-MM-dd HH:mm:ss.SSS"
            }
        }
    }
}

결국 입력 값이 정확 하면 질의 시 format 을 지정해서 편하게 검색이 가능 합니다.

 

:

[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;
  }
}

 

:

[Range Query] datetime query 작성 예제.

Elastic/Elasticsearch 2016. 10. 18. 11:15

늘 그렇듯이 기억력의 한계 극복을 위해 기록합니다.


              "range": {
                "time": {
                  "gte": "2016-10-17 00:00:00.000",
                  "lte": "2016-10-17 23:59:59.999",
                  "format": "yyyy-MM-dd HH:mm:ss.SSS",
                  "time_zone": "+09:00"
                }
              }


보시면 다들 아시는 내용입니다.


[참고문서]

https://www.elastic.co/guide/en/elasticsearch/reference/2.4/query-dsl-range-query.html

https://www.elastic.co/guide/en/elasticsearch/reference/2.4/mapping-date-format.html

https://www.elastic.co/guide/en/elasticsearch/reference/2.4/date.html

:

[Elasticsearch - The Definitive Guide] Ranges

Elastic/TheDefinitiveGuide 2015. 12. 9. 17:45

Date type의 field에 대한 range query example 입니다.

기억력 향상을 위해 기록해 봅니다.


원문링크)

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


원문 Snippet)

"range" : { "timestamp" : { "gt" : "2014-01-01 00:00:00", "lt" : "2014-01-07 00:00:00" } }


"range" : { "timestamp" : { "gt" : "now-1h" } }


"range" : { "timestamp" : { "gt" : "2014-01-01 00:00:00", "lt" : "2014-01-01 00:00:00||+1M" } }


: