grafanaでワールドマップを利用する


grafanaでworld map プラグインを使ってみたので備忘録

マッピングデータは、MaxMaindさんが提供してくれているものを使います。
https://dev.maxmind.com/ja/geolite2/

ElasticSearchを使う方法が一般的みたいですが、ざっくり国別データを集計したいだけなので、MySQLで行きます。
また、アクセスログもInfluxDBではなくMySQLです。

【環境】
python3.4
Mysql 5.7
maxminddb 1.4.1

まずはモジュールインストールと、マッピングデータの取得

pip3 install maxminddb
wget http://geolite.maxmind.com/download/geoip/database/GeoLite2-City.mmdb.gz -P /usr/local/src

MySQLにテーブルを作る

CREATE TABLE `geo2` (
  `ip_address` varchar(15) DEFAULT NULL,
  `country_name` varchar(50) DEFAULT NULL,
  UNIQUE KEY `ip_address` (`ip_address`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

pythonスクリプトを作る。
vim /usr/local/bin/insert_get2.py

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import MySQLdb
import os
import maxminddb
import datetime

DBFILE = '/usr/local/src/GeoLite2-City.mmdb'
geo2db = maxminddb.open_database(DBFILE)

# 直近1時間前のログからデータ集計を行う
todaydetail = datetime.datetime.today()
starttime = (todaydetail-datetime.timedelta(hours=1)).strftime("%Y-%m-%d %H:00")
endtime   = todaydetail.strftime("%Y-%m-%d %H:00")

def geo2(ips):
  val_list = []
  for ip in ips:
    try:
      location = geo2db.get(ip)
      # 国
      country = location["registered_country"]["iso_code"]

      # 経度と緯度も取得出来るけど今回は使わない
      # 緯度
      # latitude = location['location']['latitude']
      # 経度
      # longitude = location['location']['longitude']

      val_list.append([ip,country])
    except:
      pass

  return val_list

def db_select():
  con = MySQLdb.connect(
    host='localhost',
    db='log',
    user='DBユーザー',
    passwd='パスワード',
    charset='utf8'
  )

  cur = con.cursor()
  sql = "select distinct remote_ip from log where time between '{start}' and '{end}' and remote_ip != '::1'".format(start=starttime,end=endtime)

  result = cur.execute(sql)
  ips = []
  for ip in cur:
    ips.append(ip[0])

  cur.close()
  con.close()
  return ips


def db_bulk_insert(rows):
  con = MySQLdb.connect(
    host='localhost',
    db='log',
    user='DBユーザー',
    passwd='パスワード',
    charset='utf8'
  )

  cur = con.cursor()
  sql = "INSERT IGNORE geo2(ip_address,country_name) VALUES(%s, %s)"
  cur.executemany(sql,rows)
  con.commit()
  cur.close()
  con.close()

ips  = db_select()
rows = geo2(ips)
db_bulk_insert(rows)

あとは、/usr/local/bin/insert_get2.pyを1時間毎に実行する。