はじめに
Sitecore で Publisher.Publish() を利用したカスタムパブリッシュ処理を実装していると、パブリッシュ中にエラーが発生した場合、デフォルトのエラーログにはアイテム名しか出力されません。
同名のアイテムが複数存在する場合、デフォルトのエラーログだけでは対象のアイテムの特定が難しくなってしまいます。
本記事では、パブリッシュ中に処理されているアイテムをスレッド単位で保持し、エラー発生時に ItemID やアイテムパスをログ出力できるようにする方法を紹介します。
実装手順
1. PublishContextHolder を作成する
まず、パブリッシュ処理中の「現在のアイテム」を保持するためのクラスを作成します。
Publish は基本的に同一スレッド内で処理されるため、[ThreadStatic] を利用してスレッドごとにアイテムを保持します。
public static class PublishContextHolder
{
[ThreadStatic]
public static Sitecore.Data.Items.Item CurrentItem;
}
これにより、パブリッシュ処理のどこからでも「今処理しているアイテム」にアクセスできるようになります。
2. パブリッシュ中のアイテムを取得する Processor を作成
次に、publish:itemProcessingイベントをフックし、現在処理中のアイテムをPublishContextHolderに設定するクラスを作成します。
public class CapturePublishingItemProcessor
{
public void OnItemProcessing(object sender, EventArgs args)
{
var publishArgs = args as ItemProcessingEventArgs;
if (publishArgs != null)
{
PublishContextHolder.CurrentItem = publishArgs.Context.PublishHelper.GetSourceItem(publishArgs.Context.ItemId);
}
}
}
3. 設定ファイルにイベントハンドラを追加
作成した Processor を Sitecore のイベント設定に追加します。
※ namespaceとassemblyは実際のプロジェクトに合わせて変更してください。
これで、パブリッシュ中に各アイテムが処理されるタイミングでPublishContextHolder.CurrentItemが更新されるようになります。
例)エラーログ出力時にアイテム情報を付加する
パブリッシュ処理中に例外が発生した際、PublishContextHolder.CurrentItemを参照してログ出力することができます。
catch (Exception ex)
{
var item = PublishContextHolder.CurrentItem;
if (item != null)
{
Sitecore.Diagnostics.Log.Error(
$"Publish Error\nItemID: {item.ID}\nItemPath: {item.Paths.FullPath}",
ex,
this);
}
}
※エントリーの内容・画像等は、公開時点での情報に基づきます。
※Sitecoreのバージョンによって実装されている機能が異なります。