diff --git a/eng/Versions.props b/eng/Versions.props index 7ab37a7343..c70d7b69fb 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -110,6 +110,7 @@ $(MicrosoftVisualStudioShellPackagesVersion) $(MicrosoftVisualStudioShellPackagesVersion) 17.3.3-alpha + 16.4.137 $(MicrosoftVisualStudioPackagesVersion) $(MicrosoftVisualStudioPackagesVersion) $(MicrosoftVisualStudioPackagesVersion) diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer.Common/Microsoft.AspNetCore.Razor.LanguageServer.Common.csproj b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer.Common/Microsoft.AspNetCore.Razor.LanguageServer.Common.csproj index 28787dee7a..485d28d874 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer.Common/Microsoft.AspNetCore.Razor.LanguageServer.Common.csproj +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer.Common/Microsoft.AspNetCore.Razor.LanguageServer.Common.csproj @@ -8,9 +8,10 @@ - - - + + + + diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer.Common/Telemetry/ITelemetryReporter.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer.Common/Telemetry/ITelemetryReporter.cs new file mode 100644 index 0000000000..e61476f8fa --- /dev/null +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer.Common/Telemetry/ITelemetryReporter.cs @@ -0,0 +1,12 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT license. See License.txt in the project root for license information. + +using Microsoft.VisualStudio.Telemetry; + +namespace Microsoft.AspNetCore.Razor.LanguageServer.Common.Telemetry +{ + internal interface ITelemetryReporter + { + void ReportEvent(string name, TelemetrySeverity severity); + } +} diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/RazorLanguageServer.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/RazorLanguageServer.cs index 6ecb83e392..a4a9f20206 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/RazorLanguageServer.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/RazorLanguageServer.cs @@ -2,6 +2,7 @@ // Licensed under the MIT license. See License.txt in the project root for license information. using System; +using System.Collections.Immutable; using System.IO; using System.Linq; using System.Reflection; @@ -10,6 +11,7 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Razor.LanguageServer.AutoInsert; using Microsoft.AspNetCore.Razor.LanguageServer.CodeActions; using Microsoft.AspNetCore.Razor.LanguageServer.Common; +using Microsoft.AspNetCore.Razor.LanguageServer.Common.Telemetry; using Microsoft.AspNetCore.Razor.LanguageServer.Completion; using Microsoft.AspNetCore.Razor.LanguageServer.Completion.Delegation; using Microsoft.AspNetCore.Razor.LanguageServer.Debugging; @@ -30,6 +32,7 @@ using Microsoft.AspNetCore.Razor.LanguageServer.Refactoring; using Microsoft.AspNetCore.Razor.LanguageServer.Semantic; using Microsoft.AspNetCore.Razor.LanguageServer.Serialization; using Microsoft.AspNetCore.Razor.LanguageServer.SignatureHelp; +using Microsoft.AspNetCore.Razor.LanguageServer.Telemetry; using Microsoft.AspNetCore.Razor.LanguageServer.Tooltip; using Microsoft.AspNetCore.Razor.LanguageServer.WrapWithTag; using Microsoft.CodeAnalysis.Razor; @@ -41,6 +44,7 @@ using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Microsoft.VisualStudio.Editor.Razor; +using Microsoft.VisualStudio.Telemetry; using Newtonsoft.Json.Linq; using OmniSharp.Extensions.JsonRpc; using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; @@ -306,6 +310,12 @@ namespace Microsoft.AspNetCore.Razor.LanguageServer // Defaults: For when the caller hasn't provided them through the `configure` action. services.TryAddSingleton(); + + // Get the DefaultSession for telemetry. This is set by VS with + // TelemetryService.SetDefaultSession and provides the correct + // appinsights keys etc + services.AddSingleton(provider => + new TelemetryReporter(ImmutableArray.Create(TelemetryService.DefaultSession), provider.GetRequiredService())); })); try diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Telemetry/TelemetryReporter.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Telemetry/TelemetryReporter.cs new file mode 100644 index 0000000000..6c05d96f96 --- /dev/null +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Telemetry/TelemetryReporter.cs @@ -0,0 +1,50 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT license. See License.txt in the project root for license information. + +using System; +using System.Collections.Immutable; +using Microsoft.AspNetCore.Razor.LanguageServer.Common.Telemetry; +using Microsoft.Extensions.Logging; +using Microsoft.VisualStudio.Telemetry; + +namespace Microsoft.AspNetCore.Razor.LanguageServer.Telemetry +{ + internal class TelemetryReporter : ITelemetryReporter + { + private readonly ImmutableArray _telemetrySessions; + private readonly ILogger _logger; + + public TelemetryReporter(ImmutableArray telemetrySessions, ILoggerFactory loggerFactory) + { + _telemetrySessions = telemetrySessions; + _logger = loggerFactory.CreateLogger(); + } + + public void ReportEvent(string name, TelemetrySeverity severity) + { + var telemetryEvent = new TelemetryEvent(name, severity); + Report(telemetryEvent); + } + + private void Report(TelemetryEvent telemetryEvent) + { + try + { + foreach (var session in _telemetrySessions) + { + session.PostEvent(telemetryEvent); + } + } + catch (OutOfMemoryException) + { + // Do we want to failfast like Roslyn here? + } + catch (Exception e) + { + // No need to do anything here. We failed to report telemetry + // which isn't good, but not catastrophic for a user + _logger.LogError(e, "Failed logging telemetry event"); + } + } + } +}