Skip to content

Commit 157f324

Browse files
SLVS-2523 Implement telemetry for interacting with hotspots (#6425)
1 parent 670eff2 commit 157f324

File tree

8 files changed

+121
-9
lines changed

8 files changed

+121
-9
lines changed

src/Core/Telemetry/ITelemetryManager.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,4 +43,8 @@ public interface ITelemetryManager
4343
void AddedAutomaticBindings();
4444

4545
void DependencyRiskInvestigatedLocally();
46+
47+
void HotspotInvestigatedLocally();
48+
49+
void HotspotInvestigatedRemotely();
4650
}

src/Integration.UnitTests/Telemetry/TelemetryManagerTests.cs

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
*/
2020

2121
using Microsoft.VisualStudio.Shell;
22-
using SonarLint.VisualStudio.Core;
2322
using SonarLint.VisualStudio.Core.Telemetry;
2423
using SonarLint.VisualStudio.Integration.Telemetry;
2524
using SonarLint.VisualStudio.SLCore.Service.Telemetry;
@@ -244,6 +243,30 @@ public void DependencyRiskInvestigatedLocally_CallsRpcService()
244243
});
245244
}
246245

246+
[TestMethod]
247+
public void HotspotInvestigatedLocally_CallsRpcService()
248+
{
249+
telemetryManager.HotspotInvestigatedLocally();
250+
251+
Received.InOrder(() =>
252+
{
253+
telemetryHandler.Notify(Arg.Any<Action<ITelemetrySLCoreService>>());
254+
telemetryService.HotspotInvestigatedLocally();
255+
});
256+
}
257+
258+
[TestMethod]
259+
public void HotspotInvestigatedRemotely_CallsRpcService()
260+
{
261+
telemetryManager.HotspotInvestigatedRemotely();
262+
263+
Received.InOrder(() =>
264+
{
265+
telemetryHandler.Notify(Arg.Any<Action<ITelemetrySLCoreService>>());
266+
telemetryService.HotspotInvestigatedRemotely();
267+
});
268+
}
269+
247270
private void MockTelemetryService()
248271
{
249272
telemetryService = Substitute.For<ITelemetrySLCoreService>();

src/Integration/Telemetry/TelemetryManager.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020

2121
using System.ComponentModel.Composition;
2222
using Microsoft.VisualStudio.Shell;
23-
using SonarLint.VisualStudio.Core;
2423
using SonarLint.VisualStudio.Core.Telemetry;
2524
using SonarLint.VisualStudio.SLCore.Service.Telemetry;
2625
using SonarLint.VisualStudio.SLCore.Service.Telemetry.Models;
@@ -68,6 +67,10 @@ public void FixSuggestionResolved(string suggestionId, IEnumerable<bool> changeR
6867

6968
public void DependencyRiskInvestigatedLocally() => telemetryHelper.Notify(telemetryService => telemetryService.DependencyRiskInvestigatedLocally());
7069

70+
public void HotspotInvestigatedLocally() => telemetryHelper.Notify(telemetryService => telemetryService.HotspotInvestigatedLocally());
71+
72+
public void HotspotInvestigatedRemotely() => telemetryHelper.Notify(telemetryService => telemetryService.HotspotInvestigatedRemotely());
73+
7174
private static IEnumerable<FixSuggestionResolvedParams> ConvertFixSuggestionChangeToResolvedParams(string suggestionId, IEnumerable<bool> changeApplicationStatus) =>
7275
changeApplicationStatus
7376
.Select((status, index) =>

src/IssueViz.Security.UnitTests/ReportView/Hotspots/HotspotsReportViewModelTest.cs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
using System.Windows;
2222
using SonarLint.VisualStudio.Core;
2323
using SonarLint.VisualStudio.Core.Analysis;
24+
using SonarLint.VisualStudio.Core.Telemetry;
2425
using SonarLint.VisualStudio.Integration.TestInfrastructure;
2526
using SonarLint.VisualStudio.IssueVisualization.Models;
2627
using SonarLint.VisualStudio.IssueVisualization.Security.Hotspots;
@@ -39,6 +40,7 @@ public class HotspotsReportViewModelTest
3940
private ILocalHotspotsStore localHotspotsStore;
4041
private IMessageBox messageBox;
4142
private IReviewHotspotsService reviewHotspotsService;
43+
private ITelemetryManager telemetryManager;
4244
private HotspotsReportViewModel testSubject;
4345

4446
[TestInitialize]
@@ -47,15 +49,17 @@ public void TestInitialize()
4749
localHotspotsStore = Substitute.For<ILocalHotspotsStore>();
4850
reviewHotspotsService = Substitute.For<IReviewHotspotsService>();
4951
messageBox = Substitute.For<IMessageBox>();
50-
testSubject = new HotspotsReportViewModel(localHotspotsStore, reviewHotspotsService, messageBox);
52+
telemetryManager = Substitute.For<ITelemetryManager>();
53+
testSubject = new HotspotsReportViewModel(localHotspotsStore, reviewHotspotsService, messageBox, telemetryManager);
5154
}
5255

5356
[TestMethod]
5457
public void MefCtor_CheckIsExported() =>
5558
MefTestHelpers.CheckTypeCanBeImported<HotspotsReportViewModel, IHotspotsReportViewModel>(
5659
MefTestHelpers.CreateExport<ILocalHotspotsStore>(),
5760
MefTestHelpers.CreateExport<IReviewHotspotsService>(),
58-
MefTestHelpers.CreateExport<IMessageBox>()
61+
MefTestHelpers.CreateExport<IMessageBox>(),
62+
MefTestHelpers.CreateExport<ITelemetryManager>()
5963
);
6064

6165
[TestMethod]
@@ -127,13 +131,14 @@ public void HotspotsChanged_RaisedOnStoreIssuesChanged()
127131
}
128132

129133
[TestMethod]
130-
public async Task ShowHotspotInBrowserAsync_CallsHandler()
134+
public async Task ShowHotspotInBrowserAsync_CallsHandlerAndTelemetry()
131135
{
132136
var hotspot = CreateMockedHotspot("myFile.cs");
133137

134138
await testSubject.ShowHotspotInBrowserAsync(hotspot);
135139

136140
reviewHotspotsService.Received(1).OpenHotspotAsync(hotspot.Visualization.Issue.IssueServerKey).IgnoreAwaitForAssert();
141+
telemetryManager.Received(1).HotspotInvestigatedRemotely();
137142
}
138143

139144
[TestMethod]

src/IssueViz.Security.UnitTests/ReportView/ReportViewModelTest.cs

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,9 @@
2525
using SonarLint.VisualStudio.Core.Telemetry;
2626
using SonarLint.VisualStudio.IssueVisualization.Editor;
2727
using SonarLint.VisualStudio.IssueVisualization.IssueVisualizationControl.ViewModels.Commands;
28+
using SonarLint.VisualStudio.IssueVisualization.Models;
2829
using SonarLint.VisualStudio.IssueVisualization.Security.DependencyRisks;
30+
using SonarLint.VisualStudio.IssueVisualization.Security.Hotspots;
2931
using SonarLint.VisualStudio.IssueVisualization.Security.ReportView;
3032
using SonarLint.VisualStudio.IssueVisualization.Security.ReportView.Hotspots;
3133
using SonarLint.VisualStudio.TestInfrastructure;
@@ -182,6 +184,44 @@ public void SelectedItem_SetToIssueViewModel_DoesNotCallTelemetryForDependencyRi
182184

183185
testSubject.SelectedItem.Should().BeSameAs(issueViewModel);
184186
telemetryManager.DidNotReceive().DependencyRiskInvestigatedLocally();
187+
telemetryManager.DidNotReceive().HotspotInvestigatedLocally();
188+
}
189+
190+
[TestMethod]
191+
public void SelectedItem_SetToHotspotViewModel_CallsTelemetryForDependencyRisk()
192+
{
193+
var hotspotViewModel = new HotspotViewModel(CreateMockedHotspot());
194+
195+
testSubject.SelectedItem = hotspotViewModel;
196+
197+
testSubject.SelectedItem.Should().BeSameAs(hotspotViewModel);
198+
telemetryManager.Received(1).HotspotInvestigatedLocally();
199+
}
200+
201+
[TestMethod]
202+
public void SelectedItem_SetToSameHotspotViewModel_DoesNotCallTelemetry()
203+
{
204+
var hotspotViewModel = new HotspotViewModel(CreateMockedHotspot());
205+
testSubject.SelectedItem = hotspotViewModel;
206+
telemetryManager.ClearReceivedCalls();
207+
208+
testSubject.SelectedItem = hotspotViewModel;
209+
210+
telemetryManager.DidNotReceive().HotspotInvestigatedLocally();
211+
}
212+
213+
[TestMethod]
214+
public void SelectedItem_SetToDifferentHotspotViewModel_CallsTelemetry()
215+
{
216+
var hotspotViewModel1 = new HotspotViewModel(CreateMockedHotspot());
217+
var hotspotViewModel2 = new HotspotViewModel(CreateMockedHotspot());
218+
testSubject.SelectedItem = hotspotViewModel1;
219+
telemetryManager.ClearReceivedCalls();
220+
221+
testSubject.SelectedItem = hotspotViewModel2;
222+
223+
testSubject.SelectedItem.Should().BeSameAs(hotspotViewModel2);
224+
telemetryManager.Received(1).HotspotInvestigatedLocally();
185225
}
186226

187227
[TestMethod]
@@ -195,6 +235,7 @@ public void SelectedItem_SetToNull_DoesNotCallTelemetry()
195235

196236
testSubject.SelectedItem.Should().BeNull();
197237
telemetryManager.DidNotReceive().DependencyRiskInvestigatedLocally();
238+
telemetryManager.DidNotReceive().HotspotInvestigatedLocally();
198239
}
199240

200241
[TestMethod]
@@ -391,4 +432,6 @@ private static void VerifyExpectedDependencyRiskGroupViewModel(GroupDependencyRi
391432
}
392433

393434
private void VerifyHasGroupsUpdated() => eventHandler.Received().Invoke(Arg.Any<object>(), Arg.Is<PropertyChangedEventArgs>(p => p.PropertyName == nameof(testSubject.HasGroups)));
435+
436+
private static LocalHotspot CreateMockedHotspot() => new(Substitute.For<IAnalysisIssueVisualization>(), default, default);
394437
}

src/IssueViz.Security/ReportView/Hotspots/HotspotsReportViewModel.cs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
using System.Windows;
2424
using SonarLint.VisualStudio.Core;
2525
using SonarLint.VisualStudio.Core.Analysis;
26+
using SonarLint.VisualStudio.Core.Telemetry;
2627
using SonarLint.VisualStudio.IssueVisualization.Security.Hotspots;
2728
using SonarLint.VisualStudio.IssueVisualization.Security.Hotspots.ReviewHotspot;
2829
using SonarLint.VisualStudio.IssueVisualization.Security.IssuesStore;
@@ -49,13 +50,19 @@ internal sealed class HotspotsReportViewModel : IHotspotsReportViewModel
4950
private readonly ILocalHotspotsStore hotspotsStore;
5051
private readonly IReviewHotspotsService reviewHotspotsService;
5152
private readonly IMessageBox messageBox;
53+
private readonly ITelemetryManager telemetryManager;
5254

5355
[ImportingConstructor]
54-
public HotspotsReportViewModel(ILocalHotspotsStore hotspotsStore, IReviewHotspotsService reviewHotspotsService, IMessageBox messageBox)
56+
public HotspotsReportViewModel(
57+
ILocalHotspotsStore hotspotsStore,
58+
IReviewHotspotsService reviewHotspotsService,
59+
IMessageBox messageBox,
60+
ITelemetryManager telemetryManager)
5561
{
5662
this.hotspotsStore = hotspotsStore;
5763
this.reviewHotspotsService = reviewHotspotsService;
5864
this.messageBox = messageBox;
65+
this.telemetryManager = telemetryManager;
5966
hotspotsStore.IssuesChanged += HotspotsStore_IssuesChanged;
6067
}
6168

@@ -69,7 +76,11 @@ public ObservableCollection<IGroupViewModel> GetHotspotsGroupViewModels()
6976
return GetGroupViewModel(hotspots);
7077
}
7178

72-
public async Task ShowHotspotInBrowserAsync(LocalHotspot localHotspot) => await reviewHotspotsService.OpenHotspotAsync(localHotspot.Visualization.Issue.IssueServerKey);
79+
public async Task ShowHotspotInBrowserAsync(LocalHotspot localHotspot)
80+
{
81+
await reviewHotspotsService.OpenHotspotAsync(localHotspot.Visualization.Issue.IssueServerKey);
82+
telemetryManager.HotspotInvestigatedRemotely();
83+
}
7384

7485
public async Task<IEnumerable<HotspotStatus>> GetAllowedStatusesAsync(HotspotViewModel selectedHotspotViewModel)
7586
{

src/IssueViz.Security/ReportView/ReportViewModel.cs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,9 +96,14 @@ protected override void Dispose(bool disposing)
9696

9797
private void UpdateTelemetry(IIssueViewModel issueViewModel)
9898
{
99-
if (issueViewModel is DependencyRiskViewModel)
99+
switch (issueViewModel)
100100
{
101-
telemetryManager.DependencyRiskInvestigatedLocally();
101+
case DependencyRiskViewModel:
102+
telemetryManager.DependencyRiskInvestigatedLocally();
103+
break;
104+
case HotspotViewModel:
105+
telemetryManager.HotspotInvestigatedLocally();
106+
break;
102107
}
103108
}
104109

src/SLCore/Service/Telemetry/ITelemetrySLCoreService.cs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,18 +27,36 @@ namespace SonarLint.VisualStudio.SLCore.Service.Telemetry;
2727
public interface ITelemetrySLCoreService : ISLCoreService
2828
{
2929
Task<GetStatusResponse> GetStatusAsync();
30+
3031
void EnableTelemetry();
32+
3133
void DisableTelemetry();
34+
3235
void AnalysisDoneOnSingleLanguage(AnalysisDoneOnSingleLanguageParams parameters);
36+
3337
void DevNotificationsClicked(DevNotificationsClickedParams parameters);
38+
3439
void TaintVulnerabilitiesInvestigatedLocally();
40+
3541
void TaintVulnerabilitiesInvestigatedRemotely();
42+
3643
void AddReportedRules(AddReportedRulesParams parameters);
44+
3745
void AddQuickFixAppliedForRule(AddQuickFixAppliedForRuleParams parameters);
46+
3847
void FixSuggestionResolved(FixSuggestionResolvedParams parameters);
48+
3949
void HelpAndFeedbackLinkClicked(HelpAndFeedbackClickedParams parameters);
50+
4051
void AddedManualBindings();
52+
4153
void AddedImportedBindings();
54+
4255
void AddedAutomaticBindings();
56+
4357
void DependencyRiskInvestigatedLocally();
58+
59+
void HotspotInvestigatedLocally();
60+
61+
void HotspotInvestigatedRemotely();
4462
}

0 commit comments

Comments
 (0)