Upload the diagnostic logs to the Results Service (#3114)

* upload diagnostic logs to results

* correct casing

* correct typo

* update contract

* update constant and define private method

* fix access

* fix reference to logs url

* update

* use results func

* fix method naming

* rename to match rpc

* change API contract

* fix lint issue

* refactor

* remove unused method

* create new log type
This commit is contained in:
Jonathan Tamsut
2024-02-01 11:27:06 -08:00
committed by GitHub
parent 3e5433ec86
commit 11680fc78f
7 changed files with 91 additions and 0 deletions

View File

@@ -551,6 +551,10 @@ namespace GitHub.Runner.Common
{ {
await UploadSummaryFile(file); await UploadSummaryFile(file);
} }
if (string.Equals(file.Type, CoreAttachmentType.ResultsDiagnosticLog, StringComparison.OrdinalIgnoreCase))
{
await UploadResultsDiagnosticLogsFile(file);
}
else if (String.Equals(file.Type, CoreAttachmentType.ResultsLog, StringComparison.OrdinalIgnoreCase)) else if (String.Equals(file.Type, CoreAttachmentType.ResultsLog, StringComparison.OrdinalIgnoreCase))
{ {
if (file.RecordId != _jobTimelineRecordId) if (file.RecordId != _jobTimelineRecordId)
@@ -922,6 +926,17 @@ namespace GitHub.Runner.Common
await UploadResultsFile(file, summaryHandler); await UploadResultsFile(file, summaryHandler);
} }
private async Task UploadResultsDiagnosticLogsFile(ResultsUploadFileInfo file)
{
Trace.Info($"Starting to upload diagnostic logs file to results service {file.Name}, {file.Path}");
ResultsFileUploadHandler diagnosticLogsHandler = async (file) =>
{
await _resultsServer.CreateResultsDiagnosticLogsAsync(file.PlanId, file.JobId, file.Path, CancellationToken.None);
};
await UploadResultsFile(file, diagnosticLogsHandler);
}
private async Task UploadResultsStepLogFile(ResultsUploadFileInfo file) private async Task UploadResultsStepLogFile(ResultsUploadFileInfo file)
{ {
Trace.Info($"Starting upload of step log file to results service {file.Name}, {file.Path}"); Trace.Info($"Starting upload of step log file to results service {file.Name}, {file.Path}");

View File

@@ -35,6 +35,8 @@ namespace GitHub.Runner.Common
Task UpdateResultsWorkflowStepsAsync(Guid scopeIdentifier, string hubName, Guid planId, Guid timelineId, Task UpdateResultsWorkflowStepsAsync(Guid scopeIdentifier, string hubName, Guid planId, Guid timelineId,
IEnumerable<TimelineRecord> records, CancellationToken cancellationToken); IEnumerable<TimelineRecord> records, CancellationToken cancellationToken);
Task CreateResultsDiagnosticLogsAsync(string planId, string jobId, string file, CancellationToken cancellationToken);
} }
public sealed class ResultServer : RunnerService, IResultsServer public sealed class ResultServer : RunnerService, IResultsServer
@@ -141,6 +143,18 @@ namespace GitHub.Runner.Common
throw new InvalidOperationException("Results client is not initialized."); throw new InvalidOperationException("Results client is not initialized.");
} }
public Task CreateResultsDiagnosticLogsAsync(string planId, string jobId, string file,
CancellationToken cancellationToken)
{
if (_resultsClient != null)
{
return _resultsClient.UploadResultsDiagnosticLogsAsync(planId, jobId, file,
cancellationToken: cancellationToken);
}
throw new InvalidOperationException("Results client is not initialized.");
}
public ValueTask DisposeAsync() public ValueTask DisposeAsync()
{ {
CloseWebSocket(WebSocketCloseStatus.NormalClosure, CancellationToken.None); CloseWebSocket(WebSocketCloseStatus.NormalClosure, CancellationToken.None);

View File

@@ -108,6 +108,8 @@ namespace GitHub.Runner.Worker
parentContext.QueueAttachFile(type: CoreAttachmentType.DiagnosticLog, name: diagnosticsZipFileName, filePath: diagnosticsZipFilePath); parentContext.QueueAttachFile(type: CoreAttachmentType.DiagnosticLog, name: diagnosticsZipFileName, filePath: diagnosticsZipFilePath);
parentContext.QueueDiagnosticLogFile(name: diagnosticsZipFileName, filePath: diagnosticsZipFilePath);
executionContext.Debug("Diagnostic file upload complete."); executionContext.Debug("Diagnostic file upload complete.");
} }

View File

@@ -90,6 +90,7 @@ namespace GitHub.Runner.Worker
long Write(string tag, string message); long Write(string tag, string message);
void QueueAttachFile(string type, string name, string filePath); void QueueAttachFile(string type, string name, string filePath);
void QueueSummaryFile(string name, string filePath, Guid stepRecordId); void QueueSummaryFile(string name, string filePath, Guid stepRecordId);
void QueueDiagnosticLogFile(string name, string filePath);
// timeline record update methods // timeline record update methods
void Start(string currentOperation = null); void Start(string currentOperation = null);
@@ -982,6 +983,18 @@ namespace GitHub.Runner.Worker
_jobServerQueue.QueueResultsUpload(stepRecordId, name, filePath, ChecksAttachmentType.StepSummary, deleteSource: false, finalize: true, firstBlock: true, totalLines: 0); _jobServerQueue.QueueResultsUpload(stepRecordId, name, filePath, ChecksAttachmentType.StepSummary, deleteSource: false, finalize: true, firstBlock: true, totalLines: 0);
} }
public void QueueDiagnosticLogFile(string name, string filePath)
{
ArgUtil.NotNullOrEmpty(name, nameof(name));
ArgUtil.NotNullOrEmpty(filePath, nameof(filePath));
if (!File.Exists(filePath))
{
throw new FileNotFoundException($"Can't upload diagnostic log file: {filePath}. File does not exist.");
}
_jobServerQueue.QueueResultsUpload(_record.Id, name, filePath, CoreAttachmentType.ResultsDiagnosticLog, deleteSource: false, finalize: true, firstBlock: true, totalLines: 0);
}
// Add OnMatcherChanged // Add OnMatcherChanged
public void Add(OnMatcherChanged handler) public void Add(OnMatcherChanged handler)
{ {

View File

@@ -101,6 +101,7 @@ namespace GitHub.DistributedTask.WebApi
public static readonly String FileAttachment = "DistributedTask.Core.FileAttachment"; public static readonly String FileAttachment = "DistributedTask.Core.FileAttachment";
public static readonly String DiagnosticLog = "DistributedTask.Core.DiagnosticLog"; public static readonly String DiagnosticLog = "DistributedTask.Core.DiagnosticLog";
public static readonly String ResultsLog = "Results.Core.Log"; public static readonly String ResultsLog = "Results.Core.Log";
public static readonly String ResultsDiagnosticLog = "Results.Core.DiagnosticLog";
} }
[GenerateAllConstants] [GenerateAllConstants]

View File

@@ -89,6 +89,26 @@ namespace GitHub.Services.Results.Contracts
public long SoftSizeLimit; public long SoftSizeLimit;
} }
[DataContract]
[JsonObject(NamingStrategyType = typeof(SnakeCaseNamingStrategy))]
public class GetSignedDiagnosticLogsURLRequest
{
[DataMember]
public string WorkflowJobRunBackendId;
[DataMember]
public string WorkflowRunBackendId;
}
[DataContract]
[JsonObject(NamingStrategyType = typeof(SnakeCaseNamingStrategy))]
public class GetSignedDiagnosticLogsURLResponse
{
[DataMember]
public string DiagLogsURL;
[DataMember]
public string BlobStorageType;
}
[DataContract] [DataContract]
[JsonObject(NamingStrategyType = typeof(SnakeCaseNamingStrategy))] [JsonObject(NamingStrategyType = typeof(SnakeCaseNamingStrategy))]
public class JobLogsMetadataCreate public class JobLogsMetadataCreate

View File

@@ -81,6 +81,19 @@ namespace GitHub.Services.Results.Client
return await GetResultsSignedURLResponse<GetSignedStepLogsURLRequest, GetSignedStepLogsURLResponse>(getStepLogsSignedBlobURLEndpoint, cancellationToken, request); return await GetResultsSignedURLResponse<GetSignedStepLogsURLRequest, GetSignedStepLogsURLResponse>(getStepLogsSignedBlobURLEndpoint, cancellationToken, request);
} }
private async Task<GetSignedDiagnosticLogsURLResponse> GetDiagnosticLogsUploadUrlAsync(string planId, string jobId, CancellationToken cancellationToken)
{
var request = new GetSignedDiagnosticLogsURLRequest()
{
WorkflowJobRunBackendId = jobId,
WorkflowRunBackendId = planId,
};
var getDiagnosticLogsSignedBlobURLEndpoint = new Uri(m_resultsServiceUrl, Constants.GetJobDiagLogsSignedBlobURL);
return await GetResultsSignedURLResponse<GetSignedDiagnosticLogsURLRequest, GetSignedDiagnosticLogsURLResponse>(getDiagnosticLogsSignedBlobURLEndpoint, cancellationToken, request);
}
private async Task<GetSignedJobLogsURLResponse> GetJobLogUploadUrlAsync(string planId, string jobId, CancellationToken cancellationToken) private async Task<GetSignedJobLogsURLResponse> GetJobLogUploadUrlAsync(string planId, string jobId, CancellationToken cancellationToken)
{ {
var request = new GetSignedJobLogsURLRequest() var request = new GetSignedJobLogsURLRequest()
@@ -421,6 +434,18 @@ namespace GitHub.Services.Results.Client
} }
} }
public async Task UploadResultsDiagnosticLogsAsync(string planId, string jobId, string file, CancellationToken cancellationToken)
{
// Get the upload url
var uploadUrlResponse = await GetDiagnosticLogsUploadUrlAsync(planId, jobId, cancellationToken);
if (uploadUrlResponse == null || uploadUrlResponse.DiagLogsURL == null)
{
throw new Exception("Failed to get diagnostic logs upload url");
}
await UploadLogFile(file, true, true, uploadUrlResponse.DiagLogsURL, uploadUrlResponse.BlobStorageType, cancellationToken);
}
private Step ConvertTimelineRecordToStep(TimelineRecord r) private Step ConvertTimelineRecordToStep(TimelineRecord r)
{ {
return new Step() return new Step()
@@ -511,6 +536,7 @@ namespace GitHub.Services.Results.Client
public static readonly string CreateStepLogsMetadata = ResultsReceiverTwirpEndpoint + "CreateStepLogsMetadata"; public static readonly string CreateStepLogsMetadata = ResultsReceiverTwirpEndpoint + "CreateStepLogsMetadata";
public static readonly string GetJobLogsSignedBlobURL = ResultsReceiverTwirpEndpoint + "GetJobLogsSignedBlobURL"; public static readonly string GetJobLogsSignedBlobURL = ResultsReceiverTwirpEndpoint + "GetJobLogsSignedBlobURL";
public static readonly string CreateJobLogsMetadata = ResultsReceiverTwirpEndpoint + "CreateJobLogsMetadata"; public static readonly string CreateJobLogsMetadata = ResultsReceiverTwirpEndpoint + "CreateJobLogsMetadata";
public static readonly string GetJobDiagLogsSignedBlobURL = ResultsReceiverTwirpEndpoint + "GetJobDiagLogsSignedBlobURL";
public static readonly string ResultsProtoApiV1Endpoint = "twirp/github.actions.results.api.v1.WorkflowStepUpdateService/"; public static readonly string ResultsProtoApiV1Endpoint = "twirp/github.actions.results.api.v1.WorkflowStepUpdateService/";
public static readonly string WorkflowStepsUpdate = ResultsProtoApiV1Endpoint + "WorkflowStepsUpdate"; public static readonly string WorkflowStepsUpdate = ResultsProtoApiV1Endpoint + "WorkflowStepsUpdate";