0
votes

I'm working on using Windows Workflow 4/4.5 to do some various business tasks. These tasks take a fair amount of time to complete. I'd like to be able to show a view to the user of workflow progress.

My thought was to make something similar to the TFS build output. It uses indentions to show sub-tasks executing, logged output, etc.

From my research I think I should be using a custom tracking profile. I've written one and instructed it to handle two types of queries, ActivityStateQuery and WorkflowInstanceQuery. The former gives me information regarding when an activity starts and completes as well as other states. The latter gives me indication of a the workflow's states.

This gets me the type of information that I'd like to have.

I want to put this data into an XML document and then use XSL to transform it to HTML. The problem I'm having is that I don't have any hierarchical data with an ActivityStateRecord. I have an activity, but I do not know its parent when the Track method executes. Without that context I am unsure about how to add the activity's state to the XML document.

The activity id that is assigned when the Track method is invoked uses a '.' pattern. I thought I could use this to figure out the hierarchy, i.e 1.5.8 is an activity with a parent with id 1.5 and its parent is id 1. It appears to only be a relation to the currently executing activity because when I place activities within other activities, such as a sequence, the ids are not changing beyond a single '.'. When I do this I get the following XML structure:

<logs>
  <log workflowInstanceId="bde36e74-0b39-4445-aac7-27f3e8cf5b1d">
    <activity activityId="1" activityName="TestActivity1" activityTypeName="SumTotal.WorkflowInstaller.Tests.Resources.TestActivity1">
      <status eventTime="2013-06-14T15:14:40.7847857Z" level="INFO">Executing: TestActivity1</status>
      <activity activityId="1.1" activityName="Sequence" activityTypeName="System.Activities.Statements.Sequence">
        <status eventTime="2013-06-14T15:14:53.3645053Z" level="INFO">Executing: Sequence</status>
        <status eventTime="2013-06-14T15:15:23.5382311Z" level="INFO">Closed: Sequence</status>
      </activity>
      <activity activityId="1.11" activityName="Assign" activityTypeName="System.Activities.Statements.Assign">
        <status eventTime="2013-06-14T15:14:54.9715972Z" level="INFO">Executing: Assign</status>
        <status eventTime="2013-06-14T15:14:54.9715972Z" level="INFO">Closed: Assign</status>
      </activity>
      <activity activityId="1.7" activityName="Sequence" activityTypeName="System.Activities.Statements.Sequence">
        <status eventTime="2013-06-14T15:14:58.2097824Z" level="INFO">Executing: Sequence</status>
        <status eventTime="2013-06-14T15:15:14.410709Z" level="INFO">Closed: Sequence</status>
      </activity>
      <status eventTime="2013-06-14T11:15:14.409709-04:00" level="DEBUG">Log: Test1 value</status>
      <activity activityId="1.2" activityName="Assign" activityTypeName="System.Activities.Statements.Assign">
        <status eventTime="2013-06-14T15:15:18.7189555Z" level="INFO">Executing: Assign</status>
        <status eventTime="2013-06-14T15:15:18.7189555Z" level="INFO">Closed: Assign</status>
      </activity>
      <status eventTime="2013-06-14T15:15:26.6104068Z" level="INFO">Closed: TestActivity1</status>
    </activity>
  </log>
</logs>

Ideally I would like to generate the following XML:

<logs>
    <log workflowInstanceId="bde36e74-0b39-4445-aac7-27f3e8cf5b1d">
        <activity activityId="1" activityName="TestActivity1" activityTypeName="SumTotal.WorkflowInstaller.Tests.Resources.TestActivity1">
            <status eventTime="2013-06-14T15:14:40.7847857Z" level="INFO">Executing: TestActivity1</status>
            <activity activityId="1.1" activityName="Sequence" activityTypeName="System.Activities.Statements.Sequence">
                <status eventTime="2013-06-14T15:14:53.3645053Z" level="INFO">Executing: Sequence</status>
                <activity activityId="1.11" activityName="Assign" activityTypeName="System.Activities.Statements.Assign">
                    <status eventTime="2013-06-14T15:14:54.9715972Z" level="INFO">Executing: Assign</status>
                    <status eventTime="2013-06-14T15:14:54.9715972Z" level="INFO">Closed: Assign</status>
                </activity>
                <activity activityId="1.7" activityName="Sequence" activityTypeName="System.Activities.Statements.Sequence">
                    <status eventTime="2013-06-14T15:14:58.2097824Z" level="INFO">Executing: Sequence</status>
                    <status eventTime="2013-06-14T11:15:14.409709-04:00" level="DEBUG">Log: Test1 value</status>
                    <status eventTime="2013-06-14T15:15:14.410709Z" level="INFO">Closed: Sequence</status>
                </activity>
                <activity activityId="1.2" activityName="Assign" activityTypeName="System.Activities.Statements.Assign">
                    <status eventTime="2013-06-14T15:15:18.7189555Z" level="INFO">Executing: Assign</status>
                    <status eventTime="2013-06-14T15:15:18.7189555Z" level="INFO">Closed: Assign</status>
                </activity>
                <status eventTime="2013-06-14T15:15:23.5382311Z" level="INFO">Closed: Sequence</status>
            </activity>
            <status eventTime="2013-06-14T15:15:26.6104068Z" level="INFO">Closed: TestActivity1</status>
        </activity>
    </log>
</logs>

Is there any way to get this type of information or is there a better way to do this type of tracking/logging?

1

1 Answers

1
votes

After some fiddling and rethinking I was able to achieve the type of output I desired.

Essentially I kept using the logging that I was using during the states for ActivityStateQuery.

What I added was an additional query to the tracking profile. I added an ActivityScheduledQuery. The ActivityScheduledRecord gives the activity scheduling the activity and the child activity. This allows me to create the child's log node under the parent's node. The id on the ActivityInfo object for the child node matches the id when the "Executing" state happens for the activity and I can then link up log messages and state messages during the ActivityStateQuery.

This is the tracking profile for my tracking participant object:

TrackingProfile = new TrackingProfile
        {
          Queries = 
            {
                new ActivityStateQuery
                {
                    ActivityName = "*",
                    States = { "*" }
                },
                new WorkflowInstanceQuery
                {
                  States = { WorkflowInstanceStates.Started, WorkflowInstanceStates.Completed }
                },
                new ActivityScheduledQuery
                {
                  ActivityName = "*",
                  ChildActivityName = "*"
                }
            }
        }