C#: Introduce extractor option for logging verbosity

This commit is contained in:
Tamas Vajk
2024-01-25 17:20:47 +01:00
parent bb4327294d
commit b8c8f52efc
8 changed files with 118 additions and 6 deletions

View File

@@ -267,7 +267,11 @@ namespace Semmle.Autobuild.Shared
protected DiagnosticClassifier DiagnosticClassifier { get; } protected DiagnosticClassifier DiagnosticClassifier { get; }
private readonly ILogger logger = new ConsoleLogger(Verbosity.Info, logThreadId: false); private readonly ILogger logger = new ConsoleLogger(
VerbosityExtensions.ParseVerbosity(
Environment.GetEnvironmentVariable("CODEQL_VERBOSITY"),
logThreadId: false) ?? Verbosity.Info,
logThreadId: false);
private readonly IDiagnosticsWriter diagnostics; private readonly IDiagnosticsWriter diagnostics;

View File

@@ -48,3 +48,21 @@ options:
The default is 'true'. The default is 'true'.
type: string type: string
pattern: "^(false|true)$" pattern: "^(false|true)$"
logging:
title: Options pertaining to logging.
type: object
properties:
verbosity:
title: Extractor logging verbosity level.
description: >
Controls the level of verbosity of the extractor.
The supported levels are (in order of increasing verbosity):
- off
- errors
- warnings
- info or progress
- debug or progress+
- trace or progress++
- progress+++
type: string
pattern: "^(off|errors|warnings|(info|progress)|(debug|progress\\+)|(trace|progress\\+\\+)|progress\\+\\+\\+)$"

View File

@@ -38,7 +38,7 @@ namespace Semmle.Extraction.CIL.Driver
} }
var options = new ExtractorOptions(args); var options = new ExtractorOptions(args);
using ILogger logger = new ConsoleLogger(options.LegacyVerbosity, logThreadId: false); using ILogger logger = new ConsoleLogger(options.Verbosity, logThreadId: false);
var actions = options.AssembliesToExtract var actions = options.AssembliesToExtract
.Select(asm => asm.Filename) .Select(asm => asm.Filename)

View File

@@ -136,7 +136,7 @@ namespace Semmle.Extraction.CSharp.Standalone
var stopwatch = new Stopwatch(); var stopwatch = new Stopwatch();
stopwatch.Start(); stopwatch.Start();
using var logger = new ConsoleLogger(options.LegacyVerbosity, logThreadId: true); using var logger = new ConsoleLogger(options.Verbosity, logThreadId: true);
logger.Log(Severity.Info, "Running C# standalone extractor"); logger.Log(Severity.Info, "Running C# standalone extractor");
using var a = new Analysis(logger, options); using var a = new Analysis(logger, options);
var sourceFileCount = a.Extraction.Sources.Count; var sourceFileCount = a.Extraction.Sources.Count;
@@ -147,7 +147,7 @@ namespace Semmle.Extraction.CSharp.Standalone
return ExitCode.Errors; return ExitCode.Errors;
} }
using var fileLogger = CSharp.Extractor.MakeLogger(options.LegacyVerbosity, false); using var fileLogger = CSharp.Extractor.MakeLogger(options.Verbosity, false);
logger.Log(Severity.Info, ""); logger.Log(Severity.Info, "");
logger.Log(Severity.Info, "Extracting..."); logger.Log(Severity.Info, "Extracting...");

View File

@@ -97,7 +97,7 @@ namespace Semmle.Extraction.CSharp
var options = Options.CreateWithEnvironment(args); var options = Options.CreateWithEnvironment(args);
Entities.Compilation.Settings = (Directory.GetCurrentDirectory(), options.CompilerArguments.ToArray()); Entities.Compilation.Settings = (Directory.GetCurrentDirectory(), options.CompilerArguments.ToArray());
using var logger = MakeLogger(options.LegacyVerbosity, options.Console); using var logger = MakeLogger(options.Verbosity, options.Console);
var canonicalPathCache = CanonicalPathCache.Create(logger, 1000); var canonicalPathCache = CanonicalPathCache.Create(logger, 1000);
var pathTransformer = new PathTransformer(canonicalPathCache); var pathTransformer = new PathTransformer(canonicalPathCache);

View File

@@ -103,6 +103,37 @@ namespace Semmle.Extraction.Tests
Assert.Throws<FormatException>(() => CSharp.Options.CreateWithEnvironment(new string[] { "--verbosity", "X" })); Assert.Throws<FormatException>(() => CSharp.Options.CreateWithEnvironment(new string[] { "--verbosity", "X" }));
} }
private const string extractorVariableName = "CODEQL_EXTRACTOR_CSHARP_OPTION_LOGGING_VERBOSITY";
private const string cliVariableName = "CODEQL_VERBOSITY";
private void CheckVerbosity(string? extractor, string? cli, Verbosity expected)
{
var currentExtractorVerbosity = Environment.GetEnvironmentVariable(extractorVariableName);
var currentCliVerbosity = Environment.GetEnvironmentVariable(cliVariableName);
try
{
Environment.SetEnvironmentVariable(extractorVariableName, extractor);
Environment.SetEnvironmentVariable(cliVariableName, cli);
options = CSharp.Options.CreateWithEnvironment(new string[] { "--verbose" });
Assert.Equal(expected, options.Verbosity);
}
finally
{
Environment.SetEnvironmentVariable(extractorVariableName, currentExtractorVerbosity);
Environment.SetEnvironmentVariable(cliVariableName, currentCliVerbosity);
}
}
[Fact]
public void VerbosityTests_WithExtractorOption()
{
CheckVerbosity("progress+++", "progress++", Verbosity.All);
CheckVerbosity(null, "progress++", Verbosity.Trace);
CheckVerbosity(null, null, Verbosity.Debug);
}
[Fact] [Fact]
public void Console() public void Console()
{ {

View File

@@ -20,6 +20,36 @@ namespace Semmle.Extraction
/// </summary> /// </summary>
public Verbosity LegacyVerbosity { get; protected set; } = Verbosity.Info; public Verbosity LegacyVerbosity { get; protected set; } = Verbosity.Info;
private Verbosity? verbosity = null;
public Verbosity Verbosity
{
get
{
if (verbosity != null)
{
return verbosity.Value;
}
var envVarValue = EnvironmentVariables.GetExtractorOption("LOGGING_VERBOSITY");
verbosity = VerbosityExtensions.ParseVerbosity(envVarValue, logThreadId: true);
if (verbosity != null)
{
return verbosity.Value;
}
envVarValue = Environment.GetEnvironmentVariable("CODEQL_VERBOSITY");
verbosity = VerbosityExtensions.ParseVerbosity(envVarValue, logThreadId: true);
if (verbosity != null)
{
return verbosity.Value;
}
// This only works, because we already parsed the provided options, so `LegacyVerbosity` is already set (or it still has the default value).
verbosity = LegacyVerbosity;
return verbosity.Value;
}
}
/// <summary> /// <summary>
/// Whether to output to the console. /// Whether to output to the console.
/// </summary> /// </summary>

View File

@@ -2,7 +2,7 @@ using System;
namespace Semmle.Util.Logging namespace Semmle.Util.Logging
{ {
internal static class VerbosityExtensions public static class VerbosityExtensions
{ {
/// <summary> /// <summary>
/// Whether a message with the given severity must be included /// Whether a message with the given severity must be included
@@ -26,5 +26,34 @@ namespace Semmle.Util.Logging
throw new ArgumentOutOfRangeException(nameof(s)); throw new ArgumentOutOfRangeException(nameof(s));
} }
} }
public static Verbosity? ParseVerbosity(string? str, bool logThreadId)
{
if (str == null)
{
return null;
}
Verbosity? verbosity = str.ToLowerInvariant() switch
{
"off" => Verbosity.Off,
"errors" => Verbosity.Error,
"warnings" => Verbosity.Warning,
"info" or "progress" => Verbosity.Info,
"debug" or "progress+" => Verbosity.Debug,
"trace" or "progress++" => Verbosity.Trace,
"progress+++" => Verbosity.All,
_ => null
};
if (verbosity == null && str != null)
{
// We don't have a logger when this setting is parsed, so writing it to the console:
var prefix = logThreadId ? $"[{Environment.CurrentManagedThreadId:D3}] " : "";
Console.WriteLine($"{prefix}Error: Invalid verbosity level: '{str}'");
}
return verbosity;
}
} }
} }