I would like to see how long each item takes to publish using the event system.

To do this I am thinking I will use the Publish Transaction Item ID in the publish initiated event (instead of the normal item TCM ID) and then store it somewhere (external db?). And then in the publish committed event write again to the external storage.

Then have an external custom page that reads the external storage and gives me an idea of Publish Times per item.

Is there a better way to achieve this? Any gotchas I haven't considered?

| improve this question | | | | |
  • 1
    What do you mean by each item? Do you mean each page, component, etc, or each publish transaction? – Andrey Marchuk Oct 8 '14 at 15:01

A long time ago I wrote the following event handler Performance Counter eXtension, it was meant as a showcase of the new .NET events in SDL Tridion 2011, and it features for one, counting the averadge time a render action took.

When you take a look at the source code you will find some interesting code in my RegisterEndPublishTime() method. In short, when a Publish Transaction is finished, its Publish State will be set, and each of the items in that Transaction, will have a RenderTime:

/// <summary>
/// Register end time of set publish state event and update performance counter with render time(s) per rendered item
/// </summary>
/// <param name="subject">published item</param>
/// <param name="args">set publish state event arguments</param>
/// <param name="phase">event phase</param>
private void RegisterEndPublishTime(RepositoryLocalObject subject, SetPublishStateEventArgs args, EventPhases phase)
    if (!args.IsPublished) return;
    foreach (var item in args.ProcessedItems)

This should give you enough information, to figure out a solution yourself I think.

| improve this answer | | | | |
  • What is _renderTime, i.e. where do you maintain it across the event chain? – Nickoli Roussakov Oct 9 '14 at 19:44
  • _renderTime is just a global variable to calculate the average render time of all render actions over a certain period of time, see the source code on SDL Tridion World if you want full details. – Bart Koopman Oct 10 '14 at 7:55

you can get the publish time per item directly from a publish transaction.

It should be under ProcessedItem.RenderTime

You can get this time and time again by querying the publishing Q (this can be quite slow though, so some caching might be good)

| improve this answer | | | | |

You should be able to get what you need hooking into the following event

EventSystem.Subscribe<PublishTransaction, SaveEventArgs>(TransactionSaved, EventPhases.TransactionCommitted);
| improve this answer | | | | |

You said the Event System, but it might be easier just to pull off with a couple of TBBs:

1) Throw a DateTime.Now on top of the package as the first TBB

2) Throw the time diff as the last TBB and concatenate the Output item with an XML comment to print the string. (cheesy, but very quick and effective)

This should be good enough for a specific template. Though if you need metrics for all the hundreds of template you may have in the system, then yeah, Event System the way forward.

To do this, I would store a DateTime.Now at the PublishEventArgs Initiated phase, then record it again and calculate the delta at the PublishEventArgs TransactionCommitted/Aborted/InDoubt phases. The question now is where to record your start time and the delta output.

For the start time, I would place this into Context Variables. To output the delta time, I would open a placeholder component (an Article with a text area for instance) and record the time next to the Publish Item's TCM ID). Of course, if you want a pretty report, then store in a custom DB table (or AppData) as an XML and use that as your report's data source.

| improve this answer | | | | |
  • You need to consider here that the publish may fail. That is why I went for the PublishTransaction and testing that with "if (transaction.State == PublishTransactionState.Success)" – Chris Morgan Oct 8 '14 at 15:27
  • 2
    That's why you check what phase you're in. Perhaps just do a switch on the phases enum and only handle the phases that are not failed. Though your idea just as good (if not better). – Nickoli Roussakov Oct 8 '14 at 15:29

Your Answer

