Skip to content

Commit 6cb2ddb

Browse files
committed
Capture a few more errors in logging.
1 parent af6f152 commit 6cb2ddb

5 files changed

Lines changed: 57 additions & 9 deletions

File tree

src/VirtualClient/VirtualClient.Contracts/Exceptions.cs

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -486,10 +486,9 @@ public ProcessException(string message, Exception innerException, ErrorReason re
486486
}
487487

488488
/// <summary>
489-
/// Represents an exception/error that occurred during the execution of a process
490-
/// on the system (i.e. an OS process).
489+
/// Represents an exception/error that occurred during the startup of the application.
491490
/// </summary>
492-
public class StartupException : Exception
491+
public class StartupException : VirtualClientException
493492
{
494493
/// <summary>
495494
/// Initializes a new instance of the <see cref="StartupException"/> class.
@@ -509,6 +508,17 @@ public StartupException(string message)
509508
{
510509
}
511510

511+
/// <summary>
512+
/// Initializes a new instance of the <see cref="StartupException"/> class with
513+
/// the provided message.
514+
/// </summary>
515+
/// <param name="message">The exception message.</param>
516+
/// <param name="reason">The error reason/category.</param>
517+
public StartupException(string message, ErrorReason reason)
518+
: base(message, reason)
519+
{
520+
}
521+
512522
/// <summary>
513523
/// Initializes a new instance of the <see cref="StartupException"/> class with
514524
/// the provided message and inner exception.
@@ -519,6 +529,18 @@ public StartupException(string message, Exception innerException)
519529
: base(message, innerException)
520530
{
521531
}
532+
533+
/// <summary>
534+
/// Initializes a new instance of the <see cref="StartupException"/> class with
535+
/// the provided message and inner exception.
536+
/// </summary>
537+
/// <param name="message">The exception message.</param>
538+
/// <param name="innerException">The inner exception.</param>
539+
/// <param name="reason">The error reason/category.</param>
540+
public StartupException(string message, Exception innerException, ErrorReason reason)
541+
: base(message, innerException, reason)
542+
{
543+
}
522544
}
523545

524546
/// <summary>

src/VirtualClient/VirtualClient.Core/ProfileExecutor.cs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -520,10 +520,23 @@ protected async Task ExecuteMonitorsAsync(EventContext parentContext, Cancellati
520520
monitoringTasks.Add(monitor.ExecuteAsync(cancellationToken));
521521
}
522522
}
523-
catch (VirtualClientException)
523+
catch (VirtualClientException exc) when ((int)exc.Reason >= 500 || this.FailFast || monitor?.FailFast == true)
524524
{
525+
// Error reasons have numeric/integer values that indicate their severity. Error reasons
526+
// with a value >= 500 are terminal situations where the workload cannot run successfully
527+
// regardless of how many times we attempt it.
525528
throw;
526529
}
530+
catch (VirtualClientException)
531+
{
532+
// Exceptions with error reasons < 500 are potentially transient issues. We do not want to
533+
// cause VC to exit in these cases but to give it a chance to retry the logic that failed on
534+
// subsequent rounds of processing.
535+
//
536+
// Exceptions having error reasons with a value between 400 - 499 are serious errors but they represent
537+
// issues that may be transient and that can be resolve after a period of time. When
538+
// we catch these type of errors, we may want to reset and start over in the test workflow.
539+
}
527540
catch (MissingMemberException exc)
528541
{
529542
throw new DependencyException(

src/VirtualClient/VirtualClient.Main/ExecuteProfileCommand.cs

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -164,12 +164,22 @@ public override async Task<int> ExecuteAsync(string[] args, CancellationTokenSou
164164
Program.LogErrorMessage(logger, exc, EventContext.Persisted());
165165
exitCode = (int)ErrorReason.NotSupported;
166166
}
167+
catch (StartupException exc)
168+
{
169+
// The type of exceptions are captured upstream by the profile
170+
// execution components.
171+
Program.LogErrorMessage(logger, exc, EventContext.Persisted());
172+
exitCode = (int)exc.Reason;
173+
}
167174
catch (VirtualClientException exc)
168175
{
176+
// The type of exceptions are captured upstream by the profile
177+
// execution components.
169178
exitCode = (int)exc.Reason;
170179
}
171-
catch
180+
catch (Exception exc)
172181
{
182+
Program.LogErrorMessage(logger, exc, EventContext.Persisted());
173183
exitCode = 1;
174184
}
175185
finally
@@ -304,7 +314,7 @@ protected virtual async Task DownloadProfileAsync(IServiceCollection dependencie
304314
// If the profile defined is not a full path to a profile located on the system, then we
305315
// fallback to looking for the profile in the 'profiles' directory within the Virtual Client
306316
// parent directory itself or in any platform extensions locations.
307-
throw new DependencyException(
317+
throw new StartupException(
308318
$"Profile not found. Profile does not exist at the path '{profileFullPath}' nor in any extensions location.",
309319
ErrorReason.ProfileNotFound);
310320
}
@@ -425,8 +435,9 @@ protected async Task<EnvironmentLayout> ReadEnvironmentLayoutAsync(IServiceColle
425435

426436
if (!systemManagement.FileSystem.File.Exists(layoutFullPath))
427437
{
428-
throw new FileNotFoundException(
429-
$"Invalid path specified. An environment layout file does not exist at path '{layoutFullPath}'.");
438+
throw new StartupException(
439+
$"Invalid path specified. An environment layout file does not exist at path '{layoutFullPath}'.",
440+
ErrorReason.LayoutInvalid);
430441
}
431442

432443
string layoutContent = await RetryPolicies.FileOperations

src/VirtualClient/VirtualClient.Main/Program.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,12 +133,14 @@ public static int Main(string[] args)
133133
// Certificate-related issues.
134134
exitCode = (int)ErrorReason.InvalidCertificate;
135135
Console.Error.WriteLine(exc.ToString(withCallStack: false, withErrorTypes: false));
136+
Program.WriteCrashLog(exc);
136137
}
137138
catch (NotSupportedException exc)
138139
{
139140
// Various usages that are not supported.
140141
exitCode = (int)ErrorReason.NotSupported;
141142
Console.Error.WriteLine(exc.ToString(withCallStack: false, withErrorTypes: false));
143+
Program.WriteCrashLog(exc);
142144
}
143145
catch (Exception exc)
144146
{

website/docs/guides/0040-telemetry.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -656,7 +656,7 @@ Fields that are part of the custom dimensions.
656656
The following example illustrates the schema requirements for the various supported log file formats:
657657

658658
* **JSON Schema and Requirements**
659-
The example below illustrates the supported JSON format for log files. Each JSON data point/fragment should be separated from the next using a ```---``` delimiter as is shown in
659+
The example below illustrates the supported JSON format for log files. Each JSON data point/fragment should be separated from the next using a ```-----``` delimiter as is shown in
660660
the example.
661661

662662
``` json

0 commit comments

Comments
 (0)