Skip to content

Commit a2a514b

Browse files
authored
Remove build log queue based fanout (#3789)
1 parent 3b9baf4 commit a2a514b

File tree

5 files changed

+33
-151
lines changed

5 files changed

+33
-151
lines changed

tools/pipeline-witness/Azure.Sdk.Tools.PipelineWitness/BlobUploadProcessor.cs

Lines changed: 24 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,6 @@ public class BlobUploadProcessor
5252
private readonly BlobContainerClient testRunsContainerClient;
5353
private readonly BlobContainerClient buildDefinitionsContainerClient;
5454
private readonly BlobContainerClient buildFailuresContainerClient;
55-
private readonly QueueClient queueClient;
5655
private readonly IOptions<PipelineWitnessSettings> options;
5756
private readonly Dictionary<string, int?> cachedDefinitionRevisions = new();
5857
private readonly IFailureAnalyzer failureAnalyzer;
@@ -61,7 +60,6 @@ public BlobUploadProcessor(
6160
ILogger<BlobUploadProcessor> logger,
6261
BuildLogProvider logProvider,
6362
BlobServiceClient blobServiceClient,
64-
QueueServiceClient queueServiceClient,
6563
BuildHttpClient buildClient,
6664
TestResultsHttpClient testResultsClient,
6765
IOptions<PipelineWitnessSettings> options,
@@ -72,11 +70,6 @@ public BlobUploadProcessor(
7270
throw new ArgumentNullException(nameof(blobServiceClient));
7371
}
7472

75-
if (queueServiceClient == null)
76-
{
77-
throw new ArgumentNullException(nameof(queueServiceClient));
78-
}
79-
8073
this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
8174
this.options = options ?? throw new ArgumentNullException(nameof(options));
8275
this.logProvider = logProvider ?? throw new ArgumentNullException(nameof(logProvider));
@@ -89,8 +82,6 @@ public BlobUploadProcessor(
8982
this.buildFailuresContainerClient = blobServiceClient.GetBlobContainerClient(BuildFailuresContainerName);
9083
this.testRunsContainerClient = blobServiceClient.GetBlobContainerClient(TestRunsContainerName);
9184
this.buildDefinitionsContainerClient = blobServiceClient.GetBlobContainerClient(BuildDefinitionsContainerName);
92-
this.queueClient = queueServiceClient.GetQueueClient(this.options.Value.BuildLogBundlesQueueName);
93-
this.queueClient.CreateIfNotExists();
9485
this.failureAnalyzer = failureAnalyzer;
9586
}
9687

@@ -178,15 +169,12 @@ public async Task UploadBuildBlobsAsync(string account, Guid projectId, int buil
178169
logger.LogWarning("No logs available for build {Project}: {BuildId}", build.Project.Name, build.Id);
179170
return;
180171
}
181-
182-
var bundles = BuildLogBundles(account, build, timeline, logs);
183172

184-
// We no longer process log bundles on separate messages.
185-
// During zero downtime upgrade phase, process all the bundles sequentially but allow for processing message in the log bundle queue
186-
// After the upgrade phase, this should be rewritten to remove bundling but keep the log -> timeline record association
187-
foreach(var bundle in bundles)
173+
var buildLogInfos = GetBuildLogInfos(account, build, timeline, logs);
174+
175+
foreach (var log in buildLogInfos)
188176
{
189-
await ProcessBuildLogBundleAsync(bundle);
177+
await UploadLogLinesBlobAsync(account, build, log);
190178
}
191179
}
192180

@@ -246,14 +234,6 @@ private async Task UploadBuildFailureBlobAsync(string account, Build build, Time
246234
}
247235
}
248236

249-
public async Task ProcessBuildLogBundleAsync(BuildLogBundle buildLogBundle)
250-
{
251-
foreach (var log in buildLogBundle.TimelineLogs)
252-
{
253-
await UploadLogLinesBlobAsync(buildLogBundle, log);
254-
}
255-
}
256-
257237
public async Task UploadBuildDefinitionBlobsAsync(string account, string projectName)
258238
{
259239
var definitions = await buildClient.GetFullDefinitionsAsync2(project: projectName);
@@ -361,35 +341,14 @@ private async Task UploadBuildDefinitionBlobAsync(string account, BuildDefinitio
361341
}
362342
}
363343

364-
private List<BuildLogBundle> BuildLogBundles(string account, Build build, Timeline timeline, List<BuildLog> logs)
344+
private List<BuildLogInfo> GetBuildLogInfos(string account, Build build, Timeline timeline, List<BuildLog> logs)
365345
{
366-
BuildLogBundle CreateBundle() => new BuildLogBundle
367-
{
368-
Account = account,
369-
BuildId = build.Id,
370-
ProjectId = build.Project.Id,
371-
ProjectName = build.Project.Name,
372-
QueueTime = build.QueueTime.Value,
373-
StartTime = build.StartTime.Value,
374-
FinishTime = build.FinishTime.Value,
375-
DefinitionId = build.Definition.Id,
376-
DefinitionName = build.Definition.Name,
377-
DefinitionPath = build.Definition.Path
378-
};
379-
380-
BuildLogBundle currentBundle;
381-
var logBundles = new List<BuildLogBundle>();
382-
logBundles.Add(currentBundle = CreateBundle());
383-
384346
var logsById = logs.ToDictionary(l => l.Id);
385347

348+
var buildLogInfos = new List<BuildLogInfo>();
349+
386350
foreach (var log in logs)
387351
{
388-
if(currentBundle.TimelineLogs.Count >= this.options.Value.BuildLogBundleSize)
389-
{
390-
logBundles.Add(currentBundle = CreateBundle());
391-
}
392-
393352
var logRecords = timeline.Records.Where(x => x.Log?.Id == log.Id).ToArray();
394353

395354
if(logRecords.Length > 1)
@@ -419,7 +378,7 @@ private List<BuildLogBundle> BuildLogBundles(string account, Build build, Timeli
419378
}
420379
}
421380

422-
currentBundle.TimelineLogs.Add(new BuildLogInfo
381+
buildLogInfos.Add(new BuildLogInfo
423382
{
424383
LogId = log.Id,
425384
LineCount = log.LineCount,
@@ -430,7 +389,7 @@ private List<BuildLogBundle> BuildLogBundles(string account, Build build, Timeli
430389
});
431390
}
432391

433-
return logBundles;
392+
return buildLogInfos;
434393
}
435394

436395
private async Task UploadBuildBlobAsync(string account, Build build)
@@ -599,29 +558,29 @@ private async Task UploadTimelineBlobAsync(string account, Build build, Timeline
599558
}
600559
}
601560

602-
private async Task UploadLogLinesBlobAsync(BuildLogBundle build, BuildLogInfo log)
561+
private async Task UploadLogLinesBlobAsync(string account, Build build, BuildLogInfo log)
603562
{
604563
try
605564
{
606565
// we don't use FinishTime in the logs blob path to prevent duplicating logs when processing retries.
607566
// i.e. logs with a given buildid/logid are immutable and retries only add new logs.
608-
var blobPath = $"{build.ProjectName}/{build.QueueTime:yyyy/MM/dd}/{build.BuildId}-{log.LogId}.jsonl";
567+
var blobPath = $"{build.Project.Name}/{build.QueueTime:yyyy/MM/dd}/{build.Id}-{log.LogId}.jsonl";
609568
var blobClient = this.buildLogLinesContainerClient.GetBlobClient(blobPath);
610569

611570
if (await blobClient.ExistsAsync())
612571
{
613-
this.logger.LogInformation("Skipping existing log for build {BuildId}, record {RecordId}, log {LogId}", build.BuildId, log.RecordId, log.LogId);
572+
this.logger.LogInformation("Skipping existing log for build {BuildId}, record {RecordId}, log {LogId}", build.Id, log.RecordId, log.LogId);
614573
return;
615574
}
616575

617-
this.logger.LogInformation("Processing log for build {BuildId}, record {RecordId}, log {LogId}", build.BuildId, log.RecordId, log.LogId);
576+
this.logger.LogInformation("Processing log for build {BuildId}, record {RecordId}, log {LogId}", build.Id, log.RecordId, log.LogId);
618577

619578
var lineNumber = 0;
620579
var characterCount = 0;
621580

622581
// Over an open read stream and an open write stream, one line at a time, read, process, and write to
623582
// blob storage
624-
using (var logStream = await this.logProvider.GetLogStreamAsync(build.ProjectName, build.BuildId, log.LogId))
583+
using (var logStream = await this.logProvider.GetLogStreamAsync(build.Project.Name, build.Id, log.LogId))
625584
using (var logReader = new StreamReader(logStream))
626585
using (var blobStream = await blobClient.OpenWriteAsync(overwrite: true, new BlobOpenWriteOptions()))
627586
using (var blobWriter = new StreamWriter(blobStream))
@@ -657,13 +616,13 @@ private async Task UploadLogLinesBlobAsync(BuildLogBundle build, BuildLogInfo lo
657616

658617
await blobWriter.WriteLineAsync(JsonConvert.SerializeObject(new
659618
{
660-
OrganizationName = build.Account,
661-
ProjectId = build.ProjectId,
662-
ProjectName = build.ProjectName,
663-
BuildDefinitionId = build.DefinitionId,
664-
BuildDefinitionPath = build.DefinitionPath,
665-
BuildDefinitionName = build.DefinitionName,
666-
BuildId = build.BuildId,
619+
OrganizationName = account,
620+
ProjectId = build.Project.Id,
621+
ProjectName = build.Project.Name,
622+
BuildDefinitionId = build.Definition.Id,
623+
BuildDefinitionPath = build.Definition.Path,
624+
BuildDefinitionName = build.Definition.Name,
625+
BuildId = build.Id,
667626
LogId = log.LogId,
668627
LineNumber = lineNumber,
669628
Length = message.Length,
@@ -674,15 +633,15 @@ await blobWriter.WriteLineAsync(JsonConvert.SerializeObject(new
674633
}
675634
}
676635

677-
logger.LogInformation("Processed {CharacterCount} characters and {LineCount} lines for build {BuildId}, record {RecordId}, log {LogId}", characterCount, lineNumber, build.BuildId, log.RecordId, log.LogId);
636+
logger.LogInformation("Processed {CharacterCount} characters and {LineCount} lines for build {BuildId}, record {RecordId}, log {LogId}", characterCount, lineNumber, build.Id, log.RecordId, log.LogId);
678637
}
679638
catch (RequestFailedException ex) when (ex.Status == (int)HttpStatusCode.Conflict)
680639
{
681-
this.logger.LogInformation("Ignoring existing blob exception for build {BuildId}, record {RecordId}, log {LogId}", build.BuildId, log.RecordId, log.LogId);
640+
this.logger.LogInformation("Ignoring existing blob exception for build {BuildId}, record {RecordId}, log {LogId}", build.Id, log.RecordId, log.LogId);
682641
}
683642
catch (Exception ex)
684643
{
685-
this.logger.LogError(ex, "Error processing build {BuildId}, record {RecordId}, log {LogId}", build.BuildId, log.RecordId, log.LogId);
644+
this.logger.LogError(ex, "Error processing build {BuildId}, record {RecordId}, log {LogId}", build.Id, log.RecordId, log.LogId);
686645
throw;
687646
}
688647
}

tools/pipeline-witness/Azure.Sdk.Tools.PipelineWitness/PipelineWitnessSettings.cs

Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -6,27 +6,25 @@ namespace Azure.Sdk.Tools.PipelineWitness
66
{
77
public class PipelineWitnessSettings
88
{
9+
/// <summary>
10+
/// Gets or sets the uri of the key vault to use
11+
/// </summary>
912
public string KeyVaultUri { get; set; }
1013

11-
public string QueueStorageAccountUri { get; set; }
12-
13-
14-
public string BlobStorageAccountUri { get; set; }
15-
1614
/// <summary>
17-
/// Gets or sets the name of the build complete queue
15+
/// Gets or sets uri of the storage account use for queue processing
1816
/// </summary>
19-
public string BuildCompleteQueueName { get; set; }
17+
public string QueueStorageAccountUri { get; set; }
2018

2119
/// <summary>
22-
/// Gets or sets the name of the build log bundles queue
20+
/// Gets or sets uri of the blob storage account use for blob export
2321
/// </summary>
24-
public string BuildLogBundlesQueueName { get; set; }
22+
public string BlobStorageAccountUri { get; set; }
2523

2624
/// <summary>
27-
/// Gets or sets the number of build logs to add to each log bundle message
25+
/// Gets or sets the name of the build complete queue
2826
/// </summary>
29-
public int BuildLogBundleSize { get; set; } = 50;
27+
public string BuildCompleteQueueName { get; set; }
3028

3129
/// <summary>
3230
/// Gets or sets the amount of time a message should be invisible in the queue while being processed
@@ -63,11 +61,6 @@ public class PipelineWitnessSettings
6361
/// </summary>
6462
public TimeSpan BuildDefinitionLoopPeriod { get; set; } = TimeSpan.FromMinutes(5);
6563

66-
/// <summary>
67-
/// Gets or sets the number of concurrent log bundle queue workers to register
68-
/// </summary>
69-
public int BuildLogBundlesWorkerCount { get; set; } = 1;
70-
7164
/// <summary>
7265
/// Gets or sets the number of concurrent build complete queue workers to register
7366
/// </summary>

tools/pipeline-witness/Azure.Sdk.Tools.PipelineWitness/Services/BuildLogBundleQueueWorker.cs

Lines changed: 0 additions & 66 deletions
This file was deleted.

tools/pipeline-witness/Azure.Sdk.Tools.PipelineWitness/Startup.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,6 @@ public static void Configure(WebApplicationBuilder builder)
7979
builder.Services.Configure<PipelineWitnessSettings>(settingsSection);
8080

8181
builder.Services.AddHostedService<BuildCompleteQueueWorker>(settings.BuildCompleteWorkerCount);
82-
builder.Services.AddHostedService<BuildLogBundleQueueWorker>(settings.BuildLogBundlesWorkerCount);
8382
builder.Services.AddHostedService<AzurePipelinesBuildDefinitionWorker>();
8483
}
8584

tools/pipeline-witness/Azure.Sdk.Tools.PipelineWitness/appsettings.json

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,6 @@
1515
"BlobStorageAccountUri": "https://azsdkengsyspipelinelogs.blob.core.windows.net",
1616
"BuildCompleteQueueName": "azurepipelines-build-completed",
1717
"BuildCompleteWorkerCount": 5,
18-
"BuildLogBundlesQueueName": "azurepipelines-build-log-bundle",
19-
"BuildLogBundlesWorkerCount": 5,
20-
"BuildLogBundleSize": 50,
2118
"MessageLeasePeriod": "00:03:00",
2219
"MessageErrorSleepPeriod": "00:00:10",
2320
"MaxDequeueCount": 5,

0 commit comments

Comments
 (0)