Skip to content
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

#2228 Create --kind and --level arguments for more granular control #2241

Merged
merged 39 commits into from
Jan 25, 2021
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
d8fbaee
Creating BaseLogger to share methods
eddynaka Jan 12, 2021
dd2a148
removing logmessage from interface
eddynaka Jan 12, 2021
5bccb3d
updating more loggers
eddynaka Jan 12, 2021
ceb56ae
Merge branch 'main' into users/ednakamu/base-logger
jameswinkler Jan 14, 2021
c52e91a
Fix parameters
jameswinkler Jan 14, 2021
1b16fb8
Replace verbose in ConsoleLogger. It should know about quiet instead
jameswinkler Jan 15, 2021
ec37c1e
Merge branch 'main' into users/v-jwinkler/#2228_base-logger
jameswinkler Jan 15, 2021
c3d8e91
Remove verbose
jameswinkler Jan 15, 2021
2e07ac5
Merge main -> users/ednakamu/base-logger
jameswinkler Jan 15, 2021
d8fc5e4
Remove unused method
jameswinkler Jan 15, 2021
35247a6
Merge branch 'users/ednakamu/base-logger' into users/v-jwinkler/#2228…
jameswinkler Jan 15, 2021
e54cf2c
Remove unnecessary nullcheck
jameswinkler Jan 16, 2021
de5f2b9
fixing functional tests
eddynaka Jan 16, 2021
81fa57e
back to quiet
eddynaka Jan 16, 2021
662c140
fixing tests
eddynaka Jan 16, 2021
af84726
Use ShouldLog in more locations
jameswinkler Jan 18, 2021
0f12856
Add to release history for breaking change
jameswinkler Jan 18, 2021
3d7fab4
Merge pull request #2246 from microsoft/users/v-jwinkler/#2228_base-l…
jameswinkler Jan 18, 2021
3092114
Fix formatting
jameswinkler Jan 18, 2021
f068b44
Make more loggers children of BaseLogger. Cleanup some functionality…
jameswinkler Jan 18, 2021
cd8a99f
fixing spacing
eddynaka Jan 18, 2021
130b1fa
Rename some parameters, classes, and files. Remove "quiet" from Logg…
jameswinkler Jan 18, 2021
508ae6b
More complete renaming
jameswinkler Jan 18, 2021
0b081e3
Merge pull request #2247 from microsoft/users/v-jwinkler/#2228_base-l…
jameswinkler Jan 18, 2021
eef88e2
Rewording, minor cleanup
jameswinkler Jan 18, 2021
4cbed39
fixing sample build
eddynaka Jan 19, 2021
a1c523c
Correct validate logic. Remove redundant "none"s
jameswinkler Jan 19, 2021
6bc4b62
Rename parameters, reword helper text
jameswinkler Jan 19, 2021
b2ad7af
Add unit tests for DriverExtensionMethod and BaseLogger
jameswinkler Jan 19, 2021
7440769
Fix casting error
jameswinkler Jan 19, 2021
2b53283
fixing samples compilation issue
eddynaka Jan 20, 2021
ba0c58b
Small changes to address comments
jameswinkler Jan 20, 2021
908e5ae
Merge pull request #2249 from microsoft/users/v-jwinkler/#2228_base-l…
jameswinkler Jan 20, 2021
a49b35d
Formatting fixes
jameswinkler Jan 20, 2021
66e51f2
Address renaming and refactoring comments
jameswinkler Jan 21, 2021
1720e89
More renaming
jameswinkler Jan 21, 2021
0f0bee9
Merge branch 'main' into users/ednakamu/base-logger
eddynaka Jan 21, 2021
1a1c3fe
Change validation in BaseLogger and correct unit tests and code (#2262)
jameswinkler Jan 25, 2021
ea67391
Merge branch 'main' into users/ednakamu/base-logger
eddynaka Jan 25, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 0 additions & 8 deletions src/Sarif.Driver/Sdk/AggregatingLogger.cs
Original file line number Diff line number Diff line change
Expand Up @@ -53,14 +53,6 @@ public void AnalyzingTarget(IAnalysisContext context)
}
}

public void LogMessage(bool verbose, string message)
{
foreach (IAnalysisLogger logger in Loggers)
{
logger.LogMessage(verbose, message);
}
}

public void Log(ReportingDescriptor rule, Result result)
{
foreach (IAnalysisLogger logger in Loggers)
Expand Down
12 changes: 8 additions & 4 deletions src/Sarif.Driver/Sdk/AnalyzeCommandBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -267,13 +267,13 @@ internal AggregatingLogger InitializeLogger(AnalyzeOptionsBase analyzeOptions)

if (!analyzeOptions.Quiet)
{
_consoleLogger = new ConsoleLogger(analyzeOptions.Verbose, _tool.Driver.Name) { CaptureOutput = _captureConsoleOutput };
_consoleLogger = new ConsoleLogger(analyzeOptions.Verbose, _tool.Driver.Name, analyzeOptions.Level, analyzeOptions.Kind) { CaptureOutput = _captureConsoleOutput };
Copy link
Collaborator Author

@jameswinkler jameswinkler Jan 14, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we should remove analyzeOptions.Verbose from the ConsoleLogger constructor signature, in preparation for that Verbose's eventual retirement? Instead, if verbose is passed, we could set Level and Kind to the maximum level. We do something similar with "options.ComputeFileHashes". We could also do the opposite with analyzeOptions.Quiet. #Resolved

logger.Loggers.Add(_consoleLogger);
}

if ((analyzeOptions.DataToInsert.ToFlags() & OptionallyEmittedData.Hashes) != 0)
{
_cacheByFileHashLogger = new CacheByFileHashLogger(analyzeOptions.Verbose);
_cacheByFileHashLogger = new CacheByFileHashLogger(analyzeOptions.Level, analyzeOptions.Kind);
logger.Loggers.Add(_cacheByFileHashLogger);
}

Expand Down Expand Up @@ -426,7 +426,9 @@ private void InitializeOutputFile(TOptions analyzeOptions, TContext context, ISe
run: null,
analysisTargets: targets,
invocationTokensToRedact: GenerateSensitiveTokensList(),
invocationPropertiesToLog: analyzeOptions.InvocationPropertiesToLog);
invocationPropertiesToLog: analyzeOptions.InvocationPropertiesToLog,
level: analyzeOptions.Level,
kind: analyzeOptions.Kind);
}
else
{
Expand All @@ -439,7 +441,9 @@ private void InitializeOutputFile(TOptions analyzeOptions, TContext context, ISe
run: null,
analysisTargets: targets,
invocationTokensToRedact: GenerateSensitiveTokensList(),
invocationPropertiesToLog: analyzeOptions.InvocationPropertiesToLog);
invocationPropertiesToLog: analyzeOptions.InvocationPropertiesToLog,
level: analyzeOptions.Level,
kind: analyzeOptions.Kind);
}
_pathToHashDataMap = sarifLogger.AnalysisTargetToHashDataMap;
sarifLogger.AnalysisStarted();
Expand Down
14 changes: 14 additions & 0 deletions src/Sarif.Driver/Sdk/AnalyzeOptionsBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -96,5 +96,19 @@ public abstract class AnalyzeOptionsBase : CommonOptionsBase
"should be emitted to the console and log file (if appropriate). " +
"Valid values: ScanTime.")]
public virtual IEnumerable<string> Traces { get; set; }

[Option(
"level",
Separator = ';',
Default = new FailureLevel[] { FailureLevel.Error, FailureLevel.Warning },
HelpText = "Filter results. Valid values: None, Note, Warning, and Error.")]
Copy link
Member

@michaelcfanning michaelcfanning Jan 18, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Filter results. Valid values: None, Note, Warning, and Error. [](start = 24, length = 61)

"Filter output of scan results to one or more failure levels. Valid values: Error, Warning and Note." #Closed

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.


In reply to: 559750572 [](ancestors = 559750572)

public IEnumerable<FailureLevel> Level { get; set; }

[Option(
"kind",
Separator = ';',
Default = new ResultKind[] { ResultKind.Fail },
HelpText = "Filter results. Valid values: None, NotApplicable, Pass, Facil, Review, Open, and Informational")]
Copy link
Member

@michaelcfanning michaelcfanning Jan 18, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

HelpText = "Filter results. Valid values: None, NotApplicable, Pass, Facil, Review, Open, and Informational")] [](start = 12, length = 110)

"Filter output one or more result kinds. Valid values: Fail (for literal scan results), Pass, Review, Open, NotApplicable and Informational." #Closed

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.


In reply to: 559751125 [](ancestors = 559751125)

public IEnumerable<ResultKind> Kind { get; set; }
}
}
2 changes: 1 addition & 1 deletion src/Sarif.Driver/Sdk/MultithreadedAnalyzeCommandBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -542,7 +542,7 @@ internal AggregatingLogger InitializeLogger(AnalyzeOptionsBase analyzeOptions)

if (!analyzeOptions.Quiet)
{
_consoleLogger = new ConsoleLogger(analyzeOptions.Verbose, _tool.Driver.Name) { CaptureOutput = _captureConsoleOutput };
_consoleLogger = new ConsoleLogger(analyzeOptions.Verbose, _tool.Driver.Name, analyzeOptions.Level, analyzeOptions.Kind) { CaptureOutput = _captureConsoleOutput };
logger.Loggers.Add(_consoleLogger);
}

Expand Down
9 changes: 1 addition & 8 deletions src/Sarif/IAnalysisLogger.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ namespace Microsoft.CodeAnalysis.Sarif
public interface IAnalysisLogger
{
void AnalysisStarted();

void AnalysisStopped(RuntimeConditions runtimeConditions);

void AnalyzingTarget(IAnalysisContext context);
Expand All @@ -32,13 +33,5 @@ public interface IAnalysisLogger
/// The notification to log.
/// </param>
void LogConfigurationNotification(Notification notification);

/// <summary>
/// Log a simple message for display to users (which
/// will not be persisted to log files)
/// </summary>
/// <param name="verbose"></param>
/// <param name="message"></param>
void LogMessage(bool verbose, string message);
}
}
51 changes: 51 additions & 0 deletions src/Sarif/Writers/BaseLogger.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System;
using System.Collections.Generic;
using System.Linq;

namespace Microsoft.CodeAnalysis.Sarif.Writers
{
public class BaseLogger
{
private readonly List<FailureLevel> failureLevels;
private readonly List<ResultKind> resultKinds;

public BaseLogger(IEnumerable<FailureLevel> failureLevels,
IEnumerable<ResultKind> resultKinds)
{
this.failureLevels = failureLevels?.ToList() ?? new List<FailureLevel> { FailureLevel.Error, FailureLevel.Warning };
this.resultKinds = resultKinds?.ToList() ?? new List<ResultKind> { ResultKind.Fail };

ValidateParameters();
}

private void ValidateParameters()
{
if (resultKinds.Any(kind => kind != ResultKind.Fail))
{
if (failureLevels.Contains(FailureLevel.Error))
{
throw new ArgumentException("Invalid kind & level combination");
Copy link
Member

@michaelcfanning michaelcfanning Jan 18, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

throw new ArgumentException("Invalid kind & level combination"); [](start = 20, length = 64)

This validation is not correct. It's fine to configure a mixture of things. The levels are only relevant if kind == Fail.

And so your actual validation here is if Kind does not include Fail, then Level must be zero. #Closed

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.


In reply to: 559746343 [](ancestors = 559746343)

}
}
}

public bool ShouldLog(Notification notification)
{
return failureLevels.Contains(notification.Level);
}

public bool ShouldLog(Result result)
{
// If resultKinds is the default value (Fail), we should just filter based on failureLevels
if (resultKinds.Count == 1 && resultKinds[0] == ResultKind.Fail)
{
return failureLevels.Contains(result.Level);
}

return resultKinds.Contains(result.Kind) && failureLevels.Contains(result.Level);
}
}
}
39 changes: 6 additions & 33 deletions src/Sarif/Writers/CacheByFileHashLogger.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,16 @@ namespace Microsoft.CodeAnalysis.Sarif.Writers
/// of simply repeating the analysis. This can result in significant performance gains, when that analysis
/// is expensive (such as in the case of a binary analysis that retrieves and crawls binary PDBs).
/// </summary>
public class CacheByFileHashLogger : IAnalysisLogger
public class CacheByFileHashLogger : BaseLogger, IAnalysisLogger
{
private bool cacheLoggingData;
private string currentFileHash;

public Dictionary<string, List<Notification>> HashToNotificationsMap { get; private set; }
public Dictionary<string, List<Tuple<ReportingDescriptor, Result>>> HashToResultsMap { get; private set; }

public CacheByFileHashLogger(bool verbose)
public CacheByFileHashLogger(IEnumerable<FailureLevel> level, IEnumerable<ResultKind> kind) : base(level, kind)
Copy link
Member

@michaelcfanning michaelcfanning Jan 18, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

level [](start = 63, length = 5)

s/be plural names #Closed

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.


In reply to: 559747791 [](ancestors = 559747791)

{
Verbose = verbose;
}

public void AnalysisStarted()
Expand All @@ -34,8 +33,6 @@ public void AnalysisStarted()
HashToResultsMap = new Dictionary<string, List<Tuple<ReportingDescriptor, Result>>>();
}

public bool Verbose { get; private set; }

public void AnalysisStopped(RuntimeConditions runtimeConditions)
{
}
Expand Down Expand Up @@ -63,32 +60,12 @@ public void Log(ReportingDescriptor rule, Result result)
{
if (!cacheLoggingData) { return; }

switch (result.Level)
if (!ShouldLog(result))
{
// These result types are optionally emitted.
case FailureLevel.None:
case FailureLevel.Note:
{
if (Verbose)
{
CacheResult(rule, result);
}
break;
}

// These result types are always emitted.
case FailureLevel.Error:
case FailureLevel.Warning:
{
CacheResult(rule, result);
break;
}

default:
{
throw new InvalidOperationException();
}
return;
}

CacheResult(rule, result);
}

private void CacheResult(ReportingDescriptor rule, Result result)
Expand All @@ -111,10 +88,6 @@ public void LogConfigurationNotification(Notification notification)
notifications.Add(notification);
}

public void LogMessage(bool verbose, string message)
{
}

public void LogToolNotification(Notification notification)
{
}
Expand Down
4 changes: 0 additions & 4 deletions src/Sarif/Writers/CachingLogger.cs
Original file line number Diff line number Diff line change
Expand Up @@ -69,10 +69,6 @@ public void LogConfigurationNotification(Notification notification)
ConfigurationNotifications.Add(notification);
}

public void LogMessage(bool verbose, string message)
{
}

public void LogToolNotification(Notification notification)
{
ToolNotifications ??= new List<Notification>();
Expand Down
83 changes: 11 additions & 72 deletions src/Sarif/Writers/ConsoleLogger.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,16 @@
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;

namespace Microsoft.CodeAnalysis.Sarif.Writers
{
public class ConsoleLogger : IAnalysisLogger
public class ConsoleLogger : BaseLogger, IAnalysisLogger
Copy link
Member

@michaelcfanning michaelcfanning Jan 18, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ConsoleLogger [](start = 17, length = 13)

Note James: our console output should emit results in an ordered and deterministic way!
#Closed

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Per our emails, created an issue here: #2250


In reply to: 559749330 [](ancestors = 559749330)

{
public ConsoleLogger(bool verbose, string toolName)
public ConsoleLogger(bool verbose, string toolName, IEnumerable<FailureLevel> level = null, IEnumerable<ResultKind> kind = null) : base(level, kind)
{
Verbose = verbose;
_toolName = toolName.ToUpperInvariant();
Expand Down Expand Up @@ -89,14 +90,6 @@ public void AnalyzingTarget(IAnalysisContext context)
}
}

public void LogMessage(bool verbose, string message)
{
if (Verbose)
{
WriteLineToConsole(message);
}
}

public void Log(ReportingDescriptor rule, Result result)
{
if (result == null)
Expand All @@ -110,59 +103,12 @@ public void Log(ReportingDescriptor rule, Result result)
// Note that we can potentially emit many messages from a single result.
PhysicalLocation physicalLocation = result.Locations?.First().PhysicalLocation;

WriteToConsole(
result.Kind,
result.Level,
physicalLocation?.ArtifactLocation?.Uri,
physicalLocation?.Region,
result.RuleId,
message);
}

private void WriteToConsole(ResultKind kind, FailureLevel level, Uri uri, Region region, string ruleId, string message)
{
ValidateKindAndLevel(kind, level);

switch (level)
if (!ShouldLog(result))
{
// These result types are optionally emitted.
case FailureLevel.None:
case FailureLevel.Note:
{
if (Verbose)
{
WriteLineToConsole(GetMessageText(_toolName, uri, region, ruleId, message, kind, level));
}
break;
}

// These result types are always emitted.
case FailureLevel.Error:
case FailureLevel.Warning:
{
WriteLineToConsole(GetMessageText(_toolName, uri, region, ruleId, message, kind, level));
break;
}

default:
{
throw new InvalidOperationException();
}
}
}

private static void ValidateKindAndLevel(ResultKind kind, FailureLevel level)
{
if (level != FailureLevel.None && kind != ResultKind.Fail)
{
throw new ArgumentException("Level indicated a failure but kind was not set to 'Fail'.");
return;
}

if (level == FailureLevel.None && kind == ResultKind.Fail)
{
throw new ArgumentException("Level did not indicate a failure but kind was set to 'Fail'.");
}
return;
WriteLineToConsole(GetMessageText(_toolName, physicalLocation?.ArtifactLocation?.Uri, physicalLocation?.Region, result.RuleId, message, result.Kind, result.Level));
}

private static string GetMessageText(
Expand All @@ -174,11 +120,7 @@ private static string GetMessageText(
ResultKind kind,
FailureLevel level)
{
string path = null;

ValidateKindAndLevel(kind, level);

path = ConstructPathFromUri(uri);
string path = ConstructPathFromUri(uri);

string issueType = null;

Expand Down Expand Up @@ -217,13 +159,10 @@ private static string GetMessageText(
location = region.FormatForVisualStudio();
}

string messageText =
(path != null ? (path + location) : toolName) + ": " +
issueType + " " +
(!string.IsNullOrEmpty(ruleId) ? (ruleId + ": ") : "") +
detailedDiagnosis;

return messageText;
return (path != null ? (path + location) : toolName)
+ $": {issueType} "
+ (!string.IsNullOrEmpty(ruleId) ? (ruleId + ": ") : "")
+ detailedDiagnosis;
}

public static string NormalizeMessage(string message, bool enquote)
Expand Down
Loading