winget-cli

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

commit a32078fd14563ebdfd20ababbecec5b73ddb0dcd
parent d0dae56e4157bc930030e34347dcf08fe79e4c10
Author: Kaleb Luedtke <jluedtk@jci.com>
Date:   Wed, 16 Feb 2022 18:41:42 -0600

Setting for Logging Level (#1945)


Diffstat:
Mdoc/Settings.md | 13+++++++++++++
Mschemas/JSON/settings/settings.schema.0.2.json | 23+++++++++++++++++++++++
Msrc/AppInstallerCLICore/Core.cpp | 2+-
Msrc/AppInstallerCLITests/UserSettings.cpp | 78++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/AppInstallerCommonCore/Public/winget/UserSettings.h | 4+++-
Msrc/AppInstallerCommonCore/UserSettings.cpp | 33+++++++++++++++++++++++++++++++++
6 files changed, 151 insertions(+), 2 deletions(-)

diff --git a/doc/Settings.md b/doc/Settings.md @@ -106,6 +106,19 @@ See [details on telemetry](../README.md#datatelemetry), and our [primary privacy If set to true, the `telemetry.disable` setting will prevent any event from being written by the program. +## Logging + +The `logging` settings control the level of detail in log files. `--verbose-logs` will override this setting and always creates a verbose log. +Defaults to `info` if value is not set or is invalid + +### level + +```json + "logging": { + "level": ["verbose", "info", "warning", "error", "critical"] + }, +``` + ## Network The `network` settings influence how winget uses the network to retrieve packages and metadata. diff --git a/schemas/JSON/settings/settings.schema.0.2.json b/schemas/JSON/settings/settings.schema.0.2.json @@ -31,6 +31,23 @@ } } }, + "Logging": { + "description": "Logging settings", + "type": "object", + "properties": { + "level": { + "description": "Preferred logging level", + "type": "string", + "enum": [ + "verbose", + "info", + "warning", + "error", + "critical" + ] + } + } + }, "InstallPrefReq": { "description": "Shared schema for preferences and requirements", "type": "object", @@ -152,6 +169,12 @@ }, { "properties": { + "logging": { "$ref": "#/definitions/Logging" } + }, + "additionalItems": true + }, + { + "properties": { "source": { "$ref": "#/definitions/Source" } }, "additionalItems": true diff --git a/src/AppInstallerCLICore/Core.cpp b/src/AppInstallerCLICore/Core.cpp @@ -66,7 +66,7 @@ namespace AppInstaller::CLI // Enable all logging for this phase; we will update once we have the arguments Logging::Log().EnableChannel(Logging::Channel::All); - Logging::Log().SetLevel(Logging::Level::Info); + Logging::Log().SetLevel(Settings::User().Get<Settings::Setting::LoggingLevelPreference>()); Logging::AddFileLogger(); Logging::EnableWilFailureTelemetry(); diff --git a/src/AppInstallerCLITests/UserSettings.cpp b/src/AppInstallerCLITests/UserSettings.cpp @@ -5,6 +5,7 @@ #include "TestSettings.h" #include <AppInstallerRuntime.h> #include <winget/Settings.h> +#include "AppInstallerLogging.h" #include <AppInstallerErrors.h> @@ -13,6 +14,7 @@ #include <chrono> using namespace AppInstaller::Settings; +using namespace AppInstaller::Logging; using namespace AppInstaller::Runtime; using namespace TestCommon; using namespace std::string_literals; @@ -202,6 +204,82 @@ TEST_CASE("SettingProgressBar", "[settings]") } } +TEST_CASE("SettingLoggingLevelPreference", "[settings]") +{ + DeleteUserSettingsFiles(); + + SECTION("Default value") + { + UserSettingsTest userSettingTest; + + REQUIRE(userSettingTest.Get<Setting::LoggingLevelPreference>() == Level::Info); + REQUIRE(userSettingTest.GetWarnings().size() == 0); + } + SECTION("Info") + { + std::string_view json = R"({ "logging": { "level": "info" } })"; + SetSetting(Stream::PrimaryUserSettings, json); + UserSettingsTest userSettingTest; + + REQUIRE(userSettingTest.Get<Setting::LoggingLevelPreference>() == Level::Info); + REQUIRE(userSettingTest.GetWarnings().size() == 0); + } + SECTION("Verbose") + { + std::string_view json = R"({ "logging": { "level": "verbose" } })"; + SetSetting(Stream::PrimaryUserSettings, json); + UserSettingsTest userSettingTest; + + REQUIRE(userSettingTest.Get<Setting::LoggingLevelPreference>() == Level::Verbose); + REQUIRE(userSettingTest.GetWarnings().size() == 0); + } + SECTION("Warning") + { + std::string_view json = R"({ "logging": { "level": "warning" } })"; + SetSetting(Stream::PrimaryUserSettings, json); + UserSettingsTest userSettingTest; + + REQUIRE(userSettingTest.Get<Setting::LoggingLevelPreference>() == Level::Warning); + REQUIRE(userSettingTest.GetWarnings().size() == 0); + } + SECTION("Error") + { + std::string_view json = R"({ "logging": { "level": "error" } })"; + SetSetting(Stream::PrimaryUserSettings, json); + UserSettingsTest userSettingTest; + + REQUIRE(userSettingTest.Get<Setting::LoggingLevelPreference>() == Level::Error); + REQUIRE(userSettingTest.GetWarnings().size() == 0); + } + SECTION("Critical") + { + std::string_view json = R"({ "logging": { "level": "critical" } })"; + SetSetting(Stream::PrimaryUserSettings, json); + UserSettingsTest userSettingTest; + + REQUIRE(userSettingTest.Get<Setting::LoggingLevelPreference>() == Level::Crit); + REQUIRE(userSettingTest.GetWarnings().size() == 0); + } + SECTION("Bad value") + { + std::string_view json = R"({ "logging": { "level": "fake" } })"; + SetSetting(Stream::PrimaryUserSettings, json); + UserSettingsTest userSettingTest; + + REQUIRE(userSettingTest.Get<Setting::LoggingLevelPreference>() == Level::Info); + REQUIRE(userSettingTest.GetWarnings().size() == 1); + } + SECTION("Bad value type") + { + std::string_view json = R"({ "logging": { "level": 5 } })"; + SetSetting(Stream::PrimaryUserSettings, json); + UserSettingsTest userSettingTest; + + REQUIRE(userSettingTest.Get<Setting::LoggingLevelPreference>() == Level::Info); + REQUIRE(userSettingTest.GetWarnings().size() == 1); + } +} + TEST_CASE("SettingAutoUpdateIntervalInMinutes", "[settings]") { DeleteUserSettingsFiles(); diff --git a/src/AppInstallerCommonCore/Public/winget/UserSettings.h b/src/AppInstallerCommonCore/Public/winget/UserSettings.h @@ -2,6 +2,7 @@ // Licensed under the MIT License. #pragma once #include "AppInstallerStrings.h" +#include "AppInstallerLogging.h" #include "winget/GroupPolicy.h" #include "winget/Resources.h" @@ -56,7 +57,6 @@ namespace AppInstaller::Settings DeliveryOptimization, }; - // Enum of settings. // Must start at 0 to enable direct access to variant in UserSettings. // Max must be last and unused. @@ -82,6 +82,7 @@ namespace AppInstaller::Settings InstallLocaleRequirement, EFDirectMSI, EnableSelfInitiatedMinidump, + LoggingLevelPreference, Max }; @@ -131,6 +132,7 @@ namespace AppInstaller::Settings SETTINGMAPPING_SPECIALIZATION(Setting::InstallLocaleRequirement, std::vector<std::string>, std::vector<std::string>, {}, ".installBehavior.requirements.locale"sv); SETTINGMAPPING_SPECIALIZATION(Setting::EFDirectMSI, bool, bool, false, ".experimentalFeatures.directMSI"sv); SETTINGMAPPING_SPECIALIZATION(Setting::EnableSelfInitiatedMinidump, bool, bool, false, ".debugging.enableSelfInitiatedMinidump"sv); + SETTINGMAPPING_SPECIALIZATION(Setting::LoggingLevelPreference, std::string, Logging::Level, Logging::Level::Info, ".logging.level"sv); // Used to deduce the SettingVariant type; making a variant that includes std::monostate and all SettingMapping types. template <size_t... I> diff --git a/src/AppInstallerCommonCore/UserSettings.cpp b/src/AppInstallerCommonCore/UserSettings.cpp @@ -16,6 +16,7 @@ namespace AppInstaller::Settings using namespace std::string_view_literals; using namespace Runtime; using namespace Utility; + using namespace Logging; static constexpr std::string_view s_SettingEmpty = R"({ @@ -316,6 +317,38 @@ namespace AppInstaller::Settings { return std::chrono::seconds(value); } + + WINGET_VALIDATE_SIGNATURE(LoggingLevelPreference) + { + // logging preference possible values + static constexpr std::string_view s_logging_verbose = "verbose"; + static constexpr std::string_view s_logging_info = "info"; + static constexpr std::string_view s_logging_warning = "warning"; + static constexpr std::string_view s_logging_error = "error"; + static constexpr std::string_view s_logging_critical = "critical"; + + if (Utility::CaseInsensitiveEquals(value, s_logging_verbose)) + { + return Level::Verbose; + } + else if (Utility::CaseInsensitiveEquals(value, s_logging_info)) + { + return Level::Info; + } + else if (Utility::CaseInsensitiveEquals(value, s_logging_warning)) + { + return Level::Warning; + } + else if (Utility::CaseInsensitiveEquals(value, s_logging_error)) + { + return Level::Error; + } + else if (Utility::CaseInsensitiveEquals(value, s_logging_critical)) + { + return Level::Crit; + } + return {}; + } } #ifndef AICLI_DISABLE_TEST_HOOKS