File: ErrorReporting\VisualStudioErrorReportingService.cs
Web Access
Project: src\src\VisualStudio\Core\Def\Microsoft.VisualStudio.LanguageServices_ozsccwvc_wpftmp.csproj (Microsoft.VisualStudio.LanguageServices)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
 
using System;
using System.Collections.Generic;
using System.Composition;
using Microsoft.CodeAnalysis.Editor.Shared.Utilities;
using Microsoft.CodeAnalysis.Host.Mef;
using Microsoft.CodeAnalysis.Internal.Log;
using Microsoft.CodeAnalysis.Shared.TestHooks;
using Microsoft.CodeAnalysis.Telemetry;
using Microsoft.VisualStudio;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Shell.Interop;
 
namespace Microsoft.CodeAnalysis.ErrorReporting;
 
[ExportWorkspaceService(typeof(IErrorReportingService), ServiceLayer.Host), Shared]
internal partial class VisualStudioErrorReportingService : IErrorReportingService
{
    private readonly IThreadingContext _threadingContext;
    private readonly IVsService<IVsActivityLog> _activityLog;
    private readonly IAsynchronousOperationListener _listener;
    private readonly VisualStudioInfoBar _infoBar;
 
    [ImportingConstructor]
    [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
    public VisualStudioErrorReportingService(
        IThreadingContext threadingContext,
        IVsService<SVsActivityLog, IVsActivityLog> activityLog,
        IVsService<SVsInfoBarUIFactory, IVsInfoBarUIFactory> vsInfoBarUIFactory,
        IVsService<SVsShell, IVsShell> vsShell,
        IAsynchronousOperationListenerProvider listenerProvider)
    {
        _threadingContext = threadingContext;
        _activityLog = activityLog;
        _listener = listenerProvider.GetListener(FeatureAttribute.Workspace);
 
        // Attach this info bar to the global shell location for info-bars (independent of any particular window).
        _infoBar = new VisualStudioInfoBar(threadingContext, vsInfoBarUIFactory, vsShell, listenerProvider, windowFrame: null);
    }
 
    public string HostDisplayName => "Visual Studio";
 
    public void ShowGlobalErrorInfo(string message, TelemetryFeatureName featureName, Exception? exception, params InfoBarUI[] items)
    {
        var stackTrace = exception is null ? "" : GetFormattedExceptionStack(exception);
        LogGlobalErrorToActivityLog(message, stackTrace);
        _infoBar.ShowInfoBarMessageFromAnyThread(message, items);
 
        Logger.Log(FunctionId.VS_ErrorReportingService_ShowGlobalErrorInfo, KeyValueLogMessage.Create(LogType.UserAction, m =>
        {
            m["Message"] = message;
            m["FeatureName"] = featureName.ToString();
        }));
    }
 
    public void ShowDetailedErrorInfo(Exception exception)
    {
        var errorInfo = GetFormattedExceptionStack(exception);
        new DetailedErrorInfoDialog(exception.Message, errorInfo).ShowModal();
    }
 
    public void ShowFeatureNotAvailableErrorInfo(string message, TelemetryFeatureName featureName, Exception? exception)
    {
        var infoBarUIs = new List<InfoBarUI>();
 
        if (exception != null)
        {
            infoBarUIs.Add(new InfoBarUI(
                WorkspacesResources.Show_Stack_Trace,
                InfoBarUI.UIKind.HyperLink,
                () => ShowDetailedErrorInfo(exception),
                closeAfterAction: true));
        }
 
        ShowGlobalErrorInfo(message, featureName, exception, [.. infoBarUIs]);
    }
 
    private void LogGlobalErrorToActivityLog(string message, string? detailedError)
    {
        _ = _threadingContext.JoinableTaskFactory.RunAsync(async () =>
        {
            using var _ = _listener.BeginAsyncOperation(nameof(LogGlobalErrorToActivityLog));
 
            await _threadingContext.JoinableTaskFactory.SwitchToMainThreadAsync(_threadingContext.DisposalToken);
 
            var activityLog = await _activityLog.GetValueAsync(_threadingContext.DisposalToken).ConfigureAwait(true);
 
            activityLog.LogEntry(
                (uint)__ACTIVITYLOG_ENTRYTYPE.ALE_ERROR,
                nameof(VisualStudioErrorReportingService),
                string.Join(Environment.NewLine, message, detailedError));
        });
    }
}