Ruby
 Computer >> コンピューター >  >> プログラミング >> Ruby

名前空間(Namespace)でモノリシックアプリケーションの監視データを構造化する方法

名前空間とは?

AppSignalで監視しているアプリケーション内で発生するすべての出来事は、何らかの名前空間(namespace)に記録されます。名前空間はフォルダのような役割を果たし、イベントやインシデント、監視データを管理しやすい単位にグループ化してくれます。

デフォルトでは、すべてのアプリケーションは webbackgroundfrontend の3つの標準名前空間から始まります。

  • web:すべてのHTTPリクエストがここに記録されます。RailsやSinatraのようなMVC指向のフレームワークでは、コントローラのアクションが該当します。
  • background:バックグラウンドジョブ、ライブラリ、タスクによる処理がここに記録されます。
  • frontend:AppSignal for JavaScript連携から送信されたイベントがここに記録されます。

AppSignalは、アプリケーションごと・統合ごとに組み込まれたルールに基づいて、受信したイベントを各名前空間へ振り分けます。ただし、このマッピングはいつでも変更でき、アプリケーションの構造に合わせて新しい名前空間を作成することも可能です。

Rubyで名前空間を試してみる

Ruby on Railsアプリケーションで名前空間を実際に試してみましょう。rails new で新しいプロジェクトを作成し、Rails統合をセットアップすると、ダッシュボードに web 名前空間が表示されます。

AppSignalは、いずれかのコントローラからトランザクションを受信すると、その時点で名前空間を表示します。

残りの標準名前空間は、そこで何らかのアクティビティが発生するまでは表示されません。ここで、background 名前空間に何かを追加してみましょう。Sidekiqをプロジェクトに追加した後のダッシュボードは次のようになります(コードはサンプルリポジトリを参照してください)。

AppSignalはSidekiqをジョブプロセッサとして認識するため、アクションを自動的に background 名前空間に割り当てます。主要なバックグラウンドプロセッサのほとんどと統合されていますが、対応していないものを使っている場合は、ジョブに手動で計測コードを追加することもできます。

カスタム名前空間の作成

大規模なモノリシックアプリケーションでは、標準の名前空間だけでは抽象的すぎると感じることがあります。大きなWebサイトは通常、静的コンテンツ、動的なページ、APIエンドポイントなど、さまざまなWebサービスを提供しており、その大部分が web 名前空間に集約されてしまいます。

さらに、アプリケーションの各部分には優先度の違いがあります。ログインページの障害は、社内管理パネルの障害よりもはるかに緊急です。しかしAppSignalは、同じ名前空間内のすべての問題を同等に扱います。アクティビティが多いと、最も重大な問題を見極めるのが難しくなるでしょう。

そこで、優先度と責任範囲に基づいて名前空間を整理し、それぞれに個別の通知ポリシーを紐付けて、関係者にのみアラートを届くようにするのが有効です。この考え方に沿えば、login_pageapi_endpointsadmin_panel といったカスタム名前空間を作成できます。

Rubyで新しい名前空間を作成するには、Appsignal.set_namespace を使用します。以下は、urgent_background という名前空間にジョブを作成するコード例です。

class FetchPricesWorker
    include Sidekiq::Worker
 
    def perform
        Appsignal.set_namespace("urgent_background")
 
        # worker code ...
 
    end
end

この変更を加えてアプリを再起動すると、これらの新しいジョブが新しく作成された名前空間に表示されます。

ダッシュボードでアクション名を確認すれば、実際のジョブが正しく記録されていることを確認できます。

カスタム名前空間は、すべての統合でも利用可能です。

名前空間の除外

カスタム名前空間のもう一つの利点は、関心のない部分からのイベントを無視できることです。たとえば、admin_panel からのイベントを完全に除外することもできます。

名前空間を除外する手順は次の3ステップです。

  1. 監視したくない部分をカスタム名前空間に割り当てます。
  2. 統合の設定でその名前空間を除外します。
  3. アプリを再起動します。

Rubyの場合は、AppSignalの設定ファイルに ignore_namespaces オプションを追加します。

production:
  ignore_namespaces:
    - "admin_panel"

名前空間を除外すると、ソースの時点ですべてのトランザクションデータとスパンデータがスキップされます。カスタムメトリクスのデータは引き続きレポートされます。

ElixirおよびJavaScriptの統合にも同様のオプションがあります。詳細については、名前空間の除外に関するガイドをご覧ください。

モノリシックアプリケーションのための名前空間設計

名前空間の仕組みがわかったところで、モノリシックアプリケーションを分割するためのいくつかの活用方法を見ていきましょう。

厳密なルールはありませんが、分割のアプローチは大きく分けて2つの戦略に集約されます。どちらか一方、あるいは両方を組み合わせた形を出発点にするとよいでしょう。

  • 役割ベース:プロジェクト内の機能的・論理的な単位に名前空間を割り当てます。たとえば、billingsign_in / sign_upadmin_panelhomepage などの名前空間を定義すると理にかなっています。AppSignalのダッシュボードを一目見れば、アプリケーションのどの部分で何が起きているのかがすぐに把握できます。コードを明確な境界線できれいに分割できる場合に適したアプローチです。
  • 重要度ベース:名前空間を優先付けの仕組みとして使います。コードのどの部分が criticalimportantmediumlow なのかは自分で判断します。このアプローチにより、どの問題から先に対処すべきかを即座に判別できます。

ユーザーのサインインと登録を扱うコントローラがあるとしましょう。役割ベースで分割する場合は、これらを user_login 名前空間にマッピングできます。

# Railsでは before_action コールバックを使って
# リクエスト開始前に名前空間を変更します
class LoginController < ApplicationController
    before_action :set_appsignal_namespace
 
    def set_appsignal_namespace
        # 名前空間を設定
        Appsignal.set_namespace("user_login")
    end
 
    # controller actions ...
end

一方、優先度ベースの名前空間を使いたい場合は、請求処理を担当するコントローラはおそらく critical 名前空間に入れるべきでしょう。

class BillingPageController < ApplicationController
    before_action :set_appsignal_namespace
 
    def set_appsignal_namespace
        Appsignal.set_namespace("critical")
    end
end

これらのコントローラを継承する子クラスは、親と同じ名前空間を共有します。

# LoginController を継承するすべてのコントローラも
# "user_login" 名前空間に属します
class RegistrationController < LoginController
 
    # ここで before_action を定義する必要はありません
    # このコントローラはすでに親の名前空間にレポートされます
 
end

これまで見てきたように、ジョブやタスクは自動的に background 名前空間に割り当てられます。可能な限り、より具体的な名前空間に割り当てるべきです。たとえば、データベースのクリーンアップジョブなら、次のように database 名前空間に入れることができます。

class ActiveJobDatabaseCleanupJob < ActiveJob::Base
  queue_as :default
 
  def perform(argument = nil, options = {})
    Appsignal.set_namespace("database")

優先度はジョブにも適用できます。たとえば、重要度の低いタスクは low に割り当てられます。次はRakeタスクの例です。

task :unimportant_job do
 
  # このRakeタスクを low 名前空間で実行
  Appsignal.set_namespace("low")
 
  # job code ...
 
end

場合によっては、手動トランザクションを使ってアクションを記録したいこともあるでしょう。その場合は、トランザクションの作成時に名前空間を定義できます。以下はカスタムメーラージョブをコーディングする例です。

class Job
    def perform
 
        # このジョブ用のトランザクションを作成し、名前空間を設定
        transaction = Appsignal::Transaction.create(
            SecureRandom.uuid,
            "mailer",
            Appsignal::Transaction::GenericRequest.new(ENV.to_hash)
        )
 
        # job code ...
 
    end
end

名前空間と通知

チーム全員がすべての問題について通知を受け取る必要はありません。フロントエンドの専門家は、バックエンド開発者ほどバックグラウンドジョブを気にしません。それでも、バックエンドで問題が発生したときには知りたいはずです。また、バックエンド開発者は web 名前空間のパフォーマンス問題の通知を確実に受け取りたいでしょう。名前空間を使えば、通知を適切な人に振り分けることができます。

名前空間ごとの通知設定

特定の名前空間でのみ有効になる通知グループを作成できます。たとえば、web 名前空間のエラーにはメールを送信したり、frontend 名前空間の問題には #frontend Slackチャンネルにメッセージを送ったりすることが可能です。

名前空間ごとの通知グループを作成するには、「App Settings」→「Notifications」→「Notifiers」に移動し、Add Integration をクリックします。

統合を選択して名前を入力し、送信するメッセージの種類と対象の名前空間を選択します。ここでは、#frontend チャンネル向けのSlack通知を作成してみましょう。

ついでに、バックエンド開発者向けの2つ目の通知も作成しておきます。

チームが必要な情報をすべて把握できるよう、必要な数だけ通知先を設定できます。

名前空間ごとの通知ポリシーの変更

インシデントが作成されると、AppSignalは通知ポリシーを適用します。このポリシーは、エラーが発生した名前空間に基づきます。名前空間ごとに個別のポリシーを定義できます。

アプリケーションの名前空間のデフォルト設定を確認するには、「App Settings」→「Notifications」→「Namespace defaults」に移動します。

ここでは、各名前空間のエラー通知とパフォーマンス通知をカスタマイズするためのオプションが用意されています。

  • Every occurrence:インシデントが発生するたびに通知を送信します(5分間のクールダウン付き)。
  • First on deploy:アプリケーションのデプロイ後、最初のエラーを通知します。
  • First after close:クローズ済みの問題が再オープンされた最初のタイミングで通知を送信します。
  • Never notify:通知を完全に無効にします。

名前空間ごとのトリガーの作成

トリガーは、メトリクスが事前に定義した値を上回った、あるいは下回ったときに、インシデントを作成して通知を送るようAppSignalに指示します。アプリケーションの部分によってしきい値は異なるはずなので、名前空間ごとに個別のトリガーを作成しましょう。定番の例としては、web 名前空間のスループットが低下しすぎたときにアラートを出すトリガーが挙げられます。

トリガーを作成するには、「Anomaly Detection」→「Triggers」に移動し、Add your first trigger をクリックします。

左側のメニューでActionsトリガータイプを選択し、対象の名前空間を選びます。その後、アラートを発火させるしきい値を設定します。

ここで、通知を受け取るグループを定義することもできます。最後に「Save Trigger」をクリックして完了です。

まとめ

名前空間を活用すれば、アプリケーションの監視データに秩序をもたらせます。きめ細かなレベルで通知やインシデントを発火させ、ノイズを抑え、誤検知を避けるためにも不可欠な仕組みです。

Ruby、Node.js、Elixirでのカスタム名前空間の使い方を確認したら、次の記事を読んで、名前空間の活用方法をさらに学びましょう。

  • AppSignalにおける名前空間
  • 名前空間によるグループ化
  • Webhook監視とバックグラウンドジョブ監視の違いとは?
  • Gem 2.2 - カスタム名前空間!
  1. Rubyでコマンドラインアプリケーション(CLI)を作る方法を徹底解説

    RubyはWebアプリケーション開発のイメージが強く、それ以外の用途があることを忘れられがちです。そこで本記事では、Rubyを使ってコマンドラインアプリケーション(CLI)を構築する方法を詳しく解説します。 まず、皆さんがよく目にするコマンドラインアプリケーションの例を挙げてみましょう。 psql(PostgreSQLの対話型ターミナル) rails bundler gem git CLIアプリケーションの作り方はさまざまですが、この記事では代表的な3つの方法に焦点を当てて紹介します。 この記事で学べること ARGV配列の使い方 OptParseライブラリの使い方 Thor gemの使い

  2. 【Excel VBA】データの入力規則でドロップダウンリストを作成・活用する7つの方法

    データの入力規則(データバリデーション)によるドロップダウンリストは、Excelでのさまざまな作業を効率化できる非常に便利な機能です。そして、Excel上であらゆる操作を実行するうえで、VBAを活用するのが最も効果的かつ迅速で安全な方法です。本記事では、VBAマクロを使ったデータの入力規則ドロップダウンリストの7つの活用シーンを、具体的なコードとともにわかりやすく解説します。 練習用ワークブックのダウンロード 本記事で使用する練習用のExcelワークブックは、こちらから無料でダウンロードできます。 VBAで実現するドロップダウンリストの7つの活用方法 このセクションでは、VBAマクロを使っ