Fluentd (td-agent) の設定ファイル内の概念と記法

筆者が検証目的で Fluentd v1.15.3 を触っていた際に調べた設定ファイル内の概念についてまとめています。

- **参考文献**
    - [Fluentd v1.0 Documentation](https://docs.fluentd.org/)
    - [Fluentd実践入門 ──統合ログ基盤のためのデータ収集ツール](https://gihyo.jp/book/2022/978-4-297-13109-8)

# Fluentd (td-agent) とは？

- 様々なデータの収集を統一できるオープンソースのデータ コレクターです。2011年にTreasure Data 社により Ruby で開発され、以降は Treasure Data 社およびコミュニティベースで開発されています。
- Fluentd は個々のシステム毎に管理されている大量のログ ファイルを収集、解析し、ストレージに集約、保存を行うツールとして活用されています。 ログに限らず、各種データを NoSQL データベース (MongoDB 等)やクラウドストレージ (Amazon S3 等) など様々な媒体に出力できます。また、Elasticsearch/Kibana と連携してログを可視化する構成においてもインタラクティブなデータの取り扱いが可能です。
- Fluentd は Ruby と C 言語で実装されており、多様な入出力と実行環境を豊富なプラグインを利用することができます。
- Ruby やいくつかのプラグインが同梱されている安定版の「**td-agent**」としても提供されています。td-agent は開発元である Treasure Data 社より RedHat(rpm)、Debian(deb)、OSX(dmg) などに対応した主要なパッケージとして配布されています。
- Fluentd はプラグイン アーキテクチャを採用しており、用途に応じたプラグイン開発、拡張を自由に行うことができます。機能拡張を前提としないのであれば、td-agent により Fluentd をより手軽に導入する選択も可能です。
- Fluentd と類似コンセプトの Logstash (ELastic 社製) を利用したソリューションも存在し、ELK (Elasticsearch, Logstash, Kibana) スタックと呼ばれます。

# 設定ファイルの説明

<table>
	<tbody>
		<tr>
			<td><b>要素</b></td>
			<td><b>名称</b></td>
			<td><b>説明</b></td>
		</tr>
		<tr>
			<td colspan="2"><b>ディレクティブ</b></td>
			<td>
                <ul>
                    <li>
設定ファイル内でパラメータの集合をまとめる要素です。
                    </li>
                        <ul>
                            <li>
設定ファイルの書式上の構造をディレクティブと呼びますが、設定ファイルが実際に与えられて解析 (Parse) された後に残る構造は<b>セクション</b>と呼びます。
                            </li>
                            <li>
<b>セクション</b>は、パラメータ名と値のペアの集合を持つ構造です。
                            </li>
                        </ul>
                    <li>
<code>&lt;system&gt;</code> や <code>&lt;match *.*&gt;</code> のような開きタグと、<code>&lt;/system&gt;</code> や <code>&lt;/match *.*&gt;</code> のような閉じタグで囲まれる構造でパラメータの集合を定義します。
                    </li>
                    <li>
設定ファイルは、これらのディレクティブの集まりとして定義されます。
                    </li>
                </ul>
            </td>
		</tr>
		<tr>
			<td></td>
			<td><code>&lt;system&gt;</code> ディレクティブ</td>
			<td>
                <ul>
                    <li>
Fluentd のシステム設定、すなわち Fluentd 自身の挙動を設定するディレクティブです。設定ファイル内で設定できる <code>&lt;system&gt;</code> ディレクティブは１つのみです。
                    </li>
                    <li>
<code>&lt;system&gt;</code> ディレクティブは設定ファイルのトップレベル、すなわち他のディレクティブに囲まれない場所に記述します。
                    </li>
設定されなかったパラメータの値は既定値が適用されます。既定値が存在しないシステム設定パラメータを設定ファイル内で指定しない場合、Fluentd を動かしているシステム (OS 等) における既定の動作が適用されます。
                    <li>
<code>&lt;system&gt;</code> ディレクティブを設定ファイル内に書かなかった場合、全てのパラメータが既定値、もしくはシステムの既定の動作となります。
                    </li>
                </ul>
            </td>
		</tr>
		<tr>
			<td></td>
			<td><code>&lt;source&gt;</code> ディレクティブ</td>
			<td>
                <ul>
                    <li>
イベントを Fluentd に取り込むための Input プラグインを設定します。
                    </li>
                </ul>
            </td>
		</tr>
		<tr>
			<td></td>
			<td><code>&lt;label&gt;</code> ディレクティブ</td>
			<td>
                <ul>
                    <li>
<code>@label</code> パラメータでラベルを付けて流されたイベントをルーティングして処理します。
                    </li>
                    <li>
<code>&lt;label&gt;</code> ディレクティブ内には、直にパラメータを書かず、ルーティングされたイベントを処理するための <code>&lt;filter&gt;</code> ディレクティブと <code>&lt;match&gt;</code> ディレクティブを記述します。
                    </li>
                    <li>
引数を指定する必要があり、例えば、<code>&lt;label @my_label_name.*&gt;...&lt;/label&gt;</code> のように設定します。
                    </li>
                </ul>
            </td>
		</tr>
		<tr>
			<td></td>
			<td><code>&lt;filter&gt;</code> ディレクティブ</td>
			<td>
                <ul>
                    <li>
Fluentd に取り込まれたイベントを処理する Filter プラグインを設定します。
                    </li>
                    <li>
<code>&lt;filter&gt;</code> ディレクティブは設定ファイルのトップレベルか、<code>&lt;label&gt;</code> ディレクティブの内側に記述します。
                    </li>
                    <li>
引数を指定する必要があり、Output プラグインが処理するイベントをタグのパターンを用いて記述します。例えば、<code>&lt;filter my_log.*&gt;...&lt;/filter&gt;</code> のように設定します。
                    </li>
                    <li>
<code>&lt;filter&gt;</code> ディレクティブでは、処理したイベントを再び Fluentd 内に流します。そのため後続の別の <code>&lt;filter&gt;</code> ディレクティブが存在すれば、この後続の <code>&lt;filter&gt;</code> ディレクティブにも渡ります。 
                    </li>
                </ul>
            </td>
		</tr>
		<tr>
			<td></td>
			<td><code>&lt;match&gt;</code> ディレクティブ</td>
			<td>
                <ul>
                    <li>
Fluentd 内に取り込まれたイベントを処理する Output プラグインを設定するためのディレクティブです。
                    </li>
                    <li>
<code>&lt;match&gt;</code> ディレクティブは設定ファイルのトップレベルか、<code>&lt;label&gt;</code> ディレクティブの内側に記述します。
                    </li>
                    <li>
引数を指定する必要があり、Output プラグインが処理するイベントをタグのパターンを用いて記述します。例えば、<code>&lt;match my_service.*&gt;...&lt;/match&gt;</code> のように設定します。
                    </li>
                    <li>
設定対象の Output プラグインは、ディレクティブ内において、<code>@type</code> パラメータで指定します。
                    </li>
                    <li>
何処かの <code>&lt;match&gt;</code> セクション (設定値を与えられたディレクティブ) に一致して処理されたイベントは、その他の <code>&lt;match&gt;</code> セクションには届きません。
                    </li>
                </ul>
            </td>
		</tr>
		<tr>
			<td></td>
			<td><code>&lt;config&gt;</code> ディレクティブ</td>
			<td>
                <ul>
                    <li>
<code>in_config_expander</code>, <code>out_config_expander</code>, <code>filter_config_expander</code> プラグインの内側でのみ利用できます。
                    </li>
                    <li>
<code>&lt;config&gt;</code> セクションには、実際の Input/Filter/Output プラグインの設定を書くことができます。
                    </li>
                </ul>
            </td>
		</tr>
		<tr>
			<td></td>
			<td><code>&lt;parse&gt;</code> ディレクティブ</td>
			<td>
                <ul>
                    <li>
Parse プラグインの独自のパラメータを使用する場合に利用します。
                    </li>
                </ul>
            </td>
		</tr>
		<tr>
			<td></td>
			<td><code>&lt;exclude&gt;</code> ディレクティブ</td>
			<td>
                <ul>
                    <li>
基本的には通過させるが、特手の条件に合うイベントは取り除きたい場合に利用します。ここで指定した正規表現にマッチするイベントは除去されます。
                    </li>
                </ul>
            </td>
		</tr>
		<tr>
			<td></td>
			<td><code>&lt;format&gt;</code> ディレクティブ</td>
			<td>
                <ul>
                    <li>
Formatter プラグインの独自のパラメータを使用する場合に利用します。
                    </li>
日時や時刻をとのような書式で表現するかに関するパラメータは、Parser プラグインの場合とほとんど共通です。
                    <li>
                </ul>
            </td>
		</tr>
		<tr>
			<td></td>
			<td><code>&lt;record&gt;</code> ディレクティブ</td>
			<td>
                <ul>
                    <li>
<code>filter_record_transformer</code> プラグインの独自のパラメータを使用する場合に利用します。
                    </li>
                    <li>
<code><record></code> ディレクティブ内のパラメータは、新しいキー (例: <code>NEW_FIELD</code>) と新しい値 (例: <code>NEW_VALUE</code>) のペアと見なされます。
                        <pre><code>
&lt;record&gt;
  NEW_FIELD NEW_VALUE
&lt;/record&gt;
                        </code></pre>
                    </li>
                </ul>
            </td>
		</tr>
		<tr>
			<td></td>
			<td><code>&lt;buffer&gt;</code> ディレクティブ</td>
			<td>
                <ul>
                    <li>
Output プラグインにおけるバッファリング動作の設定できます。
                    </li>
                </ul>
            </td>
		</tr>
		<tr>
			<td colspan="2"><b>プラグイン</b></td>
			<td>
                <ul>
                    <li>
Fluentd ではプラグイン機構が採用されており、データの入力 (Input) と出力 (Output) は全てプラグインで対応します。
                    </li>
                    <li>
Fluentd に付属している『組み込みプラグイン』や、第三者やユーザー自身が開発したプラグインの何れも利用可能です。
                    </li>
                </ul>
            </td>
		</tr>
		<tr>
			<td></td>
			<td><code>in_config_expander</code> プラグイン</td>
			<td>
                <ul>
                    <li>
元 Treasure Data 社 (Fluentd 開発ベンダー) のエンジニアである田籠 聡氏により開発された <a href=”https://github.com/tagomoris/fluent-plugin-config-expander”>fluent-plugin-config-expander</a> (<a href=”https://github.com/tagomoris/fluent-plugin-config-expander”>GitHub - tagomoris/fluent-plugin-config-expander</a>) に含まれる Input プラグインです。
                    </li>
                    <li>
fluent-plugin-config-expander は Fluentd (td-agent) の MSI インストーラや Docker イメージには含まれていません。
                    </li>
                        <ul>
                            <li>
Windows OS の場合のインストール方法は、Td-agent Command Prompt を起動し、下記の <code>td-agent-gem</code> コマンドを利用します。<code>--version=?.?.?</code> オプションを利用することでプラグインのバージョンを指定することができますが、このオプションを利用しない場合は最新版がインストールされます。
                                <pre><code>
C:\opt\td-agent> td-agent-gem install fluent-plugin-config-expander
Fetching fluent-plugin-config-expander-1.0.1.gem
Successfully installed fluent-plugin-config-expander-1.0.1
Parsing documentation for fluent-plugin-config-expander-1.0.1
Installing ri documentation for fluent-plugin-config-expander-1.0.1
Done installing documentation for fluent-plugin-config-expander after 1 seconds
1 gem installed
                                </code></pre>
                            </li>
                            <li>
Fluentd コンテナへのインストールは、例えば Fluentd の Dockerfile で <code>&& gem install fluent-plugin-config-expander \</code> 行を追加することで実現します。設定例として、<a href="https://qiita.com/mishimahr/items/87d207f04f9f1697a4d6#6-efk-スタックサーバーdocker-関連ファイルと-fluentd-の設定ファイルの構成">こちら</a> の記事なども参照ください。
                            </li>
                        </ul>
                    <li>
ループ コントロールのための特別なディレクティブなどを利用することができるようになります。
                    </li>
                    <li>
<code>&lt;config&gt;</code> ディレクティブの内部で、次の組み込みプレースホルダーを利用することができます。
                    </li>
                        <ul>
                            <li>
ホスト名: <code>__HOSTNAME__</code> や <code>${HOSTNAME}</code>
                            </li>
                        </ul>
                </ul>
            </td>
		</tr>
		<tr>
			<td></td>
			<td><code>in_tail</code> プラグイン</td>
			<td>
                <ul>
                    <li>
テキストファイルに追記されていく行を継続的に読み込みます。Linux などで利用できる <code>tail -F</code> コマンドと挙動が似ています。
                    </li>
                    <li>
一度読み込んだ行を重複して読み込まない仕組みがあります。
                        <ul>
                            <li>
Fluentd が再起動された際に、再起動前の最後の位置から読み込みを再開させることが可能です。この読み込み位置は <code>pos_file</code> パラメータで指定された位置ファイルに記録されます。
                            </li>
                        </ul>
                    </li>
                </ul>
            </td>
		</tr>
		<tr>
			<td></td>
			<td><code>in_forward</code> プラグイン</td>
			<td rowspan="2">
                <ul>
                    <li>
<code>in/out_forward</code> プラグインには、データの受信／送信を安全に実施するするための多くのオプション機能が存在します。
                    </li>
                    <li>
データの送受信にはデフォルトで TCP のポート 24224 が使用されます。
                    </li>
                </ul>
            </td>
		</tr>
		<tr>
			<td></td>
			<td><code>out_forward</code> プラグイン</td>
		</tr>
		<tr>
			<td></td>
			<td><code>out_copy</code> プラグイン</td>
			<td>
                <ul>
                    <li>
複数の Output プラグインにイベントを渡します。
                    </li>
                </ul>
            </td>
		</tr>
		<tr>
			<td></td>
			<td><code>out_elasticsearch</code> プラグイン</td>
			<td>
                <ul>
                    <li>
データを Elasticsearch に送信します。
                    </li>
                    <li>
このプラグインは規定では Fluentd にインストールされていません。
                    </li>
                    <li>
v3.3.2 以降、<code>host</code> パラメータはビルトインのプレースホルダをサポートしています。
                    </li>
                    <li>
URL エンコード文字 (例: <code>!</code>, <code>#</code>, <code>$</code>, <code>%</code>, <code>&</code>, <code>+</code>, <code>@</code>, etc.) のエスケープ処理には <code>%{}</code> スペースホルダーを利用します。
                    </li>
                </ul>
            </td>
		</tr>
		<tr>
			<td></td>
			<td><code>filter_grep</code> プラグイン</td>
			<td>
                <ul>
                    <li>
一部のデータのみを選別する、あるいは一部のデータのみを除去する際に利用されます。
                    </li>
                </ul>
            </td>
		</tr>
		<tr>
			<td></td>
			<td><code>filter_parser</code> プラグイン</td>
			<td>
                <ul>
                    <li>
未解析データを含んだレコードを解析し、より意味のあるレコードに更新します。レコード内の文字列を解析し、結果を新しいレコードとして後続の Filter プラグインまたは Output プラグインに渡します。
                    </li>
                    <li>
Fluentd が扱うデータは常にタグ、タイムスタンプ、レコードが付けられます。レコードはキーと値のペアのリストとして各データに意味のある名前が付けられるという前提があります。しかし現実には、データ収集時にそのままでは解析できず、一先ずはログの一行を１つの文字列としてでも入力したい場合があります。このような場合に <code>filter_parser</code> プラグインが利用されます。
                    </li>
                </ul>
            </td>
		</tr>
		<tr>
			<td></td>
			<td><code>filter_stdout</code> プラグイン</td>
			<td>
                <ul>
                    <li>
Fluentd 内のイベントを標準出力 (デーモンとして起動した場合はログ) に出力します。このフィルタプラグインはデバッグのために有用です。
                    </li>
                </ul>
            </td>
		</tr>
		<tr>
			<td></td>
			<td><code>filter_record_transformer</code> プラグイン</td>
			<td>
                <ul>
                    <li>
独自のルールや Ruby 言語を用いて、<code>filter_parser</code> プラグインよりも更に複雑な処理を実現します。
                    </li>
                    <li>
レコードの編集に <code>Parser</code> プラグインを利用せず、独自のルールを設定ファイルに記述するため、より自由度が高い方法になります。
                    </li>
                </ul>
            </td>
		</tr>
		<tr>
			<td></td>
			<td><code>parser_none</code> プラグイン</td>
			<td>
                <ul>
                    <li>
ログの書式が不明で正規表現の記述が難しい場合でも、行全体を１つの文字列としてそのまま取り込むことができます。データの収集と保存のみが目的であれば、このような記述でも問題ありません。
                    </li>
                </ul>
            </td>
		</tr>
		<tr>
			<td></td>
			<td><code>parse_regexp</code> プラグイン</td>
			<td>
                <ul>
                    <li>
<code>&lt;parse&gt;</code> セクション内で <code>@type</code> パラメータで指定し、<code>expression</code> パラメータで解析対象の文字列のパターンをしてします。
                    </li>
                </ul>
            </td>
		</tr>
		<tr>
			<td></td>
			<td><code>formatter_single_value</code> プラグイン</td>
			<td>
                <ul>
                    <li>
レコード全体ではなく単一のフィールドの値を出力します。
                    </li>
                </ul>
            </td>
		</tr>
		<tr>
			<td></td>
			<td><code>buf_file</code> プラグイン</td>
			<td>
                <ul>
                    <li>
データを、Fluentd が動作しているサーバーのファイルシステム上に、ファイルとしてバッファ (一時的に保管) します。バッファチャンク単位でファイルが作成されます。
                    </li>
                    <li>
一度保存されたバッファチャンクは出力に成功するまで消去されません。したがって、Fluentd プロセスがふいにクラッシュする等の事象が発生してもバッファチャンクのファイルにデータが保存されているという点で、信頼性が求められる構成においては利用が推奨されるプラグインです。
                    </li>
                </ul>
            </td>
		</tr>
		<tr>
			<td colspan="2"><b>パラメータ</b></td>
			<td>
                <ul>
                    <li>
設定ファイル (<code>*.conf</code>) の中で名前と値の組み合わせを定義する要素です。この値は型を持ちます。
                    </li>
                </ul>
            </td>
		</tr>
		<tr>
			<td></td>
			<td><code>@type</code> パラメータ</td>
			<td>
                <ul>
                    <li>
<code>&lt;source&gt;</code>/<code>&lt;filter&gt;</code>/<code>&lt;match&gt;</code> ディレクティブの予約語パラメータです。
                    </li>
                    <li>
指定のディレクティブで使用するプラグインを指定する必須パラメータです。
                    </li>
                </ul>
            </td>
		</tr>
		<tr>
			<td></td>
			<td><code>@id</code> パラメータ</td>
			<td>
                <ul>
                    <li>
指定のディレクトリでのプラグイン設定に ID を付与するパラメータです。このプラグイン ID は設定ファイル内で一意である必要があり、同じプラグイン ID を重複して付与することはできません。
                    </li>
                    <li>
<code>@id</code> パラメータは必須パラメータではありませんが、設定ファイルの可読性の向上やトラブルシュート時の調査への寄与の面から、全ての <code>&lt;source&gt;</code>/<code>&lt;filter&gt;</code>/<code>&lt;match&gt;</code>  ディレクティブに指定することが推奨されます。
                    </li>
                    <li>
パラメータ型: string
                    </li>
                    <li>
既定値: 機械的に生成されたランダムな文字列
                    </li>
                </ul>
            </td>
		</tr>
		<tr>
			<td></td>
			<td><code>@label</code> パラメータ</td>
			<td>
                <ul>
                    <li>
基本的には <code>&lt;source&gt;</code> ディレクティブで有効なパラメータです。
                    </li>
                    <li>
プラグインから生成されたイベントを、特定の <code>&lt;label&gt;</code> ディレクティブに向けて流すためにラベル名を指定します。
                    </li>
                    <li>
パラメータ型: <code>@</code>で始まるstring
                    </li>
                    <li>
既定値: 無し
                    </li>
                </ul>
            </td>
		</tr>
		<tr>
			<td></td>
			<td><code>tag</code> パラメータ</td>
			<td>
                <ul>
                    <li>
<code>in_tail</code> プラグインで取得したデータのタグを指定します。
                    </li>
                    <li>
<code>in_tail</code> プラグインを用いる場合は必須パラメータです。
                    </li>
                </ul>
            </td>
		</tr>
		<tr>
			<td></td>
			<td><code>process</code> パラメータ</td>
			<td>
                <ul>
                    <li>
Fluentd プロセスの名前を指定します。
                    </li>
                    <li>
パラメータ型: string
                    </li>
                    <li>
既定値: 無し
                    </li>
                </ul>
            </td>
		</tr>
		<tr>
			<td></td>
			<td><code>workers</code> パラメータ</td>
			<td>
                <ul>
                    <li>
処理を担当するワーカー数を指定します。ワーカー数に「<code>2</code>」以上の値を指定した場合の動作を、複数ワーカーと呼びます。
                    </li>
                    <li>
パラメータ型: integer
                    </li>
                    <li>
既定値: <code>1</code>
                    </li>
                </ul>
            </td>
		</tr>
		<tr>
			<td></td>
			<td><code>log_level</code> パラメータ</td>
			<td>
                <ul>
                    <li>
Fluentd 全体のログレベルを指定します。
                    </li>
                    <li>
パラメータ型: enum={<code>trace</code>, <code>debug</code>, <code>info</code>, <code>warn</code>, <code>error</code>, <code>fatal</code>}
                    </li>
                    <li>
既定値: <code>info</code>
                    </li>
                </ul>
            </td>
		</tr>
		<tr>
			<td></td>
			<td><code>suppress_config_dump</code> パラメータ</td>
			<td>
                <ul>
                    <li>
<code>true</code> を設定した場合、Fluentd 起動直後のログへの設定ダンプ出力を行いません。
                    </li>
                    <li>
パラメータ型: bool
                    </li>
                    <li>
既定値: <code>false</code>
                    </li>
                </ul>
            </td>
		</tr>
		<tr>
			<td></td>
			<td><code>pos_file</code> パラメータ</td>
			<td>
                <ul>
                    <li>
tail しているログファイルの何処までを tail したかという位置情報をファイルに保存する場合、そのファイルパスを記述します。
                    </li>
                    <li>
規定値: 無し
                    </li>
                </ul>
            </td>
		</tr>
		<tr>
			<td></td>
			<td><code>read_from_head</code> パラメータ</td>
			<td>
                <ul>
                    <li>
Fluentd v1.14.3 より既定で <code>true</code> となっています。
                    </li>
                    <li>
<code>true</code> の場合、ファイルの先頭または <code>pos_file</code> に記録された最後の読み込み位置からログを読み始めます。
                    </li>
                </ul>
            </td>
		</tr>
		<tr>
			<td colspan="2"><b>ラベル</b></td>
			<td>
                <ul>
                    <li>
                    </li>
                </ul>
            </td>
		</tr>
		<tr>
			<td></td>
			<td><code>@FLUENT_LOG</code> ラベル</td>
			<td>
                <ul>
                    <li>
このラベルを処理する <code>&lt;label @FLUENT_LOG&gt;</code> セクションを指定した場合、Fluentd 自身のログがこのラベルに流れ、プラグインを使って処理できます。
                    </li>
                    <li>
Fluentd 自身のログは、<code>fluent.info</code> 等のように <code>fluent.接頭辞 (prefix)</code> にログレベルが付いたタグで流されます。
                    </li>
                </ul>
            </td>
		</tr>
	</tbody>
</table>

設定ファイルの具体例として、例えば下記の記事をご参照ください。

- **記事**
    - [UiPath Orchestrator (Webサーバー) の IIS アクセスログを Docker Engine 上の EFK (Elasticsearch, Fluentd, Kibana) スタックに連携する方法](https://qiita.com/mishimahr/items/87d207f04f9f1697a4d6)

以上です。