Skip to content

Commit

Permalink
Telemetry reporting improvements (#617)
Browse files Browse the repository at this point in the history
  • Loading branch information
yao-msft committed Oct 21, 2020
1 parent 959aacb commit 7ee6784
Show file tree
Hide file tree
Showing 10 changed files with 167 additions and 7 deletions.
4 changes: 4 additions & 0 deletions src/AppInstallerCLICore/Commands/InstallCommand.cpp
Expand Up @@ -97,13 +97,17 @@ namespace AppInstaller::CLI
void InstallCommand::ExecuteInternal(Execution::Context& context) const
{
context <<
Workflow::ReportExecutionStage(ExecutionStage::Discovery) <<
Workflow::GetManifest <<
Workflow::EnsureMinOSVersion <<
Workflow::SelectInstaller <<
Workflow::EnsureApplicableInstaller <<
Workflow::ShowInstallationDisclaimer <<
Workflow::ReportExecutionStage(ExecutionStage::Download) <<
Workflow::DownloadInstaller <<
Workflow::ReportExecutionStage(ExecutionStage::Execution) <<
Workflow::ExecuteInstaller <<
Workflow::ReportExecutionStage(ExecutionStage::PostExecution) <<
Workflow::RemoveInstaller;
}
}
7 changes: 7 additions & 0 deletions src/AppInstallerCLICore/Commands/UpgradeCommand.cpp
Expand Up @@ -116,6 +116,7 @@ namespace AppInstaller::CLI
WI_SetFlag(context.GetFlags(), Execution::ContextFlag::InstallerExecutionUseUpdate);

context <<
Workflow::ReportExecutionStage(ExecutionStage::Discovery) <<
OpenSource <<
OpenCompositeSource(Repository::PredefinedSource::Installed);

Expand Down Expand Up @@ -149,8 +150,11 @@ namespace AppInstaller::CLI
SelectInstaller <<
EnsureApplicableInstaller <<
ShowInstallationDisclaimer <<
Workflow::ReportExecutionStage(ExecutionStage::Download) <<
DownloadInstaller <<
Workflow::ReportExecutionStage(ExecutionStage::Execution) <<
ExecuteInstaller <<
Workflow::ReportExecutionStage(ExecutionStage::PostExecution) <<
RemoveInstaller;
}
else
Expand Down Expand Up @@ -182,8 +186,11 @@ namespace AppInstaller::CLI

context <<
ShowInstallationDisclaimer <<
Workflow::ReportExecutionStage(ExecutionStage::Download) <<
DownloadInstaller <<
Workflow::ReportExecutionStage(ExecutionStage::Execution) <<
ExecuteInstaller <<
Workflow::ReportExecutionStage(ExecutionStage::PostExecution) <<
RemoveInstaller;
}
}
Expand Down
3 changes: 3 additions & 0 deletions src/AppInstallerCLICore/Core.cpp
Expand Up @@ -4,6 +4,7 @@
#include "Public/AppInstallerCLICore.h"
#include "Commands/RootCommand.h"
#include "ExecutionContext.h"
#include "Workflows/WorkflowBase.h"
#include <winget/UserSettings.h>

using namespace winrt;
Expand Down Expand Up @@ -61,6 +62,8 @@ namespace AppInstaller::CLI
Execution::Context context{ std::cout, std::cin };
context.EnableCtrlHandler();

context << Workflow::ReportExecutionStage(Workflow::ExecutionStage::ParseArgs);

// Convert incoming wide char args to UTF8
std::vector<std::string> utf8Args;
for (int i = 1; i < argc; ++i)
Expand Down
13 changes: 13 additions & 0 deletions src/AppInstallerCLICore/ExecutionContext.h
Expand Up @@ -33,6 +33,7 @@
namespace AppInstaller::CLI::Workflow
{
struct WorkflowTask;
enum class ExecutionStage : uint32_t;
}

namespace AppInstaller::CLI::Execution
Expand All @@ -53,6 +54,7 @@ namespace AppInstaller::CLI::Execution
InstallerArgs,
CompletionData,
InstalledPackageVersion,
ExecutionStage,
Max
};

Expand Down Expand Up @@ -139,6 +141,12 @@ namespace AppInstaller::CLI::Execution
using value_t = std::shared_ptr<Repository::IPackageVersion>;
};

template <>
struct DataMapping<Data::ExecutionStage>
{
using value_t = Workflow::ExecutionStage;
};

// Used to deduce the DataVariant type; making a variant that includes std::monostate and all DataMapping types.
template <size_t... I>
inline auto Deduce(std::index_sequence<I...>) { return std::variant<std::monostate, DataMapping<static_cast<Data>(I)>::value_t...>{}; }
Expand Down Expand Up @@ -194,6 +202,11 @@ namespace AppInstaller::CLI::Execution
{
m_data[D].emplace<details::DataIndex(D)>(std::forward<typename details::DataMapping<D>::value_t>(v));
}
template <Data D>
void Add(const typename details::DataMapping<D>::value_t& v)
{
m_data[D].emplace<details::DataIndex(D)>(v);
}

// Return a value indicating whether the given data type is stored in the context.
bool Contains(Data d) { return (m_data.find(d) != m_data.end()); }
Expand Down
6 changes: 6 additions & 0 deletions src/AppInstallerCLICore/Workflows/UpdateFlow.cpp
Expand Up @@ -105,6 +105,8 @@ namespace AppInstaller::CLI::Workflow
bool updateAllHasFailure = false;
for (const auto& match : matches)
{
Logging::SubExecutionTelemetryScope subExecution;

// We want to do best effort to update all applicable updates regardless on previous update failure
auto updateContextPtr = context.Clone();
Execution::Context& updateContext = *updateContextPtr;
Expand All @@ -113,10 +115,14 @@ namespace AppInstaller::CLI::Workflow
updateContext.Add<Execution::Data::InstalledPackageVersion>(match.Package->GetInstalledVersion());

updateContext <<
Workflow::ReportExecutionStage(ExecutionStage::Discovery) <<
SelectLatestApplicableUpdate(*(match.Package)) <<
ShowInstallationDisclaimer <<
Workflow::ReportExecutionStage(ExecutionStage::Download) <<
DownloadInstaller <<
Workflow::ReportExecutionStage(ExecutionStage::Execution) <<
ExecuteInstaller <<
Workflow::ReportExecutionStage(ExecutionStage::PostExecution) <<
RemoveInstaller;

if (updateContext.GetTerminationHR() != S_OK &&
Expand Down
28 changes: 26 additions & 2 deletions src/AppInstallerCLICore/Workflows/WorkflowBase.cpp
Expand Up @@ -458,7 +458,7 @@ namespace AppInstaller::CLI::Workflow
AICLI_TERMINATE_CONTEXT(APPINSTALLER_CLI_ERROR_NO_MANIFEST_FOUND);
}

Logging::Telemetry().LogManifestFields(manifest->Id, manifest->Name, manifest->Version, false);
Logging::Telemetry().LogManifestFields(manifest->Id, manifest->Name, manifest->Version);
context.Add<Execution::Data::Manifest>(std::move(manifest.value()));
}

Expand All @@ -481,12 +481,14 @@ namespace AppInstaller::CLI::Workflow

void GetManifestFromArg(Execution::Context& context)
{
Logging::Telemetry().LogIsManifestLocal(true);

context <<
VerifyFile(Execution::Args::Type::Manifest) <<
[](Execution::Context& context)
{
Manifest::Manifest manifest = Manifest::YamlParser::CreateFromPath(Utility::ConvertToUTF16(context.Args.GetArg(Execution::Args::Type::Manifest)));
Logging::Telemetry().LogManifestFields(manifest.Id, manifest.Name, manifest.Version, true);
Logging::Telemetry().LogManifestFields(manifest.Id, manifest.Name, manifest.Version);
context.Add<Execution::Data::Manifest>(std::move(manifest));
};
}
Expand Down Expand Up @@ -600,6 +602,28 @@ namespace AppInstaller::CLI::Workflow
const auto& searchResult = context.Get<Execution::Data::SearchResult>();
context.Add<Execution::Data::InstalledPackageVersion>(searchResult.Matches.at(0).Package->GetInstalledVersion());
}

void ReportExecutionStage::operator()(Execution::Context& context) const
{
if (!context.Contains(Execution::Data::ExecutionStage))
{
context.Add<Execution::Data::ExecutionStage>(m_stage);
}
else if (context.Get<Execution::Data::ExecutionStage>() == m_stage)
{
return;
}
else if (context.Get<Execution::Data::ExecutionStage>() < m_stage || m_allowBackward)
{
context.Get<Execution::Data::ExecutionStage>() = m_stage;
}
else
{
THROW_HR_MSG(HRESULT_FROM_WIN32(ERROR_INVALID_STATE), "Reporting ExecutionStage to an earlier Stage without allowBackward as true");
}

Logging::SetExecutionStage(static_cast<uint32_t>(context.Get<Execution::Data::ExecutionStage>()));
}
}

AppInstaller::CLI::Execution::Context& operator<<(AppInstaller::CLI::Execution::Context& context, AppInstaller::CLI::Workflow::WorkflowTask::Func f)
Expand Down
25 changes: 25 additions & 0 deletions src/AppInstallerCLICore/Workflows/WorkflowBase.h
Expand Up @@ -18,6 +18,16 @@ namespace AppInstaller::CLI::Workflow
{
static const char* s_InstallationMetadata_Key_InstallerType = "InstallerType";

// Values are ordered in a typical workflow stages
enum class ExecutionStage : uint32_t
{
ParseArgs = 1000,
Discovery = 2000,
Download = 3000,
Execution = 4000,
PostExecution = 5000,
};

// A task in the workflow.
struct WorkflowTask
{
Expand Down Expand Up @@ -233,6 +243,21 @@ namespace AppInstaller::CLI::Workflow
// Inputs: SearchResult
// Outputs: InstalledPackageVersion
void GetInstalledPackageVersion(Execution::Context& context);

// Reports execution stage in a workflow
// Required Args: ExecutionStage
// Inputs: ExecutionStage?
// Outputs: ExecutionStage
struct ReportExecutionStage : public WorkflowTask
{
ReportExecutionStage(ExecutionStage stage, bool allowBackward = false) : WorkflowTask("ReportExecutionStage"), m_stage(stage), m_allowBackward(allowBackward) {}

void operator()(Execution::Context& context) const override;

private:
ExecutionStage m_stage;
bool m_allowBackward;
};
}

// Passes the context to the function if it has not been terminated; returns the context.
Expand Down

0 comments on commit 7ee6784

Please sign in to comment.