Datadog Agent によるログの解析方法

ログファイルには、アプリケーションとビジネスの貴重なデータが含まれています。 残念ながら多くの場合この重要性には気が付かずログファイルは放置されています。 Datadog Agent は、ログからメトリクスとイベントを解析することによって、その中のデータをリアルタイムでグラフ化するのに役立ちます。

メトリクスの抽出

Datadog Agent は、ログファイルから直接メトリクスを、抽出することができます:

  • Datadog の公式ログフォーマットの場合は、追加のプログラミングは不要です。
  • Datadog の公式ログフォーマット以外の場合は、Python によるログパース関数を準備し、それをimport して抽出します。

Datadog の公式ログフォーマットの場合

Datadog のログは次のようにフォーマットされています:

metric unix_timestamp value [attribute1=v1 attributes2=v2 ...]

例えば、/var/log/web.log の各レコードが次のような内容で記述されているとします:

me.web.requests 1320786966 157 metric_type=counter unit=request
me.web.latency 1320786966 250 metric_type=gauge unit=ms

Datadog Agent にこのログファイルを解析させるためには、次の行をDatadog Agent の設定ファイル(/etc/dd-agent/datadog.conf) に追記します。

dogstreams: /var/log/web.log

複数のログファイルを解析するのには、ログファイルのパスをカンマで区切って記述します:

dogstreams: /var/log/web.log, /var/log/db.log, /var/log/cache.log

カスタムフォーマットのログの場合

ベンダ専用のソフトや過去からの残留ソフトなど、Datadog が公式に使用しているフォーマットと異なるログを解析したいとします。このような場合は、Python で記述した関数によってその特殊ログの特定のフィールドを抽出することができます。Python で記述した関数を Datadog Agent から呼び出せるようにするためには、設定ファイルに次のフォーマットで、ログファイルと解析用の関数を記述します:

dogstreams: /var/log/web.log:parsers:parse_web

parsers:parse_web の部分の意味は、Datadog Agent のPYTHONPATHparsers パッケージが存在し、その中にparse_web 関数が記述されていることを意味します。 PYTHONPATH は、Datadog Agent の起動スクリプトによって設定されます。Datadog Agent 2.0 以前の場合は, /etc/init.d/datadog-agent に設定されており、Datadog Agent 2.0 以降の場合は、Datadog Agentのsupervisor の設定ファイルに記述された内容に基づいて設定されています。

もしも、パースのパッケージがPYTHONPATH にない場合は、そのパッケージを読み込むために次のようにパスを付記します:

dogstreams: /path/to/log1:/path/to/my/parsers_module.py:custom_parser

このフォーマットでは、Datadog Agent は、custom_parser 関数を、/path/to/my/parsers_module.py ファイルからimport しようとします。

もしも、カスタムログパーサが機能しない場合は、Datadog Agent のcollector が出力しているログを確認してください。 Datadog Agent がその関数をimport できていない場合は、Could not load Dogstream line parser という行が出力されます。全てが正常に動作している場合は、dogstream: parsing {filename} with {function name} (requested {config option text}) が、出力されます。

パースのための関数の書き方

カスタムログパース関数は、次の条件を満たしている必要があります:

  • パラメータを2つ受付ます: Python logger オブジェクト (デバッグ目的)と、パースするための現在行の文字列パラメータです。

  • 返される結果の出力は、タプル又は、リストの形式である必要があります:

    (metric (str), timestamp (unix timestamp), value (float), attributes (dict))

attributes には、最低限でもkey文字としてmetric_type を指定する必要があります。metric_type の値には、counter 又は、gauge を指定することになります。

カスタムログパーサの例

parsers.py には、次のような内容が記述されます:

import time
from datetime import datetime

def parse_web(logger, line):
    # Split the line into fields
    date, metric_name, metric_value, attrs = line.split('|')

    # Convert the iso8601 date into a unix timestamp, assuming the timestamp
    # string is in the same timezone as the machine that's parsing it.
    date = datetime.strptime(date, "%Y-%m-%dT%H:%M:%S")
    date = time.mktime(date.timetuple())

    # Remove surrounding whitespace from the metric name
    metric_name = metric_name.strip()

    # Convert the metric value into a float
    metric_value = float(metric_value.strip())

    # Convert the attribute string field into a dictionary
    attr_dict = {}
    for attr_pair in attrs.split(','):
        attr_name, attr_val = attr_pair.split('=')
        attr_name = attr_name.strip()
        attr_val = attr_val.strip()
        attr_dict[attr_name] = attr_val

    # Return the output as a tuple
    return (metric_name, date, metric_value, attr_dict)

Datadog Agent 以外からもパーサをテストすることをお勧めしますので、先のスクリプトにテスト関数を追記します:

def test():
    # Set up the test logger
    import logging
    logging.basicConfig(level=logging.DEBUG)

    # Set up the test input and expected output
    test_input = "2011-11-08T21:16:06|me.web.requests|157|metric_type=counter,unit=request"
    expected = (
        "me.web.requests",
        1320786966,
        157,
        {"metric_type": "counter",
         "unit":        "request" }
    )

    # Call the parse function
    actual = parse_web(logging, test_input)

    # Validate the results
    assert expected == actual, "%s != %s" % (expected, actual)
    print 'test passes'


if __name__ == '__main__':
    # For local testing, callable as "python /path/to/parsers.py"
    test()

次のようにパーサを実行し、関数のテストをします。

python /path/to/parsers.py

イベントの抽出

Event parsing is done via the same custom parsing functions as described above, except if you return a dict (or a list of dict) from your custom parsing function, Datadog will treat it as an event instead of a metric.

イベントフィールド項目 (太文字のフィールドは、必須項目です):

FieldTypeValue
msg_titlestringTitle of the event. Will get indexed by our full-text search.
timestampintegerUnix epoch timestamp. If omitted, will default to the time that the Agent parsed the event.
msg_textstringBody of the event. Will get indexed by our full-text search.
alert_typestring enumIndicates the severity of the event. Must be one of `error`, `warning`, `success` or `info`. If omitted, will default to `info`. Searchable by `alert_type:value`
event_typestringDescribes what kind of event this is. Used as part of the aggregation key
aggregation_keystringDescribes what this event affected, if anything. Used as part of the aggregation key
hoststringName of the host this event originated from. The event will automatically get tagged with any tags you've given this host using the tagging page or the tagging api. The host value is used as part of the aggregation key.
prioritystringDetermines whether the event will be visible or hidden by default in the stream; Must be one of low or normal

The events with the same aggregation key within a 24 hour time window will get aggregated together on the stream. The aggregation key is a combination of the following fields:

  • event_type
  • aggregation_key
  • host

For an example of an event parser, see our cassandra compaction event parser that is bundled with the Agent.