ActiveJob の `perform_start` イベントにアダプタ情報を追加
ActiveJob の構造化イベント active_job.started のペイロードから欠落していた :adapter キーを補完し、ログ出力とイベント消費側の情報整合性を回復した変更です。
背景
ActiveJob::StructuredEventSubscriber#perform_start が生成するペイロードには、他のイベント(enqueue、enqueue_at、enqueue_all、perform)と異なり :adapter が含まれていませんでした。その結果、ActiveJob::LogSubscriber#started が queue_name ヘルパーで期待する adapter(queue) 形式の文字列が生成できず、実行ログが「Performing … from (default)」という形でアダプタ名を省略して表示されました。
この不整合は、同一ジョブに対して開始ログと完了ログで情報が食い違うという見た目上の問題を生み、構造化イベントを利用する外部ツールでもアダプタ情報が取得できないという実用上の欠点をもたらしていました。
技術的な変更
ペイロードに :adapter を追加
perform_start メソッド内でイベントペイロードから adapter = event.payload[:adapter] を取得し、生成するハッシュに adapter: ActiveJob.adapter_name(adapter) を加えるよう修正しました。
def perform_start(event)
job = event.payload[:job]
adapter = event.payload[:adapter]
payload = {
job_class: job.class.name,
job_id: job.job_id,
queue: job.queue_name,
adapter: ActiveJob.adapter_name(adapter),
enqueued_at: job.enqueued_at&.utc&.iso8601(9),
}
if job.class.log_arguments?
# ...
end
end
テストの拡張
ペイロード検証テスト test_perform_start_job に adapter: アサートを追加し、ActiveJob.adapter_name(ActiveJob::Base.queue_adapter) が正しく含まれることを確認するよう変更しました。
assert_event_reported("active_job.started", payload: {
job_class: TestJob.name,
queue: "default",
adapter: ActiveJob.adapter_name(ActiveJob::Base.queue_adapter)
}) do
TestJob.perform_now
end
テスト結果は、修正前は active_job.started に :adapter が欠如し失敗(RED)だったのが、修正後は全テストが成功(GREEN)し、期待通りのペイロードが生成されることを示しています。
設計判断
既存インストゥルメンテーションを活用した最小限の修正
ActiveJob::Instrumentation#instrument はすべての通知で payload[:adapter] = queue_adapter を設定しているため、情報はすでに通知ペイロードに存在していました。StructuredEventSubscriber がそれを単に転送し忘れていた点を修正しただけで、他のコンポーネントや外部インターフェースへの影響はありません。
このアプローチは、後方互換性を保ちつつ情報ロスを防ぐという設計方針に沿っており、余計なロジック追加や新しい設定項目の導入を避けています。結果として、既存の perform_start ロジックはほぼ変わらず、アダプタ情報の可視化だけが向上しました。
まとめ
perform_start イベントで失われていた :adapter キーを正しく転送することで、ログ出力と構造化イベントの情報が一貫し、ユーザーおよびツールがジョブ実行時のアダプタを正確に把握できるようになりました。修正はインストゥルメンテーションが提供する情報を活かした最小限のコード追加で実現され、既存機能への影響はありません。