Skip to content

Commit 9717a32

Browse files
authored
feat(telemetry): add Otel4Vsix integration (#60)
* feat(telemetry): add Otel4Vsix integration - Add CodingWithCalvin.Otel4Vsix package reference - Configure telemetry in GitRangerPackage with Honeycomb export - Add HoneycombConfig.cs for API key placeholder - Instrument blame commands with activities and logging - Instrument BlameService with activities and cache tracking - Add proper telemetry shutdown in Dispose - Remove explicit DeployExtension (VsixSdk handles this) * fix(telemetry): remove sensitive data from telemetry Remove file paths from telemetry tags and logs to avoid sending potentially sensitive information.
1 parent 4a4431a commit 9717a32

5 files changed

Lines changed: 79 additions & 18 deletions

File tree

src/CodingWithCalvin.GitRanger/CodingWithCalvin.GitRanger.csproj

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,8 @@
99
<OutputPath>bin/$(Configuration)/</OutputPath>
1010
</PropertyGroup>
1111

12-
<PropertyGroup Condition="'$(Configuration)' == 'Debug'">
13-
<DeployExtension>True</DeployExtension>
14-
</PropertyGroup>
15-
1612
<ItemGroup>
13+
<PackageReference Include="CodingWithCalvin.Otel4Vsix" Version="0.2.2" />
1714
<PackageReference Include="Community.VisualStudio.Toolkit.17" Version="17.0.507" />
1815
<PackageReference Include="Microsoft.VisualStudio.SDK" Version="17.14.40265" ExcludeAssets="runtime" />
1916
<PackageReference Include="LibGit2Sharp" Version="0.30.0" />

src/CodingWithCalvin.GitRanger/Commands/BlameCommands.cs

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
using System;
2+
using System.Collections.Generic;
23
using System.ComponentModel.Design;
34
using System.Threading.Tasks;
45
using CodingWithCalvin.GitRanger.Options;
6+
using CodingWithCalvin.Otel4Vsix;
57
using Community.VisualStudio.Toolkit;
68
using Microsoft.VisualStudio.Shell;
79
using Task = System.Threading.Tasks.Task;
@@ -60,13 +62,17 @@ private static void OnToggleInlineBlame(object sender, EventArgs e)
6062
{
6163
ThreadHelper.ThrowIfNotOnUIThread();
6264

65+
using var activity = VsixTelemetry.StartCommandActivity("GitRanger.ToggleInlineBlame");
66+
6367
var options = GeneralOptions.Instance;
6468
if (options != null)
6569
{
6670
options.EnableInlineBlame = !options.EnableInlineBlame;
6771
options.Save();
6872

6973
var status = options.EnableInlineBlame ? "enabled" : "disabled";
74+
activity?.SetTag("inline_blame.enabled", options.EnableInlineBlame);
75+
VsixTelemetry.LogInformation("Inline blame {Status}", status);
7076
VS.StatusBar.ShowMessageAsync($"Git Ranger: Inline blame {status}").FireAndForget();
7177
}
7278
}
@@ -91,13 +97,17 @@ private static void OnToggleBlameGutter(object sender, EventArgs e)
9197
{
9298
ThreadHelper.ThrowIfNotOnUIThread();
9399

100+
using var activity = VsixTelemetry.StartCommandActivity("GitRanger.ToggleBlameGutter");
101+
94102
var options = GeneralOptions.Instance;
95103
if (options != null)
96104
{
97105
options.EnableBlameGutter = !options.EnableBlameGutter;
98106
options.Save();
99107

100108
var status = options.EnableBlameGutter ? "enabled" : "disabled";
109+
activity?.SetTag("blame_gutter.enabled", options.EnableBlameGutter);
110+
VsixTelemetry.LogInformation("Blame gutter {Status}", status);
101111
VS.StatusBar.ShowMessageAsync($"Git Ranger: Blame gutter {status}").FireAndForget();
102112
}
103113
}
@@ -119,6 +129,8 @@ private static async void OnCopyCommitSha(object sender, EventArgs e)
119129
{
120130
await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();
121131

132+
using var activity = VsixTelemetry.StartCommandActivity("GitRanger.CopyCommitSha");
133+
122134
try
123135
{
124136
var docView = await VS.Documents.GetActiveDocumentViewAsync();
@@ -129,24 +141,34 @@ private static async void OnCopyCommitSha(object sender, EventArgs e)
129141
if (string.IsNullOrEmpty(filePath))
130142
return;
131143

132-
// Get the current line
144+
// Get the current line
133145
var caretPosition = docView.TextView.Caret.Position.BufferPosition;
134146
var lineNumber = docView.TextView.TextSnapshot.GetLineNumberFromPosition(caretPosition.Position) + 1;
135147

148+
activity?.SetTag("line.number", lineNumber);
149+
136150
// Get blame for this line
137151
var blameInfo = GitRangerPackage.BlameService?.GetBlameForLine(filePath, lineNumber);
138152
if (blameInfo != null)
139153
{
140154
System.Windows.Clipboard.SetText(blameInfo.CommitSha);
155+
activity?.SetTag("commit.sha", blameInfo.ShortSha);
156+
VsixTelemetry.LogInformation("Copied commit SHA {CommitSha} to clipboard", blameInfo.ShortSha);
141157
await VS.StatusBar.ShowMessageAsync($"Git Ranger: Copied commit SHA {blameInfo.ShortSha} to clipboard");
142158
}
143159
else
144160
{
161+
VsixTelemetry.LogInformation("No blame information available for line {LineNumber}", lineNumber);
145162
await VS.StatusBar.ShowMessageAsync("Git Ranger: No blame information available for this line");
146163
}
147164
}
148165
catch (Exception ex)
149166
{
167+
activity?.RecordError(ex);
168+
VsixTelemetry.TrackException(ex, new Dictionary<string, object>
169+
{
170+
{ "operation.name", "CopyCommitSha" }
171+
});
150172
await VS.StatusBar.ShowMessageAsync($"Git Ranger: Error copying commit SHA - {ex.Message}");
151173
}
152174
}

src/CodingWithCalvin.GitRanger/GitRangerPackage.cs

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using CodingWithCalvin.GitRanger.Commands;
66
using CodingWithCalvin.GitRanger.Options;
77
using CodingWithCalvin.GitRanger.Services;
8+
using CodingWithCalvin.Otel4Vsix;
89
using Community.VisualStudio.Toolkit;
910
using Microsoft.VisualStudio;
1011
using Microsoft.VisualStudio.Shell;
@@ -85,16 +86,32 @@ protected override async Task InitializeAsync(CancellationToken cancellationToke
8586
{
8687
await base.InitializeAsync(cancellationToken, progress);
8788

89+
// Switch to the main thread for telemetry initialization
90+
await JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken);
91+
92+
// Initialize telemetry
93+
var builder = VsixTelemetry.Configure()
94+
.WithServiceName(VsixInfo.DisplayName)
95+
.WithServiceVersion(VsixInfo.Version)
96+
.WithVisualStudioAttributes(this)
97+
.WithEnvironmentAttributes();
98+
99+
#if !DEBUG
100+
builder
101+
.WithOtlpHttp("https://api.honeycomb.io")
102+
.WithHeader("x-honeycomb-team", HoneycombConfig.ApiKey);
103+
#endif
104+
105+
builder.Initialize();
106+
88107
// Initialize services
89108
await InitializeServicesAsync();
90109

91-
// Switch to the main thread for command registration
92-
await JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken);
93-
94110
// Register commands
95111
await RegisterCommandsAsync();
96112

97113
// Log successful initialization
114+
VsixTelemetry.LogInformation("Git Ranger initialized successfully");
98115
await VS.StatusBar.ShowMessageAsync("Git Ranger initialized successfully");
99116
}
100117

@@ -133,6 +150,16 @@ private async Task RegisterCommandsAsync()
133150
await BlameCommands.InitializeAsync(this);
134151
// Note: HistoryCommands and GraphCommands are not registered yet (coming soon)
135152
}
153+
154+
protected override void Dispose(bool disposing)
155+
{
156+
if (disposing)
157+
{
158+
VsixTelemetry.Shutdown();
159+
}
160+
161+
base.Dispose(disposing);
162+
}
136163
}
137164

138165
/// <summary>
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
namespace CodingWithCalvin.GitRanger
2+
{
3+
internal static class HoneycombConfig
4+
{
5+
public const string ApiKey = "PLACEHOLDER";
6+
}
7+
}

src/CodingWithCalvin.GitRanger/Services/BlameService.cs

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
using System;
22
using System.Collections.Concurrent;
33
using System.Collections.Generic;
4-
using System.Diagnostics;
54
using System.Linq;
65
using System.Threading;
76
using System.Threading.Tasks;
87
using CodingWithCalvin.GitRanger.Core.Models;
8+
using CodingWithCalvin.Otel4Vsix;
99

1010
namespace CodingWithCalvin.GitRanger.Services
1111
{
@@ -38,21 +38,28 @@ public BlameService(GitService gitService, ThemeService themeService)
3838
/// <returns>Blame line information, or empty if not available.</returns>
3939
public IReadOnlyList<BlameLineInfo> GetBlame(string filePath)
4040
{
41-
if (string.IsNullOrEmpty(filePath))
41+
using var activity = VsixTelemetry.StartCommandActivity("BlameService.GetBlame");
42+
43+
if (string.IsNullOrEmpty(filePath))
4244
return Array.Empty<BlameLineInfo>();
4345

4446
// Check cache
4547
if (_cache.TryGetValue(filePath, out var cached) && !cached.IsExpired)
4648
{
49+
activity?.SetTag("cache.hit", true);
4750
return cached.Lines;
4851
}
4952

53+
activity?.SetTag("cache.hit", false);
54+
5055
// Load synchronously
5156
var lines = _gitService.GetBlame(filePath).ToList();
5257

5358
// Update cache
5459
_cache[filePath] = new BlameCache(lines);
5560

61+
activity?.SetTag("lines.count", lines.Count);
62+
5663
return lines;
5764
}
5865

@@ -73,28 +80,29 @@ public Task<IReadOnlyList<BlameLineInfo>> GetBlameAsync(string filePath, Cancell
7380
/// <param name="filePath">The file path.</param>
7481
public void LoadBlameInBackground(string filePath)
7582
{
76-
Debug.WriteLine($"[GitRanger] BlameService.LoadBlameInBackground - FilePath: {filePath}");
83+
using var activity = VsixTelemetry.StartCommandActivity("BlameService.LoadBlameInBackground");
7784

78-
if (string.IsNullOrEmpty(filePath))
85+
if (string.IsNullOrEmpty(filePath))
7986
{
80-
Debug.WriteLine("[GitRanger] BlameService.LoadBlameInBackground - FilePath is empty");
87+
VsixTelemetry.LogInformation("LoadBlameInBackground - FilePath is empty");
8188
return;
8289
}
8390

8491
Task.Run(() =>
8592
{
8693
try
8794
{
88-
Debug.WriteLine($"[GitRanger] BlameService.LoadBlameInBackground - Starting GetBlame for {filePath}");
95+
VsixTelemetry.LogInformation("Loading blame for file");
8996
var lines = GetBlame(filePath);
90-
Debug.WriteLine($"[GitRanger] BlameService.LoadBlameInBackground - Got {lines.Count} lines");
97+
VsixTelemetry.LogInformation("Loaded {LineCount} blame lines", lines.Count);
9198
BlameLoaded?.Invoke(this, new BlameLoadedEventArgs(filePath, lines));
92-
Debug.WriteLine("[GitRanger] BlameService.LoadBlameInBackground - BlameLoaded event fired");
9399
}
94100
catch (Exception ex)
95101
{
96-
Debug.WriteLine($"[GitRanger] BlameService.LoadBlameInBackground - ERROR: {ex.Message}");
97-
Debug.WriteLine($"[GitRanger] BlameService.LoadBlameInBackground - StackTrace: {ex.StackTrace}");
102+
VsixTelemetry.TrackException(ex, new Dictionary<string, object>
103+
{
104+
{ "operation.name", "LoadBlameInBackground" },
105+
});
98106
}
99107
});
100108
}

0 commit comments

Comments
 (0)