5
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【New Relic】New Relicを使ってPostfixのデータ取得とWebhook連携設定をやってみた

Last updated at Posted at 2024-12-07

こんにちは。

勉強も兼ねて個人サーバを運用してるんですが、何かあったときってアラート
とかログをとりあえず見てなんか起こってるぽいと感じることが多々あります。
ただ、調べだすとなんだかんだ半日過ぎてたりして好きではあるんですけど、
ログをgrepしたりsedしたりでデータを抜き出すのに手間がかかってるし、
なんならログしか見られないからほぼほぼログから推測するしかなかったりで結構な手間です。

たまたま会社の先輩からイベントもやってるよということでNew Relicを教えてもらい、名前は聞いたことあったのですが触れる機会を作れていなかったし、データ収集してあれこれできるといっぱい夢を吹き込まれた(誇張)ので触ってみることにしました。

【New Relicってなんやねん】

数多くの監視ツールの一つですが、その中でもオブザーバビリティの実現に必要な機能を多数備えたツールです。
これまでの一般的な監視に用いられたリソース情報やログだけでなく処理のトレース情報などを組み合わせてどこ何が なぜ起こったのかを可視化していくことで、監視データや監視結果を組み合わせて発生している事象やトラブルを個人のナレッジや経験で突き止めていたことをシステム的に可視化できるツールだと思います。

最近触り始めたような人間の説明より公式さんでオブザーバビリティとNew Relicで何ができるかを説明しているのでぜひご覧ください。

【やってみたこと】

本当はいろいろできるNew Relicですが、いきなり全部やってみようとかはハードルが高いので、まずは個人のサーバにNew Relicを導入して触ってみることにして、個人的に現状の個人サーバで毎回コマンド使って出していたデータ出力や今後異常検知なんかもやってみたいので通知機能を試してみることにしました

  • New Relicアカウントの作成とAgentインストール
  • Postfixのデータ取得をやってみた
  • 監視アラートをWebhookでDiscordに飛ばしてみる

【サーバ環境】

個人で借りているさくらのVPSサーバです。主な環境やスペックは下記の通り。

  • プラン:さくらのVPS 1Gプラン(CPU 2vCPU,メモリ 1GB)
  • OS:AlmaLinux9
  • 主な用途:メールサーバ(postfix)

【New Relicアカウントの作成とAgentインストール】

1.New Relicのアカウント作成

利用にはNew Relicのアカウントが必要です。
登録にクレジットカードは不要で、メールアドレスなどの必要情報を登録することで提供されている機能のほとんどを利用することができる上に月間100GBまでのデータ量なら無料で利用できます。
仮にデータ量をオーバーしてもいきなり課金ってこともないのでとりあえずお試し勢も安心です。

月100GBって?
この記事で使っているサーバ1台が半月で7GB程度、1日あたり0.3GB程度です。
実際のデータ量は動作アプリケーションや取得データに依存し、このデータにはリソースメトリクスのデータも含みます。
業務で使うサーバでも数台は見ることができるのではないかと思います。

アカウント登録はこちらからどうぞ

2.Agentのインストール

New Relicアカウントの作成が終わったのでAgentを導入します。
今回はサーバのリソースとログを取得できるようにしたいので、ファーストステップガイドInfrastructure導入という公式資料を参考にインストールを進めます。
これらの基本的な導入資料は公式でまとめられたページがありますので、ここから目的のデータを探すのもいいですし、New Relicのコンソールにログインすると取得できるデータごとに一覧が用意され、各コンポーネントごとに導入をガイドしてくれますので、基本的なインストールは割と簡単です。

New Relic InfrastructureはAgentを通じてOS情報や稼働状態を取得します。

  1. 左側ガイドからIntegrations & Agentsを選択し、検索画面にLinuxと入力します
    image.png
  2. Linuxを選択すると今回は初めての登録でユーザキーが必要なのでCreate a new keyを選択すると自動でユーザキーが生成されます
    image.png
  3. インストール用コマンドが用意されますのでCopy to clipbordを押せばそのままコンソールへ貼り付けるだけでインストールコマンドが実行可能です
    Automatically answer "yes" to~にチェックを入れると自動でインストールの実行に進むコマンドが生成されます。
    image.png
  4. インストール後にNew Relicのコンソール上からAgentのインストール結果を確認できます
    image.png

ここまで終わると各種メトリクスデータとログデータの収集が開始されます。
ほかのデータやアプリケーションデータが必要な場合はNew Relicコンソールから追加でインストールします。

  • OS情報
  • リソースモニタリング情報
  • messagesログ
  • secureログ

こういったAgentは割とAgent側の設定を手動でやる必要のあることが多い印象ですが、基本的な導入だけであればNew Relicコンソール側で実行するだけで終われるのでお手軽でした。
またダッシュボードもあらかじめ用意されたものが多数あるので、メジャーなアプリケーションなら簡単なウィザードでシステムの状態を確認できるようになります。
image.png

【Postfixのデータ取得をやってみた】

postfixを使ってメールサーバを動かしているのでpostfixのデータ取得を試してみることに。

postfix用コンポーネントのインストール

postfixの場合、インストールはどうやらマニュアルに沿って行うようなので以下のURLに沿ってインストールを実施

Infrastracture Agentが未インストールの場合はインストールします

1. pflogsummのインストール

インストール手順の1~3まではマニュアル通りで、項番4はログ保存先フォルダが私の環境だと/var/log/maillogに保存されていたので、そこだけ修正して下記のようにすることでデータが出力されることを確認

cat /var/log/maillog | pflogsumm
cat /var/log/maillog | pflogsumm -d today

2. Flex設定ファイルの作成

サンプルコンフィグがあるのでこちらのログファイル参照だけ/var/log/maillogに置換してpostfix-flex-config.ymlに保存

3. ログ転送設定を追加

ログ転送ファイルを修正。
こちらはおそらくすでにmessagesやsecureのログ転送設定がされているので、追加でマニュアルに記載のログ転送設定をする。

/etc/newrelic-infra/logging.d/logging.yml
logs:
  - name: messages
    file: /var/log/messages
    attributes:
      logtype: linux_messages
  - name: secure
    file: /var/log/secure
    attributes:
      logtype: linux_secure
  - name: newrelic-cli.log
    file: /root/.newrelic/newrelic-cli.log
    attributes:
      newrelic-cli: true
      logtype: newrelic-cli
  - name: mail.log
    file: /var/log/maillog
    attributes:
      logtype: postfix_maillog

4. Agentの再起動

NewRelic Agentサービスを再起動する。

sudo systemctl restart newrelic-infra.service

5. インストール結果確認&New Relicコンソール設定

New RelicコンソールでIntegrations & Agents->postfixを選択。
まずインストールを行うように促されますがすでにインストール済みなのでDoneを選択
image.png

終わるとダッシュボードやアラートなどが自動でセットアップされますのでこれでセットアップ完了です。
image.png

インストールは終わったけどあれ?

インストールは終わってダッシュボードも見えるようになりましたが、2つほど問題が。

  1. ダッシュボードのサービスステータスがDownのまま
    ダッシュボードにもデータが出てきて おおっ!!! と思ったのもつかの間、サービスのステータスがDownのままです。
    image.png

  2. サービスダウンのアラートが発生
    さらに数分後からサーバでpostfixサービスのダウンアラートが!?
    image.png

    どうやらサービスダウンを示すメトリクス(PostfixDown)の値が障害時の値を示しているようだ。
    image.png

    ただサーバ側を見てもサービスは普通に起動している。
    image.png

修正点

・ ダッシュボード

ダッシュボードの判定式をサービス表示部分のEditから見られるので見てみると
image.png

こんな感じの式でした。NSQL式をいじってみると、前半のSELECT文にあるUp/Down判定の数字を文字列扱いしていることが悪さをしている模様。
image.png

ということで数式を以下のように直してみましたところ

- SELECT latest(if(status='1','Up','Down')) as 'Postfix Service Status' FROM (SELECT latest(value) as 'status' from PostfixUp)
+ SELECT latest(if(status=1,'Up','Down')) as 'Postfix Service Status' FROM (SELECT latest(value) as 'status' from PostfixUp)

ステータスがUpに!やったぜ!
image.png

・ アラート

ダッシュボードのほうは解消しましたが、アラートは解消しない。
サーバのステータスは問題ないので、導入時に設定したコンフィグを確認しpostfix-flex-config.ymlを見たところ・・・
PostfixUpPostfixDownの取得値が全く同じやないかい!!
image.png
ま、サンプルコンフィグですからね~。
とりあえずPostfixDownのメトリクス取得方法を下記のように変更。

  - event_type: PostfixDown
    commands:
-      - run: echo "value:$(systemctl status postfix | grep 'Active':' active' | wc -l)"
+      - run: echo "value:$(systemctl is-active postfix | grep -v 'active' | wc -l)"
        split_by: ':'

これでアラートは解消してめでたし、めでたし。
今回設定したpostfix-flex-config.ymlはこちら

設定したpostfix-flex-config.yml
/etc/newrelic-infra/integrations.d/postfix-flex-config.yml
---
  integrations:
    - name: nri-flex
      config:
        name: postfixFlex
        apis:
          #check if Postfix service is up.
          - event_type: PostfixUp
            commands:
              - run: echo "value:$(systemctl status postfix | grep 'Active':' active' | wc -l)"
                split_by: ':'

          #check if Postfix service is down.
          - event_type: PostfixDown
            commands:
              - run: echo "value:$(systemctl is-active postfix | grep -v 'active' | wc -l)"
                split_by: ':'

          #Read the grand totals messages by using the below script.
          - event_type: PostfixGrandTotals
            commands:
              - run: cat /var/log/maillog | pflogsumm | grep -A 21 'Grand Totals'
                split: horizontal
                set_header: [metricValue, message]
                regex_match: true
                split_by: \s+(\d+\w*)\s+(.*)

          #Read the number of messages delivered & received in bytes.
          - event_type: PostfixMessageBytes
            commands:
              - run: cat /var/log/maillog | pflogsumm | grep -A 1 'bytes received'
                split: horizontal
                set_header: [metricValue, messageBytes]
                regex_match: true
                split_by: \s+(\d+\w*)\s+(.*)

          #Read the number of messages held by the user.
          - event_type: PostfixHeldMessage
            commands:
              - run: echo "value:$(cat /var/mail/<USER> | grep -c 'Subject:')"
                split_by: ':'

          #Read the count of SASL authentication failure notifications.
          - event_type: PostfixSASLauthFailed
            commands:
              - run: echo "value:$(cat /var/log/maillog | grep 'status=deferred (SASL authentication failed' | wc -l)"
                split_by: ':'

          #Read the count of bounced non-delivery notifications.
          - event_type: PostfixBounceNondeliveryNotification
            commands:
              - run: echo "value:$(cat /var/log/maillog | grep 'postfix/bounce' | wc -l)"
                split_by: ':'

          #Read the number of messages passed through the email delivery process.
          - event_type: PostfixEmailDeliveryProcess
            commands:
              - run: echo "PICKUPvalue:$(cat /var/log/maillog | grep 'pickup' | wc -l)"
                split_by: ':'
              - run: echo "CLEANUPvalue:$(cat /var/log/maillog | grep 'cleanup' | wc -l)"
                split_by: ':'

          #Read the number of message inserted in mail queue.
          - event_type: PostfixMessageInsertedinMailQ
            commands:
              - run: echo "Ivalue:$(cat /var/log/maillog | grep 'queue active'| wc -l)"
                split_by: ':'

          #Read the number of message handled by SMTP process.
          - event_type: PostfixMessageHandledBySMTP
            commands:
              - run: echo "SENTmsg:$(cat /var/log/maillog | grep 'status=sent' | grep "postfix/smtp" | wc -l)"
                split_by: ':'
              - run: echo "BOUNCEDmsg:$(cat /var/log/maillog | grep 'status=bounced' | grep "postfix/smtp" | wc -l)"
                split_by: ':'
              - run: echo "DEFERREDmsg:$(cat /var/log/maillog | grep 'status=deferred' | grep "postfix/smtp" | wc -l)"
                split_by: ':'

          #Read the number of message removed from mail queue.
          - event_type: PostfixMessageRemovedFromMailQ
            commands:
              - run: echo "Rvalue:$(cat /var/log/maillog | grep 'removed'| wc -l)"
                split_by: ':'

          #Read the number of SMTPD connection.
          - event_type: PostfixSMTPDconnection
            commands:
              - run: echo "value:$(cat /var/log/maillog | grep ' connect from' | wc -l)"
                split_by: ':'

          #Read the number of SMTPD disconnection.
          - event_type: PostfixSMTPDdisconnection
            commands:
              - run: echo "value:$(cat /var/log/maillog | grep 'disconnect from' | wc -l)"
                split_by: ':'

          #Read the number of SMTP connection.
          - event_type: PostfixSMTPconnection
            commands:
              - run: echo "value:$(cat /var/log/maillog | grep ' connect to' | wc -l)"
                split_by: ':'

          #Read the number of SMTP disconnection.
          - event_type: PostfixSMTPdisconnection
            commands:
              - run: echo "value:$(cat /var/log/maillog | grep 'disconnect to' | wc -l)"
                split_by: ':'

          #Read the number of connection timed out.
          - event_type: PostfixSMTPDtimedOut
            commands:
              - run: echo "value:$(cat /var/log/maillog | grep 'timeout after CONNECT' | wc -l)"
                split_by: ':'

          #Read the number of connection lost.
          - event_type: PostfixSMTPDconnectionLost
            commands:
              - run: echo "value:$(cat /var/log/maillog | grep 'lost connection' | wc -l)"
                split_by: ':'

          #Read the per-hour traffic report.
          - event_type: PostfixMessagePerHourReport
            commands:
              - run: cat /var/log/maillog | pflogsumm -d today | grep -i 'Per-Hour Traffic Summary' -A 27
                split: horizontal
                header_split_by: \s+(\w+)\s+(\w+)\s+(\w+)\s+(\w+)\s+(\w+)\s+(.*)
                set_header:
                  [
                    time,
                    received.perhour,
                    delivered.perhour,
                    deferred.perhour,
                    bounced.perhour,
                    rejected.perhour,
                  ]
                regex_match: true
                split_by: \s+(\d+-\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)

          #Read the per-day traffic summary.
          - event_type: PostfixMessageTrafficPerDay
            commands:
              - run: cat /var/log/maillog | pflogsumm --zero_fill | grep -C 12 'Per-Day Traffic Summary' -B 0 -A 8 | sed '/Per-Hour Traffic Daily Average/q'
                split: horizontal
                header_split_by: \s+(\w+)\s+(\w+)\s+(\w+)\s+(\w+)\s+(\w+)\s+(.*)
                set_header:
                  [date, received, delivered, deferred, bounced, rejected]
                regex_match: true
                split_by: \s+(\w+\s+\d+\s+\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)

          #Read the host/domain summary: message delivery & received.
          - event_type: PostfixHostSummary
            commands:
              - run: cat /var/log/maillog | pflogsumm | grep -i 'Host/Domain Summary':' Message Delivery' -A 8 | sed -n '2,9p'
                split: horizontal
                header_split_by: \s+(\w+\s+\w+)\s+(\w+)\s+(\w+)\s+(\w+\s+\w+)\s+(\w+\s+\w+)\s+(.*.)
                set_header:
                  [sentCount, bytesDelivered, defers, avgDaily, maxDaily, host]
                regex_match: true
                split_by: \s+(\d+)\s+(\d+\w*)\s+(\d+)\s+(\d+.\d+\s+\w)\s+(\d+.\d+\s+\w)\s+(.*)
              - run: cat /var/log/maillog | pflogsumm | grep -A 15 'Host/Domain Summary':' Messages Received' | sed '/Senders by message count/q'
                split: horizontal
                header_split_by: \s+(\w+\s+\w+)\s+(\w+)\s+(.*.)
                set_header: [msgCount, bytesReceived, hostDetail]
                regex_match: true
                split_by: \s+(\d+)\s+(\d+\w*)\s+(.*)

          #Read the senders & recipients with message count.
          - event_type: PostfixSenderRecipientMessageCount
            commands:
              - run: cat /var/log/maillog | pflogsumm | grep -C 11 'Senders by message count' -B 1 -A 9 | sed '/Recipients by message count/q'
                split: horizontal
                header_split_by: (.*.)
                set_header: [sender.msgCount, senders]
                regex_match: true
                split_by: \s+(\d+)\s+(.*)
              - run: cat /var/log/maillog | pflogsumm | grep -C 11 'Recipients by message count' -B 1 -A 9 | sed '/Senders by message size/q'
                split: horizontal
                header_split_by: (.*.)
                set_header: [recipient.msgCount, recipients]
                regex_match: true
                split_by: \s+(\d+)\s+(.*)

          #Read the daemon message details.
          - event_type: PostfixDaemonMessage
            commands:
              - run: cat /var/log/maillog | pflogsumm | grep -A 10 'Master daemon messages'
                split: horizontal
                set_header: [daemon.msgCount, daemonMessage]
                regex_match: true
                split_by: \s*(\d+)\s+(\w+.*.)

          #Read the message deferral details.
          - event_type: PostfixDeferralMessage
            commands:
              - run: cat /var/log/maillog | pflogsumm | grep -A 15 'message deferral detail' | sed '/message bounce detail (by relay)/q'
                split: horizontal
                header_split_by: (\s+\w+\s+.*)
                set_header: [deferral.msgCount, deferralMessage]
                regex_match: true
                split_by: \s*(\d+)\s+(\w+.*.)

          #Read the warning message details.
          - event_type: PostfixWarningMessage
            commands:
              - run: cat /var/log/maillog | pflogsumm | grep -v 'mail_queue_enter' | grep -C 100 'Warnings' -B 1 -A 10 | sed '/Fatal Errors/q'
                split: horizontal
                header_split_by: \s+(\w+)\s+(.*)
                set_header: [Warning.msgCount, warningMessage]
                regex_match: true
                split_by: \s*(\d+)\s\s\s(.*.)

          #Read the error message details.
          - event_type: PostfixErrorMessage
            commands:
              - run: cat /var/log/maillog | pflogsumm | grep -C 15 'Fatal Errors' -B 1 -A 10 | sed '/Panics/q'
                split: horizontal
                header_split_by: \s+(\w+)\s+(.*)
                set_header: [Fatal.msgCount, fatalMessage]
                regex_match: true
                split_by: \s*(\d+)\s\s\s(.*.)

          #Read the message bounce details.
          - event_type: PostfixBounceMessage
            commands:
              - run: cat /var/log/maillog | pflogsumm | grep -A 10 'message bounce detail (by relay)' | sed '/message reject detail/q'
                split: horizontal
                header_split_by: \s+(\w+)\s+(.*)
                set_header: [Bounce.msgCount, bounceMessage]
                regex_match: true
                split_by: \s*(\d+)\s\s\s(.*.)

これで無事監視ができるようになりました。
image.png

【監視アラートをWebhookでDiscordに飛ばしてみる】

無事に監視できるようになったのでやはりアラートを飛ばせないとということで、メールでもいいんですが、そもそもそのメールの受信先はこのサーバだったりしますし、携帯メアドでもいいのですが、味気ないのでWebhook使って携帯で通知されるようにしてみましょう。
Teamsではありませんが、設定はこちらを参考にさせていただきました。

Discord(Webhook送信先設定)

自分のサーバ上に新たなチャンネルを作ってWebhookの受信設定をします。
本筋じゃないので割愛しますが、チャンネルの設定で連携サービスを設定すればウェブフックURLが取得可能になります。
image.png

New Relic側の設定

  1. Alerts->Destinationの順で移動したらAdd a destinationからWebhookを選択します。
    image.png
  2. 任意の名前と先ほど取得したウェブフックURLを入力してSave destinationを押します
    image.png
    問題なく登録できれば一覧に表示されます。
    image.png
  3. Alerts->Workflows->Create your first workflowの順で選択
    image.png
  4. ワークフロー名とアラートのフィルタ条件を指定し、通知方法としてWebhookを選択
    image.png
  5. チャンネル名(任意)を入力後、Destinationから先ほど設定した通知先名を選択
    image.png
  6. 送信メッセージテンプレートをペイロードとして設定が可能なので、送信先(今回はDiscord)の仕様に合わせて下記のように変更する
    変更後、Send test notificationを押すとテストメッセージが送信できる
    {
    	"flag": 4,
    	"content": "問題が発生しました。\n {{escape annotations.title.[0] }}"
    }
    
    Discord側で受信したテストメッセージ
    image.png
  7. Save messageを押す
    image.png

ここまで設定すると以下のアラートはすでに飛ぶようになっています。
アラート設定はAlerts->Alert policiesで見ることができます。

  • Golden Signals
  • Postfix alert policy

HostCheckerは投稿者がカスタムで作成したものです。

image.png

【まとめ】

全体としてあまり作りこみをしなくてもかなりサーバの稼働状態が見やすくなったと感じた。
今回は触れなかったがログのパースなどもプレビューを見ながらできるなどまだあまり触っていない私でも気軽にできたので、入り口のとっつきやすさと得られる結果の大きさはただただ感動であった。
APMなど他のコンポーネントとの連動に関しては見られない環境なので機会をみて試してみたいと思っている。

  • インストールはお手軽で基本機能だけでもリソースやログを取得し整理してくれるので大変便利
  • メジャーなアプリであればこちらも簡単な操作で必要データを取得し整理までしてくれる
  • メジャーなアプリであればダッシュボードテンプレートも豊富でお手軽にデータが俯瞰できるようになり、どこでどういった動きをしているかも見やすい
  • postfixはインストールで少し躓いたけど、これまで日次のテキストレポートでしか見られなかった稼働状態をリアルタイムかつグラフィカルに俯瞰できるようになった上、状態把握がすごくしやすいと感じた
5
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?