-
Notifications
You must be signed in to change notification settings - Fork 323
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Enhancing blame data collector options #1682
Enhancing blame data collector options #1682
Conversation
@@ -159,23 +167,26 @@ private void SessionEnded_Handler(object sender, SessionEndEventArgs args) | |||
|
|||
if (this.processDumpEnabled) | |||
{ | |||
try | |||
if (this.testStartCount > this.testEndCount || this.alwaysCollectProcessDump) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What if process throws before test cases start?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We have an option to collect dump no matter the number of test cases. This check is just the default behaviour.
if (isFullDump) | ||
{ | ||
// This will create a fulldump of the process with specified filename | ||
return "-accepteula -t -ma " + processId + " " + filename + ".dmp"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this args needs to change. Please check with @abhishkk .
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, I'm doing this in next task. Current PR is just for the additional collector attributes
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When discussed args are added, we need to test it for all known crashes, for 32 bit and 64 bit process with 32 and 64 bit OS.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
will do
@@ -30,6 +30,8 @@ public class BlameCollector : DataCollector, ITestExecutionEnvironmentSpecifier | |||
private int testStartCount; | |||
private int testEndCount; | |||
private bool processDumpEnabled; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we can rename this to processMiniDumpEnabled for readability
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will be true irrespective of minidump or full dump is enabled. Code logic wise this is more readable. We can discuss if needed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree this makes more sense. But you are also using processFullDumpEnabled bariable to know whether full dump is enabled or not. Rather than processFullDumpEnabled it shoule take string or enum type 'full' or 'mini'. Today we are implictly deciding that if processFullDumpEnabled is false but processEnabled is true, then that means mini dump is enabled. This should be explicit.
@@ -30,6 +30,8 @@ public class BlameCollector : DataCollector, ITestExecutionEnvironmentSpecifier | |||
private int testStartCount; | |||
private int testEndCount; | |||
private bool processDumpEnabled; | |||
private bool alwaysCollectProcessDump; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If alwaysCollectProcessDump is false but collect dump is present, then we are creating dump on process crash. As we are creating dump, alwaysCollectProcessDump
name is not incorrect. We can have name like collectDumpOnProcessAbort (or any other better name)
/// <summary> | ||
/// Configuration key name for coolect dump always | ||
/// </summary> | ||
public const string CollectDumpAlwaysKey = "AlwaysCollectDump"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same comment. CollectDumpOnProcessAbort/CollectDumpOnProcessCrash/CollectDumpOnProcessExit is more accurate.
if (this.processDumpEnabled) | ||
{ | ||
this.alwaysCollectProcessDump = string.Equals(collectDumpNode.Attributes[Constants.CollectDumpAlwaysKey]?.Value, "true", StringComparison.OrdinalIgnoreCase); | ||
this.processFullDumpEnabled = string.Equals(collectDumpNode.Attributes[Constants.DumpTypeKey]?.Value, "full", StringComparison.OrdinalIgnoreCase); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can move full
keyword to const.
@@ -42,5 +42,15 @@ internal static class Constants | |||
/// Configuration key name for dump mode | |||
/// </summary> | |||
public const string DumpModeKey = "CollectDump"; | |||
|
|||
/// <summary> | |||
/// Configuration key name for coolect dump always |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: spell
if (this.processDumpEnabled) | ||
{ | ||
this.alwaysCollectProcessDump = string.Equals(collectDumpNode.Attributes[Constants.CollectDumpAlwaysKey]?.Value, "true", StringComparison.OrdinalIgnoreCase); | ||
this.processFullDumpEnabled = string.Equals(collectDumpNode.Attributes[Constants.DumpTypeKey]?.Value, "full", StringComparison.OrdinalIgnoreCase); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mini
should also be supported as value. Any invalid value should be thrown. We should mention a list of valid values in EnabledBlameProcessor and do the validation there itself. In future we can add any list value support in that as well. Soemthing like fullDumpWithThreadStack
@@ -133,7 +136,8 @@ public void Initialize(string argument) | |||
{ | |||
bool isDumpEnabled = false; | |||
|
|||
if (!string.IsNullOrWhiteSpace(argument) && argument.Equals(Constants.BlameCollectDumpKey, StringComparison.OrdinalIgnoreCase)) | |||
var parseSucceeded = LoggerUtilities.TryParseLoggerArgument(argument, out string loggerIdentifier, out Dictionary<string, string> parameters); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So it seems like now /blame:collect;DumpType=full
is the way to collect full dump.
In platform terminology we use arg like /argName:argidentifier;key1=value1
. This makes collect
as identifier of blame arg which seem correct. @cltshivash @singhsarab @kaadhina Any suggestions here?
@@ -133,7 +136,8 @@ public void Initialize(string argument) | |||
{ | |||
bool isDumpEnabled = false; | |||
|
|||
if (!string.IsNullOrWhiteSpace(argument) && argument.Equals(Constants.BlameCollectDumpKey, StringComparison.OrdinalIgnoreCase)) | |||
var parseSucceeded = LoggerUtilities.TryParseLoggerArgument(argument, out string loggerIdentifier, out Dictionary<string, string> parameters); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need to have validation here in case any invalid args, parameters passed. Check comment in UTs for detail.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
@@ -133,7 +136,8 @@ public void Initialize(string argument) | |||
{ | |||
bool isDumpEnabled = false; | |||
|
|||
if (!string.IsNullOrWhiteSpace(argument) && argument.Equals(Constants.BlameCollectDumpKey, StringComparison.OrdinalIgnoreCase)) | |||
var parseSucceeded = LoggerUtilities.TryParseLoggerArgument(argument, out string loggerIdentifier, out Dictionary<string, string> parameters); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Update Blame usage text with these new key value pair info.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
@@ -30,6 +30,8 @@ public class BlameCollector : DataCollector, ITestExecutionEnvironmentSpecifier | |||
private int testStartCount; | |||
private int testEndCount; | |||
private bool processDumpEnabled; | |||
private bool alwaysCollectProcessDump; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we add a RFC for this as this is experience change?
/// <summary> | ||
/// Configuration key name for collect dump always | ||
/// </summary> | ||
public const string CollectDumpAlwaysKey = "CollectDumpOnProcessExit"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we rename this as well ?
/// <summary> | ||
/// Name of collect dump option for blame. | ||
/// </summary> | ||
public const string BlameCollectDumpOnlyOnAbortKey = "CollectDumpOnlyOnAbort"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Where is it being used ?
this.processDumpEnabled = collectDumpNode != null; | ||
if (this.processDumpEnabled) | ||
{ | ||
this.collectDumpOnProcessExit = string.Equals(collectDumpNode.Attributes[Constants.CollectDumpAlwaysKey]?.Value, "true", StringComparison.OrdinalIgnoreCase); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's throw a warning for invalid argument. Bool should only be true/false
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also add test for when it is explicitly set to false by user.
@@ -30,6 +30,8 @@ public class BlameCollector : DataCollector, ITestExecutionEnvironmentSpecifier | |||
private int testStartCount; | |||
private int testEndCount; | |||
private bool processDumpEnabled; | |||
private bool collectDumpOnProcessExit; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add usage docs in help for /blame command.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
@@ -30,6 +30,8 @@ public class BlameCollector : DataCollector, ITestExecutionEnvironmentSpecifier | |||
private int testStartCount; | |||
private int testEndCount; | |||
private bool processDumpEnabled; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree this makes more sense. But you are also using processFullDumpEnabled bariable to know whether full dump is enabled or not. Rather than processFullDumpEnabled it shoule take string or enum type 'full' or 'mini'. Today we are implictly deciding that if processFullDumpEnabled is false but processEnabled is true, then that means mini dump is enabled. This should be explicit.
if (this.processDumpEnabled) | ||
{ | ||
this.collectDumpOnProcessExit = string.Equals(collectDumpNode.Attributes[Constants.CollectDumpOnProcessExitKey]?.Value, "true", StringComparison.OrdinalIgnoreCase); | ||
this.processFullDumpEnabled = string.Equals(collectDumpNode.Attributes[Constants.DumpTypeKey]?.Value, "full", StringComparison.OrdinalIgnoreCase); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In case, collectDumpNode.Attributes[Constants.CollectDumpOnProcessExitKey]
has value different than true OR collectDumpNode.Attributes[Constants.DumpTypeKey]
has value different than full
, we are enabling mini dump always (even when garbage values are present).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
@@ -159,23 +167,29 @@ private void SessionEnded_Handler(object sender, SessionEndEventArgs args) | |||
|
|||
if (this.processDumpEnabled) | |||
{ | |||
try | |||
// If there was a test case crash or if we need to collect dump on process exit. | |||
if (this.testStartCount > this.testEndCount || this.collectDumpOnProcessExit) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the understanding of collectDumpOnProcessExit is incorrect here.
Variable name collectDumpOnProcessUnexpectedExit makes more sense.
So today, when tests run is successful and there is no process unexpexted exit or crash, we are still creating the dump which doesn;t make much sense.
That's why we want a new feature called collectDumpOnProcessUnexpectedExit which if set, creates dump only and only when process exits/crashes unexpectedly.
In that case, this.testStartCount > this.testEndCount && this.collectDumpOnProcessExit
will be the scenario for process unexpectde exit.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
renamed this as discussed
if (isFullDump) | ||
{ | ||
// This will create a fulldump of the process with specified filename | ||
return "-accepteula -t -ma " + processId + " " + filename + ".dmp"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
rather than creating separate if else, we can create a stringbuilder and not add -ma in case its mini dump. This allows us to enahance this argument creation based on any new functionality.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
deferred to next refactor in line
@@ -146,6 +151,10 @@ public void Initialize(string argument) | |||
Output.Warning(false, CommandLineResources.BlameCollectDumpNotSupportedForPlatform); | |||
} | |||
} | |||
else | |||
{ | |||
Output.Warning(false, CommandLineResources.BlameIncorrectParameters); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
RFC for the PR
@@ -194,13 +203,12 @@ public void Initialize(string argument) | |||
|
|||
if (isDumpEnabled) | |||
{ | |||
var dumpNode = XmlDocument.CreateElement(Constants.BlameCollectDumpKey); | |||
outernode.AppendChild(dumpNode); | |||
AddCollectDumpNode(parameters, XmlDocument, outernode); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what if user gives CollectDump in runsettings and also gives /blame:collectDump;dumpType=full?
- Which one gets preference?
- Are we overriding the existing one?
if (string.Equals(entry.Key, Constants.BlameCollectDumpOnProcessExitKey, StringComparison.OrdinalIgnoreCase)) | ||
{ | ||
attributeKey = Constants.BlameCollectDumpOnProcessExitKey; | ||
if(string.Equals(entry.Value, "true", StringComparison.OrdinalIgnoreCase) || string.Equals(entry.Value, "false", StringComparison.OrdinalIgnoreCase)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lets move value checks to blamecollector.
@@ -146,6 +151,10 @@ public void Initialize(string argument) | |||
Output.Warning(false, CommandLineResources.BlameCollectDumpNotSupportedForPlatform); | |||
} | |||
} | |||
else |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
in case of parsing error, lets throw the error.
null, | ||
null); | ||
}); | ||
{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All kind of garbage value checks unit tests will come here.
@@ -106,6 +106,86 @@ public void InitializeShouldWarnIfPlatformNotSupportedForCollectDumpOption() | |||
} | |||
} | |||
|
|||
[TestMethod] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
parsing related unit tests will come here.
else | ||
{ | ||
EqtTrace.Warning("BlameCollector.SessionEnded_Handler: blame:CollectDump was enabled but dump file was not generated."); | ||
this.logger.LogWarning(args.Context, "BlameCollector.SessionEnded_Handler: blame:CollectDump was enabled but dump file was not generated."); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Logger warning localizable.
|
||
[TestMethod] | ||
[ExpectedException(typeof(CommandLineException))] | ||
public void InitializeShouldWarnIfInvalidParameterFormatIsSpecifiedForCollectDumpOption() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: ShouldThrowError
Description
Adding two more options in blame collector
DumpType: To be able to optionally get full dump (The default is mini dump)
AlwaysCollectDump: To be able to optionally generate dump even if all test cases complete (The default behaviour has been changed to generate dump only if any test cases has crashed)
Eg usage:
/blame:collectDump;DumpType=full;AlwaysCollectDump=true