Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reduce the amount of telemetry emitted #11094

Merged
merged 5 commits into from
Oct 28, 2024
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using Microsoft.AspNetCore.Razor.Telemetry;
using Microsoft.CodeAnalysis.Razor.CodeActions;
using Microsoft.CodeAnalysis.Razor.Protocol.CodeActions;
using Microsoft.CodeAnalysis.Razor.Workspaces.Telemetry;
using Microsoft.VisualStudio.LanguageServer.Protocol;

namespace Microsoft.AspNetCore.Razor.LanguageServer.CodeActions;
Expand Down Expand Up @@ -57,7 +58,7 @@ public TextDocumentIdentifier GetTextDocumentIdentifier(VSCodeActionParams reque
}

var correlationId = Guid.NewGuid();
using var __ = _telemetryReporter.TrackLspRequest(LspEndpointName, LanguageServerConstants.RazorLanguageServerName, correlationId);
using var __ = _telemetryReporter.TrackLspRequest(LspEndpointName, LanguageServerConstants.RazorLanguageServerName, TelemetryThresholds.CodeActionRazorTelemetryThreshold, correlationId);
cancellationToken.ThrowIfCancellationRequested();

return await _codeActionsService.GetCodeActionsAsync(request, documentContext, _supportsCodeActionResolve, correlationId, cancellationToken).ConfigureAwait(false);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using System.Threading.Tasks;
using Microsoft.AspNetCore.Razor.LanguageServer.EndpointContracts;
using Microsoft.AspNetCore.Razor.Telemetry;
using Microsoft.CodeAnalysis.Razor.Workspaces.Telemetry;
using Microsoft.CodeAnalysis.Text;
using Microsoft.VisualStudio.LanguageServer.Protocol;

Expand Down Expand Up @@ -77,7 +78,7 @@ public TextDocumentIdentifier GetTextDocumentIdentifier(CompletionParams request
}

var correlationId = Guid.NewGuid();
using var _ = _telemetryReporter?.TrackLspRequest(Methods.TextDocumentCompletionName, LanguageServerConstants.RazorLanguageServerName, correlationId);
using var _ = _telemetryReporter?.TrackLspRequest(Methods.TextDocumentCompletionName, LanguageServerConstants.RazorLanguageServerName, TelemetryThresholds.CompletionRazorTelemetryThreshold, correlationId);
var completionList = await _completionListProvider.GetCompletionListAsync(
hostDocumentIndex,
completionContext,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
using Microsoft.CodeAnalysis.Razor.Protocol;
using Microsoft.CodeAnalysis.Razor.Protocol.Diagnostics;
using Microsoft.CodeAnalysis.Razor.Workspaces;
using Microsoft.CodeAnalysis.Razor.Workspaces.Telemetry;
using Microsoft.VisualStudio.LanguageServer.Protocol;

namespace Microsoft.AspNetCore.Razor.LanguageServer.Diagnostics;
Expand All @@ -30,7 +31,7 @@ internal class DocumentPullDiagnosticsEndpoint : IRazorRequestHandler<VSInternal
private readonly IClientConnection _clientConnection;
private readonly RazorTranslateDiagnosticsService _translateDiagnosticsService;
private readonly ITelemetryReporter? _telemetryReporter;
private ImmutableDictionary<ProjectKey, int> _lastReporedProjectTagHelperCount = ImmutableDictionary<ProjectKey, int>.Empty;
private ImmutableDictionary<ProjectKey, int> _lastReportedProjectTagHelperCount = ImmutableDictionary<ProjectKey, int>.Empty;

public DocumentPullDiagnosticsEndpoint(
LanguageServerFeatureOptions languageServerFeatureOptions,
Expand Down Expand Up @@ -71,7 +72,7 @@ public TextDocumentIdentifier GetTextDocumentIdentifier(VSInternalDocumentDiagno
}

var correlationId = Guid.NewGuid();
using var __ = _telemetryReporter?.TrackLspRequest(VSInternalMethods.DocumentPullDiagnosticName, LanguageServerConstants.RazorLanguageServerName, correlationId);
using var __ = _telemetryReporter?.TrackLspRequest(VSInternalMethods.DocumentPullDiagnosticName, LanguageServerConstants.RazorLanguageServerName, TelemetryThresholds.DiagnosticsRazorTelemetryThreshold, correlationId);
var documentContext = context.DocumentContext;
if (documentContext is null)
{
Expand Down Expand Up @@ -202,7 +203,7 @@ private async ValueTask ReportRZ10012TelemetryAsync(DocumentContext documentCont
var shouldReport = false;

ImmutableInterlocked.AddOrUpdate(
ref _lastReporedProjectTagHelperCount,
ref _lastReportedProjectTagHelperCount,
documentContext.Project.Key,
(k) =>
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
using Microsoft.CodeAnalysis.Razor.ProjectSystem;
using Microsoft.CodeAnalysis.Razor.Protocol;
using Microsoft.CodeAnalysis.Razor.Workspaces;
using Microsoft.CodeAnalysis.Razor.Workspaces.Telemetry;
using Microsoft.CodeAnalysis.Text;
using Microsoft.VisualStudio.LanguageServer.Protocol;
using Location = Microsoft.VisualStudio.LanguageServer.Protocol.Location;
Expand Down Expand Up @@ -70,7 +71,7 @@ public void ApplyCapabilities(VSInternalServerCapabilities serverCapabilities, V
}

var mapCodeCorrelationId = mapperParams.MapCodeCorrelationId ?? Guid.NewGuid();
using var ts = _telemetryReporter.TrackLspRequest(VSInternalMethods.WorkspaceMapCodeName, LanguageServerConstants.RazorLanguageServerName, mapCodeCorrelationId);
using var ts = _telemetryReporter.TrackLspRequest(VSInternalMethods.WorkspaceMapCodeName, LanguageServerConstants.RazorLanguageServerName, TelemetryThresholds.MapCodeRazorTelemetryThreshold, mapCodeCorrelationId);

return await HandleMappingsAsync(mapperParams.Mappings, mapCodeCorrelationId, cancellationToken).ConfigureAwait(false);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
using Microsoft.AspNetCore.Razor.Telemetry;
using Microsoft.CodeAnalysis.Razor.SemanticTokens;
using Microsoft.CodeAnalysis.Razor.Workspaces;
using Microsoft.CodeAnalysis.Razor.Workspaces.Telemetry;
using Microsoft.VisualStudio.LanguageServer.Protocol;

namespace Microsoft.AspNetCore.Razor.LanguageServer.Semantic;
Expand Down Expand Up @@ -49,7 +50,7 @@ public TextDocumentIdentifier GetTextDocumentIdentifier(SemanticTokensRangeParam
var colorBackground = _razorLSPOptionsMonitor.CurrentValue.ColorBackground;

var correlationId = Guid.NewGuid();
using var _ = _telemetryReporter?.TrackLspRequest(Methods.TextDocumentSemanticTokensRangeName, LanguageServerConstants.RazorLanguageServerName, correlationId);
using var _ = _telemetryReporter?.TrackLspRequest(Methods.TextDocumentSemanticTokensRangeName, LanguageServerConstants.RazorLanguageServerName, TelemetryThresholds.SemanticTokensRazorTelemetryThreshold, correlationId);

var data = await _semanticTokensInfoService.GetSemanticTokensAsync(documentContext, request.Range.ToLinePositionSpan(), colorBackground, correlationId, cancellationToken).ConfigureAwait(false);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@ namespace Microsoft.AspNetCore.Razor.Telemetry;

internal interface ITelemetryReporter
{
TelemetryScope BeginBlock(string name, Severity severity);
TelemetryScope BeginBlock(string name, Severity severity, Property property);
TelemetryScope BeginBlock(string name, Severity severity, Property property1, Property property2);
TelemetryScope BeginBlock(string name, Severity severity, Property property1, Property property2, Property property3);
TelemetryScope BeginBlock(string name, Severity severity, params Property[] properties);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❗ The purpose of the overloads above is to avoid allocating a params array in cases where there are zero to three properties. This change will cause any calls that now pass a TimeSpan and zero to three properties to create an extra array: one for the params array, and one for the final telemetry array of length + . I recommend adding TimeSpan to each of these overloads and then adding extension methods on ITelemetryReporter that don't have the TimeSpan parameter and just pass TimeSpan.Zero.

Also, consider turning the final overload into params ReadOnlySpan<Property> to match ReportEvent below.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think minTimeToReport seems weird on BeginBlock. Maybe it would be better to add something to TelemetryScope for this?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right. It does feel a bit strange on a method called BeginBlock. However, I think it would be awkward ergonomically to have some property to set on TelemetryScope. There are two reasons for this:

  1. Nothing actually uses a TelemetryScope today. It's always captured in a using statement.
  2. There's a race condition between the TelemetryScope being created and the value being set. So, passing it as a parameter so that it can be included in the TelemetryScope is probably the right thing.

Of course, the truth is that BeginBlock is kind of a weird name because since it produces a TelemetryScope. Also, TelemetryScope is currently a class. Should it become a struct with [NonCopyable] to avoid the extra allocation?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nothing actually uses a TelemetryScope today. It's always captured in a using statement.

But they could. Scopes probably should have a cancel anyways...

I like the idea of them being a [NonCopyable] struct. I still find it odd to add a timespan to every BeginBlock when only TrackLspRequest is using it. It seems like we're taking an implementation of one part of the API surface and expanding it.

In the end it's not a huge deal though, and with the added extension methods it won't cause any real pain

Copy link
Member

@DustinCampbell DustinCampbell Oct 28, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I still find it odd to add a timespan to every BeginBlock when only TrackLspRequest is using it.

The reason that there're five overloads of BeginBlock is really for performance. That can definitely be improved, and I'm happy to take a look at it. IMO, BeginBlock is the core API that an ITelemetryReporter should implement and the TimeSpan is a feature of that API, so it should go there. However, we should work out some of the ergonomic problems that you've pointed out. Although, there aren't actually any callers of BeginBlock other than TrackLspRequest and unit tests today.

Copy link
Member

@DustinCampbell DustinCampbell Oct 28, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But they could. Scopes probably should have a cancel anyways...

Maybe? At the moment that's kind of YAGNI isn't it?

TelemetryScope BeginBlock(string name, Severity severity, TimeSpan minTimeToReport);
TelemetryScope BeginBlock(string name, Severity severity, TimeSpan minTimeToReport, Property property);
TelemetryScope BeginBlock(string name, Severity severity, TimeSpan minTimeToReport, Property property1, Property property2);
TelemetryScope BeginBlock(string name, Severity severity, TimeSpan minTimeToReport, Property property1, Property property2, Property property3);
TelemetryScope BeginBlock(string name, Severity severity, TimeSpan minTimeToReport, params ReadOnlySpan<Property> properties);

TelemetryScope TrackLspRequest(string lspMethodName, string lspServerName, Guid correlationId);
TelemetryScope TrackLspRequest(string lspMethodName, string lspServerName, TimeSpan minTimeToReport, Guid correlationId);

void ReportEvent(string name, Severity severity);
void ReportEvent(string name, Severity severity, Property property);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the MIT license. See License.txt in the project root for license information.

using System;

namespace Microsoft.AspNetCore.Razor.Telemetry;

internal static class ITelemetryReporterExtensions
{
// These extensions effectively make TimeSpan an optional parameter on BeginBlock
public static TelemetryScope BeginBlock(this ITelemetryReporter reporter, string name, Severity severity)
=> reporter.BeginBlock(name, severity, minTimeToReport: TimeSpan.Zero);

public static TelemetryScope BeginBlock(this ITelemetryReporter reporter, string name, Severity severity, Property property)
=> reporter.BeginBlock(name, severity, minTimeToReport: TimeSpan.Zero, property);

public static TelemetryScope BeginBlock(this ITelemetryReporter reporter, string name, Severity severity, Property property1, Property property2)
=> reporter.BeginBlock(name, severity, minTimeToReport: TimeSpan.Zero, property1, property2);

public static TelemetryScope BeginBlock(this ITelemetryReporter reporter, string name, Severity severity, Property property1, Property property2, Property property3)
=> reporter.BeginBlock(name, severity, minTimeToReport: TimeSpan.Zero, property1, property2, property3);

public static TelemetryScope BeginBlock(this ITelemetryReporter reporter, string name, Severity severity, params ReadOnlySpan<Property> properties)
=> reporter.BeginBlock(name, severity, minTimeToReport: TimeSpan.Zero, properties);
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,20 +13,20 @@
{
}

public TelemetryScope BeginBlock(string name, Severity severity)
public TelemetryScope BeginBlock(string name, Severity severity, TimeSpan minTimeToReport)
=> TelemetryScope.Null;

Check failure on line 17 in src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/Telemetry/NoOpTelemetryReporter.cs

View check run for this annotation

Azure Pipelines / razor-tooling-ci (Build macOS debug)

src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/Telemetry/NoOpTelemetryReporter.cs#L17

src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/Telemetry/NoOpTelemetryReporter.cs(17,12): error RS0042: (NETCORE_ENGINEERING_TELEMETRY=Build) Cannot return a value from a reference to non-copyable type 'Microsoft.AspNetCore.Razor.Telemetry.TelemetryScope'

Check failure on line 17 in src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/Telemetry/NoOpTelemetryReporter.cs

View check run for this annotation

Azure Pipelines / razor-tooling-ci (Build macOS release)

src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/Telemetry/NoOpTelemetryReporter.cs#L17

src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/Telemetry/NoOpTelemetryReporter.cs(17,12): error RS0042: (NETCORE_ENGINEERING_TELEMETRY=Build) Cannot return a value from a reference to non-copyable type 'Microsoft.AspNetCore.Razor.Telemetry.TelemetryScope'

Check failure on line 17 in src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/Telemetry/NoOpTelemetryReporter.cs

View check run for this annotation

Azure Pipelines / razor-tooling-ci (Build Linux debug)

src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/Telemetry/NoOpTelemetryReporter.cs#L17

src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/Telemetry/NoOpTelemetryReporter.cs(17,12): error RS0042: (NETCORE_ENGINEERING_TELEMETRY=Build) Cannot return a value from a reference to non-copyable type 'Microsoft.AspNetCore.Razor.Telemetry.TelemetryScope'

Check failure on line 17 in src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/Telemetry/NoOpTelemetryReporter.cs

View check run for this annotation

Azure Pipelines / razor-tooling-ci (Build Linux release)

src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/Telemetry/NoOpTelemetryReporter.cs#L17

src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/Telemetry/NoOpTelemetryReporter.cs(17,12): error RS0042: (NETCORE_ENGINEERING_TELEMETRY=Build) Cannot return a value from a reference to non-copyable type 'Microsoft.AspNetCore.Razor.Telemetry.TelemetryScope'

Check failure on line 17 in src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/Telemetry/NoOpTelemetryReporter.cs

View check run for this annotation

Azure Pipelines / razor-tooling-ci

src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/Telemetry/NoOpTelemetryReporter.cs#L17

src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/Telemetry/NoOpTelemetryReporter.cs(17,12): error RS0042: (NETCORE_ENGINEERING_TELEMETRY=Build) Cannot return a value from a reference to non-copyable type 'Microsoft.AspNetCore.Razor.Telemetry.TelemetryScope'

public TelemetryScope BeginBlock(string name, Severity severity, Property property)
public TelemetryScope BeginBlock(string name, Severity severity, TimeSpan minTimeToReport, Property property)
=> TelemetryScope.Null;

Check failure on line 20 in src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/Telemetry/NoOpTelemetryReporter.cs

View check run for this annotation

Azure Pipelines / razor-tooling-ci (Build macOS debug)

src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/Telemetry/NoOpTelemetryReporter.cs#L20

src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/Telemetry/NoOpTelemetryReporter.cs(20,12): error RS0042: (NETCORE_ENGINEERING_TELEMETRY=Build) Cannot return a value from a reference to non-copyable type 'Microsoft.AspNetCore.Razor.Telemetry.TelemetryScope'

Check failure on line 20 in src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/Telemetry/NoOpTelemetryReporter.cs

View check run for this annotation

Azure Pipelines / razor-tooling-ci (Build macOS release)

src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/Telemetry/NoOpTelemetryReporter.cs#L20

src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/Telemetry/NoOpTelemetryReporter.cs(20,12): error RS0042: (NETCORE_ENGINEERING_TELEMETRY=Build) Cannot return a value from a reference to non-copyable type 'Microsoft.AspNetCore.Razor.Telemetry.TelemetryScope'

Check failure on line 20 in src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/Telemetry/NoOpTelemetryReporter.cs

View check run for this annotation

Azure Pipelines / razor-tooling-ci (Build Linux debug)

src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/Telemetry/NoOpTelemetryReporter.cs#L20

src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/Telemetry/NoOpTelemetryReporter.cs(20,12): error RS0042: (NETCORE_ENGINEERING_TELEMETRY=Build) Cannot return a value from a reference to non-copyable type 'Microsoft.AspNetCore.Razor.Telemetry.TelemetryScope'

Check failure on line 20 in src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/Telemetry/NoOpTelemetryReporter.cs

View check run for this annotation

Azure Pipelines / razor-tooling-ci (Build Linux release)

src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/Telemetry/NoOpTelemetryReporter.cs#L20

src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/Telemetry/NoOpTelemetryReporter.cs(20,12): error RS0042: (NETCORE_ENGINEERING_TELEMETRY=Build) Cannot return a value from a reference to non-copyable type 'Microsoft.AspNetCore.Razor.Telemetry.TelemetryScope'

Check failure on line 20 in src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/Telemetry/NoOpTelemetryReporter.cs

View check run for this annotation

Azure Pipelines / razor-tooling-ci

src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/Telemetry/NoOpTelemetryReporter.cs#L20

src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/Telemetry/NoOpTelemetryReporter.cs(20,12): error RS0042: (NETCORE_ENGINEERING_TELEMETRY=Build) Cannot return a value from a reference to non-copyable type 'Microsoft.AspNetCore.Razor.Telemetry.TelemetryScope'

public TelemetryScope BeginBlock(string name, Severity severity, Property property1, Property property2)
public TelemetryScope BeginBlock(string name, Severity severity, TimeSpan minTimeToReport, Property property1, Property property2)
=> TelemetryScope.Null;

Check failure on line 23 in src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/Telemetry/NoOpTelemetryReporter.cs

View check run for this annotation

Azure Pipelines / razor-tooling-ci (Build macOS debug)

src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/Telemetry/NoOpTelemetryReporter.cs#L23

src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/Telemetry/NoOpTelemetryReporter.cs(23,12): error RS0042: (NETCORE_ENGINEERING_TELEMETRY=Build) Cannot return a value from a reference to non-copyable type 'Microsoft.AspNetCore.Razor.Telemetry.TelemetryScope'

Check failure on line 23 in src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/Telemetry/NoOpTelemetryReporter.cs

View check run for this annotation

Azure Pipelines / razor-tooling-ci (Build macOS release)

src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/Telemetry/NoOpTelemetryReporter.cs#L23

src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/Telemetry/NoOpTelemetryReporter.cs(23,12): error RS0042: (NETCORE_ENGINEERING_TELEMETRY=Build) Cannot return a value from a reference to non-copyable type 'Microsoft.AspNetCore.Razor.Telemetry.TelemetryScope'

Check failure on line 23 in src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/Telemetry/NoOpTelemetryReporter.cs

View check run for this annotation

Azure Pipelines / razor-tooling-ci (Build Linux debug)

src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/Telemetry/NoOpTelemetryReporter.cs#L23

src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/Telemetry/NoOpTelemetryReporter.cs(23,12): error RS0042: (NETCORE_ENGINEERING_TELEMETRY=Build) Cannot return a value from a reference to non-copyable type 'Microsoft.AspNetCore.Razor.Telemetry.TelemetryScope'

Check failure on line 23 in src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/Telemetry/NoOpTelemetryReporter.cs

View check run for this annotation

Azure Pipelines / razor-tooling-ci (Build Linux release)

src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/Telemetry/NoOpTelemetryReporter.cs#L23

src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/Telemetry/NoOpTelemetryReporter.cs(23,12): error RS0042: (NETCORE_ENGINEERING_TELEMETRY=Build) Cannot return a value from a reference to non-copyable type 'Microsoft.AspNetCore.Razor.Telemetry.TelemetryScope'

Check failure on line 23 in src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/Telemetry/NoOpTelemetryReporter.cs

View check run for this annotation

Azure Pipelines / razor-tooling-ci

src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/Telemetry/NoOpTelemetryReporter.cs#L23

src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/Telemetry/NoOpTelemetryReporter.cs(23,12): error RS0042: (NETCORE_ENGINEERING_TELEMETRY=Build) Cannot return a value from a reference to non-copyable type 'Microsoft.AspNetCore.Razor.Telemetry.TelemetryScope'

public TelemetryScope BeginBlock(string name, Severity severity, Property property1, Property property2, Property property3)
public TelemetryScope BeginBlock(string name, Severity severity, TimeSpan minTimeToReport, Property property1, Property property2, Property property3)
=> TelemetryScope.Null;

Check failure on line 26 in src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/Telemetry/NoOpTelemetryReporter.cs

View check run for this annotation

Azure Pipelines / razor-tooling-ci (Build macOS debug)

src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/Telemetry/NoOpTelemetryReporter.cs#L26

src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/Telemetry/NoOpTelemetryReporter.cs(26,12): error RS0042: (NETCORE_ENGINEERING_TELEMETRY=Build) Cannot return a value from a reference to non-copyable type 'Microsoft.AspNetCore.Razor.Telemetry.TelemetryScope'

Check failure on line 26 in src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/Telemetry/NoOpTelemetryReporter.cs

View check run for this annotation

Azure Pipelines / razor-tooling-ci (Build Linux debug)

src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/Telemetry/NoOpTelemetryReporter.cs#L26

src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/Telemetry/NoOpTelemetryReporter.cs(26,12): error RS0042: (NETCORE_ENGINEERING_TELEMETRY=Build) Cannot return a value from a reference to non-copyable type 'Microsoft.AspNetCore.Razor.Telemetry.TelemetryScope'

Check failure on line 26 in src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/Telemetry/NoOpTelemetryReporter.cs

View check run for this annotation

Azure Pipelines / razor-tooling-ci (Build Linux release)

src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/Telemetry/NoOpTelemetryReporter.cs#L26

src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/Telemetry/NoOpTelemetryReporter.cs(26,12): error RS0042: (NETCORE_ENGINEERING_TELEMETRY=Build) Cannot return a value from a reference to non-copyable type 'Microsoft.AspNetCore.Razor.Telemetry.TelemetryScope'

Check failure on line 26 in src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/Telemetry/NoOpTelemetryReporter.cs

View check run for this annotation

Azure Pipelines / razor-tooling-ci

src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/Telemetry/NoOpTelemetryReporter.cs#L26

src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/Telemetry/NoOpTelemetryReporter.cs(26,12): error RS0042: (NETCORE_ENGINEERING_TELEMETRY=Build) Cannot return a value from a reference to non-copyable type 'Microsoft.AspNetCore.Razor.Telemetry.TelemetryScope'

public TelemetryScope BeginBlock(string name, Severity severity, params Property[] properties)
public TelemetryScope BeginBlock(string name, Severity severity, TimeSpan minTimeToReport, params ReadOnlySpan<Property> properties)
=> TelemetryScope.Null;

Check failure on line 29 in src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/Telemetry/NoOpTelemetryReporter.cs

View check run for this annotation

Azure Pipelines / razor-tooling-ci (Build macOS debug)

src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/Telemetry/NoOpTelemetryReporter.cs#L29

src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/Telemetry/NoOpTelemetryReporter.cs(29,12): error RS0042: (NETCORE_ENGINEERING_TELEMETRY=Build) Cannot return a value from a reference to non-copyable type 'Microsoft.AspNetCore.Razor.Telemetry.TelemetryScope'

Check failure on line 29 in src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/Telemetry/NoOpTelemetryReporter.cs

View check run for this annotation

Azure Pipelines / razor-tooling-ci (Build macOS release)

src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/Telemetry/NoOpTelemetryReporter.cs#L29

src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/Telemetry/NoOpTelemetryReporter.cs(29,12): error RS0042: (NETCORE_ENGINEERING_TELEMETRY=Build) Cannot return a value from a reference to non-copyable type 'Microsoft.AspNetCore.Razor.Telemetry.TelemetryScope'

Check failure on line 29 in src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/Telemetry/NoOpTelemetryReporter.cs

View check run for this annotation

Azure Pipelines / razor-tooling-ci (Build Linux debug)

src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/Telemetry/NoOpTelemetryReporter.cs#L29

src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/Telemetry/NoOpTelemetryReporter.cs(29,12): error RS0042: (NETCORE_ENGINEERING_TELEMETRY=Build) Cannot return a value from a reference to non-copyable type 'Microsoft.AspNetCore.Razor.Telemetry.TelemetryScope'

Check failure on line 29 in src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/Telemetry/NoOpTelemetryReporter.cs

View check run for this annotation

Azure Pipelines / razor-tooling-ci (Build Linux release)

src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/Telemetry/NoOpTelemetryReporter.cs#L29

src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/Telemetry/NoOpTelemetryReporter.cs(29,12): error RS0042: (NETCORE_ENGINEERING_TELEMETRY=Build) Cannot return a value from a reference to non-copyable type 'Microsoft.AspNetCore.Razor.Telemetry.TelemetryScope'

public void ReportEvent(string name, Severity severity)
{
Expand All @@ -52,8 +52,8 @@
{
}

public TelemetryScope TrackLspRequest(string lspMethodName, string lspServerName, Guid correlationId)
public TelemetryScope TrackLspRequest(string lspMethodName, string lspServerName, TimeSpan minTimeToReport, Guid correlationId)
=> TelemetryScope.Null;

Check failure on line 56 in src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/Telemetry/NoOpTelemetryReporter.cs

View check run for this annotation

Azure Pipelines / razor-tooling-ci (Build macOS release)

src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/Telemetry/NoOpTelemetryReporter.cs#L56

src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/Telemetry/NoOpTelemetryReporter.cs(56,12): error RS0042: (NETCORE_ENGINEERING_TELEMETRY=Build) Cannot return a value from a reference to non-copyable type 'Microsoft.AspNetCore.Razor.Telemetry.TelemetryScope'

public void ReportRequestTiming(string name, string? language, TimeSpan queuedDuration, TimeSpan requestDuration, TelemetryResult result)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@
using System;
using System.Diagnostics;
using Microsoft.AspNetCore.Razor.PooledObjects;
using Microsoft.AspNetCore.Razor.Utilities;

namespace Microsoft.AspNetCore.Razor.Telemetry;

internal sealed class TelemetryScope : IDisposable
[NonCopyable]
internal struct TelemetryScope : IDisposable
{
public static readonly TelemetryScope Null = new();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now that TelemetryScope is a struct, this is an unnecessary affordance. Plus, there's no such thing as "Null" for a struct. 😄 Please remove these and update all usages to just refer to default.


Expand All @@ -16,11 +18,12 @@ internal sealed class TelemetryScope : IDisposable
private readonly Severity _severity;
private readonly Property[] _properties;
private readonly Stopwatch _stopwatch;
private readonly TimeSpan _minTimeToReport;
private bool _disposed;

private TelemetryScope()
public TelemetryScope()
phil-allen-msft marked this conversation as resolved.
Show resolved Hide resolved
{
// This constructor is only called to initialize the Null instance
// This constructor should be called only to initialize the Null instance
// above. Rather than make _name, _properties, and _stopwatch
// nullable, we use a ! to initialize them to null for this case only.
_reporter = null;
Expand All @@ -32,6 +35,7 @@ private TelemetryScope()
private TelemetryScope(
ITelemetryReporter reporter,
string name,
TimeSpan minTimeToReport,
Severity severity,
Property[] properties)
{
Expand All @@ -45,6 +49,7 @@ private TelemetryScope(
_properties = properties;

_stopwatch = StopwatchPool.Default.Get();
_minTimeToReport = minTimeToReport;
_stopwatch.Restart();
}

Expand All @@ -59,54 +64,57 @@ public void Dispose()

_stopwatch.Stop();

// We know that we were created with an array of at least length one.
_properties[^1] = new("eventscope.ellapsedms", _stopwatch.ElapsedMilliseconds);
var elapsed = _stopwatch.Elapsed;
if (elapsed >= _minTimeToReport)
{
// We know that we were created with an array of at least length one.
_properties[^1] = new("eventscope.ellapsedms", _stopwatch.ElapsedMilliseconds);

_reporter.ReportEvent(_name, _severity, _properties);
_reporter.ReportEvent(_name, _severity, _properties);
}

StopwatchPool.Default.Return(_stopwatch);
}

public static TelemetryScope Create(ITelemetryReporter reporter, string name, Severity severity)
public static TelemetryScope Create(ITelemetryReporter reporter, string name, Severity severity, TimeSpan minTimeToReport)
{
var array = new Property[1];

return new(reporter, name, severity, array);
return new(reporter, name, minTimeToReport, severity, array);
}

public static TelemetryScope Create(ITelemetryReporter reporter, string name, Severity severity, Property property)
public static TelemetryScope Create(ITelemetryReporter reporter, string name, Severity severity, TimeSpan minTimeToReport, Property property)
{
var array = new Property[2];
array[0] = property;

return new(reporter, name, severity, array);
return new(reporter, name, minTimeToReport, severity, array);
}

public static TelemetryScope Create(ITelemetryReporter reporter, string name, Severity severity, Property property1, Property property2)
public static TelemetryScope Create(ITelemetryReporter reporter, string name, Severity severity, TimeSpan minTimeToReport, Property property1, Property property2)
{
var array = new Property[3];
array[0] = property1;
array[1] = property2;

return new(reporter, name, severity, array);
return new(reporter, name, minTimeToReport, severity, array);
}

public static TelemetryScope Create(ITelemetryReporter reporter, string name, Severity severity, Property property1, Property property2, Property property3)
public static TelemetryScope Create(ITelemetryReporter reporter, string name, Severity severity, TimeSpan minTimeToReport, Property property1, Property property2, Property property3)
{
var array = new Property[4];
array[0] = property1;
array[1] = property2;
array[2] = property3;

return new(reporter, name, severity, array);
return new(reporter, name, minTimeToReport, severity, array);
}

public static TelemetryScope Create(ITelemetryReporter reporter, string name, Severity severity, Property[] properties)
public static TelemetryScope Create(ITelemetryReporter reporter, string name, Severity severity, TimeSpan minTimeToReport, ReadOnlySpan<Property> properties)
{
var array = new Property[properties.Length + 1];

Array.Copy(properties, array, properties.Length);

return new(reporter, name, severity, array);
properties.CopyTo(array);

return new(reporter, name, minTimeToReport, severity, array);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the MIT license. See License.txt in the project root for license information.

using System;

namespace Microsoft.CodeAnalysis.Razor.Workspaces.Telemetry;

/// <summary>
/// A set of constants used to reduce the telemetry emitted to the set that help us understand
/// which LSP is taking the most time in the case that the overall call is lengthy.
/// </summary>
internal static class TelemetryThresholds
{
internal static readonly TimeSpan CodeActionRazorTelemetryThreshold = TimeSpan.FromMilliseconds(2000);
internal static readonly TimeSpan CodeActionSubLSPTelemetryThreshold = TimeSpan.FromMilliseconds(1000);

internal static readonly TimeSpan CompletionRazorTelemetryThreshold = TimeSpan.FromMilliseconds(4000);
internal static readonly TimeSpan CompletionSubLSPTelemetryThreshold = TimeSpan.FromMilliseconds(2000);

internal static readonly TimeSpan DiagnosticsRazorTelemetryThreshold = TimeSpan.FromMilliseconds(4000);
internal static readonly TimeSpan DiagnosticsSubLSPTelemetryThreshold = TimeSpan.FromMilliseconds(2000);

internal static readonly TimeSpan MapCodeRazorTelemetryThreshold = TimeSpan.FromMilliseconds(2000);
internal static readonly TimeSpan MapCodeSubLSPTelemetryThreshold = TimeSpan.FromMilliseconds(1000);

internal static readonly TimeSpan SemanticTokensRazorTelemetryThreshold = TimeSpan.FromMilliseconds(2000);
internal static readonly TimeSpan SemanticTokensSubLSPTelemetryThreshold = TimeSpan.FromMilliseconds(1000);
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
using Microsoft.CodeAnalysis.Razor.ProjectSystem;
using Microsoft.CodeAnalysis.Razor.SemanticTokens;
using Microsoft.CodeAnalysis.Razor.Workspaces;
using Microsoft.CodeAnalysis.Razor.Workspaces.Telemetry;
using Microsoft.CodeAnalysis.Remote.Razor.ProjectSystem;
using Microsoft.CodeAnalysis.Text;

Expand All @@ -26,7 +27,10 @@ internal class RemoteCSharpSemanticTokensProvider(IFilePathService filePathServi

public async Task<int[]?> GetCSharpSemanticTokensResponseAsync(DocumentContext documentContext, ImmutableArray<LinePositionSpan> csharpRanges, Guid correlationId, CancellationToken cancellationToken)
{
using var _ = _telemetryReporter.TrackLspRequest(nameof(SemanticTokensRange.GetSemanticTokensAsync), Constants.ExternalAccessServerName, correlationId);
using var _ = _telemetryReporter.TrackLspRequest(nameof(SemanticTokensRange.GetSemanticTokensAsync),
Constants.ExternalAccessServerName,
TelemetryThresholds.SemanticTokensRazorTelemetryThreshold,
correlationId);

// We have a razor document, lets find the generated C# document
Debug.Assert(documentContext is RemoteDocumentContext, "This method only works on document snapshots created in the OOP process");
Expand Down
Loading
Loading