2025년 3월 23일 일요일

Logstash 필터 geoip - 2nd

geoip 필터를 이용하면 위경도를 포함한 ip 주소의 다양한 지리 정보를 사용할 수 있다. 
{
    "message" => "122.213.34.56",
      "geoip" => {
             "longitude" => 139.6297,
                    "ip" => "122.213.34.56",
         "country_code3" => "JP",
              "latitude" => 35.5843,
              "timezone" => "Asia/Tokyo",
             "city_name" => "Chitose",
           "region_name" => "Kanagawa",
           "region_code" => "14",
              "location" => {
            "lat" => 35.5843,
            "lon" => 139.6297
        },
          "country_name" => "Japan",
           "postal_code" => "213-0021",
         "country_code2" => "JP",
        "continent_code" => "AS"
    }
}

그런데 위경도 정보가 이미 있다면?
filter {
 mutate {
  remove_field => ["@timestamp", "@version", "path", "host"]
 }

 csv {
  columns => ["lat", "lon"]
  add_field => {"point" => "%{lat}"}
  add_field => {"point" => "%{lon}"}
  convert => {"point" => "float"}
 }
}
{
    "message" => "37.48854368,126.9094842\r",
        "lat" => "37.48854368",
        "lon" => "126.9094842",
      "point" => [
        [0] "37.48854368",
        [1] "126.9094842"
    ]
}

point 필드에 위경도 정보 통합. 그런데 숫자 타입 변환이 안 된다. 옵션 순서 문제인가? 타입 변환 과정만 분리.
filter {
 mutate {
  remove_field => ["@timestamp", "@version", "path", "host"]
 }

 csv {
  columns => ["lat", "lon"]
  add_field => {"point" => "%{lat}"}
  add_field => {"point" => "%{lon}"}
 }

 mutate {
  convert => {"point" => "float"}
 }
}
{
    "message" => "37.48854368,126.9094842\r",
        "lat" => "37.48854368",
        "lon" => "126.9094842",
      "point" => [
        [0] 37.48854368,
        [1] 126.9094842
    ]
}

숫자 타입 변환은 됐는데, 이번엔 인뎅싱이 안 된다. 에러 메시지를 보니 위도 정보값이 이상하다고? 위경도 정보에 순서가 있는 모양.
Could not index event to Elasticsearch. {:status=>400, :action=>["index", {:_id=>nil, :_index=>"geotest", :routing=>nil}, {"message"=>"37.48854368,126.9094842\r", "lat"=>"37.48854368", "lon"=>"126.9094842", "point"=>[37.48854368, 126.9094842]}], :response=>{"index"=>{"status"=>400, "error"=>{"type"=>"document_parsing_exception"
"reason"=>"[1:112] failed to parse: illegal latitude value [126.9094842] for point", "caused_by"=>{"type"=>"illegal_argument_exception", "reason"=>"illegal latitude value [126.9094842] for point"}}}}}

경도 정보 먼저 저장.
filter {
 mutate {
  remove_field => ["@timestamp", "@version", "path", "host"]
 }

 csv {
  columns => ["lat", "lon"]
  add_field => {"point" => "%{lon}"}
  add_field => {"point" => "%{lat}"}
 }

 mutate {
  convert => {"point" => "float"}
 }
}
{
    "message" => "37.48854368,126.9094842\r",
        "lat" => "37.48854368",
        "lon" => "126.9094842",
      "point" => [
        [0] 126.9094842,
        [1] 37.48854368
    ]
}

geo_point 타입 필드는 당연히 인덱스 매핑에 미리 만들어놔야 한다.

    크리에이티브 커먼즈 라이선스