본문 바로가기

문돌이 존버/ELK 스터디

Kibana map 시각화에 필요한 geo_point 생성

반응형

Kibana map 시각화 실행

이번에는 키바나 지도를 통해 효과적인 시각화를 사용하는 방법을 소개하겠습니다. 키바나 지도를 쓰기 위해선 기본적으로 데이터 파일에 geo_point라는 타입이 존재해야 합니다. 그런데 이 geo_point가 일반 csv 파일이나 json 파일에 설정되어 있지 않습니다. 저도 한참 헷갈린 것이지만 본인 파일에 latitude, longitude가 있다고 해서 geo_point 타입인 것이 아니라 단순히 number 타입입니다. 

따라서 latitude, longitude 정보를 가지고 geo_point 타입을 만들어내야 하는 것이 가장 큰 과제입니다. 처음에 logstash를 활용하면 elasticsearch에 geo_point가 생성된 파일을 보낼 수 있다고 생각했는데 결국 실패했습니다. 다음은 제가 구글링하며 찾았던 자료들이고 실제 진행하면 geo_point 타입은 생깁니다만 해당되는 데이터가 없는 것으로 나옵니다. 

input {
  file {
    path => "/Users/"labtob name"/Downloads/coronavirusdataset_20200601/Case.csv"
    start_position => "beginning"
    #sincedb_path => "/dev/null"    
  }
}
filter {
  csv {
      separator => ","
      columns => ["case_id","province","city","group","infection_case","confirmed","lat","lon"]
  }
  mutate {convert => ["lat", "float"]}
  mutate {convert => ["lon", "float"]}
  mutate {convert => ["confirmed", "float"]}
  mutate {rename => ["lat", "[location][lat]"]}
  mutate {rename => ["lon", "[location][lon]"]}
output {  
    elasticsearch {
        template => "/Users/"labtop name"/Downloads/logstash-7.7.1/config/elasticsearch-template.json"
        template_overwrite => true
        action => "index"
        hosts => ["http://localhost:9200"]
        index => "geo_test"
        user => "user-name"
        password => "password"
        workers => 1
    }
    stdout {}
}

아래는 위에 적힌 elasticsearch-template.json 파일에 해당하는 코드입니다. 마지막 properties 안에 geo_point를 지정해주는 부분이 있습니다. 

{
    "template" : "geo_*",
    "settings" : {
      "index.refresh_interval" : "5s"
    },
    "mappings" : {
      "_default_" : {
        "_all" : {"enabled" : true, "omit_norms" : true},
        "dynamic_templates" : [ {
          "message_field" : {
            "match" : "message",
            "match_mapping_type" : "string",
            "mapping" : {
              "type" : "string", "index" : "analyzed", "omit_norms" : true,
              "fielddata" : { "format" : "disabled" }
            }
          }
        }, {
          "string_fields" : {
            "match" : "*",
            "match_mapping_type" : "string",
            "mapping" : {
              "type" : "string", "index" : "analyzed", "omit_norms" : true,
              "fielddata" : { "format" : "disabled" },
              "fields" : {
                "raw" : {"type": "string", "index" : "not_analyzed", "ignore_above" : 256}
              }
            }
          }
        } ],
        "properties" : {
          "@timestamp": { "type": "date" },
          "@version": { "type": "string", "index": "not_analyzed" },
          "geoip"  : {
            "dynamic": true,
            "properties" : {
              "ip": { "type": "ip" },
              "location" : { "type" : "geo_point" },
              "lat" : { "type" : "float" },
              "lon" : { "type" : "float" }
            }
          },
    "location" : { "type": "geo_point" }
        }
      }
    }
  }

지금 생각해보니 아마도 제가 사용한 코드는 ip를 읽어들여서 자동으로 geo_point에 해당하는 데이터를 뽑아주는 것 같습니다. 결론은 제가 필요한 코드는 아니었다는 것이죠.


 

제가 돌고돌아 찾은 해결법은 바로 "주차장"님의 유튜브에 있었습니다.(감사합니다!! ㅠㅠ) logstash를 사용하지 않고 kibana dev tools를 사용했는데 사용법이 매우 간단하여 정말 허무했습니다. ㅠ

일단, kibana dev tools에 가서 다음의 코드를 작성해주고 차례로 실행시켜줍니다. 순서대로 의미를 살펴보자면 geo_test라는 인덱스를 만들고, mapping 명령어를 통해 geo_point 타입을 미리 설정해줍니다. 마지막으로 GET 명령어로 geo_test가 잘 생성되었는지 확인합니다.

PUT geo_test

PUT geo_test/_mapping
{
  "properties": {
    "location-geotest": {
      "type": "geo_point"
    }
  }
}

GET geo_test

이렇게 kibana dev tools에서 먼저 설정한 이후에 logstash로 elasticsearch에 파일을 전달합니다. 다음은 logstash 코드입니다.

input {
  file {
    path => "/Users/"laptob name"/Downloads/coronavirusdataset_20200601/Case.csv"
    start_position => "beginning"
    #sincedb_path => "/dev/null"    
  }
}
filter {
  csv {
      separator => ","
      columns => ["case_id","province","city","group","infection_case","confirmed","lat","lon"]
  }
  mutate {convert => ["lat", "float"]}
  mutate {convert => ["lon", "float"]}
  mutate {convert => ["confirmed", "float"]}
  
  mutate {
    add_field => {"[location-geotest][lat]" => "%{lat}"}
    add_field => {"[location-geotest][lon]" => "%{lon}"}
  }
  mutate {
    convert => {"[location-geotest][lat]" => "float"}
    convert => {"[location-geotest][lon]" => "float"}
  }
}
output {  
    elasticsearch {
        hosts => ["http://localhost:9200"]
        index => "geo_test"
        user => "user name"
        password => "password"
    }
    stdout { codec => rubydebug {metadata => true}}
    stdout { codec => dots }
}

이제 bin/logstash -f /Users/"labtop name"/Downloads/logstash-7.7.1/config/logstash-geo.conf 를 쳐주면 파일이 잘 전달될 것이고 kibana에서 Index Patterns를 설정해주면 geo_point 타입이 생성된 데이터를 받을 수 있을 것입니다. 

제가 감격에 겨워 처음 키바나 지도에 표시한 데이터는 코로나 확진자 발생 지역 데이터입니다. 약 128개 중에 40%가 위도, 경도 값이 null이지만 키바나 지도에 잘 표시된 것을 보니 뿌듯했습니다! 

728x90
반응형