Skip to content

Commit 1bda91c

Browse files
localconstsrkiddmerlynomsft
authored
Enable stream and file logs output (#4920)
* Adding cmd option to enable both stream and log file output * Add timestamp to log line for local logs * Fixing date format for log lines * fixing the date formate to universal time for log lines * Renaming enableLogOutput to reStreamLogsToFiles and fixing error handling * Adding strings for different locals. * Removing string * Adding loc key for error message * Reuse variables * Simplify conditions by enum flags * Add trace with current logs streaming mode --------- Co-authored-by: Kidd, Steve <[email protected]> Co-authored-by: srkidd <[email protected]> Co-authored-by: MerlynOMsft <[email protected]>
1 parent 18e0084 commit 1bda91c

File tree

7 files changed

+65
-15
lines changed

7 files changed

+65
-15
lines changed

src/Agent.Listener/CommandLine/ConfigureAgent.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,9 @@ public class ConfigureAgent : ConfigureOrRemoveBase
6060
[Option(Constants.Agent.CommandLine.Flags.DisableLogUploads)]
6161
public bool DisableLogUploads { get; set; }
6262

63+
[Option(Constants.Agent.CommandLine.Flags.ReStreamLogsToFiles)]
64+
public bool ReStreamLogsToFiles { get; set; }
65+
6366
[Option(Constants.Agent.CommandLine.Flags.MachineGroup)]
6467
public bool MachineGroup { get; set; }
6568

src/Agent.Listener/CommandSettings.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -571,6 +571,11 @@ public bool GetDisableLogUploads()
571571
return TestFlag(Configure?.DisableLogUploads, Constants.Agent.CommandLine.Flags.DisableLogUploads);
572572
}
573573

574+
public bool GetReStreamLogsToFiles()
575+
{
576+
return TestFlag(Configure?.ReStreamLogsToFiles, Constants.Agent.CommandLine.Flags.ReStreamLogsToFiles);
577+
}
578+
574579
public bool Unattended()
575580
{
576581
if (TestFlag(GetConfigureOrRemoveBase()?.Unattended, Constants.Agent.CommandLine.Flags.Unattended))

src/Agent.Listener/Configuration/ConfigurationManager.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -398,6 +398,12 @@ public async Task ConfigureAsync(CommandSettings command)
398398
agentSettings.NotificationSocketAddress = command.GetNotificationSocketAddress();
399399

400400
agentSettings.DisableLogUploads = command.GetDisableLogUploads();
401+
agentSettings.ReStreamLogsToFiles = command.GetReStreamLogsToFiles();
402+
403+
if (agentSettings.DisableLogUploads && agentSettings.ReStreamLogsToFiles)
404+
{
405+
throw new NotSupportedException(StringUtil.Loc("ReStreamLogsToFilesError"));
406+
}
401407

402408
agentSettings.AlwaysExtractTask = command.GetAlwaysExtractTask();
403409

@@ -736,7 +742,7 @@ private void CheckAgentRootDirectorySecure()
736742
// Get info about root folder
737743
DirectoryInfo dirInfo = new DirectoryInfo(rootDirPath);
738744

739-
// Get directory access control list
745+
// Get directory access control list
740746
DirectorySecurity directorySecurityInfo = dirInfo.GetAccessControl();
741747
AuthorizationRuleCollection dirAccessRules = directorySecurityInfo.GetAccessRules(true, true, typeof(NTAccount));
742748

src/Agent.Worker/ExecutionContext.cs

Lines changed: 42 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ public sealed class ExecutionContext : AgentService, IExecutionContext, IDisposa
117117
private bool _throttlingReported = false;
118118
private ExecutionTargetInfo _defaultStepTarget;
119119
private ExecutionTargetInfo _currentStepTarget;
120-
private bool _disableLogUploads;
120+
private LogsStreamingOptions _logsStreamingOptions;
121121
private string _buildLogsFolderPath;
122122
private string _buildLogsFile;
123123
private FileStream _buildLogsData;
@@ -179,9 +179,21 @@ public override void Initialize(IHostContext hostContext)
179179
{
180180
base.Initialize(hostContext);
181181

182-
_disableLogUploads = HostContext.GetService<IConfigurationStore>().GetSettings().DisableLogUploads;
182+
var agentSettings = HostContext.GetService<IConfigurationStore>().GetSettings();
183183

184-
if (_disableLogUploads)
184+
185+
_logsStreamingOptions = LogsStreamingOptions.StreamToServer;
186+
if (agentSettings.ReStreamLogsToFiles)
187+
{
188+
_logsStreamingOptions |= LogsStreamingOptions.StreamToFiles;
189+
}
190+
else if (agentSettings.DisableLogUploads)
191+
{
192+
_logsStreamingOptions = LogsStreamingOptions.StreamToFiles;
193+
}
194+
Trace.Info($"Logs streaming mode: {_logsStreamingOptions}");
195+
196+
if (_logsStreamingOptions.HasFlag(LogsStreamingOptions.StreamToFiles))
185197
{
186198
_buildLogsFolderPath = Path.Combine(hostContext.GetDiagDirectory(), _buildLogsFolderName);
187199
Directory.CreateDirectory(_buildLogsFolderPath);
@@ -264,7 +276,7 @@ public void Start(string currentOperation = null)
264276

265277
_jobServerQueue.QueueTimelineRecordUpdate(_mainTimelineId, _record);
266278

267-
if (_disableLogUploads)
279+
if (_logsStreamingOptions.HasFlag(LogsStreamingOptions.StreamToFiles))
268280
{
269281
var buildLogsJobFolder = Path.Combine(_buildLogsFolderPath, _mainTimelineId.ToString());
270282
Directory.CreateDirectory(buildLogsJobFolder);
@@ -276,7 +288,14 @@ public void Start(string currentOperation = null)
276288
_buildLogsData = new FileStream(_buildLogsFile, FileMode.CreateNew);
277289
_buildLogsWriter = new StreamWriter(_buildLogsData, System.Text.Encoding.UTF8);
278290

279-
_logger.Write(StringUtil.Loc("BuildLogsMessage", _buildLogsFile));
291+
if (_logsStreamingOptions.HasFlag(LogsStreamingOptions.StreamToServerAndFiles))
292+
{
293+
_logger.Write(StringUtil.Loc("LogOutputMessage", _buildLogsFile));
294+
}
295+
else
296+
{
297+
_logger.Write(StringUtil.Loc("BuildLogsMessage", _buildLogsFile));
298+
}
280299
}
281300
}
282301

@@ -287,7 +306,7 @@ public TaskResult Complete(TaskResult? result = null, string currentOperation =
287306
Result = result;
288307
}
289308

290-
if (_disableLogUploads)
309+
if (_logsStreamingOptions.HasFlag(LogsStreamingOptions.StreamToFiles))
291310
{
292311
_buildLogsWriter.Flush();
293312
_buildLogsData.Flush();
@@ -717,21 +736,21 @@ public long Write(string tag, string inputMessage, bool canMaskSecrets = true)
717736
{
718737
totalLines = _logger.TotalLines + 1;
719738

720-
if (_disableLogUploads)
739+
if (_logsStreamingOptions.HasFlag(LogsStreamingOptions.StreamToServer))
721740
{
722-
_buildLogsWriter.WriteLine(message);
741+
_logger.Write(message);
723742
}
724-
else
743+
if (_logsStreamingOptions.HasFlag(LogsStreamingOptions.StreamToFiles))
725744
{
726-
_logger.Write(message);
745+
//Add date time stamp to log line
746+
_buildLogsWriter.WriteLine("{0:O} {1}", DateTime.UtcNow, message);
727747
}
728748
}
729749

730-
if (!_disableLogUploads)
750+
if (_logsStreamingOptions.HasFlag(LogsStreamingOptions.StreamToServer))
731751
{
732752
// write to job level execution context's log file.
733-
var parentContext = _parentExecutionContext as ExecutionContext;
734-
if (parentContext != null)
753+
if (_parentExecutionContext is ExecutionContext parentContext)
735754
{
736755
lock (parentContext._loggerLock)
737756
{
@@ -951,7 +970,7 @@ private void PublishTelemetry(
951970
publishTelemetryCmd.ProcessCommand(this, cmd);
952971
}
953972

954-
public void PublishTaskRunnerTelemetry(Dictionary<string,string> taskRunnerData)
973+
public void PublishTaskRunnerTelemetry(Dictionary<string, string> taskRunnerData)
955974
{
956975
PublishTelemetry(taskRunnerData, IsAgentTelemetry: true);
957976
}
@@ -966,6 +985,15 @@ public void Dispose()
966985
_buildLogsData?.Dispose();
967986
_buildLogsData = null;
968987
}
988+
989+
[Flags]
990+
private enum LogsStreamingOptions
991+
{
992+
None = 0,
993+
StreamToServer = 1,
994+
StreamToFiles = 2,
995+
StreamToServerAndFiles = StreamToServer | StreamToFiles
996+
}
969997
}
970998

971999
// The Error/Warning/etc methods are created as extension methods to simplify unit testing.

src/Microsoft.VisualStudio.Services.Agent/ConfigurationStore.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,9 @@ public string Fingerprint
8989
[DataMember(EmitDefaultValue = false)]
9090
public bool DisableLogUploads { get; set; }
9191

92+
[DataMember(EmitDefaultValue = false)]
93+
public bool ReStreamLogsToFiles { get; set; }
94+
9295
[DataMember(EmitDefaultValue = false)]
9396
public int PoolId { get; set; }
9497

src/Microsoft.VisualStudio.Services.Agent/Constants.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,7 @@ public static class Flags
220220
public const string GitUseSChannel = "gituseschannel";
221221
public const string Help = "help";
222222
public const string DisableLogUploads = "disableloguploads";
223+
public const string ReStreamLogsToFiles = "restreamlogstofiles";
223224
public const string MachineGroup = "machinegroup";
224225
public const string Replace = "replace";
225226
public const string NoRestart = "norestart";

src/Misc/layoutbin/en-US/strings.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,8 @@
137137
" --acceptTeeEula macOS and Linux only. Accept the TEE end user license agreement.",
138138
" --gitUseSChannel Windows only. Tell Git to use Windows' native cert store.",
139139
" --alwaysExtractTask Perform an unzip for tasks for each pipeline step.",
140+
" --disableLogUploads Don't stream or send console log output to the server. Instead, you may retrieve them from the agent host's filesystem after the job completes. NOTE: Cannot be used with --reStreamLogsToFiles, it will cause an error.",
141+
" --reStreamLogsToFiles Stream or send console log output to the server as well as a log file on the agent host's filesystem. NOTE: Cannot be used with --disableLogUploads, it will cause an error.",
140142
"",
141143
"CLI-WIDTH-OPTIONS-(35-CHARS)-------CLI-WIDTH-DESCRIPTION-(70-CHARS)--------------------------------------",
142144
"Startup options (Windows only):",
@@ -394,6 +396,7 @@
394396
"ListenForJobs": "{0:u}: Listening for Jobs",
395397
"LocalClockSkewed": "The local machine's clock may be out of sync with the server time by more than five minutes. Please sync your clock with your domain or internet time and try again.",
396398
"LocalSystemAccountNotFound": "Cannot find local system account",
399+
"LogOutputMessage": "The agent has enabled uploading logs as well as saving log to file. After the job completes, you can retrieve this step's logs at {0} on the agent.",
397400
"Maintenance": "Maintenance",
398401
"MaxHierarchyLevelReached": "Hierarchy level is more than supported limit {0}, truncating lower hierarchy.",
399402
"MaxSubResultLimitReached": "Number of subresults in test case '{0}' is more than the supported limit of {1}, truncating remaining ones.",
@@ -503,6 +506,7 @@
503506
"ResourceUtilizationWarningsIsDisabled": "Resource Utilization warnings is disabled, switch \"DISABLE_RESOURCE_UTILIZATION_WARNINGS\" variable to \"true\" if you want to enable it",
504507
"RestartIn15SecMessage": "Restarting the machine in 15 seconds...",
505508
"RestartMessage": "Restart the machine to launch agent and for autologon settings to take effect.",
509+
"ReStreamLogsToFilesError": "You cannot use --disableloguploads and --reStreamLogsToFiles at the same time!",
506510
"RetryCountLimitExceeded": "The maximum allowed number of attempts is {0} but got {1}. Retry attempts count will be decreased to {0}.",
507511
"RMApiFailure": "Api {0} failed with an error code {1}",
508512
"RMArtifactContainerDetailsInvalidError": "The artifact does not have valid container details: {0}",

0 commit comments

Comments
 (0)