Tracking Profiles

Tracking profiles contain tracking queries that permit a tracking participant to subscribe to workflow events that are emitted when the state of a workflow instance changes at run time.

Tracking Profiles

Tracking profiles are used to specify which tracking information is emitted for a workflow instance. If no profile is specified, then all tracking events are emitted. If a profile is specified, then the tracking events specified in the profile will be emitted. Depending on your monitoring requirements, you may write a profile that is very general, which subscribes to a small set of high-level state changes on a workflow. Conversely, you may create a very detailed profile whose resulting events are rich enough to reconstruct a detailed execution flow later.

Tracking profiles manifest themselves as XML elements within a standard .NET Framework configuration file or specified in code. The following example is of a .NET Framework 4.6.1 tracking profile in a configuration file that allows a tracking participant to subscribe to the Started and Completed workflow events.

<system.serviceModel>
    ...
    <tracking>
     <profiles>
      <trackingProfile name="Sample Tracking Profile">
        <workflow activityDefinitionId="*">
          <workflowInstanceQueries>
            <workflowInstanceQuery>
              <states>
                <state name="Started"/>
                <state name="Completed"/>
              </states>
            </workflowInstanceQuery>
          </workflowInstanceQueries>
        </workflow>
      </trackingProfile>
    </profiles>
  </tracking>
    ...
</system.serviceModel>

The following example shows the equivalent tracking profile created using code.

TrackingProfile profile = new TrackingProfile()
{
    Name = "CustomTrackingProfile",
    Queries =
    {
        new WorkflowInstanceQuery()
        {
            // Limit workflow instance tracking records for started and
            // completed workflow states.
            States = { WorkflowInstanceStates.Started, WorkflowInstanceStates.Completed },
        }
    }
};

Tracking records are filtered through the visibility mode within a tracking profile by using the ImplementationVisibility attribute. A composite activity is a top-level activity that contains other activities that form its implementation. The visibility mode specifies the tracking records emitted from composite activities within a workflow activity, to specify if activities that form the implementation are being tracked. The visibility mode applies at the tracking profile level. The filtering of tracking records for individual activities within a workflow is controlled by the queries within the tracking profile. For more information, see the Tracking Profile Query Types section in this document.

The two visibility modes specified by the implementationVisibility attribute in the tracking profile are RootScope and All. Using the RootScope mode suppresses the tracking records for activities that form the implementation of an activity in the case where a composite activity is not the root of a workflow. This implies that, when an activity that is implemented using other activities is added to a workflow, and the implementationVisibility set to RootScope, only the top-level activity within that composite activity is tracked. If an activity is the root of the workflow, then the implementation of the activity is the workflow itself and tracking records are emitted for activities that form the implementation. Using the All mode permits all tracking records to be emitted for the root activity and all its composite activities.

For example, suppose MyActivity is a composite activity whose implementation contains two activities, Activity1 and Activity2. When this activity is added to a workflow and tracking is enabled with a tracking profile with implementationVisibility set to RootScope, tracking records are emitted only for MyActivity. However, no records are emitted for activities Activity1 and Activity2.

However, if the implementationVisibility attribute for the tracking profile is set to All, then tracking records are emitted not only for MyActivity, but also for activities Activity1 and Activity2.

The implementationVisibility flag applies to following tracking record types:

  • ActivityStateRecord

  • FaultPropagationRecord

  • CancelRequestedRecord

  • ActivityScheduledRecord

Note

CustomTrackingRecords emitted from activity implementation are not filtered out by the implementationVisibility setting.

The implementationVisibility functionality is specified as RootScope on the tracking profile in code as follows:

TrackingProfile sampleTrackingProfile = new TrackingProfile()
{
    Name = "Sample Tracking Profile",
    ImplementationVisibility = ImplementationVisibility.RootScope
};

The implementationVisibility functionality is specified as All on the tracking profile in a configuration file as follows:

<tracking>
      <profiles>
        <trackingProfile name="Shipping Monitoring" implementationVisibility="All">
          <workflow activityDefinitionId="*">
...
         </workflow>
        </trackingProfile>
      </profiles>
</tracking>

The ImplementationVisibility setting on the tracking profile is optional. By default, its value is set to RootScope. The values for this attribute are also case-sensitive.

Tracking Profile Query Types

Tracking profiles are structured as declarative subscriptions for tracking records that allow you to query the workflow runtime for specific tracking records. There are several query types that allow you subscribe to different classes of TrackingRecord objects. Tracking profiles can be specified in configuration or through code. Here are the most common query types:

  • WorkflowInstanceQuery - Use this to track workflow instance life cycle changes like the previously-demonstrated Started and Completed. The WorkflowInstanceQuery is used to subscribe to the following TrackingRecord objects:

    The states that can be subscribed to are specified in the WorkflowInstanceStates class.

    The configuration or code used to subscribe to workflow instance-level tracking records for the Started instance state using the WorkflowInstanceQuery is shown in the following example.

    <workflowInstanceQueries>
        <workflowInstanceQuery>
          <states>
            <state name="Started"/>
          </states>
        </workflowInstanceQuery>
    </workflowInstanceQueries>
    
    TrackingProfile sampleTrackingProfile = new TrackingProfile()
    {
        Name = "Sample Tracking Profile",
        Queries =
        {
            new WorkflowInstanceQuery()
            {
                States = { WorkflowInstanceStates.Started}
            }
        }
    };
    
  • ActivityStateQuery - Use this to track life cycle changes of the activities that make up a workflow instance. For example, you may want to keep track of every time the "Send E-Mail" activity completes within a workflow instance. This query is necessary for a TrackingParticipant to subscribe to ActivityStateRecord objects. The available states to subscribe to are specified in ActivityStates.

    The configuration and code used to subscribe activity state tracking records that use the ActivityStateQuery for the SendEmailActivity activity is shown in the following example.

    <activityStateQueries>
      <activityStateQuery activityName="SendEmailActivity">
        <states>
          <state name="Closed"/>
        </states>
      </activityStateQuery>
    </activityStateQueries>
    
    TrackingProfile sampleTrackingProfile = new TrackingProfile()
    {
        Name = "Sample Tracking Profile",
        Queries =
        {
            new ActivityStateQuery()
            {
                ActivityName = "SendEmailActivity",
                States = { ActivityStates.Closed }
            }
        }
    };
    

    Note

    If multiple activityStateQuery elements have the same name, only the states in the last element are used in the tracking profile.

  • ActivityScheduledQuery - This query allows you to track an activity scheduled for execution by a parent activity. The query is necessary for a TrackingParticipant to subscribe to ActivityScheduledRecord objects.

    The configuration and code used to subscribe to records related to the SendEmailActivity child activity being scheduled using the ActivityScheduledQuery is shown in the following example.

    <activityScheduledQueries>
      <activityScheduledQuery activityName="ProcessNotificationsActivity" childActivityName="SendEmailActivity" />
    </activityScheduledQueries>
    
    TrackingProfile sampleTrackingProfile = new TrackingProfile()
    {
        Name = "Sample Tracking Profile",
        Queries =
        {
            new ActivityScheduledQuery()
            {
                ActivityName = "ProcessNotificationsActivity",
                ChildActivityName = "SendEmailActivity"
            }
        }
    };
    
  • FaultPropagationQuery - Use this to track the handling of faults that occur within an activity. The query is necessary for a TrackingParticipant to subscribe to FaultPropagationRecord objects.

    The configuration and code used to subscribe to records related to fault propagation using FaultPropagationQuery is shown in the following example.

    <faultPropagationQueries>
      <faultPropagationQuery faultSourceActivityName="SendEmailActivity" faultHandlerActivityName="NotificationsFaultHandler" />
    </faultPropagationQueries>
    
    TrackingProfile sampleTrackingProfile = new TrackingProfile()
    {
        Name = "Sample Tracking Profile",
        Queries =
        {
            new FaultPropagationQuery()
            {
                FaultSourceActivityName = "SendEmailActivity",
                FaultHandlerActivityName = "NotificationsFaultHandler"
            }
        }
    };
    
  • CancelRequestedQuery - Use this to track requests to cancel a child activity by the parent activity. The query is necessary for a TrackingParticipant to subscribe to CancelRequestedRecord objects.

    The configuration and code used to subscribe to records related to activity cancellation using CancelRequestedQuery is shown in the following example.

    <cancelRequestedQueries>
      <cancelRequestedQuery activityName="ProcessNotificationsActivity" childActivityName="SendEmailActivity" />
    </cancelRequestedQueries>
    
    TrackingProfile sampleTrackingProfile = new TrackingProfile()
    {
        Name = "Sample Tracking Profile",
        Queries =
        {
            new CancelRequestedQuery()
            {
                ActivityName = "ProcessNotificationsActivity",
                ChildActivityName = "SendEmailActivity"
            }
        }
    };
    
  • CustomTrackingQuery - Use this to track events that you define in your code activities. The query is necessary for a TrackingParticipant to subscribe to CustomTrackingRecord objects.

    The configuration and code used to subscribe to records related to custom tracking records using CustomTrackingQuery is shown in the following example.

    <customTrackingQueries>
      <customTrackingQuery name="EmailAddress" activityName="SendEmailActivity" />
    </customTrackingQueries>
    
    TrackingProfile sampleTrackingProfile = new TrackingProfile()
    {
        Name = "Sample Tracking Profile",
        Queries =
        {
            new CustomTrackingQuery()
            {
                Name = "EmailAddress",
                ActivityName = "SendEmailActivity"
            }
        }
    };
    
  • BookmarkResumptionQuery - Use this to track resumption of a bookmark within a workflow instance. This query is necessary for a TrackingParticipant to subscribe to BookmarkResumptionRecord objects.

    The configuration and code used to subscribe to records related to bookmark resumption using BookmarkResumptionQuery is shown in the following example.

    <bookmarkResumptionQueries>
      <bookmarkResumptionQuery name="SentEmailBookmark" />
    </bookmarkResumptionQueries>
    
    TrackingProfile sampleTrackingProfile = new TrackingProfile()
    {
        Name = "Sample Tracking Profile",
        Queries =
        {
            new BookmarkResumptionQuery()
            {
                Name = "sentEmailBookmark"
            }
        }
    };
    

Annotations

Annotations allow you to arbitrarily tag tracking records with a value that can be configured after build time. For example, you might want several tracking records across several workflows to be tagged with "Mail Server" == "Mail Server1". This makes it easy to find all records with this tag when querying tracking records later.

To accomplish this, an annotation is added to a tracking query as shown in the following example.

<activityStateQuery activityName="SendEmailActivity">
  <states>
    <state name="Closed"/>
  </states>
  <annotations>
    <annotation name="MailServer" value="Mail Server1"/>
  </annotations>
</activityStateQuery>

How to Create a Tracking Profile

Tracking query elements are used to create a tracking profile using either an XML configuration file or .NET Framework 4.6.1 code. Here is an example of a tracking profile created using a configuration file.

<system.serviceModel>
  <tracking>
    <profiles>
      <trackingProfile name="Sample Tracking Profile ">
        <workflow activityDefinitionId="*">
          <!--Specify the tracking profile query elements to subscribe for tracking records-->
        </workflow>
      </trackingProfile>
    </profiles>
  </tracking>
</system.serviceModel>

Warning

For a WF using the Workflow service host, the tracking profile is typically created using a configuration file. It is also possible to create a tracking profile with code using the tracking profile and tracking query API.

A profile configured as an XML configuration file is applied to a tracking participant using a behavior extension. This is added to a WorkflowServiceHost as described in the later section Configuring Tracking for a Workflow.

The verbosity of the tracking records emitted by the host is determined by configuration settings within the tracking profile. A tracking participant subscribes to tracking records by adding queries to a tracking profile. To subscribe to all tracking records, the tracking profile needs to specify all tracking queries using "*" in the name fields in each of the queries.

Here are some of the common examples of tracking profiles.

  • A tracking profile to obtain workflow instance records and faults.

    <trackingProfile name="Instance and Fault Records">
      <workflow activityDefinitionId="*">
        <workflowInstanceQueries>
          <workflowInstanceQuery>
            <states>
              <state name="*" />
            </states>
          </workflowInstanceQuery>
        </workflowInstanceQueries>
        <activityStateQueries>
          <activityStateQuery activityName="*">
            <states>
              <state name="Faulted"/>
            </states>
          </activityStateQuery>
        </activityStateQueries>
      </workflow>
    </trackingProfile>
    
  • A tracking profile to obtain all custom tracking records.

    <trackingProfile name="Instance_And_Custom_Records">
      <workflow activityDefinitionId="*">
        <customTrackingQueries>
          <customTrackingQuery name="*" activityName="*" />
        </customTrackingQueries>
      </workflow>
    </trackingProfile>
    

See also