Sidekiqロギング

ワーカーコンテキスト

GitLab 12.8で導入されました

ワーカーに関する情報をログに残すために、ApplicationContext](../logging.md#logging-context-metadata-through-rails-or-grape-requests) の形で[メタデータをジョブに追加します。ほとんどの場合、リクエストからジョブをスケジューリングするとき、このコンテキストはすでにリクエストから差し引かれ、スケジューリングされたジョブに追加されます。

ジョブが実行されると、スケジュールされたときにアクティビティだったコンテキストがリストアされます。これによって、コンテキストは、実行中のジョブ内からスケジュールされたすべてのジョブに伝搬されます。

このことは、ほとんどの場合、ジョブにコンテキストを追加するために、何もする必要がないことを意味します。

しかし、ジョブのスケジューリング時にコンテキストが存在しないインスタンスや、存在するコンテキストが正しくない可能性が高いインスタンスもあります。このようなインスタンスに対して、私たちは RuboCop のルールを追加して、注意を喚起し、ログに不正なメタデータを残さないようにしています。

私たちのほとんどの警官と同様に、それらを無効にするための完全に正当な理由があります。この場合、リクエストのコンテキストが正しい可能性があります。あるいは、警官に拾われないような方法ですでにコンテキストを指定しているのかもしれません。いずれにせよ、警官を無効にするときにどのコンテキストを使用するかを示すコードコメントを残してください。

オブジェクトをコンテキストに提供する際には、名前空間とプロジェクトのルートが事前にロードされていることを確認してください。これは、すべてのRoutableで定義されている.with_route スコープを使用することで可能です。

cron ワーカー

リクエストからスケジューリングする場合でも、cronjob キュー (include CronjobQueue) にあるワーカーのコンテキストは自動的にクリアされます。これは cron ワーカーから他のジョブがスケジューリングされたときに不正なメタデータにならないようにするためです。

cron ワーカーはインスタンス全体で動作するので、コンテキストに追加されるべきユーザー、名前空間、プロジェクト、その他のリソースにはスコープされません。

しかし、しばしばコンテキストを必要と_する_他のジョブをスケジュールします。

そのため、Worker のどこかにコンテキストを表示する必要があります。これは、Worker のどこかで以下のメソッドのいずれかを使うことで実現できます:

  1. ジョブをスケジュールするコードをwith_context ヘルパーでラップします:

      def perform
        deletion_cutoff = Gitlab::CurrentSettings
                            .deletion_adjourned_period.days.ago.to_date
        projects = Project.with_route.with_namespace
                     .aimed_for_deletion(deletion_cutoff)
       
        projects.find_each(batch_size: 100).with_index do |project, index|
          delay = index * INTERVAL
       
          with_context(project: project) do
            AdjournedProjectDeletionWorker.perform_in(delay, project.id)
          end
        end
      end
    
  2. コンテキストを提供するバッチスケジューリングメソッドを使います:

      def schedule_projects_in_batch(projects)
        ProjectImportScheduleWorker.bulk_perform_async_with_contexts(
          projects,
          arguments_proc: -> (project) { project.id },
          context_proc: -> (project) { { project: project } }
        )
      end
    

    あるいは、遅延を伴うスケジューリングの場合:

      diffs.each_batch(of: BATCH_SIZE) do |diffs, index|
        DeleteDiffFilesWorker
          .bulk_perform_in_with_contexts(index *  5.minutes,
                                         diffs,
                                         arguments_proc: -> (diff) { diff.id },
                                         context_proc: -> (diff) { { project: diff.merge_request.target_project } })
      end
    

一括でスケジュールされたジョブ

ジョブを一括でスケジューリングする場合、これらのジョブは包括的なコンテキストではなく、別のコンテキストを持つ必要があります。

そのような場合は、bulk_perform_asyncbulk_perform_async_with_context ヘルパーに置き換え、bulk_perform_in の代わりにbulk_perform_in_with_contextを使用してください。

使用例:

    ProjectImportScheduleWorker.bulk_perform_async_with_contexts(
      projects,
      arguments_proc: -> (project) { project.id },
      context_proc: -> (project) { { project: project } }
    )

第1引数の列挙可能なオブジェクトは、それぞれ2つのブロックに分けられます:

  • arguments_proc ジョブがスケジューリングされる必要がある引数のリストを返す必要があります。

  • context_proc ジョブのコンテキスト情報を持つハッシュを返す必要があります。

引数 logging

GitLab 13.6では、Sidekiqジョブの引数はSIDEKIQ_LOG_ARGUMENTS が無効になっていない限り、デフォルトでログに記録されます。

デフォルトでは、ログに記録される引数は数値引数のみです。他の型の引数には機密情報が含まれる可能性があるからです。これを上書きするには、loggable_arguments をワーカー内部で使用して、ログに記録する引数のインデックスを指定します (数値引数はここで指定する必要はありません)。

使用例:

class MyWorker
  include ApplicationWorker

  loggable_arguments 1, 3

  # object_id will be logged as it's numeric
  # string_a will be logged due to the loggable_arguments call
  # string_b will be filtered from logs
  # string_c will be logged due to the loggable_arguments call
  def perform(object_id, string_a, string_b, string_c)
  end
end