3
3
4
4
using System ;
5
5
using System . Collections . Generic ;
6
+ using System . Collections . Immutable ;
7
+ using System . Linq ;
6
8
using System . Threading ;
7
9
using System . Threading . Tasks ;
8
10
using Microsoft . AspNetCore . Razor . Language ;
11
+ using Microsoft . AspNetCore . Razor . Language . Components ;
9
12
using Microsoft . AspNetCore . Razor . LanguageServer . EndpointContracts ;
10
13
using Microsoft . AspNetCore . Razor . LanguageServer . Hosting ;
11
14
using Microsoft . AspNetCore . Razor . PooledObjects ;
15
+ using Microsoft . AspNetCore . Razor . ProjectSystem ;
12
16
using Microsoft . AspNetCore . Razor . Telemetry ;
13
17
using Microsoft . CodeAnalysis . Razor . Diagnostics ;
14
18
using Microsoft . CodeAnalysis . Razor . ProjectSystem ;
@@ -26,6 +30,7 @@ internal class DocumentPullDiagnosticsEndpoint : IRazorRequestHandler<VSInternal
26
30
private readonly IClientConnection _clientConnection ;
27
31
private readonly RazorTranslateDiagnosticsService _translateDiagnosticsService ;
28
32
private readonly ITelemetryReporter ? _telemetryReporter ;
33
+ private ImmutableDictionary < ProjectKey , int > _lastReporedProjectTagHelperCount = ImmutableDictionary < ProjectKey , int > . Empty ;
29
34
30
35
public DocumentPullDiagnosticsEndpoint (
31
36
LanguageServerFeatureOptions languageServerFeatureOptions ,
@@ -77,6 +82,8 @@ public TextDocumentIdentifier GetTextDocumentIdentifier(VSInternalDocumentDiagno
77
82
78
83
var razorDiagnostics = await GetRazorDiagnosticsAsync ( documentSnapshot ) . ConfigureAwait ( false ) ;
79
84
85
+ await ReportRZ10012TelemetryAsync ( documentContext , razorDiagnostics , cancellationToken ) . ConfigureAwait ( false ) ;
86
+
80
87
var ( csharpDiagnostics , htmlDiagnostics ) = await GetHtmlCSharpDiagnosticsAsync ( documentContext , correlationId , cancellationToken ) . ConfigureAwait ( false ) ;
81
88
82
89
var diagnosticCount =
@@ -163,4 +170,59 @@ public TextDocumentIdentifier GetTextDocumentIdentifier(VSInternalDocumentDiagno
163
170
164
171
return ( delegatedResponse . CSharpDiagnostics , delegatedResponse . HtmlDiagnostics ) ;
165
172
}
173
+
174
+ /// <summary>
175
+ /// Reports telemetry for RZ10012 "Found markup element with unexpected name" to help track down potential issues
176
+ /// with taghelpers being discovered (or lack thereof)
177
+ /// </summary>
178
+ private async ValueTask ReportRZ10012TelemetryAsync ( DocumentContext documentContext , VSInternalDiagnosticReport [ ] ? razorDiagnostics , CancellationToken cancellationToken )
179
+ {
180
+ if ( razorDiagnostics is null )
181
+ {
182
+ return ;
183
+ }
184
+
185
+ if ( _telemetryReporter is null )
186
+ {
187
+ return ;
188
+ }
189
+
190
+ var relevantDiagnosticsCount = razorDiagnostics . Sum ( CountDiagnostics ) ;
191
+ if ( relevantDiagnosticsCount == 0 )
192
+ {
193
+ return ;
194
+ }
195
+
196
+ var tagHelpers = await documentContext . Project . GetTagHelpersAsync ( cancellationToken ) . ConfigureAwait ( false ) ;
197
+ var tagHelperCount = tagHelpers . Count ( ) ;
198
+ var shouldReport = false ;
199
+
200
+ ImmutableInterlocked . AddOrUpdate (
201
+ ref _lastReporedProjectTagHelperCount ,
202
+ documentContext . Project . Key ,
203
+ ( k ) =>
204
+ {
205
+ shouldReport = true ;
206
+ return tagHelperCount ;
207
+ } ,
208
+ ( k , currentValue ) =>
209
+ {
210
+ shouldReport = currentValue != tagHelperCount ;
211
+ return tagHelperCount ;
212
+ } ) ;
213
+
214
+ if ( shouldReport )
215
+ {
216
+ _telemetryReporter . ReportEvent (
217
+ "RZ10012" ,
218
+ Severity . Low ,
219
+ new ( "tagHelpers" , tagHelperCount ) ,
220
+ new ( "RZ10012errors" , relevantDiagnosticsCount ) ,
221
+ new ( "project" , documentContext . Project . Key . Id ) ) ;
222
+ }
223
+
224
+ static int CountDiagnostics ( VSInternalDiagnosticReport report )
225
+ => report . Diagnostics ? . Count ( d => d . Code == ComponentDiagnosticFactory . UnexpectedMarkupElement . Id )
226
+ ?? 0 ;
227
+ }
166
228
}
0 commit comments