How to: Create a Custom Tracking Participant
Workflow tracking provides visibility into the status of workflow execution. The workflow runtime emits tracking records that describe workflow lifecycle events, activity lifecycle events, bookmark resumptions, and faults. These tracking records are consumed by tracking participants. Windows Workflow Foundation (WF) includes a standard tracking participant that writes tracking records as Event Tracing for Windows (ETW) events. If that does not meet your requirements, you can also write a custom tracking participant. This tutorial step describes how to create a custom tracking participant and tracking profile that capture the output of WriteLine activities so that they can be displayed to the user.
Note: |
|---|
| Each topic in the Getting Started tutorial depends on the previous topics. To complete this topic, you must first complete the previous topics. To download a completed version or view a video walkthrough of the tutorial, see Windows Workflow Foundation (WF45) - Getting Started Tutorial. |
In this topic
-
To create the custom tracking participant
-
To create the tracking profile and register the tracking participant
-
To display the tracking information
-
To build and run the application
To create the custom tracking participant
-
Right-click NumberGuessWorkflowHost in Solution Explorer and choose Add, Class. Type StatusTrackingParticipant into the Name box, and click Add.
-
Add the following using (or Imports) statements at the top of the file with the other using (or Imports) statements.
-
Modify the
StatusTrackingParticipantclass so that it inherits from TrackingParticipant.
-
Add the following Track method override. There are several different types of tracking records. We are interested in the output of WriteLine activities, which are contained in activity tracking records. If the TrackingRecord is an ActivityTrackingRecord for a WriteLine activity, the Text of the WriteLine is appended to a file named after the
InstanceIdof the workflow. In this tutorial, the file is saved to the current folder of the host application.
When no tracking profile is specified, the default tracking profile is used. When the default tracking profile is used, tracking records are emitted for all ActivityStates. Because we only need to capture the text one time during the lifecycle of the WriteLine activity, we only extract the text from the ActivityStates.Executing state. In To create the tracking profile and register the tracking participant, a tracking profile is created that specifies that only WriteLine ActivityStates.Executing tracking records are emitted.protected override void Track(TrackingRecord record, TimeSpan timeout) { ActivityStateRecord asr = record as ActivityStateRecord; if (asr != null) { if (asr.State == ActivityStates.Executing && asr.Activity.TypeName == "System.Activities.Statements.WriteLine") { // Append the WriteLine output to the tracking // file for this instance using (StreamWriter writer = File.AppendText(record.InstanceId.ToString())) { writer.WriteLine(asr.Arguments["Text"]); writer.Close(); } } } }
To create the tracking profile and register the tracking participant
-
Right-click WorkflowHostForm in Solution Explorer and choose View Code.
-
Add the following using (or Imports) statement at the top of the file with the other using (or Imports) statements.
-
Add the following code to
ConfigureWorkflowApplicationjust after the code that adds the StringWriter to the workflow extensions and before the workflow lifecycle handlers.
This tracking profile specifies that only activity state records for WriteLine activities in the Executing state are emitted to the custom tracking participant.// Add the custom tracking participant with a tracking profile // that only emits tracking records for WriteLine activities. StatusTrackingParticipant stp = new StatusTrackingParticipant { TrackingProfile = new TrackingProfile { Queries = { new ActivityStateQuery { ActivityName = "WriteLine", States = { ActivityStates.Executing }, Arguments = { "Text" } } } } }; wfApp.Extensions.Add(stp);
After adding the code, the start ofConfigureWorkflowApplicationwill look like the following example.
private void ConfigureWorkflowApplication(WorkflowApplication wfApp) { // Configure the persistence store. wfApp.InstanceStore = store; // Add a StringWriter to the extensions. This captures the output // from the WriteLine activities so we can display it in the form. StringWriter sw = new StringWriter(); wfApp.Extensions.Add(sw); // Add the custom tracking participant with a tracking profile // that only emits tracking records for WriteLine activities. StatusTrackingParticipant stp = new StatusTrackingParticipant { TrackingProfile = new TrackingProfile { Queries = { new ActivityStateQuery { ActivityName = "WriteLine", States = { ActivityStates.Executing }, Arguments = { "Text" } } } } }; wfApp.Extensions.Add(stp); // Workflow lifecycle handlers...
To display the tracking information
-
Right-click WorkflowHostForm in Solution Explorer and choose View Code.
-
In the
InstanceId_SelectedIndexChangedhandler, add the following code immediately after the code that clears the status window.
When a new workflow is selected in the workflow list, the tracking records for that workflow are loaded and displayed in the status window. The following example is the completed// If there is tracking data for this workflow, display it // in the status window. if (File.Exists(WorkflowInstanceId.ToString())) { string status = File.ReadAllText(WorkflowInstanceId.ToString()); UpdateStatus(status); }
InstanceId_SelectedIndexChangedhandler.
private void InstanceId_SelectedIndexChanged(object sender, EventArgs e) { if (InstanceId.SelectedIndex == -1) { return; } // Clear the status window. WorkflowStatus.Clear(); // If there is tracking data for this workflow, display it // in the status window. if (File.Exists(WorkflowInstanceId.ToString())) { string status = File.ReadAllText(WorkflowInstanceId.ToString()); UpdateStatus(status); } // Get the workflow version and display it. // If the workflow is just starting then this info will not // be available in the persistence store so do not try and retrieve it. if (!WorkflowStarting) { WorkflowApplicationInstance instance = WorkflowApplication.GetInstance(this.WorkflowInstanceId, store); WorkflowVersion.Text = WorkflowVersionMap.GetIdentityDescription(instance.DefinitionIdentity); // Unload the instance. instance.Abandon(); } }
To build and run the application
-
Press Ctrl+Shift+B to build the application.
-
Press Ctrl+F5 to start the application.
-
Select a range for the guessing game and the type of workflow to start, and click New Game. Enter a guess in the Guess box and click Go to submit your guess. Note that the status of the workflow is displayed in the status window. This output is captured from the WriteLine activities. Switch to a different workflow by selecting one from the Workflow Instance Id combo box and note that the status of the current workflow is removed. Switch back to the previous workflow and note that the status is restored, similar to the following example.
Note: If you switch to a workflow that was started before tracking was enabled no status is displayed. However if you make additional guesses, their status is saved because tracking is now enabled. Please enter a number between 1 and 10
Your guess is too high.
Please enter a number between 1 and 10Make a note of the workflow instance id, and play the game through to its completion.
Note: This information is useful for determining the range of the random number, but it does not contain any information about what guesses have been previously made. This information is in the next step, How to: Host Multiple Versions of a Workflow Side-by-Side. -
Open Windows Explorer and navigate to the NumberGuessWorkflowHost\bin\debug folder (or bin\release depending on your project settings). Note that in addition to the project executable files there are files with guid filenames. Identify the one that corresponds to the workflow instance id from the completed workflow in the previous step and open it in Notepad. The tracking information contains information similar to the following.In addition to the absence of the user's guesses, this tracking data does not contain information about the final guess of the workflow. That is because the tracking information consists only of the WriteLine output from the workflow, and the final message that is displayed is done so from the Completed handler after the workflow completes. In next step of the tutorial, How to: Host Multiple Versions of a Workflow Side-by-Side, the existing WriteLine activities are modified to display the user's guesses, and an additional WriteLine activity is added that displays the final results. After these changes are integrated, How to: Host Multiple Versions of a Workflow Side-by-Side demonstrates how to host multiple versions of a workflow at the same time.
Please enter a number between 1 and 10
Your guess is too high.
Please enter a number between 1 and 10
Your guess is too high.
Please enter a number between 1 and 10
Build Date: