From 90de7b8c9f70d370976bfb532937480332e535d0 Mon Sep 17 00:00:00 2001 From: Joe Schmitt Date: Wed, 3 Jul 2024 11:23:25 -0700 Subject: [PATCH 1/2] Enable nullable aware context --- .../CorsConfigurationOptions.cs | 2 +- .../ExceptionsDebugOptionsExtensions.cs | 2 +- .../Controllers/DiagController.cs | 4 +- .../DiagProcessFilter.cs | 6 +- .../Exceptions/ExceptionInstance.cs | 2 +- .../Exceptions/ExceptionsSettingsFactory.cs | 2 +- .../ICollectionRuleService.cs | 2 +- .../IDiagnosticServices.cs | 6 +- .../ITraceOperationFactory.cs | 2 +- .../ActionListExecutorTests.cs | 17 ++- ...ics.Monitoring.Tool.FunctionalTests.csproj | 1 + .../ActionDependencyAnalyzerTests.cs | 6 +- .../EgressExtensibilityTests.cs | 9 +- .../dotnet-monitor/ActivityExtensions.cs | 6 +- .../dotnet-monitor/AddressListenResults.cs | 4 +- .../AddressListenResultsStartupLogger.cs | 4 + .../Auth/ApiKey/JwtBearerChangeTokenSource.cs | 4 +- .../Auth/ApiKey/JwtBearerPostConfigure.cs | 6 +- .../ApiKey/MonitorApiKeyAuthConfigurator.cs | 4 +- .../ApiKey/MonitorApiKeyChangeTokenSource.cs | 4 +- .../Auth/ApiKey/MonitorApiKeyConfiguration.cs | 8 +- .../MonitorApiKeyConfigurationObserver.cs | 2 +- .../Auth/ApiKey/MonitorApiKeyPostConfigure.cs | 6 +- .../Auth/ApiKey/RejectAllSecurityValidator.cs | 2 +- .../Auth/ApiKey/UserAuthorizationHandler.cs | 9 +- .../Auth/AuthConfiguratorFactory.cs | 4 +- .../CollectionRules/ActionListExecutor.cs | 10 +- .../ActionOptionsDependencyAnalyzer.cs | 41 +++-- .../Actions/CollectDumpAction.cs | 2 +- .../Actions/CollectExceptionsAction.cs | 2 +- .../Actions/CollectGCDumpAction.cs | 2 +- .../Actions/CollectLiveMetricsAction.cs | 2 +- .../Actions/CollectLogsAction.cs | 4 +- .../Actions/CollectStacksAction.cs | 2 +- .../Actions/CollectTraceAction.cs | 6 +- .../Actions/CollectionRuleActionBase.cs | 10 +- .../CollectionRuleActionFactoryProxy.cs | 2 + .../Actions/CollectionRuleActionOperations.cs | 2 + .../Actions/CollectionRuleEgressActionBase.cs | 4 +- .../CollectionRules/Actions/ExecuteAction.cs | 6 +- .../Actions/GetEnvironmentVariableAction.cs | 4 +- .../ICollectionRuleActionFactoryProxy.cs | 2 +- .../ICollectionRuleActionOperations.cs | 2 + .../Actions/LoadProfilerAction.cs | 2 +- .../Actions/SetEnvironmentVariableAction.cs | 2 +- .../CollectionRuleContainer.cs | 36 +++-- .../CollectionRules/CollectionRuleContext.cs | 6 +- .../CollectionRules/CollectionRulePipeline.cs | 30 ++-- .../CollectionRules/CollectionRuleService.cs | 8 +- .../CollectionRuleConfigureNamedOptions.cs | 2 + ...CollectionRulePostConfigureNamedOptions.cs | 2 + .../CollectionRuleTriggerDescriptor.cs | 2 +- .../CollectionRulesConfigurationProvider.cs | 2 +- .../ICollectionRuleTriggerDescriptor.cs | 2 +- .../TemplatesConfigureNamedOptions.cs | 28 ++-- .../Actions/CollectLogsOptions.Validate.cs | 6 +- .../Actions/CollectTraceOptions.Validate.cs | 40 +++-- .../Options/Actions/RequiredGuidAttribute.cs | 2 +- .../ValidateEgressProviderAttribute.cs | 8 +- .../Options/CollectionRuleOptions.Validate.cs | 2 + ...faultCollectionRulePostConfigureOptions.cs | 14 +- .../Options/ValidationHelper.cs | 2 + .../CollectionRuleTriggerFactoryProxy.cs | 4 +- .../CollectionRuleTriggerOperations.cs | 2 + .../ICollectionRuleTriggerFactoryProxy.cs | 2 +- .../ICollectionRuleTriggerOperations.cs | 2 +- .../Commands/CollectCommandHandler.cs | 4 +- .../Commands/ConfigShowCommandHandler.cs | 4 +- .../Commands/GenerateApiKeyCommandHandler.cs | 6 +- .../dotnet-monitor/CommonOptionsExtensions.cs | 12 +- .../dotnet-monitor/ConfigurationExtensions.cs | 7 +- .../dotnet-monitor/ConfigurationJsonWriter.cs | 30 ++-- .../ConfigurationTokenParser.cs | 12 +- src/Tools/dotnet-monitor/ConvertUtils.cs | 16 ++ .../DataAnnotationValidateOptions.cs | 6 +- .../DiagnosticLifetimeBackgroundService.cs | 6 +- .../DiagnosticPortPostConfigureOptions.cs | 2 +- .../DiagnosticPortStartupLogger.cs | 2 + .../DiagnosticPortValidateOptions.cs | 2 +- src/Tools/dotnet-monitor/DisposableHelper.cs | 6 +- src/Tools/dotnet-monitor/DotNetHost.Unix.cs | 7 +- .../dotnet-monitor/DotNetHost.Windows.cs | 5 +- src/Tools/dotnet-monitor/DotNetHost.cs | 9 +- .../DynamicNamedOptionsCache.cs | 2 + .../EgressConfigurationProvider.cs | 2 + .../Egress/EgressArtifactSettings.cs | 2 + .../Egress/EgressProviderSource.cs | 6 +- .../dotnet-monitor/Egress/EgressService.cs | 2 + .../Egress/Extension/EgressArtifactResult.cs | 2 + .../Extension/EgressExtension.OutputParser.cs | 2 + .../Egress/Extension/EgressExtension.cs | 2 + .../Extension/ExtensionEgressPayload.cs | 2 + .../FileSystem/FileSystemEgressExtension.cs | 7 +- .../EndpointInfo/ClientEndpointInfoSource.cs | 4 +- .../EndpointInfo/EndpointInfo.cs | 23 +-- .../EndpointInfo/ScopedEndpointInfo.cs | 10 +- .../EndpointInfo/ServerEndpointInfoSource.cs | 2 + .../EventExceptionsPipelineNameCache.cs | 4 +- .../Exceptions/ExceptionsOperation.cs | 4 +- .../Exceptions/ExceptionsStore.cs | 10 +- .../ExceptionsStoreLimitsCallback.cs | 12 +- .../Extensibility/ExtensionManifest.cs | 2 + .../FolderExtensionRepository.cs | 2 + .../WellKnownExtensionRepository.cs | 2 + .../HostBuilder/HostBuilderHelper.cs | 15 +- .../HostBuilder/HostBuilderSettings.cs | 22 +-- .../HostBuilder/HostBuilderStartupLogger.cs | 2 +- ...ServerUrlsBlockingConfigurationProvider.cs | 5 +- .../InProcessPostConfigureOptions.cs | 2 +- .../DefaultSharedLibraryInitializer.cs | 2 +- .../DefaultSharedLibraryPathProvider.cs | 11 +- src/Tools/dotnet-monitor/LoggingEventIds.cs | 4 +- src/Tools/dotnet-monitor/LoggingExtensions.cs | 144 +++++++++--------- .../dotnet-monitor/MetricsPortsProvider.cs | 2 + .../CaptureParametersOperation.cs | 16 +- .../CapturedParametersBuilder.cs | 3 +- .../CapturedParametersWriter.cs | 2 +- .../EventParameterCapturingPipeline.cs | 36 ++--- .../PipelineArtifactOperation.cs | 4 +- .../Profiler/ProfilerService.cs | 6 +- src/Tools/dotnet-monitor/RuntimeInfo.cs | 2 +- .../StartupHook/StartupHookApplicator.cs | 11 +- .../StoragePostConfigureOptions.cs | 2 +- .../UnauthorizedResponseOperationFilter.cs | 2 +- .../Swagger/SwaggerGenOptionsExtensions.cs | 3 +- src/Tools/dotnet-monitor/TestAssemblies.cs | 13 +- .../dotnet-monitor/Trace/TraceOperation.cs | 2 +- .../Trace/TraceOperationFactory.cs | 2 +- .../Trace/TraceUntilEventOperation.cs | 10 +- .../ValidationResultExtensions.cs | 16 ++ .../dotnet-monitor/dotnet-monitor.csproj | 1 + 131 files changed, 609 insertions(+), 404 deletions(-) create mode 100644 src/Tools/dotnet-monitor/ConvertUtils.cs create mode 100644 src/Tools/dotnet-monitor/ValidationResultExtensions.cs diff --git a/src/Microsoft.Diagnostics.Monitoring.Options/CorsConfigurationOptions.cs b/src/Microsoft.Diagnostics.Monitoring.Options/CorsConfigurationOptions.cs index 86398d68b90..c2b905fb636 100644 --- a/src/Microsoft.Diagnostics.Monitoring.Options/CorsConfigurationOptions.cs +++ b/src/Microsoft.Diagnostics.Monitoring.Options/CorsConfigurationOptions.cs @@ -13,6 +13,6 @@ public class CorsConfigurationOptions [Required] public string AllowedOrigins { get; set; } = string.Empty; - public string[]? GetOrigins() => AllowedOrigins?.Split(';'); + public string[] GetOrigins() => AllowedOrigins.Split(';'); } } diff --git a/src/Microsoft.Diagnostics.Monitoring.Options/ExceptionsDebugOptionsExtensions.cs b/src/Microsoft.Diagnostics.Monitoring.Options/ExceptionsDebugOptionsExtensions.cs index 0e5cee50c1d..9c086e2a6c0 100644 --- a/src/Microsoft.Diagnostics.Monitoring.Options/ExceptionsDebugOptionsExtensions.cs +++ b/src/Microsoft.Diagnostics.Monitoring.Options/ExceptionsDebugOptionsExtensions.cs @@ -5,7 +5,7 @@ namespace Microsoft.Diagnostics.Monitoring.Options { internal static class ExceptionsDebugOptionsExtensions { - public static bool GetIncludeMonitorExceptions(this ExceptionsDebugOptions options) + public static bool GetIncludeMonitorExceptions(this ExceptionsDebugOptions? options) { return (options?.IncludeMonitorExceptions).GetValueOrDefault(ExceptionsDebugOptionsDefaults.IncludeMonitorExceptions); } diff --git a/src/Microsoft.Diagnostics.Monitoring.WebApi/Controllers/DiagController.cs b/src/Microsoft.Diagnostics.Monitoring.WebApi/Controllers/DiagController.cs index 7c753a47003..d3b60e46165 100644 --- a/src/Microsoft.Diagnostics.Monitoring.WebApi/Controllers/DiagController.cs +++ b/src/Microsoft.Diagnostics.Monitoring.WebApi/Controllers/DiagController.cs @@ -547,7 +547,7 @@ public Task>> GetColl [HttpGet("collectionrules/{collectionRuleName}", Name = nameof(GetCollectionRuleDetailedDescription))] [ProducesWithProblemDetails(ContentTypes.ApplicationJson)] [ProducesResponseType(typeof(CollectionRuleDetailedDescription), StatusCodes.Status200OK)] - public Task> GetCollectionRuleDetailedDescription( + public Task> GetCollectionRuleDetailedDescription( string collectionRuleName, [FromQuery] int? pid = null, @@ -556,7 +556,7 @@ public Task> GetCollectionRuleDe [FromQuery] string? name = null) { - return InvokeForProcess(processInfo => + return InvokeForProcess(processInfo => { return _collectionRuleService.GetCollectionRuleDetailedDescription(collectionRuleName, processInfo.EndpointInfo); }, diff --git a/src/Microsoft.Diagnostics.Monitoring.WebApi/DiagProcessFilter.cs b/src/Microsoft.Diagnostics.Monitoring.WebApi/DiagProcessFilter.cs index 3a417960008..e3ba066d01f 100644 --- a/src/Microsoft.Diagnostics.Monitoring.WebApi/DiagProcessFilter.cs +++ b/src/Microsoft.Diagnostics.Monitoring.WebApi/DiagProcessFilter.cs @@ -159,7 +159,7 @@ public bool MatchFilter(IProcessInfo processInfo) return false; } - private bool Compare(string value) + private bool Compare(string? value) { if (MatchType == DiagProcessFilterMatchType.Exact) { @@ -174,12 +174,12 @@ private bool Compare(string value) return false; } - private bool ExactCompare(string value) + private bool ExactCompare(string? value) { return string.Equals(Value, value, StringComparison.OrdinalIgnoreCase); } - private bool ContainsCompare(string value) + private bool ContainsCompare(string? value) { return value?.IndexOf(Value, StringComparison.OrdinalIgnoreCase) > -1; } diff --git a/src/Microsoft.Diagnostics.Monitoring.WebApi/Exceptions/ExceptionInstance.cs b/src/Microsoft.Diagnostics.Monitoring.WebApi/Exceptions/ExceptionInstance.cs index 977b3aeeffa..2a144a895f7 100644 --- a/src/Microsoft.Diagnostics.Monitoring.WebApi/Exceptions/ExceptionInstance.cs +++ b/src/Microsoft.Diagnostics.Monitoring.WebApi/Exceptions/ExceptionInstance.cs @@ -7,7 +7,7 @@ namespace Microsoft.Diagnostics.Monitoring.WebApi.Exceptions { - internal record class ExceptionInstance(ulong Id, string TypeName, string ModuleName, string Message, DateTime Timestamp, CallStack CallStack, ulong[] InnerExceptionIds, string ActivityId, ActivityIdFormat ActivityIdFormat) + internal record class ExceptionInstance(ulong Id, string TypeName, string ModuleName, string Message, DateTime Timestamp, CallStack? CallStack, ulong[] InnerExceptionIds, string ActivityId, ActivityIdFormat ActivityIdFormat) : IExceptionInstance { } diff --git a/src/Microsoft.Diagnostics.Monitoring.WebApi/Exceptions/ExceptionsSettingsFactory.cs b/src/Microsoft.Diagnostics.Monitoring.WebApi/Exceptions/ExceptionsSettingsFactory.cs index 465f1bce77d..3bff5176f8b 100644 --- a/src/Microsoft.Diagnostics.Monitoring.WebApi/Exceptions/ExceptionsSettingsFactory.cs +++ b/src/Microsoft.Diagnostics.Monitoring.WebApi/Exceptions/ExceptionsSettingsFactory.cs @@ -10,7 +10,7 @@ namespace Microsoft.Diagnostics.Monitoring.WebApi.Exceptions /// internal static class ExceptionsSettingsFactory { - public static ExceptionsConfigurationSettings ConvertExceptionsConfiguration(ExceptionsConfiguration configuration) + public static ExceptionsConfigurationSettings ConvertExceptionsConfiguration(ExceptionsConfiguration? configuration) { ExceptionsConfigurationSettings configurationSettings = new(); diff --git a/src/Microsoft.Diagnostics.Monitoring.WebApi/ICollectionRuleService.cs b/src/Microsoft.Diagnostics.Monitoring.WebApi/ICollectionRuleService.cs index 3187db73aab..6ff1be7cfa6 100644 --- a/src/Microsoft.Diagnostics.Monitoring.WebApi/ICollectionRuleService.cs +++ b/src/Microsoft.Diagnostics.Monitoring.WebApi/ICollectionRuleService.cs @@ -12,6 +12,6 @@ internal interface ICollectionRuleService : IHostedService, IAsyncDisposable { Dictionary GetCollectionRulesDescriptions(IEndpointInfo endpointInfo); - CollectionRuleDetailedDescription GetCollectionRuleDetailedDescription(string collectionRuleName, IEndpointInfo endpointInfo); + CollectionRuleDetailedDescription? GetCollectionRuleDetailedDescription(string collectionRuleName, IEndpointInfo endpointInfo); } } diff --git a/src/Microsoft.Diagnostics.Monitoring.WebApi/IDiagnosticServices.cs b/src/Microsoft.Diagnostics.Monitoring.WebApi/IDiagnosticServices.cs index b82beb50fee..73bea9d86e5 100644 --- a/src/Microsoft.Diagnostics.Monitoring.WebApi/IDiagnosticServices.cs +++ b/src/Microsoft.Diagnostics.Monitoring.WebApi/IDiagnosticServices.cs @@ -33,11 +33,11 @@ public interface IProcessInfo { IEndpointInfo EndpointInfo { get; } - string CommandLine { get; } + string? CommandLine { get; } - public string OperatingSystem { get; } + public string? OperatingSystem { get; } - public string ProcessArchitecture { get; } + public string? ProcessArchitecture { get; } string ProcessName { get; } } diff --git a/src/Microsoft.Diagnostics.Monitoring.WebApi/ITraceOperationFactory.cs b/src/Microsoft.Diagnostics.Monitoring.WebApi/ITraceOperationFactory.cs index f5964f75801..4dce4e49ed9 100644 --- a/src/Microsoft.Diagnostics.Monitoring.WebApi/ITraceOperationFactory.cs +++ b/src/Microsoft.Diagnostics.Monitoring.WebApi/ITraceOperationFactory.cs @@ -29,6 +29,6 @@ IArtifactOperation Create( TimeSpan duration, string providerName, string eventName, - IDictionary payloadFilter); + IDictionary? payloadFilter); } } diff --git a/src/Tests/CollectionRuleActions.UnitTests/ActionListExecutorTests.cs b/src/Tests/CollectionRuleActions.UnitTests/ActionListExecutorTests.cs index f5632195bfe..08ebfbc80d6 100644 --- a/src/Tests/CollectionRuleActions.UnitTests/ActionListExecutorTests.cs +++ b/src/Tests/CollectionRuleActions.UnitTests/ActionListExecutorTests.cs @@ -11,6 +11,7 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; +using Moq; using System; using System.Reflection; using System.Threading; @@ -30,6 +31,16 @@ public sealed class ActionListExecutorTests private const string DefaultRuleName = nameof(ActionListExecutorTests); + private static Microsoft.Diagnostics.Monitoring.WebApi.IProcessInfo CreateTestProcess() + { + Mock mockProcessInfo = new(); + mockProcessInfo + .Setup(p => p.EndpointInfo) + .Returns(Mock.Of); + + return mockProcessInfo.Object; + } + public ActionListExecutorTests(ITestOutputHelper outputHelper) { _outputHelper = outputHelper; @@ -54,7 +65,7 @@ await TestHostHelper.CreateCollectionRulesHost(_outputHelper, rootOptions => ILogger logger = host.Services.GetRequiredService>(); TimeProvider timeProvider = host.Services.GetRequiredService(); - CollectionRuleContext context = new(DefaultRuleName, ruleOptions, null, logger, timeProvider); + CollectionRuleContext context = new(DefaultRuleName, ruleOptions, CreateTestProcess(), logger, timeProvider); int callbackCount = 0; Action startCallback = () => callbackCount++; @@ -95,7 +106,7 @@ await TestHostHelper.CreateCollectionRulesHost(_outputHelper, rootOptions => ILogger logger = host.Services.GetRequiredService>(); TimeProvider timeProvider = host.Services.GetRequiredService(); - CollectionRuleContext context = new(DefaultRuleName, ruleOptions, null, logger, timeProvider); + CollectionRuleContext context = new(DefaultRuleName, ruleOptions, CreateTestProcess(), logger, timeProvider); int callbackCount = 0; Action startCallback = () => callbackCount++; @@ -141,7 +152,7 @@ await TestHostHelper.CreateCollectionRulesHost(_outputHelper, rootOptions => ILogger logger = host.Services.GetRequiredService>(); TimeProvider timeProvider = host.Services.GetRequiredService(); - CollectionRuleContext context = new(DefaultRuleName, ruleOptions, null, logger, timeProvider); + CollectionRuleContext context = new(DefaultRuleName, ruleOptions, CreateTestProcess(), logger, timeProvider); int callbackCount = 0; Action startCallback = () => callbackCount++; diff --git a/src/Tests/Microsoft.Diagnostics.Monitoring.Tool.FunctionalTests/Microsoft.Diagnostics.Monitoring.Tool.FunctionalTests.csproj b/src/Tests/Microsoft.Diagnostics.Monitoring.Tool.FunctionalTests/Microsoft.Diagnostics.Monitoring.Tool.FunctionalTests.csproj index 352877b0203..62326ed9299 100644 --- a/src/Tests/Microsoft.Diagnostics.Monitoring.Tool.FunctionalTests/Microsoft.Diagnostics.Monitoring.Tool.FunctionalTests.csproj +++ b/src/Tests/Microsoft.Diagnostics.Monitoring.Tool.FunctionalTests/Microsoft.Diagnostics.Monitoring.Tool.FunctionalTests.csproj @@ -74,6 +74,7 @@ + diff --git a/src/Tests/Microsoft.Diagnostics.Monitoring.Tool.UnitTests/ActionDependencyAnalyzerTests.cs b/src/Tests/Microsoft.Diagnostics.Monitoring.Tool.UnitTests/ActionDependencyAnalyzerTests.cs index 017df523328..8c3407dd765 100644 --- a/src/Tests/Microsoft.Diagnostics.Monitoring.Tool.UnitTests/ActionDependencyAnalyzerTests.cs +++ b/src/Tests/Microsoft.Diagnostics.Monitoring.Tool.UnitTests/ActionDependencyAnalyzerTests.cs @@ -107,7 +107,8 @@ await TestHostHelper.CreateCollectionRulesHost(_outputHelper, rootOptions => ILogger logger = host.Services.GetRequiredService>(); TimeProvider timeProvider = host.Services.GetRequiredService(); - CollectionRuleContext context = new(DefaultRuleName, ruleOptions, null, logger, timeProvider); + Guid instanceId = Guid.NewGuid(); + CollectionRuleContext context = new(DefaultRuleName, ruleOptions, new TestProcessInfo(instanceId), logger, timeProvider); int callbackCount = 0; Action startCallback = () => callbackCount++; @@ -200,7 +201,8 @@ await TestHostHelper.CreateCollectionRulesHost(_outputHelper, rootOptions => ILogger logger = host.Services.GetRequiredService>(); TimeProvider timeProvider = host.Services.GetRequiredService(); - CollectionRuleContext context = new(DefaultRuleName, ruleOptions, null, logger, timeProvider); + Guid instanceId = Guid.NewGuid(); + CollectionRuleContext context = new(DefaultRuleName, ruleOptions, new TestProcessInfo(instanceId), logger, timeProvider); ActionOptionsDependencyAnalyzer analyzer = ActionOptionsDependencyAnalyzer.Create(context); analyzer.GetActionDependencies(1); diff --git a/src/Tests/Microsoft.Diagnostics.Monitoring.Tool.UnitTests/EgressExtensibilityTests.cs b/src/Tests/Microsoft.Diagnostics.Monitoring.Tool.UnitTests/EgressExtensibilityTests.cs index 1683cf95254..c8a44ad4d31 100644 --- a/src/Tests/Microsoft.Diagnostics.Monitoring.Tool.UnitTests/EgressExtensibilityTests.cs +++ b/src/Tests/Microsoft.Diagnostics.Monitoring.Tool.UnitTests/EgressExtensibilityTests.cs @@ -39,7 +39,8 @@ public void FoundExtension_Failure() HostBuilderSettings settings = new() { SharedConfigDirectory = sharedConfigDir.FullName, - UserConfigDirectory = userConfigDir.FullName + UserConfigDirectory = userConfigDir.FullName, + ContentRootDirectory = AppContext.BaseDirectory }; IHost host = TestHostHelper.CreateHost(_outputHelper, rootOptions => { }, host => { }, settings: settings); @@ -61,7 +62,8 @@ public void FoundExtensionFile_Success(ConfigDirectory configDirectory) HostBuilderSettings settings = new() { SharedConfigDirectory = sharedConfigDir.FullName, - UserConfigDirectory = userConfigDir.FullName + UserConfigDirectory = userConfigDir.FullName, + ContentRootDirectory = AppContext.BaseDirectory }; IEgressExtension extension = FindEgressExtension(configDirectory, settings); @@ -96,7 +98,8 @@ private async Task GetExtensionResponse(bool shouldSucceed HostBuilderSettings settings = new() { SharedConfigDirectory = sharedConfigDir.FullName, - UserConfigDirectory = userConfigDir.FullName + UserConfigDirectory = userConfigDir.FullName, + ContentRootDirectory = AppContext.BaseDirectory }; EgressExtension extension = (EgressExtension)FindEgressExtension(ConfigDirectory.UserConfigDirectory, settings); diff --git a/src/Tools/dotnet-monitor/ActivityExtensions.cs b/src/Tools/dotnet-monitor/ActivityExtensions.cs index 670a2db4885..65f0ad71e0d 100644 --- a/src/Tools/dotnet-monitor/ActivityExtensions.cs +++ b/src/Tools/dotnet-monitor/ActivityExtensions.cs @@ -7,7 +7,7 @@ namespace Microsoft.Diagnostics.Tools.Monitor { internal static class ActivityExtensions { - public static string GetSpanId(this Activity activity) + public static string? GetSpanId(this Activity activity) { switch (activity.IdFormat) { @@ -19,7 +19,7 @@ public static string GetSpanId(this Activity activity) return string.Empty; } - public static string GetParentId(this Activity activity) + public static string? GetParentId(this Activity activity) { switch (activity.IdFormat) { @@ -31,7 +31,7 @@ public static string GetParentId(this Activity activity) return string.Empty; } - public static string GetTraceId(this Activity activity) + public static string? GetTraceId(this Activity activity) { switch (activity.IdFormat) { diff --git a/src/Tools/dotnet-monitor/AddressListenResults.cs b/src/Tools/dotnet-monitor/AddressListenResults.cs index 8127bd93a87..51341c1e025 100644 --- a/src/Tools/dotnet-monitor/AddressListenResults.cs +++ b/src/Tools/dotnet-monitor/AddressListenResults.cs @@ -69,7 +69,7 @@ public void Listen(KestrelServerOptions options, IEnumerable defaultUrls /// private bool Listen(KestrelServerOptions options, string url, bool isAuthEnabled) { - BindingAddress address = null; + BindingAddress? address = null; try { address = BindingAddress.Parse(url); @@ -95,7 +95,7 @@ private bool Listen(KestrelServerOptions options, string url, bool isAuthEnabled { options.ListenLocalhost(address.Port, configureListenOptions); } - else if (IPAddress.TryParse(address.Host, out IPAddress ipAddress)) + else if (IPAddress.TryParse(address.Host, out IPAddress? ipAddress)) { options.Listen(ipAddress, address.Port, configureListenOptions); } diff --git a/src/Tools/dotnet-monitor/AddressListenResultsStartupLogger.cs b/src/Tools/dotnet-monitor/AddressListenResultsStartupLogger.cs index 6aab3793c08..e1ab2d915d6 100644 --- a/src/Tools/dotnet-monitor/AddressListenResultsStartupLogger.cs +++ b/src/Tools/dotnet-monitor/AddressListenResultsStartupLogger.cs @@ -29,9 +29,11 @@ public AddressListenResultsStartupLogger( _logger = logger; _server = server; +#nullable disable _applicationStartedRegistration = lifetime.ApplicationStarted.Register( l => ((AddressListenResultsStartupLogger)l).OnStarted(), this); +#nullable restore } public void Dispose() @@ -52,6 +54,7 @@ public void Log() } } +#nullable disable private void OnStarted() { IServerAddressesFeature serverAddresses = _server.Features.Get(); @@ -69,5 +72,6 @@ private void OnStarted() _logger.BoundMetricsAddress(metricAddress); } } +#nullable restore } } diff --git a/src/Tools/dotnet-monitor/Auth/ApiKey/JwtBearerChangeTokenSource.cs b/src/Tools/dotnet-monitor/Auth/ApiKey/JwtBearerChangeTokenSource.cs index 180b655d798..dcfe4555301 100644 --- a/src/Tools/dotnet-monitor/Auth/ApiKey/JwtBearerChangeTokenSource.cs +++ b/src/Tools/dotnet-monitor/Auth/ApiKey/JwtBearerChangeTokenSource.cs @@ -18,7 +18,7 @@ internal sealed class JwtBearerChangeTokenSource : IDisposable { private readonly IOptionsMonitor _optionsMonitor; - private readonly IDisposable _changeRegistration; + private readonly IDisposable? _changeRegistration; private ConfigurationReloadToken _reloadToken = new ConfigurationReloadToken(); @@ -42,7 +42,7 @@ public IChangeToken GetChangeToken() public void Dispose() { - _changeRegistration.Dispose(); + _changeRegistration?.Dispose(); } private void OnReload(MonitorApiKeyConfiguration options) diff --git a/src/Tools/dotnet-monitor/Auth/ApiKey/JwtBearerPostConfigure.cs b/src/Tools/dotnet-monitor/Auth/ApiKey/JwtBearerPostConfigure.cs index d9eab1a6c30..7ab2f048449 100644 --- a/src/Tools/dotnet-monitor/Auth/ApiKey/JwtBearerPostConfigure.cs +++ b/src/Tools/dotnet-monitor/Auth/ApiKey/JwtBearerPostConfigure.cs @@ -21,10 +21,10 @@ public JwtBearerPostConfigure( _apiKeyConfig = apiKeyConfig; } - public void PostConfigure(string name, JwtBearerOptions options) + public void PostConfigure(string? name, JwtBearerOptions options) { MonitorApiKeyConfiguration configSnapshot = _apiKeyConfig.CurrentValue; - if (!configSnapshot.Configured || configSnapshot.ValidationErrors.Any()) + if (!configSnapshot.Configured || configSnapshot.ValidationErrors?.Any() == true) { #if NET8_0_OR_GREATER // https://github.com/aspnet/Announcements/issues/508 @@ -37,7 +37,9 @@ public void PostConfigure(string name, JwtBearerOptions options) return; } +#nullable disable options.ConfigureApiKeyTokenValidation(configSnapshot.PublicKey, configSnapshot.Issuer); +#nullable restore } } } diff --git a/src/Tools/dotnet-monitor/Auth/ApiKey/MonitorApiKeyAuthConfigurator.cs b/src/Tools/dotnet-monitor/Auth/ApiKey/MonitorApiKeyAuthConfigurator.cs index dc31e6b27df..8abb9236591 100644 --- a/src/Tools/dotnet-monitor/Auth/ApiKey/MonitorApiKeyAuthConfigurator.cs +++ b/src/Tools/dotnet-monitor/Auth/ApiKey/MonitorApiKeyAuthConfigurator.cs @@ -17,11 +17,11 @@ namespace Microsoft.Diagnostics.Tools.Monitor.Auth.ApiKey { internal sealed class MonitorApiKeyAuthConfigurator : IAuthenticationConfigurator { - private readonly GeneratedJwtKey _pinnedJwtKey; + private readonly GeneratedJwtKey? _pinnedJwtKey; private readonly bool _enableNegotiation; - public MonitorApiKeyAuthConfigurator(GeneratedJwtKey pinnedJwtKey = null) + public MonitorApiKeyAuthConfigurator(GeneratedJwtKey? pinnedJwtKey = null) { _pinnedJwtKey = pinnedJwtKey; diff --git a/src/Tools/dotnet-monitor/Auth/ApiKey/MonitorApiKeyChangeTokenSource.cs b/src/Tools/dotnet-monitor/Auth/ApiKey/MonitorApiKeyChangeTokenSource.cs index 6f023080d89..b44dac85b36 100644 --- a/src/Tools/dotnet-monitor/Auth/ApiKey/MonitorApiKeyChangeTokenSource.cs +++ b/src/Tools/dotnet-monitor/Auth/ApiKey/MonitorApiKeyChangeTokenSource.cs @@ -17,7 +17,7 @@ internal sealed class MonitorApiKeyChangeTokenSource : IDisposable { private readonly IOptionsMonitor _optionsMonitor; - private readonly IDisposable _changeRegistration; + private readonly IDisposable? _changeRegistration; private ConfigurationReloadToken _reloadToken = new ConfigurationReloadToken(); @@ -37,7 +37,7 @@ public IChangeToken GetChangeToken() public void Dispose() { - _changeRegistration.Dispose(); + _changeRegistration?.Dispose(); } private void OnReload(MonitorApiKeyOptions options) diff --git a/src/Tools/dotnet-monitor/Auth/ApiKey/MonitorApiKeyConfiguration.cs b/src/Tools/dotnet-monitor/Auth/ApiKey/MonitorApiKeyConfiguration.cs index 3a4dec22b22..7313e572031 100644 --- a/src/Tools/dotnet-monitor/Auth/ApiKey/MonitorApiKeyConfiguration.cs +++ b/src/Tools/dotnet-monitor/Auth/ApiKey/MonitorApiKeyConfiguration.cs @@ -16,9 +16,9 @@ namespace Microsoft.Diagnostics.Tools.Monitor.Auth.ApiKey internal class MonitorApiKeyConfiguration : AuthenticationSchemeOptions { public bool Configured { get; set; } - public string Subject { get; set; } - public SecurityKey PublicKey { get; set; } - public IEnumerable ValidationErrors { get; set; } - public string Issuer { get; set; } + public string? Subject { get; set; } + public SecurityKey? PublicKey { get; set; } + public IEnumerable? ValidationErrors { get; set; } + public string? Issuer { get; set; } } } diff --git a/src/Tools/dotnet-monitor/Auth/ApiKey/MonitorApiKeyConfigurationObserver.cs b/src/Tools/dotnet-monitor/Auth/ApiKey/MonitorApiKeyConfigurationObserver.cs index 1309a982320..2c5ca1a190c 100644 --- a/src/Tools/dotnet-monitor/Auth/ApiKey/MonitorApiKeyConfigurationObserver.cs +++ b/src/Tools/dotnet-monitor/Auth/ApiKey/MonitorApiKeyConfigurationObserver.cs @@ -17,7 +17,7 @@ internal class MonitorApiKeyConfigurationObserver : private readonly ILogger _logger; private readonly IOptionsMonitor _options; - private IDisposable _changeRegistration; + private IDisposable? _changeRegistration; public MonitorApiKeyConfigurationObserver( ILogger logger, diff --git a/src/Tools/dotnet-monitor/Auth/ApiKey/MonitorApiKeyPostConfigure.cs b/src/Tools/dotnet-monitor/Auth/ApiKey/MonitorApiKeyPostConfigure.cs index 82918259862..2cae0a91b75 100644 --- a/src/Tools/dotnet-monitor/Auth/ApiKey/MonitorApiKeyPostConfigure.cs +++ b/src/Tools/dotnet-monitor/Auth/ApiKey/MonitorApiKeyPostConfigure.cs @@ -30,7 +30,7 @@ public MonitorApiKeyPostConfigure( _apiKeyOptions = apiKeyOptions; } - public void PostConfigure(string name, MonitorApiKeyConfiguration options) + public void PostConfigure(string? name, MonitorApiKeyConfiguration options) { MonitorApiKeyOptions sourceOptions = _apiKeyOptions.CurrentValue; @@ -54,7 +54,7 @@ public void PostConfigure(string name, MonitorApiKeyConfiguration options) errors, validateAllProperties: true); - string jwkJson = null; + string? jwkJson = null; try { jwkJson = Base64UrlEncoder.Decode(sourceOptions.PublicKey); @@ -70,7 +70,7 @@ public void PostConfigure(string name, MonitorApiKeyConfiguration options) new string[] { nameof(MonitorApiKeyOptions.PublicKey) })); } - JsonWebKey jwk = null; + JsonWebKey? jwk = null; if (!string.IsNullOrEmpty(jwkJson)) { try diff --git a/src/Tools/dotnet-monitor/Auth/ApiKey/RejectAllSecurityValidator.cs b/src/Tools/dotnet-monitor/Auth/ApiKey/RejectAllSecurityValidator.cs index 1fe285dc0bd..16f055a4d53 100644 --- a/src/Tools/dotnet-monitor/Auth/ApiKey/RejectAllSecurityValidator.cs +++ b/src/Tools/dotnet-monitor/Auth/ApiKey/RejectAllSecurityValidator.cs @@ -24,7 +24,7 @@ public int MaximumTokenSizeInBytes public bool CanReadToken(string securityToken) => true; - public ClaimsPrincipal ValidateToken(string securityToken, TokenValidationParameters validationParameters, out SecurityToken validatedToken) + public ClaimsPrincipal ValidateToken(string securityToken, TokenValidationParameters validationParameters, out SecurityToken? validatedToken) { validatedToken = null; throw new InvalidOperationException(Strings.ErrorMessage_ApiKeyNotConfigured); diff --git a/src/Tools/dotnet-monitor/Auth/ApiKey/UserAuthorizationHandler.cs b/src/Tools/dotnet-monitor/Auth/ApiKey/UserAuthorizationHandler.cs index 86b841cee43..bac15350948 100644 --- a/src/Tools/dotnet-monitor/Auth/ApiKey/UserAuthorizationHandler.cs +++ b/src/Tools/dotnet-monitor/Auth/ApiKey/UserAuthorizationHandler.cs @@ -26,14 +26,21 @@ public UserAuthorizationHandler(IOptionsMonitor apiK protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, AuthorizedUserRequirement requirement) { + if (context.User?.Identity == null) + { + return Task.CompletedTask; + } + if (context.User.Identity.AuthenticationType == AuthConstants.FederationAuthType) { // If we get a FederationAuthType (Bearer from a Jwt Token) we need to check that the user has the specified subject claim. MonitorApiKeyConfiguration configSnapshot = _apiKeyConfig.CurrentValue; +#nullable disable if (context.User.HasClaim(ClaimTypes.NameIdentifier, configSnapshot.Subject)) { context.Succeed(requirement); } +#nullable restore } else if ((context.User.Identity.AuthenticationType == AuthConstants.NtlmSchema) || (context.User.Identity.AuthenticationType == AuthConstants.KerberosSchema) || @@ -57,7 +64,7 @@ protected override Task HandleRequirementAsync(AuthorizationHandlerContext conte } using WindowsIdentity currentUser = WindowsIdentity.GetCurrent(); - Claim currentUserClaim = currentUser.Claims.FirstOrDefault(claim => string.Equals(claim.Type, ClaimTypes.PrimarySid)); + Claim? currentUserClaim = currentUser.Claims.FirstOrDefault(claim => string.Equals(claim.Type, ClaimTypes.PrimarySid)); if ((currentUserClaim != null) && context.User.HasClaim(currentUserClaim.Type, currentUserClaim.Value)) { context.Succeed(requirement); diff --git a/src/Tools/dotnet-monitor/Auth/AuthConfiguratorFactory.cs b/src/Tools/dotnet-monitor/Auth/AuthConfiguratorFactory.cs index 28937a9fef3..c4dbc2bab83 100644 --- a/src/Tools/dotnet-monitor/Auth/AuthConfiguratorFactory.cs +++ b/src/Tools/dotnet-monitor/Auth/AuthConfiguratorFactory.cs @@ -29,7 +29,7 @@ public static IAuthenticationConfigurator Create(StartupAuthenticationMode start return new NoAuthConfigurator(); case StartupAuthenticationMode.TemporaryKey: - if (context.Properties.TryGetValue(typeof(GeneratedJwtKey), out object generatedJwtKeyObject)) + if (context.Properties.TryGetValue(typeof(GeneratedJwtKey), out object? generatedJwtKeyObject)) { if (generatedJwtKeyObject is GeneratedJwtKey generatedJwtKey) { @@ -62,7 +62,7 @@ public static IAuthenticationConfigurator Create(StartupAuthenticationMode start } } - private static void ValidateAuthConfigSection(T options, string configurationPath) + private static void ValidateAuthConfigSection(T options, string configurationPath) where T : notnull { List results = new(); if (!Validator.TryValidateObject(options, new ValidationContext(options), results, validateAllProperties: true)) diff --git a/src/Tools/dotnet-monitor/CollectionRules/ActionListExecutor.cs b/src/Tools/dotnet-monitor/CollectionRules/ActionListExecutor.cs index 8c3d5d4823c..bafe19a5390 100644 --- a/src/Tools/dotnet-monitor/CollectionRules/ActionListExecutor.cs +++ b/src/Tools/dotnet-monitor/CollectionRules/ActionListExecutor.cs @@ -58,7 +58,7 @@ public async Task> ExecuteAction { KeyValueLogScope actionScope = new(); actionScope.AddCollectionRuleAction(actionOption.Type, actionIndex); - using IDisposable actionScopeRegistration = _logger.BeginScope(actionScope); + using IDisposable? actionScopeRegistration = _logger.BeginScope(actionScope); _logger.CollectionRuleActionStarted(context.Name, actionOption.Type); @@ -91,8 +91,8 @@ public async Task> ExecuteAction )); } - object newSettings = dependencyAnalyzer.SubstituteOptionValues(actionResults, actionIndex, actionOption.Settings); - ICollectionRuleAction action = factory.Create(context.ProcessInfo, newSettings); + object? newSettings = dependencyAnalyzer.SubstituteOptionValues(actionResults, actionIndex, actionOption.Settings); + ICollectionRuleAction? action = factory.Create(context.ProcessInfo, newSettings); try { @@ -158,7 +158,7 @@ public async Task> ExecuteAction } private async Task WaitForCompletion(CollectionRuleContext context, - Action startCallback, + Action? startCallback, IDictionary allResults, ICollectionRuleAction action, CollectionRuleActionOptions actionOption, @@ -178,7 +178,7 @@ private async Task WaitForCompletion(CollectionRuleContext context, } private async Task WaitForCompletion(CollectionRuleContext context, - Action startCallback, + Action? startCallback, IDictionary allResults, ActionCompletionEntry entry, CancellationToken cancellationToken) diff --git a/src/Tools/dotnet-monitor/CollectionRules/ActionOptionsDependencyAnalyzer.cs b/src/Tools/dotnet-monitor/CollectionRules/ActionOptionsDependencyAnalyzer.cs index bc92579ed56..dcfab2c920b 100644 --- a/src/Tools/dotnet-monitor/CollectionRules/ActionOptionsDependencyAnalyzer.cs +++ b/src/Tools/dotnet-monitor/CollectionRules/ActionOptionsDependencyAnalyzer.cs @@ -6,6 +6,7 @@ using Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Actions; using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Reflection; using System.Text; @@ -35,7 +36,9 @@ internal sealed class ActionOptionsDependencyAnalyzer private readonly ConfigurationTokenParser _tokenParser; //Use action index instead of name, since it's possible for an unnamed action to have named dependencies. +#nullable disable private Dictionary> _dependencies; +#nullable restore private sealed class PropertyDependency { @@ -87,6 +90,7 @@ private ActionOptionsDependencyAnalyzer(CollectionRuleContext context, Configura _tokenParser = tokenParser ?? throw new ArgumentNullException(nameof(tokenParser)); } +#nullable disable public IList GetActionDependencies(int actionIndex) { if (_dependencies.TryGetValue(actionIndex, out Dictionary properties)) @@ -106,19 +110,21 @@ public IList GetActionDependencies(int actionIndex) } return Array.Empty(); } +#nullable restore - public object SubstituteOptionValues(IDictionary actionResults, int actionIndex, object settings) + public object? SubstituteOptionValues(IDictionary actionResults, int actionIndex, object? settings) { //Attempt to substitute context properties. - object originalSettings = settings; + object? originalSettings = settings; - if (_dependencies.TryGetValue(actionIndex, out Dictionary properties) && (properties.Count > 0)) + if (_dependencies.TryGetValue(actionIndex, out Dictionary? properties) && (properties.Count > 0)) { if (!_tokenParser.TryCloneSettings(originalSettings, ref settings)) { return settings; } +#nullable disable foreach ((_, PropertyDependency property) in properties) { StringBuilder builder = property.ActionDependencies.Any() ? new() : null; @@ -150,16 +156,17 @@ public object SubstituteOptionValues(IDictionary= 0) { @@ -208,7 +217,7 @@ private void EnsureDependencies(CollectionRuleActionOptions options, int actionI string actionAndResult = newValue[(foundIndex + ActionReferencePrefix.Length)..suffixIndex]; - if (!GetActionResultReference(actionAndResult, actionIndex, out CollectionRuleActionOptions dependencyOptions, out string actionResultName)) + if (!GetActionResultReference(actionAndResult, actionIndex, out CollectionRuleActionOptions? dependencyOptions, out string? actionResultName)) { continue; } @@ -223,12 +232,12 @@ private void EnsureDependencies(CollectionRuleActionOptions options, int actionI private PropertyDependency GetOrCreateDependency(int actionIndex, PropertyInfo propertyInfo, string originalValue) { - if (!_dependencies.TryGetValue(actionIndex, out Dictionary properties)) + if (!_dependencies.TryGetValue(actionIndex, out Dictionary? properties)) { properties = new Dictionary(StringComparer.Ordinal); _dependencies.Add(actionIndex, properties); } - if (!properties.TryGetValue(propertyInfo.Name, out PropertyDependency dependency)) + if (!properties.TryGetValue(propertyInfo.Name, out PropertyDependency? dependency)) { dependency = new PropertyDependency(propertyInfo, originalValue); properties.Add(propertyInfo.Name, dependency); @@ -237,7 +246,7 @@ private PropertyDependency GetOrCreateDependency(int actionIndex, PropertyInfo p } private bool GetActionResultReference(string actionReference, int actionIndex, - out CollectionRuleActionOptions action, out string actionResultName) + [NotNullWhen(true)] out CollectionRuleActionOptions? action, [NotNullWhen(true)] out string? actionResultName) { action = null; actionResultName = null; @@ -257,7 +266,7 @@ private bool GetActionResultReference(string actionReference, int actionIndex, } //We only check previous actions for our dependencies. - CollectionRuleActionOptions dependencyOptions = _ruleContext.Options.Actions.Take(actionIndex) + CollectionRuleActionOptions? dependencyOptions = _ruleContext.Options.Actions?.Take(actionIndex) .FirstOrDefault(a => string.Equals(a.Name, name, StringComparison.Ordinal)); if (dependencyOptions == null) diff --git a/src/Tools/dotnet-monitor/CollectionRules/Actions/CollectDumpAction.cs b/src/Tools/dotnet-monitor/CollectionRules/Actions/CollectDumpAction.cs index de934fd8c2c..3469fcb8453 100644 --- a/src/Tools/dotnet-monitor/CollectionRules/Actions/CollectDumpAction.cs +++ b/src/Tools/dotnet-monitor/CollectionRules/Actions/CollectDumpAction.cs @@ -45,7 +45,7 @@ public CollectDumpAction(IServiceProvider serviceProvider, IProcessInfo processI _dumpOperationFactory = serviceProvider.GetRequiredService(); } - protected override EgressOperation CreateArtifactOperation(CollectionRuleMetadata collectionRuleMetadata) + protected override EgressOperation CreateArtifactOperation(CollectionRuleMetadata? collectionRuleMetadata) { DumpType dumpType = Options.Type.GetValueOrDefault(CollectDumpOptionsDefaults.Type); string egressProvider = Options.Egress; diff --git a/src/Tools/dotnet-monitor/CollectionRules/Actions/CollectExceptionsAction.cs b/src/Tools/dotnet-monitor/CollectionRules/Actions/CollectExceptionsAction.cs index b8ab6730571..1e539f4d60a 100644 --- a/src/Tools/dotnet-monitor/CollectionRules/Actions/CollectExceptionsAction.cs +++ b/src/Tools/dotnet-monitor/CollectionRules/Actions/CollectExceptionsAction.cs @@ -37,7 +37,7 @@ public CollectExceptionsAction(IProcessInfo processInfo, CollectExceptionsOption _operationFactory = ServiceProvider.GetRequiredService(); } - protected override EgressOperation CreateArtifactOperation(CollectionRuleMetadata collectionRuleMetadata) + protected override EgressOperation CreateArtifactOperation(CollectionRuleMetadata? collectionRuleMetadata) { KeyValueLogScope scope = Utils.CreateArtifactScope(Utils.ArtifactType_Exceptions, EndpointInfo); diff --git a/src/Tools/dotnet-monitor/CollectionRules/Actions/CollectGCDumpAction.cs b/src/Tools/dotnet-monitor/CollectionRules/Actions/CollectGCDumpAction.cs index 41faa666084..397988f9ea4 100644 --- a/src/Tools/dotnet-monitor/CollectionRules/Actions/CollectGCDumpAction.cs +++ b/src/Tools/dotnet-monitor/CollectionRules/Actions/CollectGCDumpAction.cs @@ -44,7 +44,7 @@ public CollectGCDumpAction(IServiceProvider serviceProvider, IProcessInfo proces _operationFactory = serviceProvider.GetRequiredService(); } - protected override EgressOperation CreateArtifactOperation(CollectionRuleMetadata collectionRuleMetadata) + protected override EgressOperation CreateArtifactOperation(CollectionRuleMetadata? collectionRuleMetadata) { KeyValueLogScope scope = Utils.CreateArtifactScope(Utils.ArtifactType_GCDump, EndpointInfo); diff --git a/src/Tools/dotnet-monitor/CollectionRules/Actions/CollectLiveMetricsAction.cs b/src/Tools/dotnet-monitor/CollectionRules/Actions/CollectLiveMetricsAction.cs index 2e89eed7e61..1c2e31da0a5 100644 --- a/src/Tools/dotnet-monitor/CollectionRules/Actions/CollectLiveMetricsAction.cs +++ b/src/Tools/dotnet-monitor/CollectionRules/Actions/CollectLiveMetricsAction.cs @@ -51,7 +51,7 @@ public CollectLiveMetricsAction(IServiceProvider serviceProvider, IProcessInfo p _metricsOptions = serviceProvider.GetRequiredService>(); } - protected override EgressOperation CreateArtifactOperation(CollectionRuleMetadata collectionRuleMetadata) + protected override EgressOperation CreateArtifactOperation(CollectionRuleMetadata? collectionRuleMetadata) { MetricsPipelineSettings settings; if (Options.HasCustomConfiguration()) diff --git a/src/Tools/dotnet-monitor/CollectionRules/Actions/CollectLogsAction.cs b/src/Tools/dotnet-monitor/CollectionRules/Actions/CollectLogsAction.cs index 2be6414a6be..6e27a92fa7f 100644 --- a/src/Tools/dotnet-monitor/CollectionRules/Actions/CollectLogsAction.cs +++ b/src/Tools/dotnet-monitor/CollectionRules/Actions/CollectLogsAction.cs @@ -45,12 +45,12 @@ public CollectLogsAction(IServiceProvider serviceProvider, IProcessInfo processI { } - protected override EgressOperation CreateArtifactOperation(CollectionRuleMetadata collectionRuleMetadata) + protected override EgressOperation CreateArtifactOperation(CollectionRuleMetadata? collectionRuleMetadata) { TimeSpan duration = Options.Duration.GetValueOrDefault(TimeSpan.Parse(CollectLogsOptionsDefaults.Duration)); bool useAppFilters = Options.UseAppFilters.GetValueOrDefault(CollectLogsOptionsDefaults.UseAppFilters); LogLevel defaultLevel = Options.DefaultLevel.GetValueOrDefault(CollectLogsOptionsDefaults.DefaultLevel); - Dictionary filterSpecs = Options.FilterSpecs; + Dictionary? filterSpecs = Options.FilterSpecs; string egressProvider = Options.Egress; LogFormat logFormat = Options.Format.GetValueOrDefault(CollectLogsOptionsDefaults.Format); diff --git a/src/Tools/dotnet-monitor/CollectionRules/Actions/CollectStacksAction.cs b/src/Tools/dotnet-monitor/CollectionRules/Actions/CollectStacksAction.cs index 9caba1a1339..d73075b8b35 100644 --- a/src/Tools/dotnet-monitor/CollectionRules/Actions/CollectStacksAction.cs +++ b/src/Tools/dotnet-monitor/CollectionRules/Actions/CollectStacksAction.cs @@ -44,7 +44,7 @@ public CollectStacksAction(IServiceProvider serviceProvider, IProcessInfo proces _operationFactory = serviceProvider.GetRequiredService(); } - protected override EgressOperation CreateArtifactOperation(CollectionRuleMetadata collectionRuleMetadata) + protected override EgressOperation CreateArtifactOperation(CollectionRuleMetadata? collectionRuleMetadata) { KeyValueLogScope scope = Utils.CreateArtifactScope(Utils.ArtifactType_Stacks, EndpointInfo); diff --git a/src/Tools/dotnet-monitor/CollectionRules/Actions/CollectTraceAction.cs b/src/Tools/dotnet-monitor/CollectionRules/Actions/CollectTraceAction.cs index 9eff259cf4f..bdf6e8e976f 100644 --- a/src/Tools/dotnet-monitor/CollectionRules/Actions/CollectTraceAction.cs +++ b/src/Tools/dotnet-monitor/CollectionRules/Actions/CollectTraceAction.cs @@ -47,14 +47,14 @@ public CollectTraceAction(IServiceProvider serviceProvider, IProcessInfo process _counterOptions = serviceProvider.GetRequiredService>(); } - protected override EgressOperation CreateArtifactOperation(CollectionRuleMetadata collectionRuleMetadata) + protected override EgressOperation CreateArtifactOperation(CollectionRuleMetadata? collectionRuleMetadata) { TimeSpan duration = Options.Duration.GetValueOrDefault(TimeSpan.Parse(CollectTraceOptionsDefaults.Duration)); string egressProvider = Options.Egress; MonitoringSourceConfiguration configuration; - TraceEventFilter stoppingEvent = null; + TraceEventFilter? stoppingEvent = null; if (Options.Profile.HasValue) { @@ -63,7 +63,9 @@ protected override EgressOperation CreateArtifactOperation(CollectionRuleMetadat } else { +#nullable disable EventPipeProvider[] optionsProviders = Options.Providers.ToArray(); +#nullable restore bool requestRundown = Options.RequestRundown.GetValueOrDefault(CollectTraceOptionsDefaults.RequestRundown); int bufferSizeMegabytes = Options.BufferSizeMegabytes.GetValueOrDefault(CollectTraceOptionsDefaults.BufferSizeMegabytes); configuration = TraceUtilities.GetTraceConfiguration(optionsProviders, requestRundown, bufferSizeMegabytes); diff --git a/src/Tools/dotnet-monitor/CollectionRules/Actions/CollectionRuleActionBase.cs b/src/Tools/dotnet-monitor/CollectionRules/Actions/CollectionRuleActionBase.cs index 9174ad652c4..c9da07d6cf7 100644 --- a/src/Tools/dotnet-monitor/CollectionRules/Actions/CollectionRuleActionBase.cs +++ b/src/Tools/dotnet-monitor/CollectionRules/Actions/CollectionRuleActionBase.cs @@ -16,10 +16,12 @@ internal abstract class CollectionRuleActionBase : private readonly CancellationTokenSource _disposalTokenSource = new(); private readonly TaskCompletionSource _startCompletionSource = new(TaskCreationOptions.RunContinuationsAsynchronously); +#nullable disable private Task _completionTask; +#nullable restore private long _disposedState; - protected IEndpointInfo EndpointInfo => ProcessInfo?.EndpointInfo; + protected IEndpointInfo EndpointInfo => ProcessInfo.EndpointInfo; protected IProcessInfo ProcessInfo { get; } @@ -53,7 +55,7 @@ public async ValueTask DisposeAsync() _disposalTokenSource.Dispose(); } - public async Task StartAsync(CollectionRuleMetadata collectionRuleMetadata, CancellationToken token) + public async Task StartAsync(CollectionRuleMetadata? collectionRuleMetadata, CancellationToken token) { ThrowIfDisposed(); @@ -82,7 +84,7 @@ protected bool TrySetStarted() private async Task ExecuteAsync( - CollectionRuleMetadata collectionRuleMetadata, + CollectionRuleMetadata? collectionRuleMetadata, CancellationToken token) { try @@ -108,7 +110,7 @@ protected void ThrowIfDisposed() } protected abstract Task ExecuteCoreAsync( - CollectionRuleMetadata collectionRuleMetadata, + CollectionRuleMetadata? collectionRuleMetadata, CancellationToken token); } } diff --git a/src/Tools/dotnet-monitor/CollectionRules/Actions/CollectionRuleActionFactoryProxy.cs b/src/Tools/dotnet-monitor/CollectionRules/Actions/CollectionRuleActionFactoryProxy.cs index d9010905810..c8feb5843be 100644 --- a/src/Tools/dotnet-monitor/CollectionRules/Actions/CollectionRuleActionFactoryProxy.cs +++ b/src/Tools/dotnet-monitor/CollectionRules/Actions/CollectionRuleActionFactoryProxy.cs @@ -22,6 +22,7 @@ public CollectionRuleActionFactoryProxy(TFactory factory) _factory = factory; } +#nullable disable /// public ICollectionRuleAction Create(IProcessInfo processInfo, object options) { @@ -33,5 +34,6 @@ public ICollectionRuleAction Create(IProcessInfo processInfo, object options) return _factory.Create(processInfo, typedOptions); } +#nullable restore } } diff --git a/src/Tools/dotnet-monitor/CollectionRules/Actions/CollectionRuleActionOperations.cs b/src/Tools/dotnet-monitor/CollectionRules/Actions/CollectionRuleActionOperations.cs index c4f3f804df9..aea65cae497 100644 --- a/src/Tools/dotnet-monitor/CollectionRules/Actions/CollectionRuleActionOperations.cs +++ b/src/Tools/dotnet-monitor/CollectionRules/Actions/CollectionRuleActionOperations.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +#nullable disable + using Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Configuration; using Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options; using Microsoft.Extensions.Logging; diff --git a/src/Tools/dotnet-monitor/CollectionRules/Actions/CollectionRuleEgressActionBase.cs b/src/Tools/dotnet-monitor/CollectionRules/Actions/CollectionRuleEgressActionBase.cs index 7dc0acaaddb..657c9ddada9 100644 --- a/src/Tools/dotnet-monitor/CollectionRules/Actions/CollectionRuleEgressActionBase.cs +++ b/src/Tools/dotnet-monitor/CollectionRules/Actions/CollectionRuleEgressActionBase.cs @@ -24,9 +24,9 @@ protected CollectionRuleEgressActionBase(IServiceProvider serviceProvider, IProc EgressOperationStore = ServiceProvider.GetRequiredService(); } - protected abstract EgressOperation CreateArtifactOperation(CollectionRuleMetadata collectionRuleMetadata); + protected abstract EgressOperation CreateArtifactOperation(CollectionRuleMetadata? collectionRuleMetadata); - protected override async Task ExecuteCoreAsync(CollectionRuleMetadata collectionRuleMetadata, CancellationToken token) + protected override async Task ExecuteCoreAsync(CollectionRuleMetadata? collectionRuleMetadata, CancellationToken token) { EgressOperation egressOperation = CreateArtifactOperation(collectionRuleMetadata); Task> executeTask = EgressOperationStore.ExecuteOperation(egressOperation); diff --git a/src/Tools/dotnet-monitor/CollectionRules/Actions/ExecuteAction.cs b/src/Tools/dotnet-monitor/CollectionRules/Actions/ExecuteAction.cs index f010f269324..eb77d0c0926 100644 --- a/src/Tools/dotnet-monitor/CollectionRules/Actions/ExecuteAction.cs +++ b/src/Tools/dotnet-monitor/CollectionRules/Actions/ExecuteAction.cs @@ -40,11 +40,11 @@ public ExecuteAction(IProcessInfo processInfo, ExecuteOptions options) } protected override async Task ExecuteCoreAsync( - CollectionRuleMetadata collectionRuleMetadata, + CollectionRuleMetadata? collectionRuleMetadata, CancellationToken token) { string path = Options.Path; - string arguments = Options.Arguments; + string? arguments = Options.Arguments; bool IgnoreExitCode = Options.IgnoreExitCode.GetValueOrDefault(ExecuteOptionsDefaults.IgnoreExitCode); ValidateFilePath(path); @@ -52,7 +52,7 @@ protected override async Task ExecuteCoreAsync( // May want to capture stdout and stderr and return as part of the result in the future using Process process = new Process(); - process.StartInfo = new ProcessStartInfo(path, arguments); + process.StartInfo = new ProcessStartInfo(path, arguments ?? string.Empty); process.StartInfo.RedirectStandardOutput = true; process.EnableRaisingEvents = true; diff --git a/src/Tools/dotnet-monitor/CollectionRules/Actions/GetEnvironmentVariableAction.cs b/src/Tools/dotnet-monitor/CollectionRules/Actions/GetEnvironmentVariableAction.cs index 5695a695d78..a75d576916b 100644 --- a/src/Tools/dotnet-monitor/CollectionRules/Actions/GetEnvironmentVariableAction.cs +++ b/src/Tools/dotnet-monitor/CollectionRules/Actions/GetEnvironmentVariableAction.cs @@ -53,14 +53,14 @@ public GetEnvironmentVariableAction(ILogger logger, IProcessInfo processInfo, Ge } protected override async Task ExecuteCoreAsync( - CollectionRuleMetadata collectionRuleMetadata, + CollectionRuleMetadata? collectionRuleMetadata, CancellationToken token) { DiagnosticsClient client = new DiagnosticsClient(EndpointInfo.Endpoint); _logger.GettingEnvironmentVariable(_options.Name, EndpointInfo.ProcessId); Dictionary envBlock = await client.GetProcessEnvironmentAsync(token); - if (!envBlock.TryGetValue(Options.Name, out string value)) + if (!envBlock.TryGetValue(Options.Name, out string? value)) { throw new InvalidOperationException( string.Format( diff --git a/src/Tools/dotnet-monitor/CollectionRules/Actions/ICollectionRuleActionFactoryProxy.cs b/src/Tools/dotnet-monitor/CollectionRules/Actions/ICollectionRuleActionFactoryProxy.cs index 14ba353e5b1..0d8dafa534a 100644 --- a/src/Tools/dotnet-monitor/CollectionRules/Actions/ICollectionRuleActionFactoryProxy.cs +++ b/src/Tools/dotnet-monitor/CollectionRules/Actions/ICollectionRuleActionFactoryProxy.cs @@ -20,6 +20,6 @@ internal interface ICollectionRuleActionFactoryProxy /// Executes the underlying action with the specified parameters, verifying /// that the passed options are of the correct type. /// - ICollectionRuleAction Create(IProcessInfo endpointInfo, object options); + ICollectionRuleAction Create(IProcessInfo endpointInfo, object? options); } } diff --git a/src/Tools/dotnet-monitor/CollectionRules/Actions/ICollectionRuleActionOperations.cs b/src/Tools/dotnet-monitor/CollectionRules/Actions/ICollectionRuleActionOperations.cs index cb321fc1893..e6168312093 100644 --- a/src/Tools/dotnet-monitor/CollectionRules/Actions/ICollectionRuleActionOperations.cs +++ b/src/Tools/dotnet-monitor/CollectionRules/Actions/ICollectionRuleActionOperations.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +#nullable disable + using System.Collections.Generic; using System.ComponentModel.DataAnnotations; diff --git a/src/Tools/dotnet-monitor/CollectionRules/Actions/LoadProfilerAction.cs b/src/Tools/dotnet-monitor/CollectionRules/Actions/LoadProfilerAction.cs index 1fb78d1e1d7..d3338bd8520 100644 --- a/src/Tools/dotnet-monitor/CollectionRules/Actions/LoadProfilerAction.cs +++ b/src/Tools/dotnet-monitor/CollectionRules/Actions/LoadProfilerAction.cs @@ -51,7 +51,7 @@ public LoadProfilerAction(ILogger logger, IProcessInfo processInfo, LoadProfiler } protected override async Task ExecuteCoreAsync( - CollectionRuleMetadata collectionRuleMetadata, + CollectionRuleMetadata? collectionRuleMetadata, CancellationToken token) { DiagnosticsClient client = new DiagnosticsClient(EndpointInfo.Endpoint); diff --git a/src/Tools/dotnet-monitor/CollectionRules/Actions/SetEnvironmentVariableAction.cs b/src/Tools/dotnet-monitor/CollectionRules/Actions/SetEnvironmentVariableAction.cs index 3123604c93d..edd4298089c 100644 --- a/src/Tools/dotnet-monitor/CollectionRules/Actions/SetEnvironmentVariableAction.cs +++ b/src/Tools/dotnet-monitor/CollectionRules/Actions/SetEnvironmentVariableAction.cs @@ -51,7 +51,7 @@ public SetEnvironmentVariableAction(ILogger logger, IProcessInfo processInfo, Se } protected override async Task ExecuteCoreAsync( - CollectionRuleMetadata collectionRuleMetadata, + CollectionRuleMetadata? collectionRuleMetadata, CancellationToken token) { DiagnosticsClient client = new DiagnosticsClient(EndpointInfo.Endpoint); diff --git a/src/Tools/dotnet-monitor/CollectionRules/CollectionRuleContainer.cs b/src/Tools/dotnet-monitor/CollectionRules/CollectionRuleContainer.cs index 8bbbea62655..2565190a5a9 100644 --- a/src/Tools/dotnet-monitor/CollectionRules/CollectionRuleContainer.cs +++ b/src/Tools/dotnet-monitor/CollectionRules/CollectionRuleContainer.cs @@ -33,7 +33,7 @@ internal class CollectionRuleContainer : IAsyncDisposable public List Pipelines { get; set; } = new(); private long _disposalState; - private CancellationTokenSource _shutdownTokenSource; + private CancellationTokenSource? _shutdownTokenSource; public CollectionRuleContainer( IServiceProvider serviceProvider, @@ -139,7 +139,7 @@ private async Task StartRuleAsync( // executing the ApplyRules method. using CancellationTokenSource linkedSource = CancellationTokenSource.CreateLinkedTokenSource(token); - TaskCompletionSource startedSource = new(TaskCreationOptions.RunContinuationsAsynchronously); + TaskCompletionSource startedSource = new(TaskCreationOptions.RunContinuationsAsynchronously); // Start running the rule and wrap running task // in a safe awaitable task so that shutdown isn't @@ -164,37 +164,35 @@ private async Task StartRuleAsync( /// private async Task RunRuleAsync( string ruleName, - TaskCompletionSource startedSource, + TaskCompletionSource startedSource, CancellationToken token) { KeyValueLogScope scope = new(); scope.AddCollectionRuleEndpointInfo(_processInfo.EndpointInfo); scope.AddCollectionRuleName(ruleName); - using IDisposable loggerScope = _logger.BeginScope(scope); + using IDisposable? loggerScope = _logger.BeginScope(scope); +#nullable disable using CancellationTokenSource linkedSource = CancellationTokenSource.CreateLinkedTokenSource( _shutdownTokenSource.Token, token); - +#nullable restore try { CollectionRuleOptions options = _optionsMonitor.Get(ruleName); - if (null != options.Filters) - { - DiagProcessFilter filter = DiagProcessFilter.FromConfiguration(options.Filters); + DiagProcessFilter filter = DiagProcessFilter.FromConfiguration(options.Filters); - if (!filter.Filters.All(f => f.MatchFilter(_processInfo))) - { - // Collection rule filter does not match target process - _logger.CollectionRuleUnmatchedFilters(ruleName); + if (!filter.Filters.All(f => f.MatchFilter(_processInfo))) + { + // Collection rule filter does not match target process + _logger.CollectionRuleUnmatchedFilters(ruleName); - // Signal rule has "started" in order to not block - // resumption of the runtime instance. - startedSource.TrySetResult(null); + // Signal rule has "started" in order to not block + // resumption of the runtime instance. + startedSource.TrySetResult(null); - return; - } + return; } _logger.CollectionRuleStarted(ruleName); @@ -242,7 +240,7 @@ private async Task StopRulesCore(CancellationToken token) } } - private static bool TrySetCanceledAndReturnTrue(OperationCanceledException ex, TaskCompletionSource source) + private static bool TrySetCanceledAndReturnTrue(OperationCanceledException ex, TaskCompletionSource source) { // Always attempt to cancel the completion source source.TrySetCanceled(ex.CancellationToken); @@ -251,7 +249,7 @@ private static bool TrySetCanceledAndReturnTrue(OperationCanceledException ex, T return true; } - private bool LogExceptionAndReturnFalse(Exception ex, TaskCompletionSource source, string ruleName) + private bool LogExceptionAndReturnFalse(Exception ex, TaskCompletionSource source, string ruleName) { // Log failure _logger.CollectionRuleFailed(ruleName, ex); diff --git a/src/Tools/dotnet-monitor/CollectionRules/CollectionRuleContext.cs b/src/Tools/dotnet-monitor/CollectionRules/CollectionRuleContext.cs index cce2107656c..8d5992eb525 100644 --- a/src/Tools/dotnet-monitor/CollectionRules/CollectionRuleContext.cs +++ b/src/Tools/dotnet-monitor/CollectionRules/CollectionRuleContext.cs @@ -10,7 +10,7 @@ namespace Microsoft.Diagnostics.Tools.Monitor.CollectionRules { internal class CollectionRuleContext { - public CollectionRuleContext(string name, CollectionRuleOptions options, IProcessInfo processInfo, ILogger logger, TimeProvider timeProvider, Action throttledCallback = null) + public CollectionRuleContext(string name, CollectionRuleOptions options, IProcessInfo processInfo, ILogger logger, TimeProvider timeProvider, Action? throttledCallback = null) { // TODO: Allow null processInfo to allow tests to pass, but this should be provided by // tests since it will be required by all aspects in the future. For example, the ActionListExecutor @@ -29,7 +29,7 @@ public CollectionRuleContext(string name, CollectionRuleOptions options, IProces public IProcessInfo ProcessInfo { get; } - public IEndpointInfo EndpointInfo => ProcessInfo?.EndpointInfo; + public IEndpointInfo EndpointInfo => ProcessInfo.EndpointInfo; public ILogger Logger { get; } @@ -37,6 +37,6 @@ public CollectionRuleContext(string name, CollectionRuleOptions options, IProces public string Name { get; } - public Action ThrottledCallback { get; } + public Action? ThrottledCallback { get; } } } diff --git a/src/Tools/dotnet-monitor/CollectionRules/CollectionRulePipeline.cs b/src/Tools/dotnet-monitor/CollectionRules/CollectionRulePipeline.cs index f7873ba79fc..5908a350835 100644 --- a/src/Tools/dotnet-monitor/CollectionRules/CollectionRulePipeline.cs +++ b/src/Tools/dotnet-monitor/CollectionRules/CollectionRulePipeline.cs @@ -29,7 +29,9 @@ internal class CollectionRulePipeline : Pipeline // Flag used to guard against multiple invocations of _startCallback. private bool _invokedStartCallback; +#nullable disable private CollectionRulePipelineState _stateHolder; +#nullable restore public CollectionRulePipeline( ActionListExecutor actionListExecutor, @@ -84,15 +86,15 @@ protected override async Task OnRun(CancellationToken token) bool completePipeline = false; while (!completePipeline) { - TaskCompletionSource triggerSatisfiedSource = + TaskCompletionSource triggerSatisfiedSource = new(TaskCreationOptions.RunContinuationsAsynchronously); - ICollectionRuleTrigger trigger = null; + ICollectionRuleTrigger? trigger = null; try { KeyValueLogScope triggerScope = new(); triggerScope.AddCollectionRuleTrigger(Context.Options.Trigger.Type); - using IDisposable triggerScopeRegistration = Context.Logger.BeginScope(triggerScope); + using IDisposable? triggerScopeRegistration = Context.Logger.BeginScope(triggerScope); Context.Logger.CollectionRuleTriggerStarted(Context.Name, Context.Options.Trigger.Type); @@ -124,17 +126,21 @@ protected override async Task OnRun(CancellationToken token) } finally { - try + if (trigger != null) { - // Intentionally not using the linkedToken. If the linkedToken was signaled - // due to pipeline duration expiring, try to stop the trigger gracefully - // unless forced by a caller to the pipeline. - await trigger.StopAsync(token).ConfigureAwait(false); - } - finally - { - await DisposableHelper.DisposeAsync(trigger); + try + { + // Intentionally not using the linkedToken. If the linkedToken was signaled + // due to pipeline duration expiring, try to stop the trigger gracefully + // unless forced by a caller to the pipeline. + await trigger.StopAsync(token).ConfigureAwait(false); + } + finally + { + await DisposableHelper.DisposeAsync(trigger); + } } + } DateTime currentTimestamp = Context.TimeProvider.GetUtcNow().UtcDateTime; diff --git a/src/Tools/dotnet-monitor/CollectionRules/CollectionRuleService.cs b/src/Tools/dotnet-monitor/CollectionRules/CollectionRuleService.cs index 3344fd4a18d..7efe5e68a74 100644 --- a/src/Tools/dotnet-monitor/CollectionRules/CollectionRuleService.cs +++ b/src/Tools/dotnet-monitor/CollectionRules/CollectionRuleService.cs @@ -124,7 +124,7 @@ public async Task RemoveRules( IEndpointInfo endpointInfo, CancellationToken token) { - CollectionRuleContainer container; + CollectionRuleContainer? container; lock (_containersMap) { if (!_containersMap.Remove(endpointInfo, out container)) @@ -263,7 +263,7 @@ public Dictionary GetCollectionRulesDescripti { Dictionary collectionRulesDescriptions = new(); - if (_containersMap.TryGetValue(endpointInfo, out CollectionRuleContainer container)) + if (_containersMap.TryGetValue(endpointInfo, out CollectionRuleContainer? container)) { container.Pipelines.ForEach(pipeline => collectionRulesDescriptions.Add(pipeline.Context.Name, GetCollectionRuleDescription(pipeline))); } @@ -271,9 +271,9 @@ public Dictionary GetCollectionRulesDescripti return collectionRulesDescriptions; } - public CollectionRuleDetailedDescription GetCollectionRuleDetailedDescription(string collectionRuleName, IEndpointInfo endpointInfo) + public CollectionRuleDetailedDescription? GetCollectionRuleDetailedDescription(string collectionRuleName, IEndpointInfo endpointInfo) { - if (_containersMap.TryGetValue(endpointInfo, out CollectionRuleContainer container)) + if (_containersMap.TryGetValue(endpointInfo, out CollectionRuleContainer? container)) { IEnumerable pipelines = container.Pipelines.Where(pipeline => pipeline.Context.Name.Equals(collectionRuleName)); diff --git a/src/Tools/dotnet-monitor/CollectionRules/Configuration/CollectionRuleConfigureNamedOptions.cs b/src/Tools/dotnet-monitor/CollectionRules/Configuration/CollectionRuleConfigureNamedOptions.cs index 08638959d78..7aecf119a4a 100644 --- a/src/Tools/dotnet-monitor/CollectionRules/Configuration/CollectionRuleConfigureNamedOptions.cs +++ b/src/Tools/dotnet-monitor/CollectionRules/Configuration/CollectionRuleConfigureNamedOptions.cs @@ -19,6 +19,7 @@ public CollectionRuleConfigureNamedOptions( _configurationProvider = configurationProvider; } +#nullable disable public void Configure(string name, CollectionRuleOptions options) { IConfigurationSection ruleSection = _configurationProvider.GetCollectionRuleSection(name); @@ -27,6 +28,7 @@ public void Configure(string name, CollectionRuleOptions options) ruleSection.Bind(options); } } +#nullable restore public void Configure(CollectionRuleOptions options) { diff --git a/src/Tools/dotnet-monitor/CollectionRules/Configuration/CollectionRulePostConfigureNamedOptions.cs b/src/Tools/dotnet-monitor/CollectionRules/Configuration/CollectionRulePostConfigureNamedOptions.cs index fa6511acae1..1c412f58eaf 100644 --- a/src/Tools/dotnet-monitor/CollectionRules/Configuration/CollectionRulePostConfigureNamedOptions.cs +++ b/src/Tools/dotnet-monitor/CollectionRules/Configuration/CollectionRulePostConfigureNamedOptions.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +#nullable disable + using Microsoft.Diagnostics.Monitoring.WebApi; using Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Actions; using Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options; diff --git a/src/Tools/dotnet-monitor/CollectionRules/Configuration/CollectionRuleTriggerDescriptor.cs b/src/Tools/dotnet-monitor/CollectionRules/Configuration/CollectionRuleTriggerDescriptor.cs index 74b85cdee50..ab9b7a87a82 100644 --- a/src/Tools/dotnet-monitor/CollectionRules/Configuration/CollectionRuleTriggerDescriptor.cs +++ b/src/Tools/dotnet-monitor/CollectionRules/Configuration/CollectionRuleTriggerDescriptor.cs @@ -17,7 +17,7 @@ public CollectionRuleTriggerDescriptor(string triggerName) public Type FactoryType => typeof(TFactory); - public Type OptionsType => null; + public Type? OptionsType => null; public string TriggerName { get; } } diff --git a/src/Tools/dotnet-monitor/CollectionRules/Configuration/CollectionRulesConfigurationProvider.cs b/src/Tools/dotnet-monitor/CollectionRules/Configuration/CollectionRulesConfigurationProvider.cs index 070f2a87175..d3db0927206 100644 --- a/src/Tools/dotnet-monitor/CollectionRules/Configuration/CollectionRulesConfigurationProvider.cs +++ b/src/Tools/dotnet-monitor/CollectionRules/Configuration/CollectionRulesConfigurationProvider.cs @@ -55,6 +55,6 @@ public IConfigurationSection GetCollectionRuleSection(string name) public IConfigurationSection Configuration => _section; - public event EventHandler RulesChanged; + public event EventHandler? RulesChanged; } } diff --git a/src/Tools/dotnet-monitor/CollectionRules/Configuration/ICollectionRuleTriggerDescriptor.cs b/src/Tools/dotnet-monitor/CollectionRules/Configuration/ICollectionRuleTriggerDescriptor.cs index d4dbfdfea25..48846c97c29 100644 --- a/src/Tools/dotnet-monitor/CollectionRules/Configuration/ICollectionRuleTriggerDescriptor.cs +++ b/src/Tools/dotnet-monitor/CollectionRules/Configuration/ICollectionRuleTriggerDescriptor.cs @@ -9,7 +9,7 @@ interface ICollectionRuleTriggerDescriptor { Type FactoryType { get; } - Type OptionsType { get; } + Type? OptionsType { get; } string TriggerName { get; } } diff --git a/src/Tools/dotnet-monitor/CollectionRules/Configuration/TemplatesConfigureNamedOptions.cs b/src/Tools/dotnet-monitor/CollectionRules/Configuration/TemplatesConfigureNamedOptions.cs index 56fa97d38e7..ff35634307f 100644 --- a/src/Tools/dotnet-monitor/CollectionRules/Configuration/TemplatesConfigureNamedOptions.cs +++ b/src/Tools/dotnet-monitor/CollectionRules/Configuration/TemplatesConfigureNamedOptions.cs @@ -28,29 +28,35 @@ public TemplatesPostConfigureOptions( _configuration = configuration; } - public void PostConfigure(string name, TemplateOptions options) + public void PostConfigure(string? name, TemplateOptions options) { IConfigurationSection collectionRuleActionsSection = _configuration.GetSection(collectionRuleActionsPath); - foreach (string key in options.CollectionRuleActions.Keys) + if (options.CollectionRuleActions != null) { - IConfigurationSection actionSection = collectionRuleActionsSection.GetSection(key); - - if (actionSection.Exists()) + foreach (string key in options.CollectionRuleActions.Keys) { - CollectionRuleBindingHelper.BindActionSettings(actionSection, options.CollectionRuleActions[key], _actionOperations); + IConfigurationSection actionSection = collectionRuleActionsSection.GetSection(key); + + if (actionSection.Exists()) + { + CollectionRuleBindingHelper.BindActionSettings(actionSection, options.CollectionRuleActions[key], _actionOperations); + } } } IConfigurationSection collectionRuleTriggersSection = _configuration.GetSection(collectionRuleTriggersPath); - foreach (string key in options.CollectionRuleTriggers.Keys) + if (options.CollectionRuleTriggers != null) { - IConfigurationSection triggerSection = collectionRuleTriggersSection.GetSection(key); - - if (triggerSection.Exists()) + foreach (string key in options.CollectionRuleTriggers.Keys) { - CollectionRuleBindingHelper.BindTriggerSettings(triggerSection, options.CollectionRuleTriggers[key], _triggerOperations); + IConfigurationSection triggerSection = collectionRuleTriggersSection.GetSection(key); + + if (triggerSection.Exists()) + { + CollectionRuleBindingHelper.BindTriggerSettings(triggerSection, options.CollectionRuleTriggers[key], _triggerOperations); + } } } } diff --git a/src/Tools/dotnet-monitor/CollectionRules/Options/Actions/CollectLogsOptions.Validate.cs b/src/Tools/dotnet-monitor/CollectionRules/Options/Actions/CollectLogsOptions.Validate.cs index 77de3cc961b..e8ede3ded8c 100644 --- a/src/Tools/dotnet-monitor/CollectionRules/Options/Actions/CollectLogsOptions.Validate.cs +++ b/src/Tools/dotnet-monitor/CollectionRules/Options/Actions/CollectLogsOptions.Validate.cs @@ -29,14 +29,14 @@ IEnumerable IValidatableObject.Validate(ValidationContext vali // Validate that the category is not null and that the level is a valid level value. foreach ((string category, LogLevel? level) in FilterSpecs) { - ValidationResult result = requiredAttribute.GetValidationResult(category, filterSpecsContext); - if (result != ValidationResult.Success) + ValidationResult? result = requiredAttribute.GetValidationResult(category, filterSpecsContext); + if (!result.IsSuccess()) { results.Add(result); } result = enumValidationAttribute.GetValidationResult(level, filterSpecsContext); - if (result != ValidationResult.Success) + if (!result.IsSuccess()) { results.Add(result); } diff --git a/src/Tools/dotnet-monitor/CollectionRules/Options/Actions/CollectTraceOptions.Validate.cs b/src/Tools/dotnet-monitor/CollectionRules/Options/Actions/CollectTraceOptions.Validate.cs index 6ab69e32461..6874ec2354b 100644 --- a/src/Tools/dotnet-monitor/CollectionRules/Options/Actions/CollectTraceOptions.Validate.cs +++ b/src/Tools/dotnet-monitor/CollectionRules/Options/Actions/CollectTraceOptions.Validate.cs @@ -8,6 +8,7 @@ using Microsoft.Extensions.Options; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; +using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.Linq; @@ -20,17 +21,32 @@ namespace Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Actions partial record class CollectTraceOptions : IValidatableObject { + + [MemberNotNullWhen(true, nameof(StoppingEvent))] + private bool HasStoppingEvent() + { + return StoppingEvent != null; + } + + [MemberNotNullWhen(true, nameof(Providers))] + private bool HasProviders() + { + return Providers != null && Providers.Count > 0; + } + + [MemberNotNullWhen(true, nameof(Profile))] + private bool HasProfile() + { + return Profile.HasValue; + } + IEnumerable IValidatableObject.Validate(ValidationContext validationContext) { List results = new(); - bool hasProfile = Profile.HasValue; - bool hasProviders = null != Providers && Providers.Any(); - bool hasStoppingEvent = null != StoppingEvent; - - if (hasProfile) + if (HasProfile()) { - if (hasStoppingEvent) + if (HasStoppingEvent()) { results.Add(new ValidationResult( string.Format( @@ -40,7 +56,7 @@ IEnumerable IValidatableObject.Validate(ValidationContext vali nameof(StoppingEvent)))); } - if (hasProviders) + if (HasProviders()) { // Both Profile and Providers cannot be specified at the same time, otherwise // cannot determine whether to use providers from the profile or the custom @@ -53,9 +69,9 @@ IEnumerable IValidatableObject.Validate(ValidationContext vali nameof(Providers)))); } } - else if (hasProviders) + else if (HasProviders()) { - GlobalCounterOptions counterOptions = null; + GlobalCounterOptions? counterOptions = null; try { @@ -76,7 +92,7 @@ IEnumerable IValidatableObject.Validate(ValidationContext vali Validator.TryValidateObject(provider, providerContext, results, validateAllProperties: true); - if (counterOptions != null && !CounterValidator.ValidateProvider(counterOptions, provider, out string errorMessage)) + if (counterOptions != null && !CounterValidator.ValidateProvider(counterOptions, provider, out string? errorMessage)) { results.Add(new ValidationResult(errorMessage, new[] { nameof(EventPipeProvider.Arguments) })); } @@ -95,9 +111,9 @@ IEnumerable IValidatableObject.Validate(ValidationContext vali nameof(Providers)))); } - if (hasStoppingEvent) + if (HasStoppingEvent()) { - bool hasMatchingStoppingProvider = hasProviders + bool hasMatchingStoppingProvider = HasProviders() && null != Providers.Find(x => string.Equals(x.Name, StoppingEvent.ProviderName, System.StringComparison.Ordinal)); if (!hasMatchingStoppingProvider) diff --git a/src/Tools/dotnet-monitor/CollectionRules/Options/Actions/RequiredGuidAttribute.cs b/src/Tools/dotnet-monitor/CollectionRules/Options/Actions/RequiredGuidAttribute.cs index 5c6b34a2283..e23e9a230a4 100644 --- a/src/Tools/dotnet-monitor/CollectionRules/Options/Actions/RequiredGuidAttribute.cs +++ b/src/Tools/dotnet-monitor/CollectionRules/Options/Actions/RequiredGuidAttribute.cs @@ -18,7 +18,7 @@ public override string FormatErrorMessage(string name) name); } - protected override ValidationResult IsValid(object value, ValidationContext validationContext) + protected override ValidationResult? IsValid(object? value, ValidationContext validationContext) { if (!(value is Guid)) { diff --git a/src/Tools/dotnet-monitor/CollectionRules/Options/Actions/ValidateEgressProviderAttribute.cs b/src/Tools/dotnet-monitor/CollectionRules/Options/Actions/ValidateEgressProviderAttribute.cs index 2562e25793c..5e77e45e06c 100644 --- a/src/Tools/dotnet-monitor/CollectionRules/Options/Actions/ValidateEgressProviderAttribute.cs +++ b/src/Tools/dotnet-monitor/CollectionRules/Options/Actions/ValidateEgressProviderAttribute.cs @@ -12,8 +12,14 @@ namespace Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Actions internal sealed class ValidateEgressProviderAttribute : ValidationAttribute { - protected override ValidationResult IsValid(object value, ValidationContext validationContext) + protected override ValidationResult? IsValid(object? value, ValidationContext validationContext) { + if (!(value is string)) + { + return new ValidationResult( + FormatErrorMessage(validationContext.DisplayName)); + } + string egressProvider = (string)value; IEgressService egressService = validationContext.GetRequiredService(); diff --git a/src/Tools/dotnet-monitor/CollectionRules/Options/CollectionRuleOptions.Validate.cs b/src/Tools/dotnet-monitor/CollectionRules/Options/CollectionRuleOptions.Validate.cs index 7cb282a06c5..141f2d4c30b 100644 --- a/src/Tools/dotnet-monitor/CollectionRules/Options/CollectionRuleOptions.Validate.cs +++ b/src/Tools/dotnet-monitor/CollectionRules/Options/CollectionRuleOptions.Validate.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +#nullable disable + using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; diff --git a/src/Tools/dotnet-monitor/CollectionRules/Options/DefaultCollectionRulePostConfigureOptions.cs b/src/Tools/dotnet-monitor/CollectionRules/Options/DefaultCollectionRulePostConfigureOptions.cs index ffde14f8035..879941d066c 100644 --- a/src/Tools/dotnet-monitor/CollectionRules/Options/DefaultCollectionRulePostConfigureOptions.cs +++ b/src/Tools/dotnet-monitor/CollectionRules/Options/DefaultCollectionRulePostConfigureOptions.cs @@ -21,7 +21,7 @@ IOptionsMonitor defaultOptions _defaultOptions = defaultOptions; } - public void PostConfigure(string name, CollectionRuleOptions options) + public void PostConfigure(string? name, CollectionRuleOptions options) { ConfigureEgress(options); ConfigureLimits(options); @@ -32,7 +32,7 @@ public void PostConfigure(string name, CollectionRuleOptions options) private void ConfigureEgress(CollectionRuleOptions options) { - CollectionRuleActionDefaultsOptions actionDefaults = _defaultOptions.CurrentValue.Actions; + CollectionRuleActionDefaultsOptions? actionDefaults = _defaultOptions.CurrentValue.Actions; if (actionDefaults == null) { @@ -45,7 +45,9 @@ private void ConfigureEgress(CollectionRuleOptions options) { if (string.IsNullOrEmpty(egressProviderProperties.Egress)) { +#nullable disable egressProviderProperties.Egress = actionDefaults.Egress; +#nullable restore } } } @@ -53,7 +55,7 @@ private void ConfigureEgress(CollectionRuleOptions options) private void ConfigureLimits(CollectionRuleOptions options) { - CollectionRuleLimitsDefaultsOptions limitsDefaults = _defaultOptions.CurrentValue.Limits; + CollectionRuleLimitsDefaultsOptions? limitsDefaults = _defaultOptions.CurrentValue.Limits; if (limitsDefaults == null) { @@ -90,7 +92,7 @@ private void ConfigureLimits(CollectionRuleOptions options) private void ConfigureRequestCounts(CollectionRuleOptions options) { - CollectionRuleTriggerDefaultsOptions triggerDefaults = _defaultOptions.CurrentValue.Triggers; + CollectionRuleTriggerDefaultsOptions? triggerDefaults = _defaultOptions.CurrentValue.Triggers; if (triggerDefaults == null) { @@ -111,7 +113,7 @@ private void ConfigureRequestCounts(CollectionRuleOptions options) private void ConfigureResponseCounts(CollectionRuleOptions options) { - CollectionRuleTriggerDefaultsOptions triggerDefaults = _defaultOptions.CurrentValue.Triggers; + CollectionRuleTriggerDefaultsOptions? triggerDefaults = _defaultOptions.CurrentValue.Triggers; if (triggerDefaults == null) { @@ -132,7 +134,7 @@ private void ConfigureResponseCounts(CollectionRuleOptions options) private void ConfigureSlidingWindowDurations(CollectionRuleOptions options) { - CollectionRuleTriggerDefaultsOptions triggerDefaults = _defaultOptions.CurrentValue.Triggers; + CollectionRuleTriggerDefaultsOptions? triggerDefaults = _defaultOptions.CurrentValue.Triggers; if (triggerDefaults == null) { diff --git a/src/Tools/dotnet-monitor/CollectionRules/Options/ValidationHelper.cs b/src/Tools/dotnet-monitor/CollectionRules/Options/ValidationHelper.cs index 38a5826dad1..c99543df9c0 100644 --- a/src/Tools/dotnet-monitor/CollectionRules/Options/ValidationHelper.cs +++ b/src/Tools/dotnet-monitor/CollectionRules/Options/ValidationHelper.cs @@ -26,6 +26,7 @@ public static void TryValidateItems(IEnumerable items, ValidationContext } } +#nullable disable public static bool TryValidateOptions(Type optionsType, object options, ValidationContext validationContext, ICollection results) { RequiredAttribute requiredAttribute = new(); @@ -58,5 +59,6 @@ public static bool TryValidateOptions(Type optionsType, object options, Validati return false; } } +#nullable restore } } diff --git a/src/Tools/dotnet-monitor/CollectionRules/Triggers/CollectionRuleTriggerFactoryProxy.cs b/src/Tools/dotnet-monitor/CollectionRules/Triggers/CollectionRuleTriggerFactoryProxy.cs index 2455d43aa22..ea1b51f820b 100644 --- a/src/Tools/dotnet-monitor/CollectionRules/Triggers/CollectionRuleTriggerFactoryProxy.cs +++ b/src/Tools/dotnet-monitor/CollectionRules/Triggers/CollectionRuleTriggerFactoryProxy.cs @@ -22,7 +22,7 @@ public CollectionRuleTriggerFactoryProxy(TFactory factory) } /// - public ICollectionRuleTrigger Create(IEndpointInfo endpointInfo, Action callback, object options) + public ICollectionRuleTrigger Create(IEndpointInfo endpointInfo, Action callback, object? options) { return _factory.Create(endpointInfo, callback); } @@ -48,6 +48,7 @@ public CollectionRuleTriggerFactoryProxy(TFactory factory) _factory = factory; } +#nullable disable /// public ICollectionRuleTrigger Create(IEndpointInfo endpointInfo, Action callback, object options) { @@ -60,5 +61,6 @@ public ICollectionRuleTrigger Create(IEndpointInfo endpointInfo, Action callback return _factory.Create(endpointInfo, callback, typedOptions); } +#nullable restore } } diff --git a/src/Tools/dotnet-monitor/CollectionRules/Triggers/CollectionRuleTriggerOperations.cs b/src/Tools/dotnet-monitor/CollectionRules/Triggers/CollectionRuleTriggerOperations.cs index f113dbe8bf0..1b1dfac9460 100644 --- a/src/Tools/dotnet-monitor/CollectionRules/Triggers/CollectionRuleTriggerOperations.cs +++ b/src/Tools/dotnet-monitor/CollectionRules/Triggers/CollectionRuleTriggerOperations.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +#nullable disable + using Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Configuration; using Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options; using Microsoft.Extensions.Logging; diff --git a/src/Tools/dotnet-monitor/CollectionRules/Triggers/ICollectionRuleTriggerFactoryProxy.cs b/src/Tools/dotnet-monitor/CollectionRules/Triggers/ICollectionRuleTriggerFactoryProxy.cs index b344ff69d4e..ff02596af79 100644 --- a/src/Tools/dotnet-monitor/CollectionRules/Triggers/ICollectionRuleTriggerFactoryProxy.cs +++ b/src/Tools/dotnet-monitor/CollectionRules/Triggers/ICollectionRuleTriggerFactoryProxy.cs @@ -21,6 +21,6 @@ internal interface ICollectionRuleTriggerFactoryProxy /// Executes the underlying factory with the specified parameters, verifying /// that the passed options are of the correct type. /// - ICollectionRuleTrigger Create(IEndpointInfo endpointInfo, Action callback, object options); + ICollectionRuleTrigger Create(IEndpointInfo endpointInfo, Action callback, object? options); } } diff --git a/src/Tools/dotnet-monitor/CollectionRules/Triggers/ICollectionRuleTriggerOperations.cs b/src/Tools/dotnet-monitor/CollectionRules/Triggers/ICollectionRuleTriggerOperations.cs index 58b50c136be..083adf8dd5d 100644 --- a/src/Tools/dotnet-monitor/CollectionRules/Triggers/ICollectionRuleTriggerOperations.cs +++ b/src/Tools/dotnet-monitor/CollectionRules/Triggers/ICollectionRuleTriggerOperations.cs @@ -33,7 +33,7 @@ bool TryCreateOptions( /// bool TryValidateOptions( string triggerName, - object options, + object? options, ValidationContext validationContext, ICollection results); } diff --git a/src/Tools/dotnet-monitor/Commands/CollectCommandHandler.cs b/src/Tools/dotnet-monitor/Commands/CollectCommandHandler.cs index 20134f09fab..4c1410ff8d6 100644 --- a/src/Tools/dotnet-monitor/Commands/CollectCommandHandler.cs +++ b/src/Tools/dotnet-monitor/Commands/CollectCommandHandler.cs @@ -21,7 +21,7 @@ namespace Microsoft.Diagnostics.Tools.Monitor.Commands { internal static class CollectCommandHandler { - public static async Task Invoke(CancellationToken token, string[] urls, string[] metricUrls, bool metrics, string diagnosticPort, bool noAuth, bool tempApiKey, bool noHttpEgress, FileInfo configurationFilePath, bool exitOnStdinDisconnect) + public static async Task Invoke(CancellationToken token, string[]? urls, string[]? metricUrls, bool metrics, string? diagnosticPort, bool noAuth, bool tempApiKey, bool noHttpEgress, FileInfo? configurationFilePath, bool exitOnStdinDisconnect) { try { @@ -154,7 +154,7 @@ private static IHostBuilder Configure(this IHostBuilder builder, StartupAuthenti }) .ConfigureContainer((HostBuilderContext context, IServiceCollection services) => { - ServerUrlsBlockingConfigurationManager manager = + ServerUrlsBlockingConfigurationManager? manager = context.Properties[typeof(ServerUrlsBlockingConfigurationManager)] as ServerUrlsBlockingConfigurationManager; Debug.Assert(null != manager, $"Expected {typeof(ServerUrlsBlockingConfigurationManager).FullName} to be a {typeof(HostBuilderContext).FullName} property."); if (null != manager) diff --git a/src/Tools/dotnet-monitor/Commands/ConfigShowCommandHandler.cs b/src/Tools/dotnet-monitor/Commands/ConfigShowCommandHandler.cs index 36954321130..37eaefaccd9 100644 --- a/src/Tools/dotnet-monitor/Commands/ConfigShowCommandHandler.cs +++ b/src/Tools/dotnet-monitor/Commands/ConfigShowCommandHandler.cs @@ -16,7 +16,7 @@ internal sealed class ConfigShowCommandHandler // Although the "noHttpEgress" parameter is unused, it keeps the entire command parameter set a superset // of the "collect" command so that users can take the same arguments from "collect" and use it on "config show" // to get the same configuration without telling them to drop specific command line arguments. - public static void Invoke(string[] urls, string[] metricUrls, bool metrics, string diagnosticPort, bool noAuth, bool tempApiKey, bool noHttpEgress, FileInfo configurationFilePath, ConfigDisplayLevel level, bool showSources) + public static void Invoke(string[]? urls, string[]? metricUrls, bool metrics, string? diagnosticPort, bool noAuth, bool tempApiKey, bool noHttpEgress, FileInfo? configurationFilePath, ConfigDisplayLevel level, bool showSources) { Stream stream = Console.OpenStandardOutput(); @@ -28,7 +28,7 @@ public static void Invoke(string[] urls, string[] metricUrls, bool metrics, stri Write(stream, urls, metricUrls, metrics, diagnosticPort, noAuth, tempApiKey, configurationFilePath, level, showSources); } - public static void Write(Stream stream, string[] urls, string[] metricUrls, bool metrics, string diagnosticPort, bool noAuth, bool tempApiKey, FileInfo configurationFilePath, ConfigDisplayLevel level, bool showSources) + public static void Write(Stream stream, string[]? urls, string[]? metricUrls, bool metrics, string? diagnosticPort, bool noAuth, bool tempApiKey, FileInfo? configurationFilePath, ConfigDisplayLevel level, bool showSources) { StartupAuthenticationMode startupAuthMode = HostBuilderHelper.GetStartupAuthenticationMode(noAuth, tempApiKey); HostBuilderSettings settings = HostBuilderSettings.CreateMonitor(urls, metricUrls, metrics, diagnosticPort, startupAuthMode, configurationFilePath); diff --git a/src/Tools/dotnet-monitor/Commands/GenerateApiKeyCommandHandler.cs b/src/Tools/dotnet-monitor/Commands/GenerateApiKeyCommandHandler.cs index 63da008340a..a13b184fcdc 100644 --- a/src/Tools/dotnet-monitor/Commands/GenerateApiKeyCommandHandler.cs +++ b/src/Tools/dotnet-monitor/Commands/GenerateApiKeyCommandHandler.cs @@ -67,7 +67,7 @@ public static void Invoke(OutputFormat output, TimeSpan expiration, TextWriter o { // Create configuration from object model. MemoryConfigurationSource source = new(); - source.InitialData = opts.ToConfigurationValues(); + source.InitialData = (IDictionary)opts.ToConfigurationValues(); // Cast the values as nullable, since they are reference types we can safely do this. ConfigurationBuilder builder = new(); builder.Add(source); IConfigurationRoot configuration = builder.Build(); @@ -141,8 +141,8 @@ private static string GetFormatString(OutputFormat output) /// internal class MachineOutputFormat { - public AuthenticationOptions Authentication { get; set; } - public string AuthorizationHeader { get; set; } + public required AuthenticationOptions Authentication { get; set; } + public required string AuthorizationHeader { get; set; } } } } diff --git a/src/Tools/dotnet-monitor/CommonOptionsExtensions.cs b/src/Tools/dotnet-monitor/CommonOptionsExtensions.cs index 8d83c3baaee..718ffa4f27a 100644 --- a/src/Tools/dotnet-monitor/CommonOptionsExtensions.cs +++ b/src/Tools/dotnet-monitor/CommonOptionsExtensions.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +#nullable enable + #if UNITTEST using Microsoft.Diagnostics.Monitoring.TestCommon; #endif @@ -62,11 +64,11 @@ private static void MapDictionary(IDictionary dictionary, string prefix, string { foreach (var key in dictionary.Keys) { - object value = dictionary[key]; + object? value = dictionary[key]; if (null != value) { - string keyString = Convert.ToString(key, CultureInfo.InvariantCulture); + string keyString = ConvertUtils.ToString(key, CultureInfo.InvariantCulture); MapValue( value, FormattableString.Invariant($"{prefix}{keyString}"), @@ -80,7 +82,7 @@ private static void MapList(IList list, string prefix, string separator, IDictio { for (int index = 0; index < list.Count; index++) { - object value = list[index]; + object? value = list[index]; if (null != value) { MapValue( @@ -107,7 +109,7 @@ private static void MapObject(object obj, string prefix, string separator, IDict } } - private static void MapValue(object value, string valueName, string separator, IDictionary map) + private static void MapValue(object? value, string valueName, string separator, IDictionary map) { if (null != value) { @@ -120,7 +122,7 @@ private static void MapValue(object value, string valueName, string separator, I { map.Add( valueName, - Convert.ToString(value, CultureInfo.InvariantCulture)); + ConvertUtils.ToString(value, CultureInfo.InvariantCulture)); } else { diff --git a/src/Tools/dotnet-monitor/ConfigurationExtensions.cs b/src/Tools/dotnet-monitor/ConfigurationExtensions.cs index 5cc8cad0a29..3d627044d9f 100644 --- a/src/Tools/dotnet-monitor/ConfigurationExtensions.cs +++ b/src/Tools/dotnet-monitor/ConfigurationExtensions.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using Microsoft.Extensions.Configuration; +using System.Diagnostics.CodeAnalysis; using System.Linq; #if !NET7_0_OR_GREATER using System.Reflection; @@ -11,7 +12,7 @@ namespace Microsoft.Diagnostics.Tools.Monitor { internal static class ConfigurationExtensions { - public static bool TryGetProvider(this IConfigurationBuilder builder, string key, out IConfigurationProvider provider) + public static bool TryGetProvider(this IConfigurationBuilder builder, string key, [NotNullWhen(true)] out IConfigurationProvider? provider) { foreach (IConfigurationSource source in builder.Sources.Reverse()) { @@ -27,7 +28,7 @@ public static bool TryGetProvider(this IConfigurationBuilder builder, string key return false; } - public static bool TryGetProviderAndValue(this IConfiguration configuration, string key, out IConfigurationProvider provider, out string value) + public static bool TryGetProviderAndValue(this IConfiguration configuration, string key, [NotNullWhen(true)] out IConfigurationProvider? provider, out string? value) { if (configuration is IConfigurationRoot configurationRoot) { @@ -39,7 +40,7 @@ public static bool TryGetProviderAndValue(this IConfiguration configuration, str return false; } - public static bool TryGetProviderAndValue(this IConfigurationRoot configurationRoot, string key, out IConfigurationProvider provider, out string value) + public static bool TryGetProviderAndValue(this IConfigurationRoot configurationRoot, string key, [NotNullWhen(true)] out IConfigurationProvider? provider, out string? value) { foreach (IConfigurationProvider candidate in configurationRoot.Providers.Reverse()) { diff --git a/src/Tools/dotnet-monitor/ConfigurationJsonWriter.cs b/src/Tools/dotnet-monitor/ConfigurationJsonWriter.cs index 77dda75718f..9724f1588e3 100644 --- a/src/Tools/dotnet-monitor/ConfigurationJsonWriter.cs +++ b/src/Tools/dotnet-monitor/ConfigurationJsonWriter.cs @@ -20,7 +20,7 @@ namespace Microsoft.Diagnostics.Tools.Monitor internal sealed class ConfigurationJsonWriter : IDisposable { private readonly Utf8JsonWriter _writer; - private IConfiguration _configuration; + private IConfiguration? _configuration; public ConfigurationJsonWriter(Stream outputStream) { JsonWriterOptions options = new() { Indented = true }; @@ -39,17 +39,17 @@ public void Write(IConfiguration configuration, bool full, bool skipNotPresent, using (new JsonObjectContext(_writer)) { ProcessChildSection(configuration, WebHostDefaults.ServerUrlsKey, skipNotPresent, showSources: showSources); - IConfigurationSection kestrel = ProcessChildSection(configuration, "Kestrel", skipNotPresent, includeChildSections: false, showSources: showSources); + IConfigurationSection? kestrel = ProcessChildSection(configuration, "Kestrel", skipNotPresent, includeChildSections: false, showSources: showSources); if (kestrel != null) { using (new JsonObjectContext(_writer)) { - IConfigurationSection certificates = ProcessChildSection(kestrel, "Certificates", skipNotPresent, includeChildSections: false, showSources: showSources); + IConfigurationSection? certificates = ProcessChildSection(kestrel, "Certificates", skipNotPresent, includeChildSections: false, showSources: showSources); if (certificates != null) { using (new JsonObjectContext(_writer)) { - IConfigurationSection defaultCert = ProcessChildSection(certificates, "Default", skipNotPresent, includeChildSections: false, showSources: showSources); + IConfigurationSection? defaultCert = ProcessChildSection(certificates, "Default", skipNotPresent, includeChildSections: false, showSources: showSources); if (defaultCert != null) { using (new JsonObjectContext(_writer)) @@ -84,12 +84,12 @@ public void Write(IConfiguration configuration, bool full, bool skipNotPresent, } else { - IConfigurationSection auth = ProcessChildSection(configuration, ConfigurationKeys.Authentication, skipNotPresent, includeChildSections: false, showSources: showSources); + IConfigurationSection? auth = ProcessChildSection(configuration, ConfigurationKeys.Authentication, skipNotPresent, includeChildSections: false, showSources: showSources); if (null != auth) { using (new JsonObjectContext(_writer)) { - IConfigurationSection monitorApiKey = ProcessChildSection(auth, ConfigurationKeys.MonitorApiKey, skipNotPresent, includeChildSections: false, showSources: showSources); + IConfigurationSection? monitorApiKey = ProcessChildSection(auth, ConfigurationKeys.MonitorApiKey, skipNotPresent, includeChildSections: false, showSources: showSources); if (null != monitorApiKey) { using (new JsonObjectContext(_writer)) @@ -102,11 +102,11 @@ public void Write(IConfiguration configuration, bool full, bool skipNotPresent, } // No sensitive information - IConfigurationSection azureAd = ProcessChildSection(auth, ConfigurationKeys.AzureAd, skipNotPresent, includeChildSections: true, showSources: showSources); + IConfigurationSection? azureAd = ProcessChildSection(auth, ConfigurationKeys.AzureAd, skipNotPresent, includeChildSections: true, showSources: showSources); } } - IConfigurationSection egress = ProcessChildSection(configuration, ConfigurationKeys.Egress, skipNotPresent, includeChildSections: false, showSources: showSources); + IConfigurationSection? egress = ProcessChildSection(configuration, ConfigurationKeys.Egress, skipNotPresent, includeChildSections: false, showSources: showSources); if (egress != null) { using (new JsonObjectContext(_writer)) @@ -123,13 +123,13 @@ private void ProcessEgressSection(IConfiguration egress, bool skipNotPresent, bo IList processedSectionPaths = new List(); // Redact all the properties since they could include secrets such as storage keys - IConfigurationSection propertiesSection = ProcessChildSection(egress, ConfigurationKeys.Egress_Properties, skipNotPresent, includeChildSections: true, redact: true, showSources: showSources); + IConfigurationSection? propertiesSection = ProcessChildSection(egress, ConfigurationKeys.Egress_Properties, skipNotPresent, includeChildSections: true, redact: true, showSources: showSources); if (null != propertiesSection) { processedSectionPaths.Add(propertiesSection.Path); } - IConfigurationSection fileSystemProviderSection = ProcessChildSection(egress, EgressProviderTypes.FileSystem, skipNotPresent, includeChildSections: false, showSources: showSources); + IConfigurationSection? fileSystemProviderSection = ProcessChildSection(egress, EgressProviderTypes.FileSystem, skipNotPresent, includeChildSections: false, showSources: showSources); if (fileSystemProviderSection != null) { processedSectionPaths.Add(fileSystemProviderSection.Path); @@ -159,7 +159,7 @@ private void ProcessEgressSection(IConfiguration egress, bool skipNotPresent, bo } } - private IConfigurationSection ProcessChildSection(IConfiguration parentSection, string key, bool skipNotPresent, bool includeChildSections = true, bool redact = false, bool showSources = false) + private IConfigurationSection? ProcessChildSection(IConfiguration parentSection, string key, bool skipNotPresent, bool includeChildSections = true, bool redact = false, bool showSources = false) { IConfigurationSection section = parentSection.GetSection(key); if (!section.Exists()) @@ -238,16 +238,16 @@ private void ProcessSection(IConfigurationSection section, bool includeChildSect } } } - +#nullable disable private string GetConfigurationProvider(IConfigurationSection section, bool showSources) { if (showSources && _configuration.TryGetProviderAndValue(section.Path, out IConfigurationProvider provider, out _)) { return provider.ToString(); } - return string.Empty; } +#nullable restore private static bool CanWriteChildren(IConfigurationSection section, IEnumerable children) { @@ -259,9 +259,9 @@ private static bool CanWriteChildren(IConfigurationSection section, IEnumerable< return children.Any(); } - private void WriteValue(string value, bool redact) + private void WriteValue(string? value, bool redact) { - string valueToWrite = redact ? Strings.Placeholder_Redacted : value; + string? valueToWrite = redact ? Strings.Placeholder_Redacted : value; _writer.WriteStringValue(valueToWrite); } diff --git a/src/Tools/dotnet-monitor/ConfigurationTokenParser.cs b/src/Tools/dotnet-monitor/ConfigurationTokenParser.cs index 3b4e034b7d1..6fce6ead540 100644 --- a/src/Tools/dotnet-monitor/ConfigurationTokenParser.cs +++ b/src/Tools/dotnet-monitor/ConfigurationTokenParser.cs @@ -50,13 +50,13 @@ public ConfigurationTokenParser(ILogger logger) _logger = logger; } - public object SubstituteOptionValues(object originalSettings, TokenContext context) + public object? SubstituteOptionValues(object? originalSettings, TokenContext context) { - object settings = originalSettings; + object? settings = originalSettings; foreach (PropertyInfo propertyInfo in GetPropertiesFromSettings(settings)) { - string originalPropertyValue = (string)propertyInfo.GetValue(settings); + string? originalPropertyValue = (string?)propertyInfo.GetValue(settings); if (string.IsNullOrEmpty(originalPropertyValue)) { continue; @@ -80,7 +80,7 @@ public object SubstituteOptionValues(object originalSettings, TokenContext conte return settings; } - public bool TryCloneSettings(object originalSettings, ref object settings) + public bool TryCloneSettings(object? originalSettings, ref object? settings) { if (originalSettings == null) { @@ -97,7 +97,9 @@ public bool TryCloneSettings(object originalSettings, ref object settings) } else { +#nullable disable _logger.ActionSettingsTokenizationNotSupported(settings.GetType().FullName); +#nullable restore settings = originalSettings; return false; } @@ -105,7 +107,7 @@ public bool TryCloneSettings(object originalSettings, ref object settings) return true; } - public static IEnumerable GetPropertiesFromSettings(object settings, Predicate predicate = null) => + public static IEnumerable GetPropertiesFromSettings(object? settings, Predicate? predicate = null) => settings?.GetType() .GetProperties(BindingFlags.Public | BindingFlags.Instance) .Where(p => p.PropertyType == typeof(string) && (predicate?.Invoke(p) ?? true)) ?? diff --git a/src/Tools/dotnet-monitor/ConvertUtils.cs b/src/Tools/dotnet-monitor/ConvertUtils.cs new file mode 100644 index 00000000000..f386b149580 --- /dev/null +++ b/src/Tools/dotnet-monitor/ConvertUtils.cs @@ -0,0 +1,16 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#nullable enable + +using System; + +namespace Microsoft.Diagnostics.Tools.Monitor; + +internal static class ConvertUtils +{ + public static string ToString(object value, IFormatProvider? provider) + { + return Convert.ToString(value, provider)!; // Since value is not null this will never return null. + } +} diff --git a/src/Tools/dotnet-monitor/DataAnnotationValidateOptions.cs b/src/Tools/dotnet-monitor/DataAnnotationValidateOptions.cs index 02b72973556..2b6548a03b3 100644 --- a/src/Tools/dotnet-monitor/DataAnnotationValidateOptions.cs +++ b/src/Tools/dotnet-monitor/DataAnnotationValidateOptions.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +#nullable enable + using Microsoft.Extensions.Options; using System; using System.Collections.Generic; @@ -24,7 +26,7 @@ public DataAnnotationValidateOptions(IServiceProvider serviceProvider) _serviceProvider = serviceProvider; } - public ValidateOptionsResult Validate(string name, TOptions options) + public ValidateOptionsResult Validate(string? name, TOptions options) { ValidationContext validationContext = new(options, _serviceProvider, null); ICollection results = new Collection(); @@ -35,7 +37,9 @@ public ValidateOptionsResult Validate(string name, TOptions options) { if (ValidationResult.Success != result) { +#nullable disable failures.Add(result.ErrorMessage); +#nullable restore } } diff --git a/src/Tools/dotnet-monitor/DiagnosticLifetimeBackgroundService.cs b/src/Tools/dotnet-monitor/DiagnosticLifetimeBackgroundService.cs index 58300370655..86f5bc41475 100644 --- a/src/Tools/dotnet-monitor/DiagnosticLifetimeBackgroundService.cs +++ b/src/Tools/dotnet-monitor/DiagnosticLifetimeBackgroundService.cs @@ -18,9 +18,9 @@ internal abstract class DiagnosticLifetimeBackgroundService : IDiagnosticLifetimeService, IAsyncDisposable { - private Task _executingTask; + private Task? _executingTask; private object _executionLock = new object(); - private CancellationTokenSource _stoppingSource; + private CancellationTokenSource? _stoppingSource; public virtual ValueTask DisposeAsync() { @@ -72,7 +72,7 @@ public async ValueTask StopAsync(CancellationToken cancellationToken) } // Signal to the execution that it should stop. - _stoppingSource.SafeCancel(); + _stoppingSource?.SafeCancel(); // Safe await the execution regardless of the completion type, // but allow cancelling waiting for it to finish. diff --git a/src/Tools/dotnet-monitor/DiagnosticPort/DiagnosticPortPostConfigureOptions.cs b/src/Tools/dotnet-monitor/DiagnosticPort/DiagnosticPortPostConfigureOptions.cs index 153ae0b55f4..bb7016852cf 100644 --- a/src/Tools/dotnet-monitor/DiagnosticPort/DiagnosticPortPostConfigureOptions.cs +++ b/src/Tools/dotnet-monitor/DiagnosticPort/DiagnosticPortPostConfigureOptions.cs @@ -23,7 +23,7 @@ public DiagnosticPortPostConfigureOptions( _storageOptions = storageOptions; } - public void PostConfigure(string name, DiagnosticPortOptions options) + public void PostConfigure(string? name, DiagnosticPortOptions options) { IConfigurationSection diagPortSection = _configuration.GetSection(nameof(RootOptions.DiagnosticPort)); diff --git a/src/Tools/dotnet-monitor/DiagnosticPort/DiagnosticPortStartupLogger.cs b/src/Tools/dotnet-monitor/DiagnosticPort/DiagnosticPortStartupLogger.cs index adbd574b81e..da529fa374d 100644 --- a/src/Tools/dotnet-monitor/DiagnosticPort/DiagnosticPortStartupLogger.cs +++ b/src/Tools/dotnet-monitor/DiagnosticPort/DiagnosticPortStartupLogger.cs @@ -26,6 +26,7 @@ public DiagnosticPortStartupLogger( _options = options.Value; } +#nullable disable public void Log() { switch (_options.GetConnectionMode()) @@ -48,5 +49,6 @@ public void Log() break; } } +#nullable restore } } diff --git a/src/Tools/dotnet-monitor/DiagnosticPort/DiagnosticPortValidateOptions.cs b/src/Tools/dotnet-monitor/DiagnosticPort/DiagnosticPortValidateOptions.cs index f6ac06fb6d8..9fff752557e 100644 --- a/src/Tools/dotnet-monitor/DiagnosticPort/DiagnosticPortValidateOptions.cs +++ b/src/Tools/dotnet-monitor/DiagnosticPort/DiagnosticPortValidateOptions.cs @@ -11,7 +11,7 @@ namespace Microsoft.Diagnostics.Tools.Monitor internal class DiagnosticPortValidateOptions : IValidateOptions { - public ValidateOptionsResult Validate(string name, DiagnosticPortOptions options) + public ValidateOptionsResult Validate(string? name, DiagnosticPortOptions options) { var failures = new List(); diff --git a/src/Tools/dotnet-monitor/DisposableHelper.cs b/src/Tools/dotnet-monitor/DisposableHelper.cs index 39f1e935bb2..020acc771fa 100644 --- a/src/Tools/dotnet-monitor/DisposableHelper.cs +++ b/src/Tools/dotnet-monitor/DisposableHelper.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +#nullable enable + using System; using System.Threading; using System.Threading.Tasks; @@ -60,7 +62,7 @@ public static bool IsDisposed(ref long state) /// Calls on object if object /// implements interface. /// - public static void Dispose(object obj) + public static void Dispose(object? obj) { if (obj is IDisposable disposable) { @@ -72,7 +74,7 @@ public static void Dispose(object obj) /// Checks if the object implements /// or and calls the corresponding dispose method. /// - public static async ValueTask DisposeAsync(object obj) + public static async ValueTask DisposeAsync(object? obj) { if (obj is IAsyncDisposable asyncDisposable) { diff --git a/src/Tools/dotnet-monitor/DotNetHost.Unix.cs b/src/Tools/dotnet-monitor/DotNetHost.Unix.cs index 9fad910fbed..d2a5e8bf00a 100644 --- a/src/Tools/dotnet-monitor/DotNetHost.Unix.cs +++ b/src/Tools/dotnet-monitor/DotNetHost.Unix.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; +using System.Diagnostics.CodeAnalysis; using System.IO; using System.Runtime.InteropServices; @@ -20,7 +21,7 @@ private sealed class UnixDotNetHostHelper : IDotNetHostHelper public string ExecutableName => ExecutableRootName; - public bool TryGetDefaultInstallationDirectory(out string dotnetRoot) + public bool TryGetDefaultInstallationDirectory([NotNullWhen(true)] out string? dotnetRoot) { if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { @@ -38,13 +39,13 @@ public bool TryGetDefaultInstallationDirectory(out string dotnetRoot) return false; } - public bool TryGetSelfRegisteredDirectory(out string dotnetRoot) + public bool TryGetSelfRegisteredDirectory([NotNullWhen(true)] out string? dotnetRoot) { return TryReadFileFirstLine(CurrentArchInstallationFilePath, out dotnetRoot) || TryReadFileFirstLine(InstallationFilePath, out dotnetRoot); } - private static bool TryReadFileFirstLine(string filePath, out string content) + private static bool TryReadFileFirstLine(string filePath, [NotNullWhen(true)] out string? content) { try { diff --git a/src/Tools/dotnet-monitor/DotNetHost.Windows.cs b/src/Tools/dotnet-monitor/DotNetHost.Windows.cs index fc240d9822f..c086e4ebfc1 100644 --- a/src/Tools/dotnet-monitor/DotNetHost.Windows.cs +++ b/src/Tools/dotnet-monitor/DotNetHost.Windows.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; +using System.Diagnostics.CodeAnalysis; using System.IO; namespace Microsoft.Diagnostics.Tools.Monitor @@ -12,14 +13,14 @@ private sealed class WindowsDotNetHostHelper : IDotNetHostHelper { public string ExecutableName => FormattableString.Invariant($"{ExecutableRootName}.exe"); - public bool TryGetDefaultInstallationDirectory(out string dotnetRoot) + public bool TryGetDefaultInstallationDirectory([NotNullWhen(true)] out string? dotnetRoot) { // CONSIDER: Account for emulation (emulated path would be under ".\x64\") dotnetRoot = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), InstallationDirectoryName); return true; } - public bool TryGetSelfRegisteredDirectory(out string dotnetRoot) + public bool TryGetSelfRegisteredDirectory([NotNullWhen(true)] out string? dotnetRoot) { // CONSIDER: Lookup dotnet installation from registry dotnetRoot = null; diff --git a/src/Tools/dotnet-monitor/DotNetHost.cs b/src/Tools/dotnet-monitor/DotNetHost.cs index 1d0b0e17847..045044e1292 100644 --- a/src/Tools/dotnet-monitor/DotNetHost.cs +++ b/src/Tools/dotnet-monitor/DotNetHost.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; +using System.Diagnostics.CodeAnalysis; using System.IO; using System.Runtime.InteropServices; using System.Threading; @@ -27,7 +28,7 @@ internal static partial class DotNetHost private static string GetPath() { // If current executable is already dotnet, return its path - string executablePath = Environment.ProcessPath; + string? executablePath = Environment.ProcessPath; if (!string.IsNullOrEmpty(executablePath) && executablePath.EndsWith(Helper.ExecutableName, StringComparison.OrdinalIgnoreCase)) { @@ -39,7 +40,7 @@ private static string GetPath() // Get dotnet root from environment variable // TODO: check architecture specific environment variables (e.g. *_X86, *_X64, *_ARM64) - string dotnetRoot = Environment.GetEnvironmentVariable("DOTNET_ROOT"); + string? dotnetRoot = Environment.GetEnvironmentVariable("DOTNET_ROOT"); if (string.IsNullOrEmpty(dotnetRoot) && !Helper.TryGetSelfRegisteredDirectory(out dotnetRoot) && @@ -58,9 +59,9 @@ private static string GetPath() private interface IDotNetHostHelper { - bool TryGetSelfRegisteredDirectory(out string dotnetRoot); + bool TryGetSelfRegisteredDirectory([NotNullWhen(true)] out string? dotnetRoot); - bool TryGetDefaultInstallationDirectory(out string dotnetRoot); + bool TryGetDefaultInstallationDirectory([NotNullWhen(true)] out string? dotnetRoot); string ExecutableName { get; } } diff --git a/src/Tools/dotnet-monitor/DynamicNamedOptionsCache.cs b/src/Tools/dotnet-monitor/DynamicNamedOptionsCache.cs index 9909a9f6b1e..8efbcff1595 100644 --- a/src/Tools/dotnet-monitor/DynamicNamedOptionsCache.cs +++ b/src/Tools/dotnet-monitor/DynamicNamedOptionsCache.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +#nullable disable + using Microsoft.Extensions.Options; using System; using System.Diagnostics; diff --git a/src/Tools/dotnet-monitor/Egress/Configuration/EgressConfigurationProvider.cs b/src/Tools/dotnet-monitor/Egress/Configuration/EgressConfigurationProvider.cs index 077b3461d0c..769206cb608 100644 --- a/src/Tools/dotnet-monitor/Egress/Configuration/EgressConfigurationProvider.cs +++ b/src/Tools/dotnet-monitor/Egress/Configuration/EgressConfigurationProvider.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +#nullable disable + using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Primitives; using System.Collections.Generic; diff --git a/src/Tools/dotnet-monitor/Egress/EgressArtifactSettings.cs b/src/Tools/dotnet-monitor/Egress/EgressArtifactSettings.cs index c2e9ea961c1..8e1f8e2c5db 100644 --- a/src/Tools/dotnet-monitor/Egress/EgressArtifactSettings.cs +++ b/src/Tools/dotnet-monitor/Egress/EgressArtifactSettings.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +#nullable disable + using System; using System.Collections.Generic; diff --git a/src/Tools/dotnet-monitor/Egress/EgressProviderSource.cs b/src/Tools/dotnet-monitor/Egress/EgressProviderSource.cs index a6e80289292..780b43344bc 100644 --- a/src/Tools/dotnet-monitor/Egress/EgressProviderSource.cs +++ b/src/Tools/dotnet-monitor/Egress/EgressProviderSource.cs @@ -22,7 +22,7 @@ internal sealed class EgressProviderSource : IDisposable private readonly ILogger _logger; private readonly IDictionary _providerNameToTypeMap; public IReadOnlyCollection ProviderNames { get; set; } = new List(); - public event EventHandler ProvidersChanged; + public event EventHandler? ProvidersChanged; public EgressProviderSource( IEgressConfigurationProvider configurationProvider, @@ -51,7 +51,7 @@ public void Initialize() public IEgressExtension GetEgressProvider(string name) { - if (!_providerNameToTypeMap.TryGetValue(name, out string providerType)) + if (!_providerNameToTypeMap.TryGetValue(name, out string? providerType)) { throw new EgressException(string.Format(CultureInfo.CurrentCulture, Strings.ErrorMessage_EgressProviderDoesNotExist, name)); } @@ -90,7 +90,7 @@ private void Reload() foreach (IConfigurationSection optionsSection in typeSection.GetChildren()) { string providerName = optionsSection.Key; - if (_providerNameToTypeMap.TryGetValue(providerName, out string existingProviderType)) + if (_providerNameToTypeMap.TryGetValue(providerName, out string? existingProviderType)) { _logger.DuplicateEgressProviderIgnored(providerName, providerType, existingProviderType); } diff --git a/src/Tools/dotnet-monitor/Egress/EgressService.cs b/src/Tools/dotnet-monitor/Egress/EgressService.cs index c17b36c0764..0652441c6ed 100644 --- a/src/Tools/dotnet-monitor/Egress/EgressService.cs +++ b/src/Tools/dotnet-monitor/Egress/EgressService.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +#nullable disable + using Microsoft.Diagnostics.Monitoring.WebApi; using Microsoft.Diagnostics.NETCore.Client; using System; diff --git a/src/Tools/dotnet-monitor/Egress/Extension/EgressArtifactResult.cs b/src/Tools/dotnet-monitor/Egress/Extension/EgressArtifactResult.cs index a62464f328d..90e9034d146 100644 --- a/src/Tools/dotnet-monitor/Egress/Extension/EgressArtifactResult.cs +++ b/src/Tools/dotnet-monitor/Egress/Extension/EgressArtifactResult.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +#nullable disable + using Microsoft.Diagnostics.Tools.Monitor.Extensibility; using System.Diagnostics; diff --git a/src/Tools/dotnet-monitor/Egress/Extension/EgressExtension.OutputParser.cs b/src/Tools/dotnet-monitor/Egress/Extension/EgressExtension.OutputParser.cs index e8648df6983..a95ab55d174 100644 --- a/src/Tools/dotnet-monitor/Egress/Extension/EgressExtension.OutputParser.cs +++ b/src/Tools/dotnet-monitor/Egress/Extension/EgressExtension.OutputParser.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +#nullable disable + using Microsoft.Diagnostics.Tools.Monitor.Extensibility; using Microsoft.Extensions.Logging; using System; diff --git a/src/Tools/dotnet-monitor/Egress/Extension/EgressExtension.cs b/src/Tools/dotnet-monitor/Egress/Extension/EgressExtension.cs index d9f4dcbcd37..fdcf814c0ac 100644 --- a/src/Tools/dotnet-monitor/Egress/Extension/EgressExtension.cs +++ b/src/Tools/dotnet-monitor/Egress/Extension/EgressExtension.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +#nullable disable + using Microsoft.Diagnostics.Tools.Monitor.Egress.Configuration; using Microsoft.Diagnostics.Tools.Monitor.Extensibility; using Microsoft.Extensions.Configuration; diff --git a/src/Tools/dotnet-monitor/Egress/Extension/ExtensionEgressPayload.cs b/src/Tools/dotnet-monitor/Egress/Extension/ExtensionEgressPayload.cs index 72c8713bd0c..429ee50a786 100644 --- a/src/Tools/dotnet-monitor/Egress/Extension/ExtensionEgressPayload.cs +++ b/src/Tools/dotnet-monitor/Egress/Extension/ExtensionEgressPayload.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +#nullable disable + using Microsoft.Extensions.Logging; using System.Collections.Generic; using System.Text.Json.Serialization; diff --git a/src/Tools/dotnet-monitor/Egress/FileSystem/FileSystemEgressExtension.cs b/src/Tools/dotnet-monitor/Egress/FileSystem/FileSystemEgressExtension.cs index 1a25cd0c3e9..72bd6b2f638 100644 --- a/src/Tools/dotnet-monitor/Egress/FileSystem/FileSystemEgressExtension.cs +++ b/src/Tools/dotnet-monitor/Egress/FileSystem/FileSystemEgressExtension.cs @@ -58,7 +58,7 @@ public async Task EgressArtifact( WrapException(() => Directory.CreateDirectory(options.IntermediateDirectoryPath)); } - string intermediateFilePath = null; + string? intermediateFilePath = null; try { int remainingAttempts = 10; @@ -92,7 +92,10 @@ public async Task EgressArtifact( } catch (Exception ex) { - _logger.IntermediateFileDeletionFailed(intermediateFilePath, ex); + if (intermediateFilePath != null) + { + _logger.IntermediateFileDeletionFailed(intermediateFilePath, ex); + } } } } diff --git a/src/Tools/dotnet-monitor/EndpointInfo/ClientEndpointInfoSource.cs b/src/Tools/dotnet-monitor/EndpointInfo/ClientEndpointInfoSource.cs index c132b09378e..defdf1f9ec7 100644 --- a/src/Tools/dotnet-monitor/EndpointInfo/ClientEndpointInfoSource.cs +++ b/src/Tools/dotnet-monitor/EndpointInfo/ClientEndpointInfoSource.cs @@ -36,7 +36,7 @@ public async Task> GetEndpointInfoAsync(CancellationT CancellationToken timeoutToken = timeoutTokenSource.Token; CancellationToken linkedToken = linkedTokenSource.Token; - var endpointInfoTasks = new List>(); + var endpointInfoTasks = new List>(); // Run the EndpointInfo creation parallel. The call to FromProcessId sends // a GetProcessInfo command to the runtime instance to get additional information. foreach (int pid in DiagnosticsClient.GetPublishedProcesses()) @@ -68,7 +68,7 @@ public async Task> GetEndpointInfoAsync(CancellationT await Task.WhenAll(endpointInfoTasks); - return endpointInfoTasks.Where(t => t.Result != null).Select(t => t.Result); + return endpointInfoTasks.Where(t => t.Result != null).Select(t => t.Result).Cast(); } } } diff --git a/src/Tools/dotnet-monitor/EndpointInfo/EndpointInfo.cs b/src/Tools/dotnet-monitor/EndpointInfo/EndpointInfo.cs index 82482718762..ade313fb0a7 100644 --- a/src/Tools/dotnet-monitor/EndpointInfo/EndpointInfo.cs +++ b/src/Tools/dotnet-monitor/EndpointInfo/EndpointInfo.cs @@ -5,6 +5,7 @@ using Microsoft.Diagnostics.NETCore.Client; using System; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Threading; using System.Threading.Tasks; @@ -17,7 +18,7 @@ public static async Task FromProcessIdAsync(int processId, IServic { var client = new DiagnosticsClient(processId); - ProcessInfo processInfo = null; + ProcessInfo? processInfo = null; try { // Primary motivation is to get the runtime instance cookie in order to @@ -36,7 +37,7 @@ public static async Task FromProcessIdAsync(int processId, IServic // Runtime didn't respond within client timeout. } - _ = TryParseVersion(processInfo?.ClrProductVersionString, out Version runtimeVersion); + _ = TryParseVersion(processInfo?.ClrProductVersionString, out Version? runtimeVersion); // CONSIDER: Generate a runtime instance identifier based on the pipe name // for .NET Core 3.1 e.g. pid + disambiguator in GUID form. @@ -59,7 +60,7 @@ public static async Task FromIpcEndpointInfoAsync(IpcEndpointInfo { var client = new DiagnosticsClient(info.Endpoint); - ProcessInfo processInfo = null; + ProcessInfo? processInfo = null; try { // Primary motivation is to keep parity with the FromProcessId implementation, @@ -79,7 +80,7 @@ public static async Task FromIpcEndpointInfoAsync(IpcEndpointInfo // Runtime didn't respond within client timeout. } - _ = TryParseVersion(processInfo?.ClrProductVersionString, out Version runtimeVersion); + _ = TryParseVersion(processInfo?.ClrProductVersionString, out Version? runtimeVersion); return new EndpointInfo() { @@ -94,7 +95,7 @@ public static async Task FromIpcEndpointInfoAsync(IpcEndpointInfo }; } - private static bool TryParseVersion(string versionString, out Version version) + private static bool TryParseVersion(string? versionString, [NotNullWhen(true)] out Version? version) { version = null; if (string.IsNullOrEmpty(versionString)) @@ -122,21 +123,25 @@ private static bool TryParseVersion(string versionString, out Version version) return Version.TryParse(noMetadataVersion[..prereleaseIndex], out version); } +#nullable disable public override IpcEndpoint Endpoint { get; protected set; } +#nullable restore public override int ProcessId { get; protected set; } public override Guid RuntimeInstanceCookie { get; protected set; } - public override string CommandLine { get; protected set; } + public override string? CommandLine { get; protected set; } - public override string OperatingSystem { get; protected set; } + public override string? OperatingSystem { get; protected set; } - public override string ProcessArchitecture { get; protected set; } + public override string? ProcessArchitecture { get; protected set; } - public override Version RuntimeVersion { get; protected set; } + public override Version? RuntimeVersion { get; protected set; } +#nullable disable public override IServiceProvider ServiceProvider { get; protected set; } +#nullable restore internal string DebuggerDisplay => FormattableString.Invariant($"PID={ProcessId}, Cookie={RuntimeInstanceCookie}"); } diff --git a/src/Tools/dotnet-monitor/EndpointInfo/ScopedEndpointInfo.cs b/src/Tools/dotnet-monitor/EndpointInfo/ScopedEndpointInfo.cs index ebffd6efa67..14064a2bcc0 100644 --- a/src/Tools/dotnet-monitor/EndpointInfo/ScopedEndpointInfo.cs +++ b/src/Tools/dotnet-monitor/EndpointInfo/ScopedEndpointInfo.cs @@ -9,7 +9,9 @@ namespace Microsoft.Diagnostics.Tools.Monitor { internal sealed class ScopedEndpointInfo : IEndpointInfo { +#nullable disable private IEndpointInfo _endpointInfo; +#nullable restore public void Set(IEndpointInfo endpointInfo) { @@ -20,13 +22,13 @@ public void Set(IEndpointInfo endpointInfo) public Guid RuntimeInstanceCookie => _endpointInfo.RuntimeInstanceCookie; - public string CommandLine => _endpointInfo.CommandLine; + public string? CommandLine => _endpointInfo.CommandLine; - public string OperatingSystem => _endpointInfo.OperatingSystem; + public string? OperatingSystem => _endpointInfo.OperatingSystem; - public string ProcessArchitecture => _endpointInfo.ProcessArchitecture; + public string? ProcessArchitecture => _endpointInfo.ProcessArchitecture; - public Version RuntimeVersion => _endpointInfo.RuntimeVersion; + public Version? RuntimeVersion => _endpointInfo.RuntimeVersion; IpcEndpoint IEndpointInfo.Endpoint => _endpointInfo.Endpoint; diff --git a/src/Tools/dotnet-monitor/EndpointInfo/ServerEndpointInfoSource.cs b/src/Tools/dotnet-monitor/EndpointInfo/ServerEndpointInfoSource.cs index e7a66afb3b1..4a925a8faf8 100644 --- a/src/Tools/dotnet-monitor/EndpointInfo/ServerEndpointInfoSource.cs +++ b/src/Tools/dotnet-monitor/EndpointInfo/ServerEndpointInfoSource.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +#nullable disable + using Microsoft.Diagnostics.Monitoring.WebApi; using Microsoft.Diagnostics.NETCore.Client; using Microsoft.Extensions.DependencyInjection; diff --git a/src/Tools/dotnet-monitor/Exceptions/EventExceptionsPipelineNameCache.cs b/src/Tools/dotnet-monitor/Exceptions/EventExceptionsPipelineNameCache.cs index 3660d68925b..5cb3169509a 100644 --- a/src/Tools/dotnet-monitor/Exceptions/EventExceptionsPipelineNameCache.cs +++ b/src/Tools/dotnet-monitor/Exceptions/EventExceptionsPipelineNameCache.cs @@ -54,7 +54,7 @@ public bool TryGetExceptionGroup(ulong groupId, out ulong exceptionClassId, out throwingMethodId = 0; ilOffset = 0; - if (!_exceptionGroupMap.TryGetValue(groupId, out ExceptionGroup identifier)) + if (!_exceptionGroupMap.TryGetValue(groupId, out ExceptionGroup? identifier)) return false; exceptionClassId = identifier.ClassId; @@ -68,7 +68,7 @@ public bool TryGetStackFrameIds(ulong stackFrameId, out ulong methodId, out int methodId = 0; ilOffset = 0; - if (!_stackFrames.TryGetValue(stackFrameId, out StackFrameInstance instance)) + if (!_stackFrames.TryGetValue(stackFrameId, out StackFrameInstance? instance)) return false; methodId = instance.MethodId; diff --git a/src/Tools/dotnet-monitor/Exceptions/ExceptionsOperation.cs b/src/Tools/dotnet-monitor/Exceptions/ExceptionsOperation.cs index bd1ee3eb0cc..257d8f43256 100644 --- a/src/Tools/dotnet-monitor/Exceptions/ExceptionsOperation.cs +++ b/src/Tools/dotnet-monitor/Exceptions/ExceptionsOperation.cs @@ -292,7 +292,7 @@ private static async Task WriteTextInnerExceptionsAndStackFrames(TextWriter writ { if (priorInstances.TryGetValue( currentInstance.InnerExceptionIds[0], - out IExceptionInstance primaryInnerInstance)) + out IExceptionInstance? primaryInnerInstance)) { await WriteTextInnerException(writer, primaryInnerInstance, 0, priorInstances); @@ -333,7 +333,7 @@ private static async Task WriteTextInnerExceptionsAndStackFrames(TextWriter writ { if (priorInstances.TryGetValue( currentInstance.InnerExceptionIds[index], - out IExceptionInstance secondaryInnerInstance)) + out IExceptionInstance? secondaryInnerInstance)) { await WriteTextInnerException(writer, secondaryInnerInstance, index, priorInstances); } diff --git a/src/Tools/dotnet-monitor/Exceptions/ExceptionsStore.cs b/src/Tools/dotnet-monitor/Exceptions/ExceptionsStore.cs index 6233d1389b9..e1849aa2330 100644 --- a/src/Tools/dotnet-monitor/Exceptions/ExceptionsStore.cs +++ b/src/Tools/dotnet-monitor/Exceptions/ExceptionsStore.cs @@ -87,7 +87,7 @@ public void AddExceptionInstance( public void RemoveExceptionInstance(ulong exceptionId) { - ExceptionInstance removedInstance = null; + ExceptionInstance? removedInstance = null; lock (_instances) { @@ -145,7 +145,7 @@ private async Task ProcessEntriesAsync(CancellationToken token) // it in the future, with either periodic retry OR registering a callback system for the missing IDs. if (entry.Cache.TryGetExceptionGroup(entry.GroupId, out ulong exceptionClassId, out _, out _)) { - string exceptionTypeName; + string? exceptionTypeName; if (!_exceptionTypeNameMap.TryGetValue(exceptionClassId, out exceptionTypeName)) { _builder.Clear(); @@ -154,12 +154,12 @@ private async Task ProcessEntriesAsync(CancellationToken token) } string moduleName = string.Empty; - if (entry.Cache.NameCache.ClassData.TryGetValue(exceptionClassId, out ClassData exceptionClassData)) + if (entry.Cache.NameCache.ClassData.TryGetValue(exceptionClassId, out ClassData? exceptionClassData)) { moduleName = NameFormatter.GetModuleName(entry.Cache.NameCache, exceptionClassData.ModuleId); } - CallStackModel callStack = GenerateCallStack(entry.StackFrameIds, entry.Cache, entry.ThreadId); + CallStackModel? callStack = GenerateCallStack(entry.StackFrameIds, entry.Cache, entry.ThreadId); ExceptionInstance instance = new( entry.ExceptionId, @@ -196,7 +196,7 @@ private async Task ProcessEntriesAsync(CancellationToken token) } } - internal static CallStackModel GenerateCallStack(ulong[] stackFrameIds, IExceptionsNameCache cache, int threadId) + internal static CallStackModel? GenerateCallStack(ulong[] stackFrameIds, IExceptionsNameCache cache, int threadId) { // Exceptions without stack frames were not thrown; do not create a call stack object, // which makes it clear that this exception was not thrown. diff --git a/src/Tools/dotnet-monitor/Exceptions/ExceptionsStoreLimitsCallback.cs b/src/Tools/dotnet-monitor/Exceptions/ExceptionsStoreLimitsCallback.cs index e9163264075..d8ec8ecca65 100644 --- a/src/Tools/dotnet-monitor/Exceptions/ExceptionsStoreLimitsCallback.cs +++ b/src/Tools/dotnet-monitor/Exceptions/ExceptionsStoreLimitsCallback.cs @@ -51,7 +51,7 @@ public override void BeforeAdd(IExceptionInstance instance) // Make sure all of the inner exceptions are no longer top-level exceptions. foreach (ulong innerExceptionId in instance.InnerExceptionIds) { - if (_outerExceptionMap.TryGetValue(innerExceptionId, out List outerExceptions)) + if (_outerExceptionMap.TryGetValue(innerExceptionId, out List? outerExceptions)) { outerExceptions.Add(instance.Id); } @@ -65,9 +65,9 @@ public override void BeforeAdd(IExceptionInstance instance) // exceptions that are not shared with any current top-level exception. if (_topLevelExceptions.Count > _topLevelLimit) { - LinkedListNode lastNode = _topLevelExceptions.Last; + // The linked list is guaranteed to have an entry due to the above check and constraints on _topLevelLimit + LinkedListNode lastNode = _topLevelExceptions.Last!; _topLevelExceptions.RemoveLast(); - RemoveIfNoOuterExceptions(lastNode.Value); } } @@ -76,7 +76,7 @@ private void RemoveIfNoOuterExceptions(ulong exceptionId) { // Remove the exception if it no longer belongs to any other exception in the store // as an inner exception. - if (_outerExceptionMap.TryGetValue(exceptionId, out List outerExceptionIds)) + if (_outerExceptionMap.TryGetValue(exceptionId, out List? outerExceptionIds)) { if (outerExceptionIds.Count == 0) { @@ -85,11 +85,11 @@ private void RemoveIfNoOuterExceptions(ulong exceptionId) // Check the inner exceptions of this exception, decouple them from this exception, // and remove them if they are not shared with any current top-level exception. - if (_innerExceptionMap.Remove(exceptionId, out List innerExceptionIds)) + if (_innerExceptionMap.Remove(exceptionId, out List? innerExceptionIds)) { foreach (ulong innerExceptionId in innerExceptionIds) { - if (_outerExceptionMap.TryGetValue(innerExceptionId, out List innerOuterExceptionIds)) + if (_outerExceptionMap.TryGetValue(innerExceptionId, out List? innerOuterExceptionIds)) { innerOuterExceptionIds.Remove(exceptionId); } diff --git a/src/Tools/dotnet-monitor/Extensibility/ExtensionManifest.cs b/src/Tools/dotnet-monitor/Extensibility/ExtensionManifest.cs index 2637ed4f751..4af5efa5c31 100644 --- a/src/Tools/dotnet-monitor/Extensibility/ExtensionManifest.cs +++ b/src/Tools/dotnet-monitor/Extensibility/ExtensionManifest.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +#nullable disable + using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Globalization; diff --git a/src/Tools/dotnet-monitor/Extensibility/FolderExtensionRepository.cs b/src/Tools/dotnet-monitor/Extensibility/FolderExtensionRepository.cs index 7afc15abd2e..ad08a0a336a 100644 --- a/src/Tools/dotnet-monitor/Extensibility/FolderExtensionRepository.cs +++ b/src/Tools/dotnet-monitor/Extensibility/FolderExtensionRepository.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +#nullable disable + using Microsoft.Diagnostics.Tools.Monitor.Egress.Extension; using Microsoft.Extensions.FileProviders; using Microsoft.Extensions.Logging; diff --git a/src/Tools/dotnet-monitor/Extensibility/WellKnownExtensionRepository.cs b/src/Tools/dotnet-monitor/Extensibility/WellKnownExtensionRepository.cs index a38aa2b9544..3e3245c2f98 100644 --- a/src/Tools/dotnet-monitor/Extensibility/WellKnownExtensionRepository.cs +++ b/src/Tools/dotnet-monitor/Extensibility/WellKnownExtensionRepository.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; diff --git a/src/Tools/dotnet-monitor/HostBuilder/HostBuilderHelper.cs b/src/Tools/dotnet-monitor/HostBuilder/HostBuilderHelper.cs index 42291c2c35b..bfcdbe0e0b2 100644 --- a/src/Tools/dotnet-monitor/HostBuilder/HostBuilderHelper.cs +++ b/src/Tools/dotnet-monitor/HostBuilder/HostBuilderHelper.cs @@ -21,7 +21,7 @@ internal static class HostBuilderHelper public static IHostBuilder CreateHostBuilder(HostBuilderSettings settings) { - string aspnetUrls = string.Empty; + string? aspnetUrls = string.Empty; ServerUrlsBlockingConfigurationManager manager = new(); manager.IsBlocking = true; @@ -63,7 +63,7 @@ public static IHostBuilder CreateHostBuilder(HostBuilderSettings settings) //in Kubernetes. //We get around this by watching the target folder of the symlink instead. //See https://github.com/kubernetes/kubernetes/master/pkg/volume/util/atomic_writer.go - string path = settings.SharedConfigDirectory; + string? path = settings.SharedConfigDirectory; if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) && RuntimeInfo.IsInKubernetes) { string symlinkTarget = Path.Combine(settings.SharedConfigDirectory, "..data"); @@ -78,7 +78,7 @@ public static IHostBuilder CreateHostBuilder(HostBuilderSettings settings) builder.AddEnvironmentVariables(ToolIdentifiers.StandardPrefix); // User-specified configuration file path is considered highest precedence, but does NOT override other configuration sources - FileInfo userFilePath = settings.UserProvidedConfigFilePath; + FileInfo? userFilePath = settings.UserProvidedConfigFilePath; if (null != userFilePath) { @@ -146,6 +146,7 @@ public static IHostBuilder CreateHostBuilder(HostBuilderSettings settings) // Unblock reading of the Urls option from configuration, read it, and block it again so that Kestrel // is unable to read this option when it starts. +#nullable disable manager.IsBlocking = false; string[] urls = ConfigurationHelper.SplitValue(context.Configuration[WebHostDefaults.ServerUrlsKey]); manager.IsBlocking = true; @@ -155,7 +156,7 @@ public static IHostBuilder CreateHostBuilder(HostBuilderSettings settings) string metricHostingUrls = metricsOptions.Endpoints; string[] metricUrls = ConfigurationHelper.SplitValue(metricHostingUrls); - +#nullable restore //Workaround for lack of default certificate. See https://github.com/dotnet/aspnetcore/issues/28120 options.Configure(context.Configuration.GetSection("Kestrel")).Load(); @@ -175,7 +176,7 @@ public static IHostBuilder CreateHostBuilder(HostBuilderSettings settings) // Restore the Urls option to the configuration provider that originally provided the value // before it was cleared during the IWebHostBuilder configuration callback. if (!string.IsNullOrEmpty(aspnetUrls) && - builder.TryGetProvider(WebHostDefaults.ServerUrlsKey, out IConfigurationProvider provider)) + builder.TryGetProvider(WebHostDefaults.ServerUrlsKey, out IConfigurationProvider? provider)) { provider.Set(WebHostDefaults.ServerUrlsKey, aspnetUrls); } @@ -237,7 +238,7 @@ public static StartupAuthenticationMode GetStartupAuthenticationMode(bool noAuth private static void ConfigureMetricsDefaults(IConfigurationBuilder builder) { - builder.AddInMemoryCollection(new Dictionary + builder.AddInMemoryCollection(new Dictionary { {ConfigurationPath.Combine(ConfigurationKeys.Metrics, nameof(MetricsOptions.MetricCount)), MetricsOptionsDefaults.MetricCount.ToString()}, {ConfigurationPath.Combine(ConfigurationKeys.Metrics, nameof(MetricsOptions.IncludeDefaultProviders)), MetricsOptionsDefaults.IncludeDefaultProviders.ToString()} @@ -246,7 +247,7 @@ private static void ConfigureMetricsDefaults(IConfigurationBuilder builder) private static void ConfigureGlobalMetricsDefaults(IConfigurationBuilder builder) { - builder.AddInMemoryCollection(new Dictionary + builder.AddInMemoryCollection(new Dictionary { {ConfigurationPath.Combine(ConfigurationKeys.GlobalCounter, nameof(GlobalCounterOptions.IntervalSeconds)), GlobalCounterOptionsDefaults.IntervalSeconds.ToString() } }); diff --git a/src/Tools/dotnet-monitor/HostBuilder/HostBuilderSettings.cs b/src/Tools/dotnet-monitor/HostBuilder/HostBuilderSettings.cs index c2d6d9cb83c..ed56d1a5a6e 100644 --- a/src/Tools/dotnet-monitor/HostBuilder/HostBuilderSettings.cs +++ b/src/Tools/dotnet-monitor/HostBuilder/HostBuilderSettings.cs @@ -42,34 +42,34 @@ private const string UserConfigDirectoryOverrideEnvironmentVariable Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), "." + ProductFolderName) : Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), ProductFolderName)); - public string[] Urls { get; set; } + public string[]? Urls { get; set; } - public string[] MetricsUrls { get; set; } + public string[]? MetricsUrls { get; set; } public bool EnableMetrics { get; set; } - public string DiagnosticPort { get; set; } + public string? DiagnosticPort { get; set; } public StartupAuthenticationMode AuthenticationMode { get; set; } - public string ContentRootDirectory { get; set; } + public required string ContentRootDirectory { get; set; } - public string SharedConfigDirectory { get; set; } + public required string SharedConfigDirectory { get; set; } - public string UserConfigDirectory { get; set; } + public required string UserConfigDirectory { get; set; } - public FileInfo UserProvidedConfigFilePath { get; set; } + public FileInfo? UserProvidedConfigFilePath { get; set; } /// /// Create settings for dotnet-monitor hosting. /// public static HostBuilderSettings CreateMonitor( - string[] urls, - string[] metricUrls, + string[]? urls, + string[]? metricUrls, bool metrics, - string diagnosticPort, + string? diagnosticPort, StartupAuthenticationMode startupAuthMode, - FileInfo userProvidedConfigFilePath) + FileInfo? userProvidedConfigFilePath) { return new HostBuilderSettings() { diff --git a/src/Tools/dotnet-monitor/HostBuilder/HostBuilderStartupLogger.cs b/src/Tools/dotnet-monitor/HostBuilder/HostBuilderStartupLogger.cs index 3b0487b1cf5..3fa06357afc 100644 --- a/src/Tools/dotnet-monitor/HostBuilder/HostBuilderStartupLogger.cs +++ b/src/Tools/dotnet-monitor/HostBuilder/HostBuilderStartupLogger.cs @@ -22,7 +22,7 @@ public HostBuilderStartupLogger( public void Log() { - if (_builderContext.Properties.TryGetValue(HostBuilderResults.ResultKey, out object resultsObject)) + if (_builderContext.Properties.TryGetValue(HostBuilderResults.ResultKey, out object? resultsObject)) { if (resultsObject is HostBuilderResults hostBuilderResults) { diff --git a/src/Tools/dotnet-monitor/HostBuilder/ServerUrlsBlockingConfigurationProvider.cs b/src/Tools/dotnet-monitor/HostBuilder/ServerUrlsBlockingConfigurationProvider.cs index ccc9b7e117f..977e952dcc5 100644 --- a/src/Tools/dotnet-monitor/HostBuilder/ServerUrlsBlockingConfigurationProvider.cs +++ b/src/Tools/dotnet-monitor/HostBuilder/ServerUrlsBlockingConfigurationProvider.cs @@ -4,6 +4,7 @@ using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; using System; +using System.Diagnostics.CodeAnalysis; namespace Microsoft.Diagnostics.Tools.Monitor { @@ -17,13 +18,13 @@ public ServerUrlsBlockingConfigurationProvider(ServerUrlsBlockingConfigurationMa _manager = manager; } - public override void Set(string key, string value) + public override void Set(string key, string? value) { // Overridden to prevent set of data since this provider does not // provide any real data from any source. } - public override bool TryGet(string key, out string value) + public override bool TryGet(string key, [NotNullWhen(true)] out string? value) { // Block reading of the Urls option if the manager says to block. This will prevent other // configuration providers that were configured at a lower priority from providing their diff --git a/src/Tools/dotnet-monitor/InProcessFeatures/InProcessPostConfigureOptions.cs b/src/Tools/dotnet-monitor/InProcessFeatures/InProcessPostConfigureOptions.cs index b42e0499f77..2db792e94dd 100644 --- a/src/Tools/dotnet-monitor/InProcessFeatures/InProcessPostConfigureOptions.cs +++ b/src/Tools/dotnet-monitor/InProcessFeatures/InProcessPostConfigureOptions.cs @@ -22,7 +22,7 @@ public InProcessFeaturePostConfigureOptions(IConfiguration configuration, string _enabledByDefault = enabledByDefault; } - void IPostConfigureOptions.PostConfigure(string name, T options) + void IPostConfigureOptions.PostConfigure(string? name, T options) { InProcessFeatureOptionsBinder.BindEnabled( options, diff --git a/src/Tools/dotnet-monitor/LibrarySharing/DefaultSharedLibraryInitializer.cs b/src/Tools/dotnet-monitor/LibrarySharing/DefaultSharedLibraryInitializer.cs index 799c9a6205e..a39b2d48eb8 100644 --- a/src/Tools/dotnet-monitor/LibrarySharing/DefaultSharedLibraryInitializer.cs +++ b/src/Tools/dotnet-monitor/LibrarySharing/DefaultSharedLibraryInitializer.cs @@ -75,7 +75,7 @@ public async Task InitializeAsync(CancellationToken cancel // Go through each directory and validate the existing files are exactly the same as expected // or create new files if they do not exist. Hold onto the file handles to prevent modification // of the shared files while they are being offered for use in target applications. - while (subDirectories.TryDequeue(out string subDirectory)) + while (subDirectories.TryDequeue(out string? subDirectory)) { DirectoryInfo sourceDir = new(Path.Combine(sharedLibrarySourceDir.FullName, subDirectory)); DirectoryInfo targetDir = Directory.CreateDirectory(Path.Combine(_pathProvider.TargetPath, subDirectory)); diff --git a/src/Tools/dotnet-monitor/LibrarySharing/DefaultSharedLibraryPathProvider.cs b/src/Tools/dotnet-monitor/LibrarySharing/DefaultSharedLibraryPathProvider.cs index e56365bfe8f..fdae123155a 100644 --- a/src/Tools/dotnet-monitor/LibrarySharing/DefaultSharedLibraryPathProvider.cs +++ b/src/Tools/dotnet-monitor/LibrarySharing/DefaultSharedLibraryPathProvider.cs @@ -14,10 +14,12 @@ internal sealed class DefaultSharedLibraryPathProvider /// /// Provides libraries from the 'shared' folder under the .NET Monitor installation. /// + #nullable disable public DefaultSharedLibraryPathProvider(IOptions _storageOptions) : this(Path.Combine(AppContext.BaseDirectory, "shared"), ComputeTargetPath(_storageOptions)) { } +#nullable restore public DefaultSharedLibraryPathProvider(string sourcePath, string targetPath) { @@ -25,13 +27,16 @@ public DefaultSharedLibraryPathProvider(string sourcePath, string targetPath) TargetPath = targetPath; } - private static string ComputeTargetPath(IOptions options) + private static string? ComputeTargetPath(IOptions options) { - string rootPath = options.Value.SharedLibraryPath; + string? rootPath = options.Value.SharedLibraryPath; if (string.IsNullOrEmpty(rootPath)) return null; - string expectedVersion = Assembly.GetExecutingAssembly().GetInformationalVersionString(); + string? expectedVersion = Assembly.GetExecutingAssembly()?.GetInformationalVersionString(); + if (expectedVersion == null) + return null; + // Remove '+' and commit hash from version string int hashSeparatorIndex = expectedVersion.IndexOf('+'); if (hashSeparatorIndex > 0) diff --git a/src/Tools/dotnet-monitor/LoggingEventIds.cs b/src/Tools/dotnet-monitor/LoggingEventIds.cs index b6385361c15..7c4c942772a 100644 --- a/src/Tools/dotnet-monitor/LoggingEventIds.cs +++ b/src/Tools/dotnet-monitor/LoggingEventIds.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +#nullable enable + using Microsoft.Extensions.Logging; using System; @@ -119,7 +121,7 @@ internal static class LoggingEventIdsExtensions { public static EventId EventId(this LoggingEventIds enumVal) { - string name = Enum.GetName(typeof(LoggingEventIds), enumVal); + string? name = Enum.GetName(typeof(LoggingEventIds), enumVal); int id = enumVal.Id(); return new EventId(id, name); } diff --git a/src/Tools/dotnet-monitor/LoggingExtensions.cs b/src/Tools/dotnet-monitor/LoggingExtensions.cs index 5578be3cee7..22523777625 100644 --- a/src/Tools/dotnet-monitor/LoggingExtensions.cs +++ b/src/Tools/dotnet-monitor/LoggingExtensions.cs @@ -14,361 +14,361 @@ namespace Microsoft.Diagnostics.Tools.Monitor { internal static class LoggingExtensions { - private static readonly Action _egressProviderInvalidOptions = + private static readonly Action _egressProviderInvalidOptions = LoggerMessage.Define( eventId: LoggingEventIds.EgressProviderInvalidOptions.EventId(), logLevel: LogLevel.Error, formatString: Strings.LogFormatString_EgressProviderInvalidOptions); - private static readonly Action _egressCopyActionStreamToEgressStream = + private static readonly Action _egressCopyActionStreamToEgressStream = LoggerMessage.Define( eventId: LoggingEventIds.EgressCopyActionStreamToEgressStream.EventId(), logLevel: LogLevel.Debug, formatString: Strings.LogFormatString_EgressCopyActionStreamToEgressStream); - private static readonly Action _egressProviderOptionsValidationFailure = + private static readonly Action _egressProviderOptionsValidationFailure = LoggerMessage.Define( eventId: LoggingEventIds.EgressProviderOptionsValidationFailure.EventId(), logLevel: LogLevel.Error, formatString: Strings.LogFormatString_EgressProviderOptionsValidationError); - private static readonly Action _egressProviderInvokeStreamAction = + private static readonly Action _egressProviderInvokeStreamAction = LoggerMessage.Define( eventId: LoggingEventIds.EgressProviderInvokeStreamAction.EventId(), logLevel: LogLevel.Debug, formatString: Strings.LogFormatString_EgressProviderInvokeStreamAction); - private static readonly Action _egressProviderSavedStream = + private static readonly Action _egressProviderSavedStream = LoggerMessage.Define( eventId: LoggingEventIds.EgressProviderSavedStream.EventId(), logLevel: LogLevel.Debug, formatString: Strings.LogFormatString_EgressProviderSavedStream); - private static readonly Action _noAuthentication = + private static readonly Action _noAuthentication = LoggerMessage.Define( eventId: LoggingEventIds.NoAuthentication.EventId(), logLevel: LogLevel.Warning, formatString: Strings.LogFormatString_NoAuthentication); - private static readonly Action _insecureAuthenticationConfiguration = + private static readonly Action _insecureAuthenticationConfiguration = LoggerMessage.Define( eventId: LoggingEventIds.InsecureAuthenticationConfiguration.EventId(), logLevel: LogLevel.Warning, formatString: Strings.LogFormatString_InsecureAuthenticationConfiguration); - private static readonly Action _unableToListenToAddress = + private static readonly Action _unableToListenToAddress = LoggerMessage.Define( eventId: LoggingEventIds.UnableToListenToAddress.EventId(), logLevel: LogLevel.Error, formatString: Strings.LogFormatString_UnableToListenToAddress); - private static readonly Action _boundDefaultAddress = + private static readonly Action _boundDefaultAddress = LoggerMessage.Define( eventId: LoggingEventIds.BoundDefaultAddress.EventId(), logLevel: LogLevel.Debug, formatString: Strings.LogFormatString_BoundDefaultAddress); - private static readonly Action _boundMetricsAddress = + private static readonly Action _boundMetricsAddress = LoggerMessage.Define( eventId: LoggingEventIds.BoundMetricsAddress.EventId(), logLevel: LogLevel.Debug, formatString: Strings.LogFormatString_BoundMetricsAddress); - private static readonly Action _optionsValidationFailure = + private static readonly Action _optionsValidationFailure = LoggerMessage.Define( eventId: LoggingEventIds.OptionsValidationFailure.EventId(), logLevel: LogLevel.Critical, formatString: Strings.LogFormatString_OptionsValidationFailure); - private static readonly Action _runningElevated = + private static readonly Action _runningElevated = LoggerMessage.Define( eventId: LoggingEventIds.RunningElevated.EventId(), logLevel: LogLevel.Warning, formatString: Strings.LogFormatString_RunningElevated); - private static readonly Action _disabledNegotiateWhileElevated = + private static readonly Action _disabledNegotiateWhileElevated = LoggerMessage.Define( eventId: LoggingEventIds.DisabledNegotiateWhileElevated.EventId(), logLevel: LogLevel.Warning, formatString: Strings.LogFormatString_DisabledNegotiateWhileElevated); - private static readonly Action _apiKeyValidationFailure = + private static readonly Action _apiKeyValidationFailure = LoggerMessage.Define( eventId: LoggingEventIds.ApiKeyValidationFailure.EventId(), logLevel: LogLevel.Warning, formatString: Strings.LogFormatString_ApiKeyValidationFailure); - private static readonly Action _logTempKey = + private static readonly Action _logTempKey = LoggerMessage.Define( eventId: LoggingEventIds.LogTempApiKey.EventId(), logLevel: LogLevel.Warning, formatString: Strings.LogFormatString_LogTempApiKey); - private static readonly Action _duplicateEgressProviderIgnored = + private static readonly Action _duplicateEgressProviderIgnored = LoggerMessage.Define( eventId: LoggingEventIds.DuplicateEgressProviderIgnored.EventId(), logLevel: LogLevel.Warning, formatString: Strings.LogFormatString_DuplicateEgressProviderIgnored); - private static readonly Action _apiKeyAuthenticationOptionsValidated = + private static readonly Action _apiKeyAuthenticationOptionsValidated = LoggerMessage.Define( eventId: LoggingEventIds.ApiKeyAuthenticationOptionsValidated.EventId(), logLevel: LogLevel.Information, formatString: Strings.LogFormatString_ApiKeyAuthenticationOptionsValidated); - private static readonly Action _notifyPrivateKey = + private static readonly Action _notifyPrivateKey = LoggerMessage.Define( eventId: LoggingEventIds.NotifyPrivateKey.EventId(), logLevel: LogLevel.Warning, formatString: Strings.LogFormatString_NotifyPrivateKey); - private static readonly Action _duplicateCollectionRuleActionIgnored = + private static readonly Action _duplicateCollectionRuleActionIgnored = LoggerMessage.Define( eventId: LoggingEventIds.DuplicateCollectionRuleActionIgnored.EventId(), logLevel: LogLevel.Warning, formatString: Strings.LogFormatString_DuplicateCollectionRuleActionIgnored); - private static readonly Action _duplicateCollectionRuleTriggerIgnored = + private static readonly Action _duplicateCollectionRuleTriggerIgnored = LoggerMessage.Define( eventId: LoggingEventIds.DuplicateCollectionRuleTriggerIgnored.EventId(), logLevel: LogLevel.Warning, formatString: Strings.LogFormatString_DuplicateCollectionRuleTriggerIgnored); - private static readonly Action _collectionRuleStarted = + private static readonly Action _collectionRuleStarted = LoggerMessage.Define( eventId: LoggingEventIds.CollectionRuleStarted.EventId(), logLevel: LogLevel.Information, formatString: Strings.LogFormatString_CollectionRuleStarted); - private static readonly Action _collectionRuleFailed = + private static readonly Action _collectionRuleFailed = LoggerMessage.Define( eventId: LoggingEventIds.CollectionRuleFailed.EventId(), logLevel: LogLevel.Error, formatString: Strings.LogFormatString_CollectionRuleFailed); - private static readonly Action _collectionRuleCompleted = + private static readonly Action _collectionRuleCompleted = LoggerMessage.Define( eventId: LoggingEventIds.CollectionRuleCompleted.EventId(), logLevel: LogLevel.Information, formatString: Strings.LogFormatString_CollectionRuleCompleted); - private static readonly Action _collectionRulesStarted = + private static readonly Action _collectionRulesStarted = LoggerMessage.Define( eventId: LoggingEventIds.CollectionRulesStarted.EventId(), logLevel: LogLevel.Information, formatString: Strings.LogFormatString_CollectionRulesStarted); - private static readonly Action _collectionRuleActionStarted = + private static readonly Action _collectionRuleActionStarted = LoggerMessage.Define( eventId: LoggingEventIds.CollectionRuleActionStarted.EventId(), logLevel: LogLevel.Information, formatString: Strings.LogFormatString_CollectionRuleActionStarted); - private static readonly Action _collectionRuleActionCompleted = + private static readonly Action _collectionRuleActionCompleted = LoggerMessage.Define( eventId: LoggingEventIds.CollectionRuleActionCompleted.EventId(), logLevel: LogLevel.Information, formatString: Strings.LogFormatString_CollectionRuleActionCompleted); - private static readonly Action _collectionRuleTriggerStarted = + private static readonly Action _collectionRuleTriggerStarted = LoggerMessage.Define( eventId: LoggingEventIds.CollectionRuleTriggerStarted.EventId(), logLevel: LogLevel.Information, formatString: Strings.LogFormatString_CollectionRuleTriggerStarted); - private static readonly Action _collectionRuleTriggerCompleted = + private static readonly Action _collectionRuleTriggerCompleted = LoggerMessage.Define( eventId: LoggingEventIds.CollectionRuleTriggerCompleted.EventId(), logLevel: LogLevel.Information, formatString: Strings.LogFormatString_CollectionRuleTriggerCompleted); - private static readonly Action _collectionRuleActionsThrottled = + private static readonly Action _collectionRuleActionsThrottled = LoggerMessage.Define( eventId: LoggingEventIds.CollectionRuleActionsThrottled.EventId(), logLevel: LogLevel.Warning, formatString: Strings.LogFormatString_CollectionRuleActionsThrottled); - private static readonly Action _collectionRuleActionFailed = + private static readonly Action _collectionRuleActionFailed = LoggerMessage.Define( eventId: LoggingEventIds.CollectionRuleActionFailed.EventId(), logLevel: LogLevel.Error, formatString: Strings.LogFormatString_CollectionRuleActionFailed); - private static readonly Action _collectionRuleActionsCompleted = + private static readonly Action _collectionRuleActionsCompleted = LoggerMessage.Define( eventId: LoggingEventIds.CollectionRuleActionsCompleted.EventId(), logLevel: LogLevel.Information, formatString: Strings.LogFormatString_CollectionRuleActionsCompleted); - private static readonly Action _collectionRulesStarting = + private static readonly Action _collectionRulesStarting = LoggerMessage.Define( eventId: LoggingEventIds.CollectionRulesStarting.EventId(), logLevel: LogLevel.Information, formatString: Strings.LogFormatString_CollectionRulesStarting); - private static readonly Action _diagnosticRequestCancelled = + private static readonly Action _diagnosticRequestCancelled = LoggerMessage.Define( eventId: LoggingEventIds.DiagnosticRequestCancelled.EventId(), logLevel: LogLevel.Warning, formatString: Strings.LogFormatString_DiagnosticRequestCancelled); - private static readonly Action _collectionRuleUnmatchedFilters = + private static readonly Action _collectionRuleUnmatchedFilters = LoggerMessage.Define( eventId: LoggingEventIds.CollectionRuleUnmatchedFilters.EventId(), logLevel: LogLevel.Information, formatString: Strings.LogFormatString_CollectionRuleUnmatchedFilters); - private static readonly Action _collectionRuleConfigurationChanged = + private static readonly Action _collectionRuleConfigurationChanged = LoggerMessage.Define( eventId: LoggingEventIds.CollectionRuleConfigurationChanged.EventId(), logLevel: LogLevel.Information, formatString: Strings.LogFormatString_CollectionRuleConfigurationChanged); - private static readonly Action _collectionRulesStopping = + private static readonly Action _collectionRulesStopping = LoggerMessage.Define( eventId: LoggingEventIds.CollectionRulesStopping.EventId(), logLevel: LogLevel.Information, formatString: Strings.LogFormatString_CollectionRulesStopping); - private static readonly Action _collectionRulesStopped = + private static readonly Action _collectionRulesStopped = LoggerMessage.Define( eventId: LoggingEventIds.CollectionRulesStopped.EventId(), logLevel: LogLevel.Information, formatString: Strings.LogFormatString_CollectionRulesStopped); - private static readonly Action _collectionRuleCancelled = + private static readonly Action _collectionRuleCancelled = LoggerMessage.Define( eventId: LoggingEventIds.CollectionRuleCancelled.EventId(), logLevel: LogLevel.Information, formatString: Strings.LogFormatString_CollectionRuleCancelled); - private static readonly Action _diagnosticRequestFailed = + private static readonly Action _diagnosticRequestFailed = LoggerMessage.Define( eventId: LoggingEventIds.DiagnosticRequestFailed.EventId(), logLevel: LogLevel.Debug, formatString: Strings.LogFormatString_DiagnosticRequestFailed); - private static readonly Action _invalidActionReferenceToken = + private static readonly Action _invalidActionReferenceToken = LoggerMessage.Define( eventId: LoggingEventIds.InvalidActionReferenceToken.EventId(), logLevel: LogLevel.Error, formatString: Strings.LogFormatString_InvalidToken); - private static readonly Action _invalidActionReference = + private static readonly Action _invalidActionReference = LoggerMessage.Define( eventId: LoggingEventIds.InvalidActionReference.EventId(), logLevel: LogLevel.Error, formatString: Strings.LogFormatString_InvalidActionReference); - private static readonly Action _invalidActionResultReference = + private static readonly Action _invalidActionResultReference = LoggerMessage.Define( eventId: LoggingEventIds.InvalidActionResultReference.EventId(), logLevel: LogLevel.Error, formatString: Strings.LogFormatString_InvalidActionResultReference); - private static readonly Action _actionSettingsTokenizationNotSupported = + private static readonly Action _actionSettingsTokenizationNotSupported = LoggerMessage.Define( eventId: LoggingEventIds.ActionSettingsTokenizationNotSupported.EventId(), logLevel: LogLevel.Error, formatString: Strings.LogFormatString_ActionSettingsTokenizationNotSupported); - private static readonly Action _endpointTimeout = + private static readonly Action _endpointTimeout = LoggerMessage.Define( eventId: LoggingEventIds.EndpointTimeout.EventId(), logLevel: LogLevel.Warning, formatString: Strings.LogFormatString_EndpointTimeout); - private static readonly Action _loadingProfiler = + private static readonly Action _loadingProfiler = LoggerMessage.Define( eventId: LoggingEventIds.LoadingProfiler.EventId(), logLevel: LogLevel.Information, formatString: Strings.LogFormatString_LoadingProfiler); - private static readonly Action _setEnvironmentVariable = + private static readonly Action _setEnvironmentVariable = LoggerMessage.Define( eventId: LoggingEventIds.SetEnvironmentVariable.EventId(), logLevel: LogLevel.Information, formatString: Strings.LogFormatString_SetEnvironmentVariable); - private static readonly Action _getEnvironmentVariable = + private static readonly Action _getEnvironmentVariable = LoggerMessage.Define( eventId: LoggingEventIds.GetEnvironmentVariable.EventId(), logLevel: LogLevel.Information, formatString: Strings.LogFormatString_GetEnvironmentVariable); - private static readonly Action _monitorApiKeyNotConfigured = + private static readonly Action _monitorApiKeyNotConfigured = LoggerMessage.Define( eventId: LoggingEventIds.MonitorApiKeyNotConfigured.EventId(), logLevel: LogLevel.Warning, formatString: Strings.LogFormatString_ApiKeyNotConfigured); - private static readonly Action _experienceSurvey = + private static readonly Action _experienceSurvey = LoggerMessage.Define( eventId: LoggingEventIds.ExperienceSurvey.EventId(), logLevel: LogLevel.Information, formatString: Strings.LogFormatString_ExperienceSurvey); - private static readonly Action _diagnosticPortNotInListenModeForCollectionRules = + private static readonly Action _diagnosticPortNotInListenModeForCollectionRules = LoggerMessage.Define( eventId: LoggingEventIds.DiagnosticPortNotInListenModeForCollectionRules.EventId(), logLevel: LogLevel.Warning, formatString: Strings.LogFormatString_DiagnosticPortNotInListenModeForCollectionRules); - private static readonly Action _extensionProbeStart = + private static readonly Action _extensionProbeStart = LoggerMessage.Define( eventId: LoggingEventIds.ExtensionProbeStart.EventId(), logLevel: LogLevel.Debug, formatString: Strings.LogFormatString_ExtensionProbeStart); - private static readonly Action _extensionProbeSucceeded = + private static readonly Action _extensionProbeSucceeded = LoggerMessage.Define( eventId: LoggingEventIds.ExtensionProbeSucceeded.EventId(), logLevel: LogLevel.Debug, formatString: Strings.LogFormatString_ExtensionProbeSucceeded); - private static readonly Action _extensionProbeFailed = + private static readonly Action _extensionProbeFailed = LoggerMessage.Define( eventId: LoggingEventIds.ExtensionProbeFailed.EventId(), logLevel: LogLevel.Error, formatString: Strings.LogFormatString_ExtensionProbeFailed); - private static readonly Action _extensionStarting = + private static readonly Action _extensionStarting = LoggerMessage.Define( eventId: LoggingEventIds.ExtensionStarting.EventId(), logLevel: LogLevel.Debug, formatString: Strings.LogFormatString_ExtensionStarting); - private static readonly Action _extensionConfigured = + private static readonly Action _extensionConfigured = LoggerMessage.Define( eventId: LoggingEventIds.ExtensionConfigured.EventId(), logLevel: LogLevel.Debug, formatString: Strings.LogFormatString_ExtensionConfigured); - private static readonly Action _extensionEgressPayloadCompleted = + private static readonly Action _extensionEgressPayloadCompleted = LoggerMessage.Define( eventId: LoggingEventIds.ExtensionEgressPayloadCompleted.EventId(), logLevel: LogLevel.Debug, formatString: Strings.LogFormatString_ExtensionEgressPayloadCompleted); - private static readonly Action _extensionExited = + private static readonly Action _extensionExited = LoggerMessage.Define( eventId: LoggingEventIds.ExtensionExited.EventId(), logLevel: LogLevel.Debug, formatString: Strings.LogFormatString_ExtensionExited); - private static readonly Action _extensionOutputMessage = + private static readonly Action _extensionOutputMessage = LoggerMessage.Define( eventId: LoggingEventIds.ExtensionOutputMessage.EventId(), logLevel: LogLevel.Information, formatString: Strings.LogFormatString_ExtensionOutputMessage); - private static readonly Action _extensionErrorMessage = + private static readonly Action _extensionErrorMessage = LoggerMessage.Define( eventId: LoggingEventIds.ExtensionErrorMessage.EventId(), logLevel: LogLevel.Warning, formatString: Strings.LogFormatString_ExtensionErrorMessage); - private static readonly Action _extensionNotOfType = + private static readonly Action _extensionNotOfType = LoggerMessage.Define( eventId: LoggingEventIds.ExtensionNotOfType.EventId(), logLevel: LogLevel.Error, @@ -380,7 +380,7 @@ internal static class LoggingExtensions logLevel: LogLevel.Error, formatString: Strings.LogFormatString_ExtensionManifestNotParsable); - private static readonly Action _extensionMalformedOutput = + private static readonly Action _extensionMalformedOutput = LoggerMessage.Define( eventId: LoggingEventIds.ExtensionMalformedOutput.EventId(), logLevel: LogLevel.Error, @@ -404,7 +404,7 @@ internal static class LoggingExtensions logLevel: LogLevel.Debug, formatString: Strings.LogFormatString_IntermediateFileDeletionFailed); - private static readonly Action _diagnosticPortDeleteAttempt = + private static readonly Action _diagnosticPortDeleteAttempt = LoggerMessage.Define( eventId: LoggingEventIds.DiagnosticPortDeleteAttempt.EventId(), logLevel: LogLevel.Warning, @@ -416,7 +416,7 @@ internal static class LoggingExtensions logLevel: LogLevel.Warning, formatString: Strings.LogFormatString_DiagnosticPortDeleteFailed); - private static readonly Action _diagnosticPortAlteredWhileInUse = + private static readonly Action _diagnosticPortAlteredWhileInUse = LoggerMessage.Define( eventId: LoggingEventIds.DiagnosticPortAlteredWhileInUse.EventId(), logLevel: LogLevel.Warning, @@ -440,37 +440,37 @@ internal static class LoggingExtensions logLevel: LogLevel.Error, formatString: Strings.LogFormatString_UnableToApplyProfiler); - private static readonly Action _sharedlibraryPath = + private static readonly Action _sharedlibraryPath = LoggerMessage.Define( eventId: LoggingEventIds.SharedLibraryPath.EventId(), logLevel: LogLevel.Debug, formatString: Strings.LogFormatString_SharedLibraryPath); - private static readonly Action _connectionModeConnect = + private static readonly Action _connectionModeConnect = LoggerMessage.Define( eventId: LoggingEventIds.ConnectionModeConnect.EventId(), logLevel: LogLevel.Information, formatString: Strings.LogFormatString_ConnectionModeConnect); - private static readonly Action _connectionModeListen = + private static readonly Action _connectionModeListen = LoggerMessage.Define( eventId: LoggingEventIds.ConnectionModeListen.EventId(), logLevel: LogLevel.Information, formatString: Strings.LogFormatString_ConnectionModeListen); - private static readonly Action _experimentalFeatureEnabled = + private static readonly Action _experimentalFeatureEnabled = LoggerMessage.Define( eventId: LoggingEventIds.ExperimentalFeatureEnabled.EventId(), logLevel: LogLevel.Warning, formatString: Strings.LogFormatString_ExperimentalFeatureEnabled); - private static readonly Action _startCollectArtifact = + private static readonly Action _startCollectArtifact = LoggerMessage.Define( eventId: LoggingEventIds.StartCollectArtifact.EventId(), logLevel: LogLevel.Debug, formatString: Strings.LogFormatString_StartCollectArtifact); - private static readonly Action _startupHookInstructions = + private static readonly Action _startupHookInstructions = LoggerMessage.Define( eventId: LoggingEventIds.StartupHookInstructions.EventId(), logLevel: LogLevel.Warning, @@ -482,13 +482,13 @@ internal static class LoggingExtensions logLevel: LogLevel.Error, formatString: Strings.LogFormatString_UnableToWatchForDisconnect); - private static readonly Action _egressProviderTypeNotExist = + private static readonly Action _egressProviderTypeNotExist = LoggerMessage.Define( eventId: LoggingEventIds.EgressProviderTypeNotExist.EventId(), logLevel: LogLevel.Warning, formatString: Strings.LogFormatString_EgressProviderTypeNotExist); - private static readonly Action _profilerRuntimeIdentifier = + private static readonly Action _profilerRuntimeIdentifier = LoggerMessage.Define( eventId: LoggingEventIds.ProfilerRuntimeIdentifier.EventId(), logLevel: LogLevel.Debug, @@ -588,7 +588,9 @@ public static void ApiKeyValidationFailures(this ILogger logger, IEnumerable env = await client.GetProcessEnvironmentAsync(token); - if (!env.TryGetValue(InProcessFeaturesIdentifiers.EnvironmentVariables.AvailableInfrastructure.ManagedMessaging, out string isManagedMessagingAvailable) || + if (!env.TryGetValue(InProcessFeaturesIdentifiers.EnvironmentVariables.AvailableInfrastructure.ManagedMessaging, out string? isManagedMessagingAvailable) || !ToolIdentifiers.IsEnvVarValueEnabled(isManagedMessagingAvailable)) { throw getNotAvailableException(Strings.ParameterCapturingNotAvailable_Reason_ManagedMessagingDidNotLoad); } - if (!env.TryGetValue(InProcessFeaturesIdentifiers.EnvironmentVariables.AvailableInfrastructure.StartupHook, out string isStartupHookAvailable) || + if (!env.TryGetValue(InProcessFeaturesIdentifiers.EnvironmentVariables.AvailableInfrastructure.StartupHook, out string? isStartupHookAvailable) || !ToolIdentifiers.IsEnvVarValueEnabled(isStartupHookAvailable)) { throw getNotAvailableException(Strings.ParameterCapturingNotAvailable_Reason_StartupHookDidNotLoad); } const string EditAndContinueEnvName = "COMPLUS_ForceEnc"; - if (env.TryGetValue(EditAndContinueEnvName, out string editAndContinueEnvValue) && + if (env.TryGetValue(EditAndContinueEnvName, out string? editAndContinueEnvValue) && ToolIdentifiers.IsEnvVarValueEnabled(editAndContinueEnvValue)) { // Having Enc enabled results in methods belonging to debug modules to silently fail being instrumented. @@ -180,7 +180,7 @@ await Task.WhenAny( } } - private void OnStartedCapturing(object sender, Guid requestId) + private void OnStartedCapturing(object? sender, Guid requestId) { if (requestId != _requestId) { @@ -190,7 +190,7 @@ private void OnStartedCapturing(object sender, Guid requestId) _ = _capturingStartedCompletionSource.TrySetResult(); } - private void OnStoppedCapturing(object sender, Guid requestId) + private void OnStoppedCapturing(object? sender, Guid requestId) { if (requestId != _requestId) { @@ -200,7 +200,7 @@ private void OnStoppedCapturing(object sender, Guid requestId) _ = _capturingStoppedCompletionSource.TrySetResult(); } - private void OnCapturingFailed(object sender, CapturingFailedArgs args) + private void OnCapturingFailed(object? sender, CapturingFailedArgs args) { if (args.RequestId != _requestId) { @@ -222,7 +222,7 @@ private void OnCapturingFailed(object sender, CapturingFailedArgs args) _ = _capturingStartedCompletionSource.TrySetException(ex); } - private void OnServiceStateUpdate(object sender, ServiceStateUpdateArgs args) + private void OnServiceStateUpdate(object? sender, ServiceStateUpdateArgs args) { Exception ex; switch (args.ServiceState) @@ -241,7 +241,7 @@ private void OnServiceStateUpdate(object sender, ServiceStateUpdateArgs args) _ = _capturingStoppedCompletionSource.TrySetException(ex); } - private void OnUnknownRequestId(object sender, Guid requestId) + private void OnUnknownRequestId(object? sender, Guid requestId) { if (requestId != _requestId) { diff --git a/src/Tools/dotnet-monitor/ParameterCapturing/CapturedParametersBuilder.cs b/src/Tools/dotnet-monitor/ParameterCapturing/CapturedParametersBuilder.cs index 83f0e614b21..5fe11c82d20 100644 --- a/src/Tools/dotnet-monitor/ParameterCapturing/CapturedParametersBuilder.cs +++ b/src/Tools/dotnet-monitor/ParameterCapturing/CapturedParametersBuilder.cs @@ -6,6 +6,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; #nullable enable @@ -20,7 +21,7 @@ public bool TryStartNewCaptureResponse(Guid captureId, string? activityId, Activ return _capturedParameters.TryAdd(captureId, new CapturedParameters(activityId, activityIdFormat, threadId, capturedDateTime, methodName, methodTypeName, methodModuleName)); } - public bool TryFinalizeParameters(Guid captureId, out ICapturedParameters? capturedParameters) + public bool TryFinalizeParameters(Guid captureId, [NotNullWhen(true)] out ICapturedParameters? capturedParameters) { if (_capturedParameters.Remove(captureId, out CapturedParameters? captured)) { diff --git a/src/Tools/dotnet-monitor/ParameterCapturing/CapturedParametersWriter.cs b/src/Tools/dotnet-monitor/ParameterCapturing/CapturedParametersWriter.cs index 9e29528af8f..5ec183ebfb7 100644 --- a/src/Tools/dotnet-monitor/ParameterCapturing/CapturedParametersWriter.cs +++ b/src/Tools/dotnet-monitor/ParameterCapturing/CapturedParametersWriter.cs @@ -51,7 +51,7 @@ private async Task WriterLoop() while (await _parameters.Reader.WaitToReadAsync(_cancellationToken)) { - if (_parameters.Reader.TryRead(out ICapturedParameters parameter)) + if (_parameters.Reader.TryRead(out ICapturedParameters? parameter)) { await _formatter.WriteParameters(parameter, _cancellationToken); } diff --git a/src/Tools/dotnet-monitor/ParameterCapturing/EventParameterCapturingPipeline.cs b/src/Tools/dotnet-monitor/ParameterCapturing/EventParameterCapturingPipeline.cs index 8d4fc967433..e2349194751 100644 --- a/src/Tools/dotnet-monitor/ParameterCapturing/EventParameterCapturingPipeline.cs +++ b/src/Tools/dotnet-monitor/ParameterCapturing/EventParameterCapturingPipeline.cs @@ -19,15 +19,15 @@ namespace Microsoft.Diagnostics.Tools.Monitor.ParameterCapturing { internal sealed class CapturingFailedArgs { - public Guid RequestId { get; set; } - public ParameterCapturingEvents.CapturingFailedReason Reason { get; set; } - public string Details { get; set; } + public required Guid RequestId { get; set; } + public required ParameterCapturingEvents.CapturingFailedReason Reason { get; set; } + public required string Details { get; set; } } internal sealed class ServiceStateUpdateArgs { - public ParameterCapturingEvents.ServiceState ServiceState { get; set; } - public string Details { get; set; } + public required ParameterCapturingEvents.ServiceState ServiceState { get; set; } + public required string Details { get; set; } } internal sealed class EventParameterCapturingPipeline : EventSourcePipeline @@ -65,19 +65,19 @@ private void Callback(TraceEvent traceEvent) case "Capturing/Start": { Guid requestId = traceEvent.GetPayload(ParameterCapturingEvents.CapturingActivityPayload.RequestId); - Settings.OnStartedCapturing.Invoke(this, requestId); + Settings.OnStartedCapturing?.Invoke(this, requestId); break; } case "Capturing/Stop": { Guid requestId = traceEvent.GetPayload(ParameterCapturingEvents.CapturingActivityPayload.RequestId); - Settings.OnStoppedCapturing.Invoke(this, requestId); + Settings.OnStoppedCapturing?.Invoke(this, requestId); break; } case "UnknownRequestId": { Guid requestId = traceEvent.GetPayload(ParameterCapturingEvents.UnknownRequestIdPayload.RequestId); - Settings.OnUnknownRequestId.Invoke(this, requestId); + Settings.OnUnknownRequestId?.Invoke(this, requestId); break; } case "FailedToCapture": @@ -86,7 +86,7 @@ private void Callback(TraceEvent traceEvent) ParameterCapturingEvents.CapturingFailedReason reason = traceEvent.GetPayload(ParameterCapturingEvents.CapturingFailedPayloads.Reason); string details = traceEvent.GetPayload(ParameterCapturingEvents.CapturingFailedPayloads.Details); - Settings.OnCapturingFailed.Invoke(this, new CapturingFailedArgs() + Settings.OnCapturingFailed?.Invoke(this, new CapturingFailedArgs() { RequestId = requestId, Reason = reason, @@ -98,7 +98,7 @@ private void Callback(TraceEvent traceEvent) { ParameterCapturingEvents.ServiceState state = traceEvent.GetPayload(ParameterCapturingEvents.ServiceStatePayload.State); string details = traceEvent.GetPayload(ParameterCapturingEvents.ServiceStatePayload.Details); - Settings.OnServiceStateUpdate.Invoke(this, new ServiceStateUpdateArgs() + Settings.OnServiceStateUpdate?.Invoke(this, new ServiceStateUpdateArgs() { ServiceState = state, Details = details @@ -166,9 +166,9 @@ private void Callback(TraceEvent traceEvent) Guid requestId = traceEvent.GetPayload(ParameterCapturingEvents.CapturedParametersStopPayloads.RequestId); Guid captureId = traceEvent.GetPayload(ParameterCapturingEvents.CapturedParametersStopPayloads.CaptureId); - if (_parameterBuilder.TryFinalizeParameters(captureId, out ICapturedParameters capturedParameters)) + if (_parameterBuilder.TryFinalizeParameters(captureId, out ICapturedParameters? capturedParameters)) { - Settings.OnParametersCaptured.Invoke(this, capturedParameters); + Settings.OnParametersCaptured?.Invoke(this, capturedParameters); } break; } @@ -189,14 +189,14 @@ private void Callback(TraceEvent traceEvent) internal sealed class EventParameterCapturingPipelineSettings : EventSourcePipelineSettings { - public EventHandler OnStartedCapturing; - public EventHandler OnStoppedCapturing; - public EventHandler OnUnknownRequestId; + public EventHandler? OnStartedCapturing; + public EventHandler? OnStoppedCapturing; + public EventHandler? OnUnknownRequestId; - public EventHandler OnCapturingFailed; - public EventHandler OnServiceStateUpdate; + public EventHandler? OnCapturingFailed; + public EventHandler? OnServiceStateUpdate; - public EventHandler OnParametersCaptured; + public EventHandler? OnParametersCaptured; public EventParameterCapturingPipelineSettings() { diff --git a/src/Tools/dotnet-monitor/PipelineArtifactOperation.cs b/src/Tools/dotnet-monitor/PipelineArtifactOperation.cs index 429bce43fe5..5aa0150d730 100644 --- a/src/Tools/dotnet-monitor/PipelineArtifactOperation.cs +++ b/src/Tools/dotnet-monitor/PipelineArtifactOperation.cs @@ -18,7 +18,7 @@ internal abstract class PipelineArtifactOperation : private readonly string _artifactType; private readonly TaskCompletionSource _startCompletionSource = new(TaskCreationOptions.RunContinuationsAsynchronously); - private Func _stopFunc; + private Func? _stopFunc; protected OperationTrackerService OperationTrackerService { get; } @@ -43,7 +43,7 @@ public async Task ExecuteAsync(Stream outputStream, CancellationToken token) _stopFunc = pipeline.StopAsync; - using IDisposable trackerRegistration = Register ? OperationTrackerService.Register(EndpointInfo) : null; + using IDisposable? trackerRegistration = Register ? OperationTrackerService.Register(EndpointInfo) : null; Task runTask = await StartPipelineAsync(pipeline, token); diff --git a/src/Tools/dotnet-monitor/Profiler/ProfilerService.cs b/src/Tools/dotnet-monitor/Profiler/ProfilerService.cs index 7b84ecc88f5..b781a6bf931 100644 --- a/src/Tools/dotnet-monitor/Profiler/ProfilerService.cs +++ b/src/Tools/dotnet-monitor/Profiler/ProfilerService.cs @@ -77,7 +77,7 @@ public async Task ApplyProfilersAsync(IEndpointInfo endpointInfo, CancellationTo // and where to provide any additional files to dotnet-monitor. // CONSIDER: Include the runtime instance identifier in the path in order to keep // target processes assets separated from one another. - string defaultSharedPath = _storageOptions.Value.DefaultSharedPath; + string? defaultSharedPath = _storageOptions.Value.DefaultSharedPath; if (!string.IsNullOrEmpty(defaultSharedPath)) { // Create sharing directory in case it doesn't exist. @@ -115,7 +115,7 @@ private async Task CalculateRuntimeIdentifierAsync(DiagnosticsClient cli Dictionary env = await client.GetProcessEnvironmentAsync(cancellationToken); string runtimeIdentifierSource = RuntimeIdentifierSource.ProcessEnvironment; - if (!env.TryGetValue(ToolIdentifiers.EnvironmentVariables.RuntimeIdentifier, out string runtimeIdentifier)) + if (!env.TryGetValue(ToolIdentifiers.EnvironmentVariables.RuntimeIdentifier, out string? runtimeIdentifier)) { ProcessInfo processInfo = await client.GetProcessInfoAsync(cancellationToken); @@ -210,6 +210,7 @@ private static IFileInfo GetProfilerFileInfo(string libraryRootFileName, IFilePr return profilerFileInfo; } +#nullable disable private async Task ApplyNotifyOnlyProfilerAsync(DiagnosticsClient client, IFileProvider nativeFileProvider, CancellationToken cancellationToken) { IFileInfo profilerFileInfo = GetProfilerFileInfo(ProfilerIdentifiers.NotifyOnlyProfiler.LibraryRootFileName, nativeFileProvider); @@ -231,6 +232,7 @@ await ApplyProfilerCoreAsync( ProfilerIdentifiers.MutatingProfiler.Clsid.Guid, cancellationToken); } +#nullable restore private async Task ApplyProfilerCoreAsync(DiagnosticsClient client, string physicalPath, string moduleEnvVarName, Guid clsid, CancellationToken cancellationToken) { diff --git a/src/Tools/dotnet-monitor/RuntimeInfo.cs b/src/Tools/dotnet-monitor/RuntimeInfo.cs index 05949910626..d739384147a 100644 --- a/src/Tools/dotnet-monitor/RuntimeInfo.cs +++ b/src/Tools/dotnet-monitor/RuntimeInfo.cs @@ -11,7 +11,7 @@ public static bool IsDiagnosticsEnabled { get { - string enableDiagnostics = Environment.GetEnvironmentVariable("COMPlus_EnableDiagnostics"); + string? enableDiagnostics = Environment.GetEnvironmentVariable("COMPlus_EnableDiagnostics"); return string.IsNullOrEmpty(enableDiagnostics) || !"0".Equals(enableDiagnostics, StringComparison.Ordinal); } } diff --git a/src/Tools/dotnet-monitor/StartupHook/StartupHookApplicator.cs b/src/Tools/dotnet-monitor/StartupHook/StartupHookApplicator.cs index 9cf4dafc944..6623bc1e351 100644 --- a/src/Tools/dotnet-monitor/StartupHook/StartupHookApplicator.cs +++ b/src/Tools/dotnet-monitor/StartupHook/StartupHookApplicator.cs @@ -48,14 +48,15 @@ public async Task ApplyAsync(string tfm, string fileName, CancellationToke return true; } - - if (_endpointInfo.RuntimeVersion.Major < 8) +#nullable disable + if (_endpointInfo.RuntimeVersion?.Major < 8) { _logger.StartupHookInstructions(_endpointInfo.ProcessId, fileInfo.Name, fileInfo.PhysicalPath); return false; } +#nullable restore - return await ApplyUsingDiagnosticClientAsync(fileInfo, _endpointInfo, client, token); + return await ApplyUsingDiagnosticClientAsync(fileInfo, client, token); } private async Task GetFileInfoAsync(string tfm, string fileName, CancellationToken token) @@ -66,10 +67,10 @@ private async Task GetFileInfoAsync(string tfm, string fileName, Canc } private static bool IsEnvironmentConfiguredForStartupHook(IFileInfo fileInfo, IDictionary env) - => env.TryGetValue(ToolIdentifiers.EnvironmentVariables.StartupHooks, out string startupHookPaths) && + => env.TryGetValue(ToolIdentifiers.EnvironmentVariables.StartupHooks, out string? startupHookPaths) && startupHookPaths?.Contains(fileInfo.Name, StringComparison.OrdinalIgnoreCase) == true; - private async Task ApplyUsingDiagnosticClientAsync(IFileInfo fileInfo, IEndpointInfo endpointInfo, DiagnosticsClient client, CancellationToken token) + private async Task ApplyUsingDiagnosticClientAsync(IFileInfo fileInfo, DiagnosticsClient client, CancellationToken token) { try { diff --git a/src/Tools/dotnet-monitor/StoragePostConfigureOptions.cs b/src/Tools/dotnet-monitor/StoragePostConfigureOptions.cs index bd603ac1d0b..5a071d341c2 100644 --- a/src/Tools/dotnet-monitor/StoragePostConfigureOptions.cs +++ b/src/Tools/dotnet-monitor/StoragePostConfigureOptions.cs @@ -12,7 +12,7 @@ public class StoragePostConfigureOptions : IPostConfigureOptions private const string DefaultSharedPathDumpsFolderName = "dumps"; private const string DefaultSharedPathLibrariesFolderName = "libs"; - void IPostConfigureOptions.PostConfigure(string name, StorageOptions options) + void IPostConfigureOptions.PostConfigure(string? name, StorageOptions options) { if (string.IsNullOrEmpty(options.DumpTempFolder)) { diff --git a/src/Tools/dotnet-monitor/Swagger/Filters/UnauthorizedResponseOperationFilter.cs b/src/Tools/dotnet-monitor/Swagger/Filters/UnauthorizedResponseOperationFilter.cs index c9542c3a87c..7a491fe7f3f 100644 --- a/src/Tools/dotnet-monitor/Swagger/Filters/UnauthorizedResponseOperationFilter.cs +++ b/src/Tools/dotnet-monitor/Swagger/Filters/UnauthorizedResponseOperationFilter.cs @@ -14,7 +14,7 @@ internal sealed class UnauthorizedResponseOperationFilter : IOperationFilter { public void Apply(OpenApiOperation operation, OperationFilterContext context) { - if (operation.Responses.TryGetValue(StatusCodeStrings.Status401Unauthorized, out OpenApiResponse unauthorizedResponse)) + if (operation.Responses.TryGetValue(StatusCodeStrings.Status401Unauthorized, out OpenApiResponse? unauthorizedResponse)) { unauthorizedResponse.Content.Clear(); unauthorizedResponse.Reference = new OpenApiReference() diff --git a/src/Tools/dotnet-monitor/Swagger/SwaggerGenOptionsExtensions.cs b/src/Tools/dotnet-monitor/Swagger/SwaggerGenOptionsExtensions.cs index 569294d53e2..82943dccd6c 100644 --- a/src/Tools/dotnet-monitor/Swagger/SwaggerGenOptionsExtensions.cs +++ b/src/Tools/dotnet-monitor/Swagger/SwaggerGenOptionsExtensions.cs @@ -29,8 +29,9 @@ public static void ConfigureMonitorSwaggerGen(this SwaggerGenOptions options) options.OperationFilter(); string documentationFile = $"{typeof(DiagController).Assembly.GetName().Name}.xml"; +#nullable disable options.IncludeXmlComments(() => new XPathDocument(Assembly.GetExecutingAssembly().GetManifestResourceStream(documentationFile))); - +#nullable restore // Make sure TimeSpan is represented as a string instead of a full object type options.MapType(() => new OpenApiSchema() { Type = "string", Format = "time-span", Example = new OpenApiString("00:00:30") }); } diff --git a/src/Tools/dotnet-monitor/TestAssemblies.cs b/src/Tools/dotnet-monitor/TestAssemblies.cs index ab1f837d937..92aab047af5 100644 --- a/src/Tools/dotnet-monitor/TestAssemblies.cs +++ b/src/Tools/dotnet-monitor/TestAssemblies.cs @@ -4,6 +4,7 @@ using Microsoft.AspNetCore.Hosting; using System; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.IO; using System.Linq; using System.Reflection; @@ -20,6 +21,7 @@ internal static class TestAssemblies private const string TestHostingStartupAssemblyName = "Microsoft.Diagnostics.Monitoring.Tool.TestHostingStartup"; private const string TestStartupHookAssemblyName = "Microsoft.Diagnostics.Monitoring.Tool.TestStartupHook"; +#nullable disable [Conditional("DEBUG")] public static void SimulateStartupHook() { @@ -42,6 +44,7 @@ public static void SimulateStartupHook() } } } +#nullable restore [Conditional("DEBUG")] public static void AddHostingStartup(IWebHostBuilder builder) @@ -64,10 +67,16 @@ public static void AddHostingStartup(IWebHostBuilder builder) } } - private static bool TryComputeBuildOutputAssemblyPath(string assemblyName, out string path) + private static bool TryComputeBuildOutputAssemblyPath(string assemblyName, [NotNullWhen(true)] out string? path) { Assembly thisAssembly = Assembly.GetExecutingAssembly(); - string thisAssemblyName = thisAssembly.GetName().Name; + string? thisAssemblyName = thisAssembly.GetName()?.Name; + if (thisAssemblyName == null) + { + path = null; + return false; + } + string separator = Path.DirectorySeparatorChar + ArtifactsDirectoryName + Path.DirectorySeparatorChar; int artifactsIndex = AppContext.BaseDirectory.IndexOf(separator); if (artifactsIndex != -1) diff --git a/src/Tools/dotnet-monitor/Trace/TraceOperation.cs b/src/Tools/dotnet-monitor/Trace/TraceOperation.cs index 7afda1e3576..bc64056767d 100644 --- a/src/Tools/dotnet-monitor/Trace/TraceOperation.cs +++ b/src/Tools/dotnet-monitor/Trace/TraceOperation.cs @@ -13,7 +13,7 @@ namespace Microsoft.Diagnostics.Tools.Monitor { internal sealed class TraceOperation : AbstractTraceOperation { - private readonly TaskCompletionSource _eventStreamAvailableCompletionSource = new(TaskCreationOptions.RunContinuationsAsynchronously); + private readonly TaskCompletionSource _eventStreamAvailableCompletionSource = new(TaskCreationOptions.RunContinuationsAsynchronously); public TraceOperation(IEndpointInfo endpointInfo, EventTracePipelineSettings settings, OperationTrackerService trackerService, ILogger logger) : base(endpointInfo, settings, trackerService, logger) { } diff --git a/src/Tools/dotnet-monitor/Trace/TraceOperationFactory.cs b/src/Tools/dotnet-monitor/Trace/TraceOperationFactory.cs index 216b5faa135..5d7173f8bf1 100644 --- a/src/Tools/dotnet-monitor/Trace/TraceOperationFactory.cs +++ b/src/Tools/dotnet-monitor/Trace/TraceOperationFactory.cs @@ -31,7 +31,7 @@ public IArtifactOperation Create(IEndpointInfo endpointInfo, MonitoringSourceCon return new TraceOperation(endpointInfo, settings, _operationTrackerService, _logger); } - public IArtifactOperation Create(IEndpointInfo endpointInfo, MonitoringSourceConfiguration configuration, TimeSpan duration, string providerName, string eventName, IDictionary payloadFilter) + public IArtifactOperation Create(IEndpointInfo endpointInfo, MonitoringSourceConfiguration configuration, TimeSpan duration, string providerName, string eventName, IDictionary? payloadFilter) { EventTracePipelineSettings settings = new() { diff --git a/src/Tools/dotnet-monitor/Trace/TraceUntilEventOperation.cs b/src/Tools/dotnet-monitor/Trace/TraceUntilEventOperation.cs index 9c3741154b1..fab37f5d29b 100644 --- a/src/Tools/dotnet-monitor/Trace/TraceUntilEventOperation.cs +++ b/src/Tools/dotnet-monitor/Trace/TraceUntilEventOperation.cs @@ -16,17 +16,17 @@ internal sealed class TraceUntilEventOperation : AbstractTraceOperation { private readonly string _providerName; private readonly string _eventName; - private readonly IDictionary _payloadFilter; + private readonly IDictionary? _payloadFilter; - private readonly TaskCompletionSource _eventStreamAvailableCompletionSource = new(TaskCreationOptions.RunContinuationsAsynchronously); - private readonly TaskCompletionSource _stoppingEventHitSource = new(TaskCreationOptions.RunContinuationsAsynchronously); + private readonly TaskCompletionSource _eventStreamAvailableCompletionSource = new(TaskCreationOptions.RunContinuationsAsynchronously); + private readonly TaskCompletionSource _stoppingEventHitSource = new(TaskCreationOptions.RunContinuationsAsynchronously); public TraceUntilEventOperation( IEndpointInfo endpointInfo, EventTracePipelineSettings settings, string providerName, string eventName, - IDictionary payloadFilter, + IDictionary? payloadFilter, OperationTrackerService trackerService, ILogger logger) : base(endpointInfo, settings, trackerService, logger) @@ -42,7 +42,7 @@ protected override EventTracePipeline CreatePipeline(Stream outputStream) return new EventTracePipeline(client, _settings, async (eventStream, token) => { - _eventStreamAvailableCompletionSource?.TrySetResult(null); + _eventStreamAvailableCompletionSource.TrySetResult(null); await using EventMonitor eventMonitor = new( _providerName, diff --git a/src/Tools/dotnet-monitor/ValidationResultExtensions.cs b/src/Tools/dotnet-monitor/ValidationResultExtensions.cs new file mode 100644 index 00000000000..308cd1074d9 --- /dev/null +++ b/src/Tools/dotnet-monitor/ValidationResultExtensions.cs @@ -0,0 +1,16 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.ComponentModel.DataAnnotations; +using System.Diagnostics.CodeAnalysis; + +namespace Microsoft.Diagnostics.Tools.Monitor +{ + internal static class ValidationResultExtensions + { + public static bool IsSuccess([NotNullWhen(false)] this ValidationResult? result) + { + return result == ValidationResult.Success; + } + } +} diff --git a/src/Tools/dotnet-monitor/dotnet-monitor.csproj b/src/Tools/dotnet-monitor/dotnet-monitor.csproj index 241ee397586..3b881f6617a 100644 --- a/src/Tools/dotnet-monitor/dotnet-monitor.csproj +++ b/src/Tools/dotnet-monitor/dotnet-monitor.csproj @@ -8,6 +8,7 @@ $(Description) false false + enable From d01b9143fb97dc505505c0484c336dec973e4729 Mon Sep 17 00:00:00 2001 From: Joe Schmitt Date: Tue, 23 Jul 2024 09:24:10 -0700 Subject: [PATCH 2/2] PR feedback --- src/Tools/dotnet-monitor/StartupHook/StartupHookApplicator.cs | 4 ++-- src/Tools/dotnet-monitor/ValidationResultExtensions.cs | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Tools/dotnet-monitor/StartupHook/StartupHookApplicator.cs b/src/Tools/dotnet-monitor/StartupHook/StartupHookApplicator.cs index 6623bc1e351..7f84318382a 100644 --- a/src/Tools/dotnet-monitor/StartupHook/StartupHookApplicator.cs +++ b/src/Tools/dotnet-monitor/StartupHook/StartupHookApplicator.cs @@ -48,13 +48,13 @@ public async Task ApplyAsync(string tfm, string fileName, CancellationToke return true; } -#nullable disable if (_endpointInfo.RuntimeVersion?.Major < 8) { +#nullable disable _logger.StartupHookInstructions(_endpointInfo.ProcessId, fileInfo.Name, fileInfo.PhysicalPath); +#nullable restore return false; } -#nullable restore return await ApplyUsingDiagnosticClientAsync(fileInfo, client, token); } diff --git a/src/Tools/dotnet-monitor/ValidationResultExtensions.cs b/src/Tools/dotnet-monitor/ValidationResultExtensions.cs index 308cd1074d9..f31b8396132 100644 --- a/src/Tools/dotnet-monitor/ValidationResultExtensions.cs +++ b/src/Tools/dotnet-monitor/ValidationResultExtensions.cs @@ -10,6 +10,7 @@ internal static class ValidationResultExtensions { public static bool IsSuccess([NotNullWhen(false)] this ValidationResult? result) { + // ValidationResult.Success is null, and a null value indicates there are no validation errors. return result == ValidationResult.Success; } }