Skip to content

Commit

Permalink
Add Telemetry Opt-Out and Settings Command (#94)
Browse files Browse the repository at this point in the history
* Add settings command and TelemetryEventListener

* setup settings command

* Refactor UserSettings class

* add welcome message

* finish settings command

* add settings command documentation

* add unit tests for settings command

* clean up

* Fix telemetry disable logic

* make eventsourcename accessible

* fix bugs and modify schema to add schema header

* address PR comments

Co-authored-by: Ryan Fu <[email protected]>
  • Loading branch information
ryfu-msft and Ryan Fu authored Jun 28, 2021
1 parent e17fba2 commit cd54329
Show file tree
Hide file tree
Showing 14 changed files with 619 additions and 11 deletions.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ The **Windows Package Manager Manifest Creator** is available for download from
| [Update](doc/update.md) | Command for updating an existing manifest |
| [Submit](doc/submit.md) | Command for submitting an existing PR |
| [Token](doc/token.md) | Command for managing cached GitHub personal access tokens |
| [Settings](doc/settings.md) | Command for editing the settings file configurations |
| [-?](doc/help.md) | Displays command line help |

Click on the individual commands to learn more.
Expand Down Expand Up @@ -110,6 +111,8 @@ The wingetcreate.exe client respects machine wide privacy settings and users can

In short to opt-out, go to `Start`, then select `Settings` > `Privacy` > `Diagnostics & feedback`, and select `Basic`.

You can also opt-out of telemetry by configuring the `settings.json` file and setting the `telemetry.disabled` field to true. More information can be found in our [Settings Command documentation](/doc/settings.md)

See the [privacy statement](/PRIVACY.md) for more details.

## Known Issues
20 changes: 20 additions & 0 deletions doc/settings.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@

# Winget-Create CLI Settings

You can configure Winget-Create by editing the `settings.json` file. Running `wingetcreate settings` will open the file in the default json editor; if no editor is configured, Windows will prompt for you to select an editor, and Notepad is sensible option if you have no other preference.

## Telemetry

The `telemetry` settings control whether Winget-Create writes ETW events that may be sent to Microsoft on a default installation of Windows.

See [details on telemetry](https://github.com/microsoft/winget-create#datatelemetry), and our [primary privacy statement](../PRIVACY.md).

### disable

```json
"telemetry": {
"disable": true
},
```

If set to true, the `telemetry.disable` setting will prevent any event from being written by the program.
105 changes: 105 additions & 0 deletions src/WingetCreateCLI/Commands/SettingsCommand.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license.

namespace Microsoft.WingetCreateCLI.Commands
{
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Threading.Tasks;
using CommandLine;
using Microsoft.WingetCreateCLI.Logging;
using Microsoft.WingetCreateCLI.Models.Settings;
using Microsoft.WingetCreateCLI.Properties;
using Microsoft.WingetCreateCLI.Telemetry;
using Microsoft.WingetCreateCLI.Telemetry.Events;

/// <summary>
/// Command to either update or delete the cached GitHub Oauth token.
/// </summary>
[Verb("settings", HelpText = "SettingsCommand_HelpText", ResourceType = typeof(Resources))]
public class SettingsCommand : BaseCommand
{
/// <summary>
/// Executes the token command flow.
/// </summary>
/// <returns>Boolean representing success or fail of the command.</returns>
public override Task<bool> Execute()
{
CommandExecutedEvent commandEvent = new CommandExecutedEvent
{
Command = nameof(SettingsCommand),
};

try
{
if (!File.Exists(UserSettings.SettingsJsonPath))
{
Logger.WarnLocalized(nameof(Resources.GenerateNewSettingsFile_Message));
UserSettings.SaveSettings();
}
else
{
(bool isSettingsValid, List<string> settingsFileErrors) = UserSettings.ParseJsonFile(UserSettings.SettingsJsonPath, out SettingsManifest manifest);

if (isSettingsValid)
{
File.Copy(UserSettings.SettingsJsonPath, UserSettings.SettingsBackupJsonPath, true);
}
else
{
this.DisplayParsingErrors(settingsFileErrors, UserSettings.SettingsJsonPath);
}
}

if (File.Exists(UserSettings.SettingsBackupJsonPath))
{
(bool isBackupValid, List<string> backupFileErrors) = UserSettings.ParseJsonFile(UserSettings.SettingsBackupJsonPath, out SettingsManifest manifest);

if (!isBackupValid)
{
this.DisplayParsingErrors(backupFileErrors, UserSettings.SettingsBackupJsonPath);
}
}

return Task.FromResult(commandEvent.IsSuccessful = this.OpenJsonFile(UserSettings.SettingsJsonPath));
}
finally
{
TelemetryManager.Log.WriteEvent(commandEvent);
}
}

private void DisplayParsingErrors(List<string> errors, string path)
{
Logger.WarnLocalized(nameof(Resources.ErrorParsingSettingsFile_Message), Path.GetFileName(path));

Console.WriteLine();
foreach (string e in errors)
{
Logger.Warn(e);
}
}

private bool OpenJsonFile(string path)
{
if (!File.Exists(path))
{
return false;
}

try
{
Process.Start(new ProcessStartInfo { UseShellExecute = true, FileName = path });
return true;
}
catch (Win32Exception e)
{
Logger.ErrorLocalized(nameof(Resources.Error_Prefix), e.Message);
return false;
}
}
}
}
34 changes: 34 additions & 0 deletions src/WingetCreateCLI/Models/SettingsModel.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
//----------------------
// <auto-generated>
// Generated using the NJsonSchema v10.4.3.0 (Newtonsoft.Json v11.0.0.0) (http://NJsonSchema.org)
// </auto-generated>
//----------------------

namespace Microsoft.WingetCreateCLI.Models.Settings
{
#pragma warning disable // Disable all warnings

/// <summary>Telemetry settings</summary>
[System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "10.4.3.0 (Newtonsoft.Json v11.0.0.0)")]
public partial class Telemetry
{
/// <summary>Controls whether telemetry events are written</summary>
[Newtonsoft.Json.JsonProperty("disable", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)]
public bool Disable { get; set; } = false;


}

[System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "10.4.3.0 (Newtonsoft.Json v11.0.0.0)")]
public partial class SettingsManifest
{
/// <summary>The settings json schema</summary>
[Newtonsoft.Json.JsonProperty("$schema", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)]
public string Schema { get; set; } = "https://aka.ms/wingetcreate-settings.schema.json";

[Newtonsoft.Json.JsonProperty("telemetry", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)]
public Telemetry Telemetry { get; set; }


}
}
18 changes: 10 additions & 8 deletions src/WingetCreateCLI/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,16 @@
namespace Microsoft.WingetCreateCLI
{
using System;
using System.Collections.Generic;
using System.Collections.Generic;
using System.Threading.Tasks;
using CommandLine;
using CommandLine.Text;
using CommandLine.Text;
using Microsoft.WingetCreateCLI.Commands;
using Microsoft.WingetCreateCLI.Logging;
using Microsoft.WingetCreateCLI.Properties;
using Microsoft.WingetCreateCLI.Telemetry;
using Microsoft.WingetCreateCLI.Telemetry.Events;
using Microsoft.WingetCreateCore.Common;
using Microsoft.WingetCreateCore.Common;

/// <summary>
/// Main entry class for the CLI.
Expand All @@ -23,18 +23,20 @@ internal class Program
/// <summary>
/// Program name of the app.
/// </summary>
private const string ProgramName = "wingetcreate";

private const string ProgramName = "wingetcreate";

private static async Task<int> Main(string[] args)
{
Logger.Initialize();
{
Logger.Initialize();
UserSettings.FirstRunTelemetryConsent();
TelemetryEventListener.EventListener.IsTelemetryEnabled();

string arguments = string.Join(' ', Environment.GetCommandLineArgs());
Logger.Trace($"Command line args: {arguments}");

Parser myParser = new Parser(config => config.HelpWriter = null);

var parserResult = myParser.ParseArguments<NewCommand, UpdateCommand, SubmitCommand, TokenCommand>(args);
var parserResult = myParser.ParseArguments<NewCommand, UpdateCommand, SubmitCommand, TokenCommand, SettingsCommand>(args);
BaseCommand command = parserResult.MapResult(c => c as BaseCommand, err => null);
if (command == null)
{
Expand Down
90 changes: 90 additions & 0 deletions src/WingetCreateCLI/Properties/Resources.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit cd54329

Please sign in to comment.