|
12 | 12 | using Microsoft.Diagnostics.Monitoring.WebApi;
|
13 | 13 | using Microsoft.Diagnostics.Monitoring.WebApi.Models;
|
14 | 14 | using Microsoft.Extensions.DependencyInjection;
|
| 15 | +using Microsoft.Extensions.Logging; |
15 | 16 | using System;
|
16 | 17 | using System.Collections.Generic;
|
17 | 18 | using System.IO;
|
@@ -876,6 +877,79 @@ await ScenarioRunner.SingleTarget(
|
876 | 877 | });
|
877 | 878 | }
|
878 | 879 |
|
| 880 | + [Fact] |
| 881 | + public async Task Exceptions_ResetState() |
| 882 | + { |
| 883 | + DiagnosticPortHelper.Generate( |
| 884 | + DiagnosticPortConnectionMode.Listen, |
| 885 | + out DiagnosticPortConnectionMode appConnectionMode, |
| 886 | + out string diagnosticPortPath); |
| 887 | + |
| 888 | + Func<Task<(MonitorCollectRunner Runner, HttpClient Client, ApiClient ApiClient)>> createMonitorRunner = async () => |
| 889 | + { |
| 890 | + MonitorCollectRunner toolRunner = new(_outputHelper); |
| 891 | + toolRunner.ConnectionModeViaCommandLine = DiagnosticPortConnectionMode.Listen; |
| 892 | + toolRunner.DiagnosticPortPath = diagnosticPortPath; |
| 893 | + toolRunner.DisableAuthentication = true; |
| 894 | + toolRunner.ConfigurationFromEnvironment.EnableInProcessFeatures(); |
| 895 | + |
| 896 | + await toolRunner.StartAsync(); |
| 897 | + HttpClient httpClient = await toolRunner.CreateHttpClientDefaultAddressAsync(_httpClientFactory); |
| 898 | + ApiClient apiClient = new(_outputHelper, httpClient); |
| 899 | + |
| 900 | + return (toolRunner, httpClient, apiClient); |
| 901 | + }; |
| 902 | + |
| 903 | + var result = await createMonitorRunner(); |
| 904 | + await using MonitorCollectRunner firstRunner = result.Runner; |
| 905 | + using HttpClient firstClient = result.Client; |
| 906 | + ApiClient apiClient = result.ApiClient; |
| 907 | + |
| 908 | + await using AppRunner appRunner = new(_outputHelper, Assembly.GetExecutingAssembly()); |
| 909 | + appRunner.ProfilerLogLevel = LogLevel.Information.ToString("G"); |
| 910 | + appRunner.ConnectionMode = appConnectionMode; |
| 911 | + appRunner.DiagnosticPortPath = diagnosticPortPath; |
| 912 | + appRunner.ScenarioName = TestAppScenarios.Exceptions.Name; |
| 913 | + appRunner.SubScenarioName = TestAppScenarios.Exceptions.SubScenarios.MultiPhase; |
| 914 | + appRunner.EnableMonitorStartupHook = true; |
| 915 | + |
| 916 | + await appRunner.ExecuteAsync(async () => |
| 917 | + { |
| 918 | + await GetExceptions(apiClient, appRunner, ExceptionFormat.PlainText); |
| 919 | + |
| 920 | + ValidateSingleExceptionText( |
| 921 | + SystemInvalidOperationException, |
| 922 | + ExceptionMessage, |
| 923 | + FrameTypeName, |
| 924 | + FrameMethodName, |
| 925 | + new List<string> { SimpleFrameParameterType, SimpleFrameParameterType }); |
| 926 | + |
| 927 | + await firstRunner.StopAsync(); |
| 928 | + await firstRunner.DisposeAsync(); |
| 929 | + |
| 930 | + result = await createMonitorRunner(); |
| 931 | + await using MonitorCollectRunner secondRunner = result.Runner; |
| 932 | + using HttpClient secondClient = result.Client; |
| 933 | + ApiClient secondApiClient = result.ApiClient; |
| 934 | + |
| 935 | + // We cannot resume the scenario immediately against the second runner. |
| 936 | + // If the target application throws the second exception while we are starting up, it will be missed. |
| 937 | + // We wait until the process is perceived by dotnet-monitor. |
| 938 | + int appPid = await appRunner.ProcessIdTask; |
| 939 | + |
| 940 | + _ = await secondApiClient.GetProcessWithRetryAsync(_outputHelper, pid: appPid); |
| 941 | + |
| 942 | + await GetExceptions(secondApiClient, appRunner, ExceptionFormat.PlainText); |
| 943 | + |
| 944 | + ValidateSingleExceptionText( |
| 945 | + SystemInvalidOperationException, |
| 946 | + ExceptionMessage, |
| 947 | + FrameTypeName, |
| 948 | + FrameMethodName, |
| 949 | + new List<string> { SimpleFrameParameterType, SimpleFrameParameterType }); |
| 950 | + }); |
| 951 | + } |
| 952 | + |
879 | 953 | private void ValidateMultipleExceptionsText(int exceptionsCount, List<string> exceptionTypes)
|
880 | 954 | {
|
881 | 955 | var exceptions = exceptionsResult.Split(new[] { FirstChanceExceptionMessage }, StringSplitOptions.RemoveEmptyEntries);
|
@@ -979,15 +1053,15 @@ private async Task GetExceptions(ApiClient apiClient, AppRunner appRunner, Excep
|
979 | 1053 | int processId = await appRunner.ProcessIdTask;
|
980 | 1054 |
|
981 | 1055 | await RetryUtilities.RetryAsync(
|
982 |
| - () => CaptureExtensions(apiClient, processId, format, configuration), |
| 1056 | + () => CaptureExceptions(apiClient, processId, format, configuration), |
983 | 1057 | shouldRetry: (Exception ex) => ex is ArgumentException,
|
984 | 1058 | maxRetryCount: 5,
|
985 | 1059 | outputHelper: _outputHelper);
|
986 | 1060 |
|
987 | 1061 | await appRunner.SendCommandAsync(TestAppScenarios.Exceptions.Commands.End);
|
988 | 1062 | }
|
989 | 1063 |
|
990 |
| - private async Task CaptureExtensions(ApiClient apiClient, int processId, ExceptionFormat format, ExceptionsConfiguration configuration) |
| 1064 | + private async Task CaptureExceptions(ApiClient apiClient, int processId, ExceptionFormat format, ExceptionsConfiguration configuration) |
991 | 1065 | {
|
992 | 1066 | await Task.Delay(500);
|
993 | 1067 |
|
|
0 commit comments