Ejemplo n.º 1
0
        public async Task <List <SearchBuildLogsResult> > SearchBuildLogsAsync(
            IEnumerable <BuildResultInfo> builds,
            SearchBuildLogsRequest request,
            Action <Exception>?onError = null)
        {
            if (request.Text is null)
            {
                throw new ArgumentException("Need text to search for", nameof(request));
            }

            var nameRegex = CreateSearchRegex(request.LogName);
            var textRegex = CreateSearchRegex(request.Text);

            var list = new List <(BuildResultInfo BuildInfo, TimelineTree Tree, TimelineRecord TimelineRecord, BuildLogReference BuildLogReference)>();

            foreach (var buildInfo in builds)
            {
                try
                {
                    var timeline = await Server.GetTimelineAsync(buildInfo.Project, buildInfo.Number).ConfigureAwait(false);

                    if (timeline is object)
                    {
                        var tree    = TimelineTree.Create(timeline);
                        var records = timeline.Records.Where(r => nameRegex is null || nameRegex.IsMatch(r.Name));
                        foreach (var record in records)
                        {
                            if (record.Log is { } log)
                            {
                                list.Add((buildInfo, tree, record, log));
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    onError?.Invoke(ex);
                }
            }

            if (list.Count > request.Limit)
            {
                onError?.Invoke(new Exception($"Limiting the {list.Count} logs to first {request.Limit}"));
                list = list.Take(request.Limit).ToList();
            }

            var resultTasks = list
                              .AsParallel()
                              .Select(async x =>
            {
                var match = await SearchFileForFirstMatchAsync(x.BuildLogReference.Url, textRegex, onError).ConfigureAwait(false);
                var line  = match is object && match.Success
                        ? match.Value
                        : null;
                return(Query: x, Line: line);
            });
            var results = new List <SearchBuildLogsResult>();

            foreach (var task in resultTasks)
            {
                try
                {
                    var result = await task.ConfigureAwait(false);

                    if (result.Line is object)
                    {
                        string jobName = "";
                        if (result.Query.Tree.TryGetJob(result.Query.TimelineRecord, out var jobRecord))
                        {
                            jobName = jobRecord.Name;
                        }
                        results.Add(new SearchBuildLogsResult(result.Query.BuildInfo, jobName, result.Query.TimelineRecord, result.Query.BuildLogReference, result.Line));
                    }
                }
                catch (Exception ex)
                {
                    onError?.Invoke(ex);
                }
            }

            return(results);
        }
Ejemplo n.º 2
0
        public async Task OnGet()
        {
            if (User.GetVsoIdentity() is { } identity)
            {
                AzureDevOpsEmail = identity.FindFirst(ClaimTypes.Email)?.Value;
            }

            if (string.IsNullOrEmpty(BuildQuery))
            {
                BuildQuery = new SearchBuildsRequest()
                {
                    Definition = "roslyn-ci",
                    Started    = new DateRequestValue(dayQuery: 3),
                }.GetQueryString();
                return;
            }

            if (!SearchBuildsRequest.TryCreate(BuildQuery, out var buildsRequest, out var errorMessage) ||
                !SearchBuildLogsRequest.TryCreate(LogQuery ?? "", out var logsRequest, out errorMessage))
            {
                ErrorMessage = errorMessage;
                return;
            }

            if (string.IsNullOrEmpty(logsRequest.Text))
            {
                ErrorMessage = @"Must specify text to search for 'text: ""StackOverflowException""'";
                return;
            }

            ErrorMessage = null;

            List <BuildResultInfo> buildInfos;

            try
            {
                buildInfos = await buildsRequest
                             .Filter(TriageContextUtil.Context.ModelBuilds)
                             .OrderByDescending(x => x.BuildNumber)
                             .ToBuildResultInfoListAsync();
            }
            catch (SqlException ex) when(ex.IsTimeoutViolation())
            {
                ErrorMessage = "Timeout fetching data from server";
                return;
            }

            BuildCount = buildInfos.Count;

            var queryUtil = await DotNetQueryUtilFactory.CreateDotNetQueryUtilForUserAsync();

            var errorBuilder = new StringBuilder();
            var results      = await queryUtil.SearchBuildLogsAsync(buildInfos, logsRequest, ex => errorBuilder.AppendLine(ex.Message));

            foreach (var result in results)
            {
                BuildLogs.Add(new BuildLogData()
                {
                    BuildNumber = result.BuildInfo.Number,
                    Line        = result.Line,
                    JobName     = result.JobName,
                    BuildLogUri = result.BuildLogReference.Url,
                });
            }

            if (errorBuilder.Length > 0)
            {
                ErrorMessage = errorBuilder.ToString();
            }
        }