DevOps.Util.DotNet/DotNetQueryUtil.cs
/// <summary>
/// Find the mapping between TimelineRecord instances and the HelixJobs. It's possible and
/// expected that a single TimelineRecord will map to multiple HelixJobs.
///
/// TODO: this method works by knowing the display name of timeline records. That is very 
/// fragile and we should find a better way to do this.
/// </summary>
Find the mapping between TimelineRecord instances and the HelixJobs. It's possible and
expected that a single TimelineRecord will map to multiple HelixJobs.

this method works by knowing the display name of timeline records. That is very
fragile and we should find a better way to do this.
Find the mapping between TimelineRecord instances and the HelixJobs . It ' s possible and expected that a single TimelineRecord will map to multiple HelixJobs . this method works by knowing the display name of timeline records . That is very fragile and we should find a better way to do this .
public async Task<List<HelixTimelineResult>> ListHelixJobsAsync(
            Timeline timeline,
            Action<Exception>? onError = null)
        {
            var timelineTree = TimelineTree.Create(timeline);
            var comparer = StringComparer.OrdinalIgnoreCase;
            var comparison = StringComparison.OrdinalIgnoreCase;
            var sentRegex = new Regex(@"Sent Helix Job ([\d\w-]+)", RegexOptions.Compiled | RegexOptions.IgnoreCase);
            var queueRegex = new Regex(@"Sending Job to (.*)\.\.\.", RegexOptions.Compiled | RegexOptions.IgnoreCase);
            var list = new List<HelixTimelineResult>();
            var helixRecords = timelineTree.Records.Where(x => 
                comparer.Equals(x.Name, "Send to Helix") ||
                comparer.Equals(x.Name, "Send tests to Helix") ||
                x.Name.StartsWith("Run native crossgen and compare", comparison));
            foreach (var record in helixRecords)
            {
                if (record.Log is null)
                {
                    continue;
                }
                using var stream = await Server.DownloadFileStreamAsync(
                    record.Log.Url,
                    onError).ConfigureAwait(false);
                if (stream is null)
                {
                    continue;
                }
                var jobName = timelineTree.TryGetJob(record, out var job)
                    ? job.Name
                    : "";
                string? queueName = null;
                string? containerName = null;
                string? containerImage = null;
                using var reader = new StreamReader(stream);
                do
                {
                    var line = reader.ReadLine();
                    if (line is null)
                    {
                        break;
                    }
                    var match = queueRegex.Match(line);
                    if (match.Success)
                    {
                        queueName = match.Groups[1].Value;
                        containerImage = null;
                        containerName = null;
                        match = Regex.Match(queueName, @"\(([\w\d.-]+)\)?([\w\d.-]+)@(.*)");
                        if (match.Success)
                        {
                            queueName = match.Groups[2].Value;
                            containerName = match.Groups[1].Value;
                            containerImage = match.Groups[3].Value;
                        }
                        continue;
                    }
                    match = sentRegex.Match(line);
                    if (match.Success)
                    {
                        var id = match.Groups[1].Value;
                        var machineInfo = new MachineInfo(
                            queueName ?? MachineInfo.UnknownHelixQueueName,
                            jobName,
                            containerName,
                            containerImage,
                            isHelixSubmission: true);
                        var info = new HelixJobTimelineInfo(id, machineInfo);
                        list.Add(new HelixTimelineResult(
                            new TimelineRecordItem(record, timelineTree),
                            info));
                    }
                } while (true);
            }
            return list;
        }
public async Task < List < HelixTimelineResult > > ListHelixJobsAsync ( Timeline timeline , Action < Exception > ? onError = null ) { var timelineTree = TimelineTree . Create ( timeline ) ; var comparer = StringComparer . OrdinalIgnoreCase ; var comparison = StringComparison . OrdinalIgnoreCase ; var sentRegex = new Regex ( @"Sent Helix Job ([\d\w-]+)" , RegexOptions . Compiled | RegexOptions . IgnoreCase ) ; var queueRegex = new Regex ( @"Sending Job to (.*)\.\.\." , RegexOptions . Compiled | RegexOptions . IgnoreCase ) ; var list = new List < HelixTimelineResult > ( ) ; var helixRecords = timelineTree . Records . Where ( x => comparer . Equals ( x . Name , " " ) || comparer . Equals ( x . Name , " " ) || x . Name . StartsWith ( " " , comparison ) ) ; foreach ( var record in helixRecords ) { if ( record . Log is null ) { continue ; } using var stream = await Server . DownloadFileStreamAsync ( record . Log . Url , onError ) . ConfigureAwait ( false ) ; if ( stream is null ) { continue ; } var jobName = timelineTree . TryGetJob ( record , out var job ) ? job . Name : " " ; string ? queueName = null ; string ? containerName = null ; string ? containerImage = null ; using var reader = new StreamReader ( stream ) ; do { var line = reader . ReadLine ( ) ; if ( line is null ) { break ; } var match = queueRegex . Match ( line ) ; if ( match . Success ) { queueName = match . Groups [ 1 ] . Value ; containerImage = null ; containerName = null ; match = Regex . Match ( queueName , @"\(([\w\d.-]+)\)?([\w\d.-]+)@(.*)" ) ; if ( match . Success ) { queueName = match . Groups [ 2 ] . Value ; containerName = match . Groups [ 1 ] . Value ; containerImage = match . Groups [ 3 ] . Value ; } continue ; } match = sentRegex . Match ( line ) ; if ( match . Success ) { var id = match . Groups [ 1 ] . Value ; var machineInfo = new MachineInfo ( queueName ?? MachineInfo . UnknownHelixQueueName , jobName , containerName , containerImage , isHelixSubmission : true ) ; var info = new HelixJobTimelineInfo ( id , machineInfo ) ; list . Add ( new HelixTimelineResult ( new TimelineRecordItem ( record , timelineTree ) , info ) ) ; } } while ( true ) ; } return list ; }
Find the mapping between TimelineRecord instances and the HelixJobs.
Find the mapping between TimelineRecord instances and the HelixJobs .
// TODO: this scheme really relies on this name. This is pretty fragile. Should work with // core-eng to find a more robust way of detecting this
timeline
Timeline
onError
Action<Exception>?