Sidekiq 로깅

Worker 컨텍스트

로그에서 worker에 대한 추가 정보를 얻기 위해, 우리는 ApplicationContext 형태로 작업에 메타데이터를 추가합니다. 대부분의 경우에는 요청에서 작업을 예약할 때, 이 컨텍스트가 이미 요청에서 유도되어 예약된 작업에 추가됩니다.

작업이 실행될 때 예약된 시점의 컨텍스트가 복원됩니다. 이로써 해당 컨텍스트가 실행 중인 작업 내에서 예약된 작업으로 전파됩니다.

이 모든 것은 대부분의 경우에는 작업에 컨텍스트를 추가하기 위해 우리가 아무것도 할 필요가 없다는 뜻입니다.

그러나 작업을 예약할 때 컨텍스트가 존재하지 않거나, 존재하는 컨텍스트가 잘못된 경우도 있습니다. 이러한 경우에 우리는 로그에서 잘못된 메타데이터를 피하기 위해 RuboCop 규칙을 추가했습니다.

대부분의 경우 우리의 검사 요소들처럼, 이들을 비활성화하는 데 완전히 타당한 이유들이 있습니다. 예를 들어, 요청에서의 컨텍스트가 올바르다고 할 수 있습니다. 혹은 이미 검사 요소에 의해 인식되지 않는 방법으로 컨텍스트를 지정했을 수 있습니다. 어떤 경우에든, 검사 요소를 비활성화하는 경우에 어떤 컨텍스트를 사용해야 하는지 가리키는 코드 주석을 남겨주세요.

컨텍스트에 객체를 제공할 때, 네임스페이스와 프로젝트의 루트가 사전로딩(pre-loaded)되었는지 확인하세요. 이는 모든 Routable에 정의된 .with_route 스코프를 사용하여 수행할 수 있습니다.

크론 워커

크론잡(cronjob) 큐에 속하는 워커의 경우, 컨텍스트는 자동으로 지워집니다. 심지어 요청에서 스케줄링되었을 때에도요. 우리는 다른 작업들이 크론 워커에서 예약될 때 잘못된 메타데이터를 피하기 위해 이를 수행합니다.

크론 워커는 자체적으로 인스턴스 전역에서 실행되므로, 사용자, 네임스페이스, 프로젝트 또는 다른 리소스에 스코프가 지정되지 않습니다.

그러나, 그들은 종종 컨텍스트가 필요한 다른 작업들을 예약합니다.

그래서 워커 내 어딘가에서 컨텍스트를 나타내는 표시가 필요합니다. 이는 워커 내의 다음 메소드 중 하나를 사용하여 수행할 수 있습니다:

  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 } }
    )

첫 번째 인수의 열거 가능한 개체마다 두 개의 블록으로 전달됩니다:

  • arguments_proc은 작업이 예약되어야 하는 인수 디렉터리을 반환해야 합니다.

  • context_proc은 작업의 컨텍스트 정보를 담은 해시를 반환해야 합니다.

인수 로깅

Sidekiq 작업 인수는 기본적으로 로깅되지만, SIDEKIQ_LOG_ARGUMENTS가 비활성화되지 않는 한입니다.

기본적으로 숫자 인수만 로깅되며, 다른 유형의 인수는 민감한 정보를 포함할 수 있기 때문에 로깅되지 않습니다. 이를 재정의하려면, 숫자 인수는 여기에 명시할 필요가 없기 때문에, 워커 내에서 loggable_arguments를 사용하세요.

예를 들어:

class MyWorker
  include ApplicationWorker
  
  loggable_arguments 1, 3
  
  # object_id는 숫자이므로 로깅될 것입니다
  # string_a는 loggable_arguments 호출로 인해 로깅될 것입니다
  # string_b는 로그에서 필터링될 것입니다
  # string_c는 loggable_arguments 호출로 인해 로깅될 것입니다
  def perform(object_id, string_a, string_b, string_c)
  end
end