Skip to content

Commit

Permalink
Add ODS logger and use it during init (#4969)
Browse files Browse the repository at this point in the history
## Change
The user settings (and then group policy) initialization happen before
we get the file logger set up. To be able to see into what is happening
there more easily, this change creates a logger that uses
`OutputDebugString` and uses it during the initial file logger creation.
  • Loading branch information
JohnMcPMS authored Nov 20, 2024
1 parent 03df824 commit 25ccc2a
Show file tree
Hide file tree
Showing 6 changed files with 131 additions and 8 deletions.
8 changes: 8 additions & 0 deletions src/AppInstallerCLICore/COMContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include "COMContext.h"
#include <AppInstallerFileLogger.h>
#include <winget/TraceLogger.h>
#include <winget/OutputDebugStringLogger.h>

namespace AppInstaller::CLI::Execution
{
Expand Down Expand Up @@ -77,12 +78,19 @@ namespace AppInstaller::CLI::Execution

void COMContext::SetLoggers(std::optional<AppInstaller::Logging::Channel> channel, std::optional<AppInstaller::Logging::Level> level)
{
// Set up debug string logging during initialization
Logging::OutputDebugStringLogger::Add();
Logging::Log().EnableChannel(Logging::Channel::All);
Logging::Log().SetLevel(Logging::Level::Verbose);

Logging::Log().EnableChannel(channel.has_value() ? channel.value() : Settings::User().Get<Settings::Setting::LoggingChannelPreference>());
Logging::Log().SetLevel(level.has_value() ? level.value() : Settings::User().Get<Settings::Setting::LoggingLevelPreference>());

// TODO: Log to file for COM API calls only when debugging in visual studio
Logging::FileLogger::Add(s_comLogFileNamePrefix);

Logging::OutputDebugStringLogger::Remove();

#ifndef AICLI_DISABLE_TEST_HOOKS
if (!Settings::User().Get<Settings::Setting::KeepAllLogFiles>())
#endif
Expand Down
44 changes: 36 additions & 8 deletions src/AppInstallerCLICore/Core.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include "Commands/InstallCommand.h"
#include "COMContext.h"
#include <AppInstallerFileLogger.h>
#include <winget/OutputDebugStringLogger.h>

#ifndef AICLI_DISABLE_TEST_HOOKS
#include <winget/Debugging.h>
Expand Down Expand Up @@ -66,21 +67,34 @@ namespace AppInstaller::CLI

init_apartment();

#ifndef AICLI_DISABLE_TEST_HOOKS
#ifndef AICLI_DISABLE_TEST_HOOKS
// We have to do this here so the auto minidump config initialization gets caught
Logging::OutputDebugStringLogger::Add();
Logging::Log().EnableChannel(Logging::Channel::All);
Logging::Log().SetLevel(Logging::Level::Verbose);

if (Settings::User().Get<Settings::Setting::EnableSelfInitiatedMinidump>())
{
Debugging::EnableSelfInitiatedMinidump();
}
}

Logging::OutputDebugStringLogger::Remove();
#endif

Logging::UseGlobalTelemetryLoggerActivityIdOnly();

Execution::Context context{ std::cout, std::cin };
auto previousThreadGlobals = context.SetForCurrentThread();
auto previousThreadGlobals = context.SetForCurrentThread();

// Set up debug string logging during initialization
Logging::OutputDebugStringLogger::Add();
Logging::Log().EnableChannel(Logging::Channel::All);
Logging::Log().SetLevel(Logging::Level::Verbose);

Logging::Log().EnableChannel(Settings::User().Get<Settings::Setting::LoggingChannelPreference>());
Logging::Log().SetLevel(Settings::User().Get<Settings::Setting::LoggingLevelPreference>());
Logging::FileLogger::Add();
Logging::FileLogger::Add();
Logging::OutputDebugStringLogger::Remove();
Logging::EnableWilFailureTelemetry();

// Set output to UTF8
Expand Down Expand Up @@ -171,23 +185,37 @@ namespace AppInstaller::CLI

void ServerInitialize()
{
#ifndef AICLI_DISABLE_TEST_HOOKS
#ifndef AICLI_DISABLE_TEST_HOOKS
// We have to do this here so the auto minidump config initialization gets caught
Logging::OutputDebugStringLogger::Add();
Logging::Log().EnableChannel(Logging::Channel::All);
Logging::Log().SetLevel(Logging::Level::Verbose);

if (Settings::User().Get<Settings::Setting::EnableSelfInitiatedMinidump>())
{
Debugging::EnableSelfInitiatedMinidump();
}
}

Logging::OutputDebugStringLogger::Remove();
#endif

AppInstaller::CLI::Execution::COMContext::SetLoggers();
}

void InProcInitialize()
{
#ifndef AICLI_DISABLE_TEST_HOOKS
#ifndef AICLI_DISABLE_TEST_HOOKS
// We have to do this here so the auto minidump config initialization gets caught
Logging::OutputDebugStringLogger::Add();
Logging::Log().EnableChannel(Logging::Channel::All);
Logging::Log().SetLevel(Logging::Level::Verbose);

if (Settings::User().Get<Settings::Setting::EnableSelfInitiatedMinidump>())
{
Debugging::EnableSelfInitiatedMinidump();
}
}

Logging::OutputDebugStringLogger::Remove();
#endif

// Explicitly set default channel and level before user settings from PackageManagerSettings
Expand Down
2 changes: 2 additions & 0 deletions src/AppInstallerCommonCore/AppInstallerCommonCore.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -448,6 +448,7 @@
</ClInclude>
<ClInclude Include="Public\winget\NameNormalization.h" />
<ClInclude Include="Public\winget\NetworkSettings.h" />
<ClInclude Include="Public\winget\OutputDebugStringLogger.h" />
<ClInclude Include="Public\winget\PackageDependenciesValidationUtil.h" />
<ClInclude Include="Public\winget\PackageVersionDataManifest.h" />
<ClInclude Include="Public\winget\Pin.h" />
Expand Down Expand Up @@ -504,6 +505,7 @@
</ClCompile>
<ClCompile Include="NameNormalization.cpp" />
<ClCompile Include="NetworkSettings.cpp" />
<ClCompile Include="OutputDebugStringLogger.cpp" />
<ClCompile Include="PackageDependenciesValidationUtil.cpp" />
<ClCompile Include="PackageVersionDataManifest.cpp" />
<ClCompile Include="Pin.cpp" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,9 @@
<ClInclude Include="Public\winget\Fonts.h">
<Filter>Public\winget</Filter>
</ClInclude>
<ClInclude Include="Public\winget\OutputDebugStringLogger.h">
<Filter>Public\winget</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="pch.cpp">
Expand Down Expand Up @@ -374,6 +377,9 @@
<ClCompile Include="Fonts.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="OutputDebugStringLogger.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="PropertySheet.props" />
Expand Down
50 changes: 50 additions & 0 deletions src/AppInstallerCommonCore/OutputDebugStringLogger.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
#include "pch.h"
#include "winget/OutputDebugStringLogger.h"

namespace AppInstaller::Logging
{
namespace
{
static constexpr std::string_view s_OutputDebugStringLoggerName = "OutputDebugStringLogger";
}

std::string OutputDebugStringLogger::GetName() const
{
return std::string{ s_OutputDebugStringLoggerName };
}

void OutputDebugStringLogger::Write(Channel channel, Level, std::string_view message) noexcept try
{
std::stringstream strstr;
strstr << "[" << std::setw(GetMaxChannelNameLength()) << std::left << std::setfill(' ') << GetChannelName(channel) << "] " << message << std::endl;
std::string formattedMessage = std::move(strstr).str();

OutputDebugStringA(formattedMessage.c_str());
}
catch (...)
{
// Just eat any exceptions here; better than losing logs
}

void OutputDebugStringLogger::WriteDirect(Channel, Level, std::string_view message) noexcept try
{
std::string nullTerminatedMessage{ message };
OutputDebugStringA(nullTerminatedMessage.c_str());
}
catch (...)
{
// Just eat any exceptions here; better than losing logs
}

void OutputDebugStringLogger::Add()
{
Log().AddLogger(std::make_unique<OutputDebugStringLogger>());
}

void OutputDebugStringLogger::Remove()
{
Log().RemoveLogger(std::string{ s_OutputDebugStringLoggerName });
}
}
29 changes: 29 additions & 0 deletions src/AppInstallerCommonCore/Public/winget/OutputDebugStringLogger.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
#pragma once
#include <AppInstallerLogging.h>

namespace AppInstaller::Logging
{
// Sends logs to the OutputDebugString function.
// Intended for use during initialization debugging.
struct OutputDebugStringLogger : ILogger
{
OutputDebugStringLogger() = default;

~OutputDebugStringLogger() = default;

// ILogger
std::string GetName() const override;

void Write(Channel channel, Level, std::string_view message) noexcept override;

void WriteDirect(Channel channel, Level level, std::string_view message) noexcept override;

// Adds OutputDebugStringLogger to the current Log
static void Add();

// Removes OutputDebugStringLogger from the current Log
static void Remove();
};
}

0 comments on commit 25ccc2a

Please sign in to comment.