mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-04-03 17:56:44 +02:00
[General]Add an option for telemetry opt-in and visualization(#34078)
* Data diagnostics opt-in
* [c++] Drop DROP_PII flag
* Bump telemtry package to 2.0.2
* Drop DropPii from custom actions
* Cleanup
* Do not start manually C# EtwTrace. FZ engine exit event.
* ImageResizer, PowerRename, FileLocksmith prev handlers
* Revert C# handlers exe logging
* Revert "Revert C# handlers exe logging"
This reverts commit 4c75a3953b.
* Do not recreate EtwTrace
* consume package
* xaml formatting
* Fix deps.json audit
* Update telem package paths
* Address PR comments
* Fix AdvancedPaste close on PT close
* Override etl file name for explorer loaded dlls
Start/stop tracer when needed for explorer loaded dlls to prevent explorer overload
* Fix setting desc
* Fix missing events
* Add infobar to restart when enable data viewing
* Flush on timer every 30s
* [Settings] Update View Data diagnostic description text
[New+] Add tracer
* Show Restart info bar for both enable/disable data viewer
* Fix newplus
* Fix stuck on restart and terminate AdvPaste exe on destroy()
* [Installer] Add tracer
* Address PR comment
* Add missing tracers
* Exclude etw dir from BugReport
* Fix bad merge
* [Hosts] Proper exit on initial dialog
* [OOBE] Make Data diagnostic setting visible without scroll
* [OOBE] Add hiperlynk to open general settings
* Disable data view on disabling data diagnostics
* Don't disable View data button
* Fix disabling data viewing
* Add missing dot
* Revert formatting
This commit is contained in:
107
src/common/ManagedTelemetry/Telemetry/DataDiagnosticsSettings.cs
Normal file
107
src/common/ManagedTelemetry/Telemetry/DataDiagnosticsSettings.cs
Normal file
@@ -0,0 +1,107 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using Microsoft.Win32;
|
||||
|
||||
namespace Microsoft.PowerToys.Telemetry
|
||||
{
|
||||
public static class DataDiagnosticsSettings
|
||||
{
|
||||
private static readonly string DataDiagnosticsRegistryKey = @"HKEY_CURRENT_USER\Software\Classes\PowerToys\";
|
||||
private static readonly string DataDiagnosticsRegistryValueName = @"AllowDataDiagnostics";
|
||||
private static readonly string DataDiagnosticsDataDiagnosticsUserActionRegistryValueName = @"DataDiagnosticsUserAction";
|
||||
private static readonly string DataDiagnosticsDataDiagnosticsViewDataRegistryValueName = @"DataDiagnosticsViewEnabled";
|
||||
|
||||
public static bool GetEnabledValue()
|
||||
{
|
||||
object registryValue = null;
|
||||
try
|
||||
{
|
||||
registryValue = Registry.GetValue(DataDiagnosticsRegistryKey, DataDiagnosticsRegistryValueName, 0);
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
|
||||
if (registryValue is not null)
|
||||
{
|
||||
return (int)registryValue == 1 ? true : false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void SetEnabledValue(bool value)
|
||||
{
|
||||
try
|
||||
{
|
||||
Registry.SetValue(DataDiagnosticsRegistryKey, DataDiagnosticsRegistryValueName, value ? 1 : 0);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public static bool GetUserActionValue()
|
||||
{
|
||||
object registryValue = null;
|
||||
try
|
||||
{
|
||||
registryValue = Registry.GetValue(DataDiagnosticsRegistryKey, DataDiagnosticsDataDiagnosticsUserActionRegistryValueName, 0);
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
|
||||
if (registryValue is not null)
|
||||
{
|
||||
return (int)registryValue == 1 ? true : false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void SetUserActionValue(bool value)
|
||||
{
|
||||
try
|
||||
{
|
||||
Registry.SetValue(DataDiagnosticsRegistryKey, DataDiagnosticsDataDiagnosticsUserActionRegistryValueName, value ? 1 : 0);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public static bool GetViewEnabledValue()
|
||||
{
|
||||
object registryValue = null;
|
||||
try
|
||||
{
|
||||
registryValue = Registry.GetValue(DataDiagnosticsRegistryKey, DataDiagnosticsDataDiagnosticsViewDataRegistryValueName, 0);
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
|
||||
if (registryValue is not null)
|
||||
{
|
||||
return (int)registryValue == 1 ? true : false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void SetViewEnabledValue(bool value)
|
||||
{
|
||||
try
|
||||
{
|
||||
Registry.SetValue(DataDiagnosticsRegistryKey, DataDiagnosticsDataDiagnosticsViewDataRegistryValueName, value ? 1 : 0);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
158
src/common/ManagedTelemetry/Telemetry/EtwTrace.cs
Normal file
158
src/common/ManagedTelemetry/Telemetry/EtwTrace.cs
Normal file
@@ -0,0 +1,158 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Diagnostics.Tracing;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Diagnostics.Tracing.Session;
|
||||
|
||||
namespace Microsoft.PowerToys.Telemetry
|
||||
{
|
||||
/// <summary>
|
||||
/// This class is based loosely on the C++ ETWTrace class in Win32client/Framework project.
|
||||
/// It is intended to record telemetry events generated by the PowerToys processes so that end users
|
||||
/// can view them if they want.
|
||||
/// </summary>
|
||||
public class ETWTrace : IDisposable
|
||||
{
|
||||
internal const EventKeywords TelemetryKeyword = (EventKeywords)0x0000200000000000;
|
||||
internal const EventKeywords MeasuresKeyword = (EventKeywords)0x0000400000000000;
|
||||
internal const EventKeywords CriticalDataKeyword = (EventKeywords)0x0000800000000000;
|
||||
|
||||
private readonly bool telemetryEnabled = DataDiagnosticsSettings.GetEnabledValue(); // This is the global telemetry setting on whether to log events
|
||||
private readonly bool telemetryRecordingEnabled = DataDiagnosticsSettings.GetViewEnabledValue(); // This is the setting for recording telemetry events to disk for viewing
|
||||
private readonly string etwFolderPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), @"Microsoft\PowerToys\", "etw");
|
||||
private bool disposedValue;
|
||||
private string sessionName;
|
||||
private string etwFilePath;
|
||||
private bool started;
|
||||
#nullable enable
|
||||
private TraceEventSession? traceSession;
|
||||
|
||||
internal sealed class Lister : EventListener
|
||||
{
|
||||
public Lister()
|
||||
: base()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
private Lister? listener;
|
||||
#nullable disable
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ETWTrace"/> class.
|
||||
/// </summary>
|
||||
public ETWTrace()
|
||||
{
|
||||
if (File.Exists(etwFolderPath))
|
||||
{
|
||||
File.Delete(etwFolderPath);
|
||||
}
|
||||
|
||||
if (!Directory.Exists(etwFolderPath))
|
||||
{
|
||||
Directory.CreateDirectory(etwFolderPath);
|
||||
}
|
||||
|
||||
if (this.telemetryEnabled && this.telemetryRecordingEnabled)
|
||||
{
|
||||
this.Start();
|
||||
}
|
||||
|
||||
listener = new Lister();
|
||||
listener.EnableEvents(PowerToysTelemetry.Log, EventLevel.LogAlways);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Dispose()
|
||||
{
|
||||
// Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
|
||||
this.Dispose(disposing: true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Starts the trace session.
|
||||
/// </summary>
|
||||
public void Start()
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
if (this.started)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
new Task(() =>
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
Thread.Sleep(30 * 1000);
|
||||
|
||||
this.traceSession.Flush();
|
||||
}
|
||||
}).Start();
|
||||
|
||||
string executable = Process.GetCurrentProcess().ProcessName;
|
||||
string dateTimeNow = DateTime.Now.ToString("MM-d-yyyy__H_mm_ss", CultureInfo.InvariantCulture);
|
||||
this.sessionName = string.Format(CultureInfo.InvariantCulture, "{0}-{1}-{2}", executable, Environment.ProcessId, dateTimeNow);
|
||||
this.etwFilePath = Path.Combine(etwFolderPath, $"{this.sessionName}.etl");
|
||||
|
||||
this.traceSession = new TraceEventSession(
|
||||
this.sessionName, this.etwFilePath, (TraceEventSessionOptions)(TraceEventSessionOptions.Create | TraceEventSessionOptions.PrivateLogger | TraceEventSessionOptions.PrivateInProcLogger));
|
||||
TraceEventProviderOptions args = new TraceEventProviderOptions();
|
||||
|
||||
this.traceSession.EnableProvider(
|
||||
PowerToysTelemetry.Log.Guid,
|
||||
matchAnyKeywords: (ulong)TelemetryKeyword | (ulong)MeasuresKeyword | (ulong)CriticalDataKeyword);
|
||||
|
||||
this.started = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stops the trace session.
|
||||
/// </summary>
|
||||
public void Stop()
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
if (!this.started)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.traceSession != null)
|
||||
{
|
||||
Trace.TraceInformation("Disposing EventTraceSession");
|
||||
this.traceSession.Dispose();
|
||||
this.traceSession = null;
|
||||
this.started = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Disposes the object.
|
||||
/// </summary>
|
||||
/// <param name="disposing">boolean for disposing.</param>
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (!this.disposedValue)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
this.Stop();
|
||||
}
|
||||
|
||||
this.disposedValue = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<!-- Look at Directory.Build.props in root for common stuff as well -->
|
||||
<Import Project="..\..\..\Common.Dotnet.CsWinRT.props" />
|
||||
|
||||
|
||||
<PropertyGroup>
|
||||
<Description>PowerToys Telemetry</Description>
|
||||
<AssemblyName>PowerToys.ManagedTelemetry</AssemblyName>
|
||||
@@ -11,4 +11,8 @@
|
||||
<Compile Include="..\..\Telemetry\TelemetryBase.cs" Link="TelemetryBase.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.Logging" />
|
||||
<PackageReference Include="Microsoft.Diagnostics.Tracing.TraceEvent" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
||||
@@ -37,14 +37,17 @@ namespace Microsoft.PowerToys.Telemetry
|
||||
public void WriteEvent<T>(T telemetryEvent)
|
||||
where T : EventBase, IEvent
|
||||
{
|
||||
this.Write<T>(
|
||||
telemetryEvent.EventName,
|
||||
new EventSourceOptions()
|
||||
{
|
||||
Keywords = ProjectKeywordMeasure,
|
||||
Tags = ProjectTelemetryTagProductAndServicePerformance,
|
||||
},
|
||||
telemetryEvent);
|
||||
if (DataDiagnosticsSettings.GetEnabledValue())
|
||||
{
|
||||
this.Write<T>(
|
||||
telemetryEvent.EventName,
|
||||
new EventSourceOptions()
|
||||
{
|
||||
Keywords = ProjectKeywordMeasure,
|
||||
Tags = ProjectTelemetryTagProductAndServicePerformance,
|
||||
},
|
||||
telemetryEvent);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user