さまよう大アリクイ

横浜市に住む。ホームページを作っていたりするが、最近滞り気味。

hadoopのHDFSの使用量をGangliaで見る

hadoopのログ /var/log/hadoop/hdfsmetrics.log のデータを読み出して、Gangliaに登録する方法です。なお、OSはCentOSです。

NameNodeにpyhonモジュールをインストールします。

#cat > /usr/lib64/ganglia/python_modules/Hdfsmetrics.py <<EOF

import re

# Handler of Metrics

def Hdfsmetrics_handler(name):

    log_file = "/var/log/hadoop/hdfsmetrics.log"

    tmp_file = "/tmp/hdfs_"+name+".log"

    olog = ""

    nlog = ""

    # Read old data

    try:

        fp = open( tmp_file )

        olog = fp.read(2000)

        fp.close()

    except:

        pass

    # Read new data  

    try:

        fp = open( log_file )

        # Read the last 2000 byte of the log file.

        fp.seek(0, 2)         

        if fp.tell() > 2000:

            fp.seek(-2000, 2)

        else:

            fp.seek(0,0)

        nlog = fp.read(2000)

        fp.close()

    except:

        pass

    # Look for the 'name' value.

    r = re.compile( '([A-Za-z_]+)=([0-9]*)' )

    result = 0

    # Check old data

    l = r.findall(olog)

    for v in l:

        if v[0] == name:

            result = int(v[1])

    # Check new data

    l = r.findall(nlog)

    for v in l:

        if v[0] == name:

            result = int(v[1])

            try:

                fp = open( tmp_file, 'w' )

                fp.write(nlog)

                fp.close()

            except:

                pass

    return result

# The list of descriptors

_descriptors = []

# Make descriptor

def make_descriptor(name, units):

    descriptor = {'call_back': Hdfsmetrics_handler,

        'time_max': 60,

        'value_type': 'uint',

        'slope': 'both',

        'format': '%u',

        'groups': 'Hdfsmetrics'}

    descriptor['name'] = name

    descriptor['description'] = name

    descriptor['units'] = units

    return descriptor

# This method is called first and returns descriptors

def metric_init(params):

    global _descriptors

    _descriptors = []

    _descriptors.append( make_descriptor('BlocksTotal', 'blocks') )

    _descriptors.append( make_descriptor('CapacityRemainingGB', 'GB') )

    _descriptors.append( make_descriptor('CapacityTotalGB', 'GB') )

    _descriptors.append( make_descriptor('CapacityUsedGB', 'GB') )

    _descriptors.append( make_descriptor('FilesTotal', 'files') )

    _descriptors.append( make_descriptor('PendingReplicationBlocks', 'blocks') )

    _descriptors.append( make_descriptor('ScheduledReplicationBlocks', 'blocks') )

    _descriptors.append( make_descriptor('UnderReplicatedBlocks', 'blocks') )

    return _descriptors

# Nothing to do

def metric_cleanup():

    pass

#This code is for debugging and unit testing

if __name__ == '__main__':

    metric_init(None)

    for d in _descriptors:

        v = d['call_back'](d['name'])

        print 'value for %s is %u [%s]' % (d['name'],  v, d['units'])

EOF

Hdfsmetrics_handlerは、/var/log/hadoop/hdfsmetrics.logの後半部分を読み出して、name=数字にマッチする部分を探して数字を返すします。pythonにtailコマンドのようなものがあれば最後の3行だけを見ればいいのですが、よくわからなかったので、/var/log/hadoop/hdfsmetrics.logの後半2000バイトだけをサーチするようにしています。多分、ログ全部をサーチすると時間がかかると思いますが試してはいません。ログの切り替え直後にはデータが取れないので、過去データで補完するようにしています。metric_initと、make_descriptorは、収集するデータを定義しています。今回は8つのデータを取っているが、ログを見るともっと他のデータを取ることもできそうです。

ganglia設定ファイルを作ります。

#cat > /etc/ganglia/conf.d/Hdfsmetrics_handler.pyconf <<EOF

modules {

  module {

    name = "Hdfsmetrics"

    language = "python"

  }

}

collection_group {

  collect_every = 60

  time_threshold = 300

  metric {

    name = "BlocksTotal"

    title = "HDFS Blocks Total"

    value_threshold = 100

  }

  metric {

    name = "CapacityRemainingGB"

    title = "HDFS Capacity Remaining"

    value_threshold = 1000

  }

  metric {

    name = "CapacityTotalGB"

    title = "HDFS Capacity Total"

    value_threshold = 1000

  }

  metric {

    name = "CapacityUsedGB"

    title = "HDFS Capacity Used"

    value_threshold = 1000

  }

  metric {

    name = "FilesTotal"

    title = "HDFS Files Total"

    value_threshold = 1000

  }

  metric {

    name = "PendingReplicationBlocks"

    title = "HDFS Pending Replication Blocks"

    value_threshold = 1

  }

  metric {

    name = "ScheduledReplicationBlocks"

    title = "HDFS Scheduled Replication Blocks"

    value_threshold = 1

  }

  metric {

    name = "UnderReplicatedBlocks"

    title = "HDFS Under Replicated Blocks"

    value_threshold = 1

  }

}

EOF

pyhonスクリプトで定義した8つのデータに対して設定を書いています。collect_every = 60 は60秒ごとにデータ収集をする意味です。time_threshold = 300 はデータが変化しなくても300秒毎にgmond間でデータを送ることを意味します。value_threshold = 1000 は値が1000変化したらgmond間でデータを送ることを意味するとらしいです。

gmondを再起動します。

#/etc/init.d/gmond restart

しばらく待つとgangliaのhost画面でHDFSのデータが見れるようになります。但し、ログの値そのままなので、このままでは見にくいです。