// Copyright (c) Microsoft. All rights reserved. using System; using System.Collections.Generic; using System.Linq; using System.Text; using Microsoft.Agents.Workflows.Execution; namespace Microsoft.Agents.Workflows.InProc; internal sealed class InProcStepTracer : IStepTracer { private int _nextStepNumber; public int StepNumber => this._nextStepNumber - 1; public bool StateUpdated { get; private set; } public CheckpointInfo? Checkpoint { get; private set; } public HashSet Instantiated { get; } = []; public HashSet Activated { get; } = []; public void TraceIntantiated(string executorId) => this.Instantiated.Add(executorId); public void TraceActivated(string executorId) => this.Activated.Add(executorId); public void TraceStatePublished() => this.StateUpdated = true; public void TraceCheckpointCreated(CheckpointInfo checkpoint) => this.Checkpoint = checkpoint; /// /// Reset the tracer to the specified step number. /// /// The Step Number of the last SuperStep. Note that Step Numbers are 0-indexed. public void Reload(int lastStepNumber = 0) => this._nextStepNumber = lastStepNumber + 1; public SuperStepStartedEvent Advance(StepContext step) { this._nextStepNumber++; this.Activated.Clear(); this.Instantiated.Clear(); this.StateUpdated = false; this.Checkpoint = null; HashSet sendingExecutors = []; bool hasExternalMessages = false; foreach (ExecutorIdentity identity in step.QueuedMessages.Keys) { if (identity == ExecutorIdentity.None) { hasExternalMessages = true; } else { sendingExecutors.Add(identity.Id!); } } return new SuperStepStartedEvent(this.StepNumber, new SuperStepStartInfo(sendingExecutors) { HasExternalMessages = hasExternalMessages }); } public SuperStepCompletedEvent Complete(bool nextStepHasActions, bool hasPendingRequests) => new(this.StepNumber, new SuperStepCompletionInfo(this.Activated, this.Instantiated) { HasPendingMessages = nextStepHasActions, HasPendingRequests = hasPendingRequests, StateUpdated = this.StateUpdated, Checkpoint = this.Checkpoint, }); public override string ToString() { StringBuilder sb = new(); if (this.Instantiated.Count != 0) { sb.Append("Instantiated: ").Append(string.Join(", ", this.Instantiated.OrderBy(id => id, StringComparer.Ordinal))); } if (this.Activated.Count != 0) { if (sb.Length != 0) { sb.AppendLine(); } sb.Append("Activated: ").Append(string.Join(", ", this.Activated.OrderBy(id => id, StringComparer.Ordinal))); } return sb.ToString(); } }