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

Make telemetry logger per context and send summary event on destruction #1718

Merged
merged 10 commits into from
Nov 30, 2021
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
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
4 changes: 2 additions & 2 deletions src/AppInstallerCLICore/COMContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,11 @@ namespace AppInstaller::CLI::Execution
FireCallbacks(ReportType::EndProgress, 0, 0, ProgressType::None, m_executionStage);
};

void COMContext::SetExecutionStage(CLI::Workflow::ExecutionStage executionStage, bool)
void COMContext::SetExecutionStage(CLI::Workflow::ExecutionStage executionStage)
{
m_executionStage = executionStage;
FireCallbacks(ReportType::ExecutionPhaseUpdate, 0, 0, ProgressType::None, m_executionStage);
Logging::SetExecutionStage(static_cast<uint32_t>(m_executionStage));
Logging::Telemetry().SetExecutionStage(static_cast<uint32_t>(m_executionStage));
}

void COMContext::SetContextLoggers(const std::wstring_view telemetryCorrelationJson, const std::string& caller)
Expand Down
2 changes: 1 addition & 1 deletion src/AppInstallerCLICore/COMContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ namespace AppInstaller::CLI::Execution
void EndProgress(bool) override;

//Execution::Context
void SetExecutionStage(CLI::Workflow::ExecutionStage executionPhase, bool);
void SetExecutionStage(CLI::Workflow::ExecutionStage executionPhase);

CLI::Workflow::ExecutionStage GetExecutionStage() const { return m_executionStage; }

Expand Down
4 changes: 3 additions & 1 deletion src/AppInstallerCLICore/Commands/CompleteCommand.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,10 @@ namespace AppInstaller::CLI
}

// Create a new Context to execute the Complete from
auto subContextPtr = context.Clone();
auto subContextPtr = context.CreateSubContext();
Context& subContext = *subContextPtr;
auto previousThreadGlobals = subContext.GetThreadGlobals().SetForCurrentThread();
JohnMcPMS marked this conversation as resolved.
Show resolved Hide resolved

subContext.Reporter.SetChannel(Execution::Reporter::Channel::Completion);
subContext.Add<Data::CompletionData>(std::move(data));

Expand Down
4 changes: 3 additions & 1 deletion src/AppInstallerCLICore/Core.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ namespace AppInstaller::CLI
{
init_apartment();

Logging::UseGlobalTelemetryLoggerActivityIdOnly();
JohnMcPMS marked this conversation as resolved.
Show resolved Hide resolved

// 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);
Expand All @@ -61,7 +63,7 @@ namespace AppInstaller::CLI
// Initiate the background cleanup of the log file location.
Logging::BeginLogFileCleanup();

Execution::Context context{ std::cout, std::cin };
Execution::Context context{ std::cout, std::cin, nullptr /* Command execution always use global diagnostic logger */, Logging::Telemetry().CreateSubTraceLogger() };
JohnMcPMS marked this conversation as resolved.
Show resolved Hide resolved
context.EnableCtrlHandler();

context << Workflow::ReportExecutionStage(Workflow::ExecutionStage::ParseArgs);
Expand Down
10 changes: 5 additions & 5 deletions src/AppInstallerCLICore/ExecutionContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -118,9 +118,9 @@ namespace AppInstaller::CLI::Execution
}
}

std::unique_ptr<Context> Context::Clone()
std::unique_ptr<Context> Context::CreateSubContext()
{
auto clone = std::make_unique<Context>(Reporter);
auto clone = std::make_unique<Context>(Reporter, m_threadGlobals);
clone->m_flags = m_flags;
// If the parent is hooked up to the CTRL signal, have the clone be as well
if (m_disableCtrlHandlerOnExit)
Expand Down Expand Up @@ -192,19 +192,19 @@ namespace AppInstaller::CLI::Execution
Reporter.CancelInProgressTask(bypassUser);
}

void Context::SetExecutionStage(Workflow::ExecutionStage stage, bool allowBackward)
void Context::SetExecutionStage(Workflow::ExecutionStage stage)
{
if (m_executionStage == stage)
{
return;
}
else if (m_executionStage > stage && !allowBackward)
else if (m_executionStage > stage)
{
THROW_HR_MSG(HRESULT_FROM_WIN32(ERROR_INVALID_STATE), "Reporting ExecutionStage to an earlier Stage without allowBackward as true");
}

m_executionStage = stage;
Logging::SetExecutionStage(static_cast<uint32_t>(m_executionStage));
Logging::Telemetry().SetExecutionStage(static_cast<uint32_t>(m_executionStage));
JohnMcPMS marked this conversation as resolved.
Show resolved Hide resolved
}

AppInstaller::ThreadLocalStorage::ThreadGlobals& Context::GetThreadGlobals()
Expand Down
18 changes: 13 additions & 5 deletions src/AppInstallerCLICore/ExecutionContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,16 @@ namespace AppInstaller::CLI::Execution
{
Context(std::ostream& out, std::istream& in) : Reporter(out, in) {}

// Clone the reporter for this constructor.
Context(Execution::Reporter& reporter) : Reporter(reporter, Execution::Reporter::clone_t{}) {}
Context(
std::ostream& out,
std::istream& in,
std::shared_ptr<AppInstaller::Logging::DiagnosticLogger> diagnosticLogger,
std::unique_ptr<AppInstaller::Logging::TelemetryTraceLogger>&& telemetryLogger) : Reporter(out, in), m_threadGlobals(diagnosticLogger, std::move(telemetryLogger)) {}

// Constructor for creating a sub-context.
Context(Execution::Reporter& reporter, const ThreadLocalStorage::ThreadGlobals& threadGlobals) :
Reporter(reporter, Execution::Reporter::clone_t{}),
m_threadGlobals(threadGlobals, ThreadLocalStorage::ThreadGlobals::create_sub_thread_globals_t{}) {}

virtual ~Context();

Expand All @@ -81,8 +89,8 @@ namespace AppInstaller::CLI::Execution
// The arguments given to execute with.
Args Args;

// Creates a copy of this context as it was at construction.
virtual std::unique_ptr<Context> Clone();
// Creates a child of this context.
virtual std::unique_ptr<Context> CreateSubContext();

// Enables reception of CTRL signals.
void EnableCtrlHandler(bool enabled = true);
Expand Down Expand Up @@ -125,7 +133,7 @@ namespace AppInstaller::CLI::Execution
WI_ClearAllFlags(m_flags, flags);
}

virtual void SetExecutionStage(Workflow::ExecutionStage stage, bool);
virtual void SetExecutionStage(Workflow::ExecutionStage stage);

// Get Globals for Current Thread
AppInstaller::ThreadLocalStorage::ThreadGlobals& GetThreadGlobals();
Expand Down
33 changes: 2 additions & 31 deletions src/AppInstallerCLICore/ExecutionContextData.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,36 +53,7 @@ namespace AppInstaller::CLI::Execution
Max
};

// Contains all the information needed to install a package.
// This is used when installing multiple packages to pass all the
// data to a sub-context.
struct PackageToInstall
{
PackageToInstall(
std::shared_ptr<Repository::IPackageVersion>&& packageVersion,
std::shared_ptr<Repository::IPackageVersion>&& installedPackageVersion,
Manifest::Manifest&& manifest,
Manifest::ManifestInstaller&& installer,
Manifest::ScopeEnum scope = Manifest::ScopeEnum::Unknown,
uint32_t packageSubExecutionId = 0)
: PackageVersion(std::move(packageVersion)), InstalledPackageVersion(std::move(installedPackageVersion)), Manifest(std::move(manifest)), Installer(std::move(installer)), Scope(scope), PackageSubExecutionId(packageSubExecutionId) { }

std::shared_ptr<Repository::IPackageVersion> PackageVersion;

// Used to uninstall the old version if needed.
std::shared_ptr<Repository::IPackageVersion> InstalledPackageVersion;

// Use this instead of the PackageVersion->GetManifest() as the locale was
// applied when selecting the installer.
Manifest::Manifest Manifest;

Manifest::ManifestInstaller Installer;
Manifest::ScopeEnum Scope = Manifest::ScopeEnum::Unknown;

// Use this sub execution id when installing this package so that
// install telemetry is captured with the same sub execution id as other events in Search phase.
uint32_t PackageSubExecutionId = 0;
};
struct Context;

namespace details
{
Expand Down Expand Up @@ -203,7 +174,7 @@ namespace AppInstaller::CLI::Execution
template <>
struct DataMapping<Data::PackagesToInstall>
{
using value_t = std::vector<PackageToInstall>;
using value_t = std::vector<std::unique_ptr<Context>>;
};

template <>
Expand Down
68 changes: 54 additions & 14 deletions src/AppInstallerCLICore/Workflows/DependenciesFlow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,33 @@ using namespace AppInstaller::Manifest;

namespace AppInstaller::CLI::Workflow
{
namespace
{
// Contains all the information needed to install a dependency package.
struct DependencyPackageCandidate
{
DependencyPackageCandidate(
std::shared_ptr<Repository::IPackageVersion>&& packageVersion,
std::shared_ptr<Repository::IPackageVersion>&& installedPackageVersion,
Manifest::Manifest&& manifest,
Manifest::ManifestInstaller&& installer)
: PackageVersion(std::move(packageVersion)), InstalledPackageVersion(std::move(installedPackageVersion)), Manifest(std::move(manifest)), Installer(std::move(installer)) { }

std::shared_ptr<Repository::IPackageVersion> PackageVersion;
std::shared_ptr<Repository::IPackageVersion> InstalledPackageVersion;
Manifest::Manifest Manifest;
Manifest::ManifestInstaller Installer;
};
}

void ReportDependencies::operator()(Execution::Context& context) const
{
if (!Settings::ExperimentalFeature::IsEnabled(Settings::ExperimentalFeature::Feature::Dependencies))
{
return;
}
auto info = context.Reporter.Info();

const auto& dependencies = context.Get<Execution::Data::Dependencies>();
if (dependencies.HasAny())
{
Expand Down Expand Up @@ -114,7 +133,6 @@ namespace AppInstaller::CLI::Workflow
}
}


void ManagePackageDependencies::operator()(Execution::Context& context) const
{
if (!Settings::ExperimentalFeature::IsEnabled(Settings::ExperimentalFeature::Feature::Dependencies))
Expand All @@ -127,7 +145,7 @@ namespace AppInstaller::CLI::Workflow
const auto& rootManifest = context.Get<Execution::Data::Manifest>();

Dependency rootAsDependency = Dependency(DependencyType::Package, rootManifest.Id, rootManifest.Version);

const auto& rootInstaller = context.Get<Execution::Data::Installer>();
const auto& rootDependencies = rootInstaller->Dependencies;

Expand All @@ -146,25 +164,25 @@ namespace AppInstaller::CLI::Workflow
AICLI_TERMINATE_CONTEXT(APPINSTALLER_CLI_ERROR_INTERNAL_ERROR);
}


std::map<string_t, Execution::PackageToInstall> idToPackageMap;
std::map<string_t, DependencyPackageCandidate> idToPackageMap;
bool foundError = false;
DependencyGraph dependencyGraph(rootAsDependency, rootDependencies,
[&](Dependency node) {
[&](Dependency node)
{
DependencyNodeProcessor nodeProcessor(context);

auto result = nodeProcessor.EvaluateDependencies(node);
DependencyList list = nodeProcessor.GetDependencyList();
foundError = foundError || (result == DependencyNodeProcessorResult::Error);

if (result == DependencyNodeProcessorResult::Success)
{
Execution::PackageToInstall packageToInstall{
DependencyPackageCandidate dependencyPackageCandidate{
std::move(nodeProcessor.GetPackageLatestVersion()),
std::move(nodeProcessor.GetPackageInstalledVersion()),
std::move(nodeProcessor.GetManifest()),
std::move(nodeProcessor.GetPreferredInstaller()) };
idToPackageMap.emplace(node.Id, std::move(packageToInstall));
idToPackageMap.emplace(node.Id, std::move(dependencyPackageCandidate));
};

return list;
Expand All @@ -185,21 +203,43 @@ namespace AppInstaller::CLI::Workflow

const auto& installationOrder = dependencyGraph.GetInstallationOrder();

std::vector<Execution::PackageToInstall> installers;
std::vector<std::unique_ptr<Execution::Context>> dependencyPackageContexts;

for (auto const& node : installationOrder)
{
{
auto itr = idToPackageMap.find(node.Id);
// if the package was already installed (with a useful version) or is the root
// then there will be no installer for it on the map.
if (itr != idToPackageMap.end())
{
installers.push_back(std::move(itr->second));
auto dependencyContextPtr = context.CreateSubContext();
Execution::Context& dependencyContext = *dependencyContextPtr;
auto previousThreadGlobals = dependencyContext.GetThreadGlobals().SetForCurrentThread();

Logging::Telemetry().LogSelectedInstaller(
static_cast<int>(itr->second.Installer.Arch),
itr->second.Installer.Url,
Manifest::InstallerTypeToString(itr->second.Installer.InstallerType),
Manifest::ScopeToString(itr->second.Installer.Scope),
itr->second.Installer.Locale);

Logging::Telemetry().LogManifestFields(
itr->second.Manifest.Id,
itr->second.Manifest.DefaultLocalization.Get<Manifest::Localization::PackageName>(),
itr->second.Manifest.Version);

// Extract the data needed for installing
dependencyContext.Add<Execution::Data::PackageVersion>(itr->second.PackageVersion);
dependencyContext.Add<Execution::Data::Manifest>(itr->second.Manifest);
dependencyContext.Add<Execution::Data::InstalledPackageVersion>(itr->second.InstalledPackageVersion);
dependencyContext.Add<Execution::Data::Installer>(itr->second.Installer);

dependencyPackageContexts.emplace_back(std::move(dependencyContextPtr));
}
}

// Install dependencies in the correct order
context.Add<Execution::Data::PackagesToInstall>(installers);
context.Add<Execution::Data::PackagesToInstall>(std::move(dependencyPackageContexts));
context << Workflow::InstallMultiplePackages(m_dependencyReportMessage, APPINSTALLER_CLI_ERROR_INSTALL_DEPENDENCIES, {}, false, true);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ using namespace AppInstaller::Repository;

namespace AppInstaller::CLI::Workflow
{
DependencyNodeProcessor::DependencyNodeProcessor(Execution::Context& context)
: m_context(context) {}
DependencyNodeProcessor::DependencyNodeProcessor(Execution::Context& context)
: m_context(context) {}

DependencyNodeProcessorResult DependencyNodeProcessor::EvaluateDependencies(Dependency& dependencyNode)
{
Expand Down
46 changes: 23 additions & 23 deletions src/AppInstallerCLICore/Workflows/DependencyNodeProcessor.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,35 +11,35 @@ using namespace AppInstaller::Repository;

namespace AppInstaller::CLI::Workflow
{
enum DependencyNodeProcessorResult
{
Error,
Success,
Skipped,
};
enum DependencyNodeProcessorResult
{
Error,
Success,
Skipped,
};

struct DependencyNodeProcessor
{
DependencyNodeProcessor(Execution::Context& context);
struct DependencyNodeProcessor
{
DependencyNodeProcessor(Execution::Context& context);

DependencyNodeProcessorResult EvaluateDependencies(Dependency& dependencyNode);
DependencyNodeProcessorResult EvaluateDependencies(Dependency& dependencyNode);

DependencyList GetDependencyList() { return m_dependenciesList; }
DependencyList GetDependencyList() { return m_dependenciesList; }

std::shared_ptr<IPackageVersion> GetPackageLatestVersion() { return m_nodePackageLatestVersion; }
std::shared_ptr<IPackageVersion> GetPackageLatestVersion() { return m_nodePackageLatestVersion; }

std::shared_ptr<IPackageVersion> GetPackageInstalledVersion() { return m_nodePackageInstalledVersion; }
std::shared_ptr<IPackageVersion> GetPackageInstalledVersion() { return m_nodePackageInstalledVersion; }

Manifest::Manifest GetManifest() { return m_nodeManifest; }
Manifest::Manifest GetManifest() { return m_nodeManifest; }

Manifest::ManifestInstaller GetPreferredInstaller() { return m_installer; }
Manifest::ManifestInstaller GetPreferredInstaller() { return m_installer; }

private:
Execution::Context& m_context;
DependencyList m_dependenciesList;
std::shared_ptr<IPackageVersion> m_nodePackageLatestVersion;
std::shared_ptr<IPackageVersion> m_nodePackageInstalledVersion;
Manifest::ManifestInstaller m_installer;
Manifest::Manifest m_nodeManifest;
};
private:
Execution::Context& m_context;
DependencyList m_dependenciesList;
std::shared_ptr<IPackageVersion> m_nodePackageLatestVersion;
std::shared_ptr<IPackageVersion> m_nodePackageInstalledVersion;
Manifest::ManifestInstaller m_installer;
Manifest::Manifest m_nodeManifest;
};
}
Loading