diff --git a/src/CodingWithCalvin.SuperClean/CodingWithCalvin.SuperClean.csproj b/src/CodingWithCalvin.SuperClean/CodingWithCalvin.SuperClean.csproj index 322ec51..a19c06d 100644 --- a/src/CodingWithCalvin.SuperClean/CodingWithCalvin.SuperClean.csproj +++ b/src/CodingWithCalvin.SuperClean/CodingWithCalvin.SuperClean.csproj @@ -8,11 +8,8 @@ bin/$(Configuration)/ - - True - - + diff --git a/src/CodingWithCalvin.SuperClean/Commands/SuperCleanCommand.cs b/src/CodingWithCalvin.SuperClean/Commands/SuperCleanCommand.cs index 90f9081..9834d79 100644 --- a/src/CodingWithCalvin.SuperClean/Commands/SuperCleanCommand.cs +++ b/src/CodingWithCalvin.SuperClean/Commands/SuperCleanCommand.cs @@ -1,8 +1,10 @@ -using System; +using System; +using System.Collections.Generic; using System.ComponentModel.Design; using System.IO; using System.Text; using System.Threading.Tasks; +using CodingWithCalvin.Otel4Vsix; using Community.VisualStudio.Toolkit; using Microsoft.VisualStudio.Shell; using MessageBox = System.Windows.Forms.MessageBox; @@ -42,12 +44,20 @@ public static void Initialize(Package package) private static void OpenPathWrapper(object sender, EventArgs e) { + using var activity = VsixTelemetry.StartCommandActivity("SuperClean.OpenPathWrapper"); + try { _ = OpenPathAsync(sender, e); } catch (Exception ex) { + activity?.RecordError(ex); + VsixTelemetry.TrackException(ex, new Dictionary + { + { "operation.name", "OpenPathWrapper" } + }); + MessageBox.Show( $@" Fatal Error! Unable to invoke Super Clean! @@ -60,14 +70,18 @@ Fatal Error! Unable to invoke Super Clean! private static async Task OpenPathAsync(object sender, EventArgs e) { + using var activity = VsixTelemetry.StartCommandActivity("SuperClean.OpenPathAsync"); + var activeItem = await VS.Solutions.GetActiveItemAsync(); if (activeItem == null) { + VsixTelemetry.LogInformation("No active item found"); return; } - switch (activeItem.Type) + activity?.SetTag("item.type", activeItem.Type.ToString()); + switch (activeItem.Type) { case SolutionItemType.Solution: try @@ -78,9 +92,17 @@ private static async Task OpenPathAsync(object sender, EventArgs e) { throw new ApplicationException(errors); } + + VsixTelemetry.LogInformation("Solution super cleaned successfully"); } catch (Exception ex) { + activity?.RecordError(ex); + VsixTelemetry.TrackException(ex, new Dictionary + { + { "operation.name", "SuperCleanSolution" } + }); + MessageBox.Show( $@" Unable to Super Clean solution @@ -95,9 +117,16 @@ Unable to Super Clean solution try { SuperCleanProject(activeItem); + VsixTelemetry.LogInformation("Project super cleaned successfully"); } catch (Exception ex) { + activity?.RecordError(ex); + VsixTelemetry.TrackException(ex, new Dictionary + { + { "operation.name", "SuperCleanProject" }, + }); + MessageBox.Show( $@" Unable to Super Clean project ${activeItem.Name} @@ -112,28 +141,38 @@ Unable to Super Clean project ${activeItem.Name} async Task<(bool, string)> SuperCleanSolution() { + using var solutionActivity = VsixTelemetry.StartCommandActivity("SuperClean.SuperCleanSolution"); + var success = true; var errors = new StringBuilder(); + var projectCount = 0; foreach (var project in await VS.Solutions.GetAllProjectsAsync()) { try { SuperCleanProject(project); + projectCount++; } catch (Exception ex) { errors.AppendLine(ex.Message); success = false; + solutionActivity?.RecordError(ex); } } + solutionActivity?.SetTag("projects.cleaned", projectCount); + solutionActivity?.SetTag("success", success); + return (success, errors.ToString()); } void SuperCleanProject(SolutionItem project) { - var projectPath = + using var projectActivity = VsixTelemetry.StartCommandActivity("SuperClean.SuperCleanProject"); + + var projectPath = Path.GetDirectoryName(project.FullPath) ?? throw new InvalidOperationException(); @@ -143,11 +182,13 @@ void SuperCleanProject(SolutionItem project) if (Directory.Exists(binPath)) { Directory.Delete(binPath, true); + projectActivity?.SetTag("bin.deleted", true); } if (Directory.Exists(objPath)) { Directory.Delete(objPath, true); + projectActivity?.SetTag("obj.deleted", true); } } } diff --git a/src/CodingWithCalvin.SuperClean/HoneycombConfig.cs b/src/CodingWithCalvin.SuperClean/HoneycombConfig.cs new file mode 100644 index 0000000..99eb0fb --- /dev/null +++ b/src/CodingWithCalvin.SuperClean/HoneycombConfig.cs @@ -0,0 +1,7 @@ +namespace CodingWithCalvin.SuperClean +{ + internal static class HoneycombConfig + { + public const string ApiKey = "PLACEHOLDER"; + } +} diff --git a/src/CodingWithCalvin.SuperClean/SuperCleanPackage.cs b/src/CodingWithCalvin.SuperClean/SuperCleanPackage.cs index a064cea..2328fe2 100644 --- a/src/CodingWithCalvin.SuperClean/SuperCleanPackage.cs +++ b/src/CodingWithCalvin.SuperClean/SuperCleanPackage.cs @@ -1,6 +1,7 @@ -using System; +using System; using System.Runtime.InteropServices; using System.Threading; +using CodingWithCalvin.Otel4Vsix; using CodingWithCalvin.SuperClean.Commands; using Microsoft.VisualStudio.Shell; using Task = System.Threading.Tasks.Task; @@ -20,7 +21,31 @@ IProgress progress { await JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken); + var builder = VsixTelemetry.Configure() + .WithServiceName(VsixInfo.DisplayName) + .WithServiceVersion(VsixInfo.Version) + .WithVisualStudioAttributes(this) + .WithEnvironmentAttributes(); + +#if !DEBUG + builder + .WithOtlpHttp("https://api.honeycomb.io") + .WithHeader("x-honeycomb-team", HoneycombConfig.ApiKey); +#endif + + builder.Initialize(); + SuperCleanCommand.Initialize(this); } + + protected override void Dispose(bool disposing) + { + if (disposing) + { + VsixTelemetry.Shutdown(); + } + + base.Dispose(disposing); + } } }