InstanceService.GetInstanceActivities
Reference
PagedData<InstanceActivity> GetInstanceActivities(Guid instanceId, ActivityQuery activityQuery)
Use GetInstanceActivities to retrieve a chronological list of activities and events that have occurred on a specific Protrak instance. This API is commonly used for tracking instance history, generating audit trails, and analyzing workflow patterns.
Parameters
instanceId: The unique identifier of the instance for which to retrieve activity history.activityQuery: Query object containing activity filtering criteria and pagination settings:Type: Optional activity type filter. UseActivityType.ActionPromotedfor state transitions,ActivityType.MessagePostedfor messages, or0for all activity types.StartDate,EndDate: Optional date range filters to limit activities to a specific time period.Skip,Take: Pagination parameters for result set. Default:Skip = 0,Take = 100.IsSortByDescending: Optional flag to control sort order. Default is true (newest first).
Returns
PagedData<InstanceActivity>:
- Collection of InstanceActivity objects representing activities for the specified instance.
- Each InstanceActivity contains details about the activity performed.
- Includes pagination metadata (TotalCount, Skip, Take).
- Returns empty collection if no activities are found.
Error Handling & Caveats
- If the instance does not exist or the user lacks permission to view it, an AccessDeniedException is thrown.
- If the instanceId is empty or invalid, an ArgumentException is thrown.
- If date range filters are invalid (StartDate > EndDate), results may be empty.
- The API enforces access control and only returns activities the current user has permission to view.
- Message activities and standard activities are merged when Type = 0 (all activities).
- EndTime for the most recent activity is set to the current UTC time.
- For large activity histories, consider using appropriate pagination to optimize performance.
Usage
try {
// Get all promotion activities for the last 30 days
var activityQuery = new ActivityQuery {
Type = ActivityType.ActionPromoted,
StartDate = DateTime.UtcNow.AddDays(-30),
EndDate = DateTime.UtcNow,
Skip = 0,
Take = 100,
IsSortByDescending = true
};
var activities = InstanceService.GetInstanceActivities(instanceId, activityQuery);
Console.WriteLine($"Found {activities.TotalCount} promotion activities in the last 30 days");
foreach (var activity in activities.Items) {
Console.WriteLine($"{activity.StartTime:yyyy-MM-dd HH:mm} - {activity.ActivityType}");
Console.WriteLine($" From: {activity.FromState?.Name} -> To: {activity.ToState?.Name}");
Console.WriteLine($" User: {activity.UserName}");
if (activity.EndTime.HasValue) {
var duration = activity.EndTime.Value - activity.StartTime;
Console.WriteLine($" Duration: {duration.TotalHours:F1} hours");
}
}
} catch (AccessDeniedException ex) {
Console.WriteLine("Access denied: " + ex.Message);
} catch (ArgumentException ex) {
Console.WriteLine("Invalid parameters: " + ex.Message);
}
Example: Getting Recent Promotion Activities
try {
// Most common pattern - get recent state transitions for reporting
var activityQuery = new ActivityQuery {
Type = ActivityType.ActionPromoted,
IsSortByDescending = false, // Chronological order
Take = int.MaxValue // Get all activities
};
var activities = InstanceService.GetInstanceActivities(taskId, activityQuery);
if (activities?.Items != null && activities.Items.Any()) {
Console.WriteLine($"Task progression history:");
foreach (var activity in activities.Items) {
var fromState = activity.FromState?.Name ?? "Created";
var toState = activity.ToState?.Name ?? "Unknown";
Console.WriteLine($"- {activity.StartTime:yyyy-MM-dd}: {fromState} → {toState}");
if (activity.EndTime.HasValue) {
var timeInState = activity.EndTime.Value - activity.StartTime;
Console.WriteLine($" Time in {toState}: {timeInState.TotalDays:F1} days");
}
}
} else {
Console.WriteLine("No promotion activities found for this task");
}
} catch (Exception ex) {
Console.WriteLine($"Error retrieving activities: {ex.Message}");
}
Example: Validating Instance State History
try {
// Common pattern in pre-delete triggers - check for specific activities
var activityQuery = new ActivityQuery {
Type = ActivityType.ActionPromoted,
Take = 0 // Only need count, not actual data
};
var activities = InstanceService.GetInstanceActivities(instanceId, activityQuery);
if (activities != null && activities.TotalCount > 1) {
throw new Exception("Delete operation is not allowed after task has been submitted.");
}
Console.WriteLine("Instance can be safely deleted - no promotion history found");
} catch (Exception ex) {
Console.WriteLine($"Validation error: {ex.Message}");
}
Example: Calculating Time Spent in Each State
try {
var activityQuery = new ActivityQuery {
Type = ActivityType.ActionPromoted,
IsSortByDescending = false, // Chronological order for calculations
Take = int.MaxValue
};
var activities = InstanceService.GetInstanceActivities(projectId, activityQuery);
if (activities?.Items != null && activities.Items.Any()) {
Console.WriteLine("Time spent in each state:");
foreach (var activity in activities.Items) {
var stateName = activity.ToState?.Name ?? "Unknown State";
var timeInState = TimeSpan.Zero;
if (activity.EndTime.HasValue) {
timeInState = activity.EndTime.Value - activity.StartTime;
} else {
// Current state - calculate time from start to now
timeInState = DateTime.UtcNow - activity.StartTime;
}
Console.WriteLine($"- {stateName}: {timeInState.TotalDays:F1} days");
}
// Calculate total processing time
if (activities.Items.Any()) {
var firstActivity = activities.Items.First();
var lastActivity = activities.Items.Last();
var totalTime = DateTime.UtcNow - firstActivity.StartTime;
Console.WriteLine($"\nTotal processing time: {totalTime.TotalDays:F1} days");
}
}
} catch (Exception ex) {
Console.WriteLine($"Error calculating state durations: {ex.Message}");
}
Troubleshooting
- If AccessDeniedException occurs, ensure the current user has permission to view the instance and its activity history.
- If date range queries return unexpected results, verify that StartDate is earlier than EndDate and dates are in UTC format.
- For performance issues with large activity histories, use appropriate pagination with reasonable
Takevalues instead ofint.MaxValue. - If specific activity types are missing, verify that the
Typeparameter matches the expectedActivityTypeenum values. - When calculating state durations, always check if
EndTimehas a value - the most recent activity may not have an end time. - Use
Take = 0when you only need the total count of activities without retrieving the actual data. - For audit and compliance requirements, ensure all activity types are captured by using
Type = 0and appropriate date ranges. - The API returns activities based on the current user's permissions - system/admin users may see more activities than regular users.
- Always handle the case where
activities?.Itemsmight be null or empty before iterating. - For reporting scenarios, use
IsSortByDescending = falseto get chronological order for timeline analysis. - Activity EndTime is calculated based on the next activity's StartTime - the current state activity will have null EndTime.