ログを集めるのにfluentdをよく使っているのだが,fluentd自身も実はログを吐いており,それをfluentdでハンドリングできる.できるというか,何もケアしてやらないと
2020-06-17 03:41:01 +0000 [warn]: #0 no patterns matched tag="fluent.warn"
みたいなログが出ることになる.
もちろん受け取ったログのmatch節がなければこうなるのはわかるのだが,fluent自身のログでもこれがでるので,何かしらハンドリングしてやる必要がある.
ログの内容はS3とかに送ればいいとして,とりあえず件数だけモニタリングしてアラートを飛ばしたいなと思った.
Datadogに送りたい
アラートを飛ばすとなると,送る場所は結構限られてくる.幸い,DatadogはDogStatDというプロセスを持っており,こいつに適当なカスタムメトリクスを送りつければ,それをDatadog側でモニタリングできる.
というわけでfluentdからDogStatsDにメトリクスを送りつける方法を考える.
これを使う. ちょっと古いプラグインだがちゃんと動く.
# トップレベルにfilterを書くのは非推奨になっている # fluent自身のログをハンドリングするには@FLUENT_LOGラベルを使う # https://docs.fluentd.org/deployment/logging#capture-fluentd-logs <label @FLUENT_LOG> <filter fluent.*> @type record_transformer <record> host "#{Socket.gethostname}" original_tag ${tag} </record> </filter> <match fluent.*> @type route add_tag_prefix fluentd <route **> copy </route> <route **> copy @label @dogstatsd </route> </match> <match fluentd.fluent.**> @type s3 # ここはs3にログ本文を保存する処理でも書いておく # ... </match> </label> <label @dogstatsd> <match fluentd.fluent.info> @type record_reformer renew_record true tag dogstatsd.increment <record> @type increment key fluent.info host ${record["host"]} original_tag ${tag} </record> </match> <match fluentd.fluent.warn> @type record_reformer renew_record true tag dogstatsd.increment <record> @type increment key fluent.warn host ${record["host"]} original_tag ${tag} </record> </match> <match fluentd.fluent.error> @type record_reformer renew_record true tag dogstatsd.increment <record> @type increment key fluent.error host ${record["host"]} original_tag ${tag} </record> </match> <match dogstatsd.increment> @type dogstatsd host "#{ENV['DOGSTATSD_HOST']}" port "#{ENV['DOGSTATSD_PORT']}" use_tag_as_key false flat_tags true metric_type increment value_key Value </match> </label>
こんな感じの設定でいける.
本文はS3に送る前提だったので,routeでcopyしている.
DogStatsDはあくまで,何かしらの件数や数,値を送るものなのでログ本文を送れるわけではない.なので,record_reformerを使ってrecordの数を数えて,それをmetric_type increment
でDogStatsDに送っている.
これで無事にDataDog側でfluent.info
, fluent.warn
, fluent.error
というカスタムメトリクスが生成されているので,これを元にDashboardを作ったりアラートを作ったりすれば良い.
DogStatsDはどうやって用意したらいい?
先の設定で,さらっと
- DOGSTATSD_HOST
- DOGSTATSD_PORT
という環境変数を使って,送信先を指定していたが,DogStatsDは我々がどこかしらにホストして,そこにメトリクスを送りつけてやる必要がある.
これについては,以前の記事で書いているが,
Kubernetesクラスタであるなら,helmで入れたDatadogのDaemonSetにDogStatsDが同居しているので,そこに送りつければ良い.
DownwardAPIを使えば,自身のホスト上にいるDaemonSetと通信することができる.
releases: - name: datadog namespace: kube-system chart: stable/datadog values: - agents: useHostNetwork: true - datadog: apiKey: hogehoge appKey: fugafuga dogstatsd: nonLocalTraffic: true
こんなhelmfileを書いておいて,
containers: - name: fluentd image: fluent/fluentd:latest env: - name: DOGSTATSD_HOST valueFrom: fieldRef: fieldPath: status.hostIP - name: DOGSTATSD_PORT value: "8125"
fluentdはこういう定義にしておけば疎通できる.
ポート番号8125
はDogStatsDのポート番号としてデフォルトで定義されているので,変更したい場合はchartのvaluesを変えれば良い.
本当はDatadogLogsを使うのが良い
今回試していないのだが,本来であれば,そもそもfluentdのログは全部DatadogLogsに送ってしまうと楽だ.Logsを使うのであれば,公式で用意されている
を使うと良い.
これであれば,今回みたいにfluentd側でカウントしたりする必要はなく,DatadogLogs側で受け取ったログをフィルタリングして,カスタムメトリクスを生成できる.
Logsにお金を払えるのであれば,こちらを選択したほうが楽になると思う.
そもそもLog本文もDatadogLogsで見られるようになるしね.