FluentdでPythonのログをTeamsに通知する

Fluentd では Python のログを収集していますので、 ログレベルが WARNING 以上のログを抽出して、Teams に送信したいです。

Teams のプラグイン は既にありますが、Python のログを送信するために、ちょっと変更しました。 変更した後のコードを out_teams.rb として保存し、/etc/fluent/plugin にコピーすれば、プラグインとして使えます。

パラメータについて、

  • webhook_url(必須):Teams の Webhook URL
  • title(オプション):メッセージのタイトル
  • text(オプション):メッセージの本文
require 'rest-client'
require 'fluent/plugin/output'

module Fluent
  module Plugin
    class TeamsOutput < Output
      Fluent::Plugin.register_output('teams', self)

      DEFAULT_BUFFER_TYPE = 'memory'.freeze

      desc 'Webhook URL'
      config_param :webhook_url, :string

      desc 'Title'
      config_param :title, :string, default: nil

      desc 'Message content. Supported erb format and newline character.'
      config_param :text, :string, default: nil

      ...

      def post_message(args = {})
        payload = build_payload(args)
        RestClient.post(@webhook_url, payload.to_json, content_type: :json)
      end

      def build_payload(args = {})
        tag = args[:tag]
        time = args[:time]
        record = args[:record]
        log_level = record['level']

        if log_level == 'WARNING'
          color = 'ffc986'
        else
          color = 'ff4e4e'
        end

        sections = [{
          "activityTitle" => build_title(record),
          "facts" => build_facts(record)}, {
          "text" => build_text(record),
          "markdown" => true
        }]
        { themeColor: color, summary: title, sections: sections }
      end

      def build_title(record)
        return @title unless @title.nil?
        record['title']
      end

      def build_text(record)
        text = "`#{record['message']}`"
        return text if @text.nil?
        ERB.new(@text).result(binding).gsub('\\n', "\n")
      end

      def build_facts(record)
        keys = record.keys
        facts = []
        keys.each do |key|
          next if (key == 'message' || key == 'title')
          facts << {"name" => key, "value" => record[key]}
        end
        facts
      end
    end
  end
end

Teams プラグイン以外に使用しているプラグインは、

  • filter_grep: ログレベルが WARNING / ERROR のログを抽出します。
  • filter_record_transformer: 新しいフィールド title を追加します。

Fluentd の設定例:

<match test.*>
  @type copy
  <store>
    @type relabel
    @label @teams_notification
  </store>
</match>

<label @teams_notification>
  <filter test.*>
    @type grep
    <regexp>
      key level
      pattern /^(?:WARNING|ERROR)$/
    </regexp>
  </filter>

  <filter test.*>
    @type record_transformer
    <record>
      title "An error occurred in ${tag_parts[1]}"
    </record>
  </filter>

  <match test.*>
    @type teams
    webhook_url WEBHOOK_URL
  </match>
</label>
```