From 4e1979a8f501c0cc3f727ab081fa4bc5033eacc1 Mon Sep 17 00:00:00 2001 From: Joe Schmitt Date: Mon, 1 Jul 2024 14:36:22 -0700 Subject: [PATCH 01/20] Enable nullable context for options --- .../ExperimentalSchemaProcessor.cs | 2 +- ...tics.Monitoring.ConfigurationSchema.csproj | 1 + .../Options/ConsoleFormatterOptions.cs | 2 +- .../Options/ConsoleLoggerOptions.cs | 4 +-- .../Options/JsonConsoleFormatterOptions.cs | 2 +- .../Options/LogLevelOptions.cs | 2 +- .../Options/LoggingOptions.cs | 10 +++---- .../Options/RootOptions.Logging.cs | 2 +- .../Options/SimpleConsoleFormatterOptions.cs | 2 +- .../SchemaGenerator.cs | 4 +-- .../Options/Actions/CollectDumpOptions.cs | 2 +- .../Actions/CollectExceptionsOptions.cs | 6 ++-- .../Options/Actions/CollectGCDumpOptions.cs | 2 +- .../Actions/CollectLiveMetricsOptions.cs | 8 ++++-- .../Options/Actions/CollectLogsOptions.cs | 6 ++-- .../Options/Actions/CollectStacksOptions.cs | 2 +- .../Options/Actions/CollectTraceOptions.cs | 8 ++++-- .../Options/Actions/ExecuteOptions.cs | 6 ++-- .../Actions/GetEnvironmentVariableOptions.cs | 2 +- .../Options/Actions/LoadProfilerOptions.cs | 2 +- .../Actions/SetEnvironmentVariableOptions.cs | 6 ++-- .../Options/Actions/TraceEventFilter.cs | 8 ++++-- .../CollectionRuleActionDefaultsOptions.cs | 4 ++- .../Options/CollectionRuleActionOptions.cs | 8 ++++-- .../Options/CollectionRuleDefaultsOptions.cs | 8 ++++-- .../Options/CollectionRuleOptions.cs | 10 ++++--- .../Options/CollectionRuleTriggerOptions.cs | 6 ++-- .../Options/RegularExpressionsAttribute.cs | 4 ++- .../Options/TemplateOptions.cs | 10 ++++--- .../Triggers/AspNetRequestCountOptions.cs | 6 ++-- .../Triggers/AspNetRequestDurationOptions.cs | 6 ++-- .../Triggers/AspNetResponseStatusOptions.cs | 8 ++++-- .../Options/Triggers/EventCounterOptions.cs | 4 +-- .../Options/Triggers/EventMeterOptions.cs | 4 +-- .../Triggers/IAspNetActionPathFilters.cs | 6 ++-- src/Tools/dotnet-monitor/RootOptions.cs | 28 ++++++++++--------- 36 files changed, 120 insertions(+), 81 deletions(-) diff --git a/src/Tests/Microsoft.Diagnostics.Monitoring.ConfigurationSchema/ExperimentalSchemaProcessor.cs b/src/Tests/Microsoft.Diagnostics.Monitoring.ConfigurationSchema/ExperimentalSchemaProcessor.cs index e71abb219d6..f1fa97e620a 100644 --- a/src/Tests/Microsoft.Diagnostics.Monitoring.ConfigurationSchema/ExperimentalSchemaProcessor.cs +++ b/src/Tests/Microsoft.Diagnostics.Monitoring.ConfigurationSchema/ExperimentalSchemaProcessor.cs @@ -17,7 +17,7 @@ public void Process(SchemaProcessorContext context) { if (null != property.GetCustomAttribute()) { - string description = context.Schema.Properties[property.Name].Description; + string? description = context.Schema.Properties[property.Name].Description; if (string.IsNullOrEmpty(description)) { description = ExperimentalPrefix; diff --git a/src/Tests/Microsoft.Diagnostics.Monitoring.ConfigurationSchema/Microsoft.Diagnostics.Monitoring.ConfigurationSchema.csproj b/src/Tests/Microsoft.Diagnostics.Monitoring.ConfigurationSchema/Microsoft.Diagnostics.Monitoring.ConfigurationSchema.csproj index a7af91ecb20..2ec74e69f6c 100644 --- a/src/Tests/Microsoft.Diagnostics.Monitoring.ConfigurationSchema/Microsoft.Diagnostics.Monitoring.ConfigurationSchema.csproj +++ b/src/Tests/Microsoft.Diagnostics.Monitoring.ConfigurationSchema/Microsoft.Diagnostics.Monitoring.ConfigurationSchema.csproj @@ -2,6 +2,7 @@ Exe + enable $(SchemaTargetFramework) $(DefineConstants);SCHEMAGEN diff --git a/src/Tests/Microsoft.Diagnostics.Monitoring.ConfigurationSchema/Options/ConsoleFormatterOptions.cs b/src/Tests/Microsoft.Diagnostics.Monitoring.ConfigurationSchema/Options/ConsoleFormatterOptions.cs index 6f7de9245b1..111d30c9897 100644 --- a/src/Tests/Microsoft.Diagnostics.Monitoring.ConfigurationSchema/Options/ConsoleFormatterOptions.cs +++ b/src/Tests/Microsoft.Diagnostics.Monitoring.ConfigurationSchema/Options/ConsoleFormatterOptions.cs @@ -18,7 +18,7 @@ internal sealed class ConsoleFormatterOptions ResourceType = typeof(OptionsDisplayStrings), Description = nameof(OptionsDisplayStrings.DisplayAttributeDescription_ConsoleFormatterOptions_TimestampFormat))] [DefaultValue(null)] - public string TimestampFormat { get; set; } + public string? TimestampFormat { get; set; } [Display( ResourceType = typeof(OptionsDisplayStrings), diff --git a/src/Tests/Microsoft.Diagnostics.Monitoring.ConfigurationSchema/Options/ConsoleLoggerOptions.cs b/src/Tests/Microsoft.Diagnostics.Monitoring.ConfigurationSchema/Options/ConsoleLoggerOptions.cs index 07a31e754e3..67a672fda0e 100644 --- a/src/Tests/Microsoft.Diagnostics.Monitoring.ConfigurationSchema/Options/ConsoleLoggerOptions.cs +++ b/src/Tests/Microsoft.Diagnostics.Monitoring.ConfigurationSchema/Options/ConsoleLoggerOptions.cs @@ -25,11 +25,11 @@ internal sealed class ConsoleLoggerOptions [Display( ResourceType = typeof(OptionsDisplayStrings), Description = nameof(OptionsDisplayStrings.DisplayAttributeDescription_ConsoleLoggerOptions_FormatterOptions))] - public object FormatterOptions { get; set; } + public object? FormatterOptions { get; set; } [Display( ResourceType = typeof(OptionsDisplayStrings), Description = nameof(OptionsDisplayStrings.DisplayAttributeDescription_ConsoleLoggerOptions_LogLevel))] - public IDictionary LogLevel { get; set; } + public IDictionary? LogLevel { get; set; } } } diff --git a/src/Tests/Microsoft.Diagnostics.Monitoring.ConfigurationSchema/Options/JsonConsoleFormatterOptions.cs b/src/Tests/Microsoft.Diagnostics.Monitoring.ConfigurationSchema/Options/JsonConsoleFormatterOptions.cs index b12b7a7cdf7..340249c50ba 100644 --- a/src/Tests/Microsoft.Diagnostics.Monitoring.ConfigurationSchema/Options/JsonConsoleFormatterOptions.cs +++ b/src/Tests/Microsoft.Diagnostics.Monitoring.ConfigurationSchema/Options/JsonConsoleFormatterOptions.cs @@ -24,7 +24,7 @@ internal sealed class JsonConsoleFormatterOptions ResourceType = typeof(OptionsDisplayStrings), Description = nameof(OptionsDisplayStrings.DisplayAttributeDescription_ConsoleFormatterOptions_TimestampFormat))] [DefaultValue(null)] - public string TimestampFormat { get; set; } + public string? TimestampFormat { get; set; } [Display( ResourceType = typeof(OptionsDisplayStrings), diff --git a/src/Tests/Microsoft.Diagnostics.Monitoring.ConfigurationSchema/Options/LogLevelOptions.cs b/src/Tests/Microsoft.Diagnostics.Monitoring.ConfigurationSchema/Options/LogLevelOptions.cs index f1595e11e02..e98f40cc06d 100644 --- a/src/Tests/Microsoft.Diagnostics.Monitoring.ConfigurationSchema/Options/LogLevelOptions.cs +++ b/src/Tests/Microsoft.Diagnostics.Monitoring.ConfigurationSchema/Options/LogLevelOptions.cs @@ -13,6 +13,6 @@ internal sealed class LogLevelOptions [Display( ResourceType = typeof(OptionsDisplayStrings), Description = nameof(OptionsDisplayStrings.DisplayAttributeDescription_LogLevelOptions_LogLevel))] - public IDictionary LogLevel { get; set; } + public IDictionary? LogLevel { get; set; } } } diff --git a/src/Tests/Microsoft.Diagnostics.Monitoring.ConfigurationSchema/Options/LoggingOptions.cs b/src/Tests/Microsoft.Diagnostics.Monitoring.ConfigurationSchema/Options/LoggingOptions.cs index 1fc38a4ea3b..87b2191428d 100644 --- a/src/Tests/Microsoft.Diagnostics.Monitoring.ConfigurationSchema/Options/LoggingOptions.cs +++ b/src/Tests/Microsoft.Diagnostics.Monitoring.ConfigurationSchema/Options/LoggingOptions.cs @@ -14,27 +14,27 @@ internal sealed class LoggingOptions [Display( ResourceType = typeof(OptionsDisplayStrings), Description = nameof(OptionsDisplayStrings.DisplayAttributeDescription_LoggingOptions_LogLevel))] - public IDictionary LogLevel { get; set; } + public IDictionary? LogLevel { get; set; } [Display( ResourceType = typeof(OptionsDisplayStrings), Description = nameof(OptionsDisplayStrings.DisplayAttributeDescription_LoggingOptions_Console))] - public ConsoleLoggerOptions Console { get; set; } + public ConsoleLoggerOptions? Console { get; set; } [Display( ResourceType = typeof(OptionsDisplayStrings), Description = nameof(OptionsDisplayStrings.DisplayAttributeDescription_LoggingOptions_EventLog))] - public LogLevelOptions EventLog { get; set; } + public LogLevelOptions? EventLog { get; set; } [Display( ResourceType = typeof(OptionsDisplayStrings), Description = nameof(OptionsDisplayStrings.DisplayAttributeDescription_LoggingOptions_Debug))] - public LogLevelOptions Debug { get; set; } + public LogLevelOptions? Debug { get; set; } [Display( ResourceType = typeof(OptionsDisplayStrings), Description = nameof(OptionsDisplayStrings.DisplayAttributeDescription_LoggingOptions_EventSource))] - public LogLevelOptions EventSource { get; set; } + public LogLevelOptions? EventSource { get; set; } [Display( ResourceType = typeof(OptionsDisplayStrings), diff --git a/src/Tests/Microsoft.Diagnostics.Monitoring.ConfigurationSchema/Options/RootOptions.Logging.cs b/src/Tests/Microsoft.Diagnostics.Monitoring.ConfigurationSchema/Options/RootOptions.Logging.cs index 23cfda4f420..94b426c85e8 100644 --- a/src/Tests/Microsoft.Diagnostics.Monitoring.ConfigurationSchema/Options/RootOptions.Logging.cs +++ b/src/Tests/Microsoft.Diagnostics.Monitoring.ConfigurationSchema/Options/RootOptions.Logging.cs @@ -7,6 +7,6 @@ namespace Microsoft.Diagnostics.Tools.Monitor { internal partial class RootOptions { - public LoggingOptions Logging { get; set; } + public LoggingOptions? Logging { get; set; } } } diff --git a/src/Tests/Microsoft.Diagnostics.Monitoring.ConfigurationSchema/Options/SimpleConsoleFormatterOptions.cs b/src/Tests/Microsoft.Diagnostics.Monitoring.ConfigurationSchema/Options/SimpleConsoleFormatterOptions.cs index c448362a34c..5e947480b99 100644 --- a/src/Tests/Microsoft.Diagnostics.Monitoring.ConfigurationSchema/Options/SimpleConsoleFormatterOptions.cs +++ b/src/Tests/Microsoft.Diagnostics.Monitoring.ConfigurationSchema/Options/SimpleConsoleFormatterOptions.cs @@ -31,7 +31,7 @@ internal sealed class SimpleConsoleFormatterOptions ResourceType = typeof(OptionsDisplayStrings), Description = nameof(OptionsDisplayStrings.DisplayAttributeDescription_ConsoleFormatterOptions_TimestampFormat))] [DefaultValue(null)] - public string TimestampFormat { get; set; } + public string? TimestampFormat { get; set; } [Display( ResourceType = typeof(OptionsDisplayStrings), diff --git a/src/Tests/Microsoft.Diagnostics.Monitoring.ConfigurationSchema/SchemaGenerator.cs b/src/Tests/Microsoft.Diagnostics.Monitoring.ConfigurationSchema/SchemaGenerator.cs index 3770ce11241..52f9739293d 100644 --- a/src/Tests/Microsoft.Diagnostics.Monitoring.ConfigurationSchema/SchemaGenerator.cs +++ b/src/Tests/Microsoft.Diagnostics.Monitoring.ConfigurationSchema/SchemaGenerator.cs @@ -275,7 +275,7 @@ private static JsonSchemaProperty AddDiscriminatedSubSchema( string discriminatingPropertyName, string discriminatingPropertyValue, string discriminatedPropertyName, - JsonSchema subSchema = null) + JsonSchema? subSchema = null) { if (null == subSchema) { @@ -283,7 +283,7 @@ private static JsonSchemaProperty AddDiscriminatedSubSchema( } JsonSchemaProperty discriminatingProperty = new JsonSchemaProperty(); - discriminatingProperty.ExtensionData = new Dictionary(); + discriminatingProperty.ExtensionData = new Dictionary(); discriminatingProperty.ExtensionData.Add("const", discriminatingPropertyValue); subSchema.Properties.Add(discriminatingPropertyName, discriminatingProperty); diff --git a/src/Tools/dotnet-monitor/CollectionRules/Options/Actions/CollectDumpOptions.cs b/src/Tools/dotnet-monitor/CollectionRules/Options/Actions/CollectDumpOptions.cs index 666b0ada60c..ac0c66196af 100644 --- a/src/Tools/dotnet-monitor/CollectionRules/Options/Actions/CollectDumpOptions.cs +++ b/src/Tools/dotnet-monitor/CollectionRules/Options/Actions/CollectDumpOptions.cs @@ -35,6 +35,6 @@ internal sealed partial record class CollectDumpOptions : BaseRecordOptions, IEg #if !UNITTEST && !SCHEMAGEN [ValidateEgressProvider] #endif - public string Egress { get; set; } + public string Egress { get; set; } = string.Empty; } } diff --git a/src/Tools/dotnet-monitor/CollectionRules/Options/Actions/CollectExceptionsOptions.cs b/src/Tools/dotnet-monitor/CollectionRules/Options/Actions/CollectExceptionsOptions.cs index b35bc2f22e7..babcf8286df 100644 --- a/src/Tools/dotnet-monitor/CollectionRules/Options/Actions/CollectExceptionsOptions.cs +++ b/src/Tools/dotnet-monitor/CollectionRules/Options/Actions/CollectExceptionsOptions.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.Diagnostics.Monitoring.Options; using Microsoft.Diagnostics.Monitoring.WebApi; using Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.CollectionRuleDefaultsInterfaces; @@ -25,7 +27,7 @@ internal sealed partial record class CollectExceptionsOptions : BaseRecordOption #if !UNITTEST && !SCHEMAGEN [ValidateEgressProvider] #endif - public string Egress { get; set; } + public string Egress { get; set; } = string.Empty; [Display( ResourceType = typeof(OptionsDisplayStrings), @@ -36,6 +38,6 @@ internal sealed partial record class CollectExceptionsOptions : BaseRecordOption [Display( ResourceType = typeof(OptionsDisplayStrings), Description = nameof(OptionsDisplayStrings.DisplayAttributeDescription_CollectExceptionsOptions_Filters))] - public ExceptionsConfiguration Filters { get; set; } + public ExceptionsConfiguration? Filters { get; set; } } } diff --git a/src/Tools/dotnet-monitor/CollectionRules/Options/Actions/CollectGCDumpOptions.cs b/src/Tools/dotnet-monitor/CollectionRules/Options/Actions/CollectGCDumpOptions.cs index 00754715914..7f3c302f075 100644 --- a/src/Tools/dotnet-monitor/CollectionRules/Options/Actions/CollectGCDumpOptions.cs +++ b/src/Tools/dotnet-monitor/CollectionRules/Options/Actions/CollectGCDumpOptions.cs @@ -26,6 +26,6 @@ internal sealed partial record class CollectGCDumpOptions : BaseRecordOptions, I #if !UNITTEST && !SCHEMAGEN [ValidateEgressProvider] #endif - public string Egress { get; set; } + public string Egress { get; set; } = string.Empty; } } diff --git a/src/Tools/dotnet-monitor/CollectionRules/Options/Actions/CollectLiveMetricsOptions.cs b/src/Tools/dotnet-monitor/CollectionRules/Options/Actions/CollectLiveMetricsOptions.cs index 5803078acc3..49af7fe1319 100644 --- a/src/Tools/dotnet-monitor/CollectionRules/Options/Actions/CollectLiveMetricsOptions.cs +++ b/src/Tools/dotnet-monitor/CollectionRules/Options/Actions/CollectLiveMetricsOptions.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.Diagnostics.Monitoring.WebApi; using Microsoft.Diagnostics.Monitoring.WebApi.Models; using Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.CollectionRuleDefaultsInterfaces; @@ -29,12 +31,12 @@ internal sealed partial record class CollectLiveMetricsOptions : BaseRecordOptio [Display( ResourceType = typeof(OptionsDisplayStrings), Description = nameof(OptionsDisplayStrings.DisplayAttributeDescription_CollectLiveMetricsOptions_Providers))] - public EventMetricsProvider[] Providers { get; set; } + public EventMetricsProvider[]? Providers { get; set; } [Display( ResourceType = typeof(OptionsDisplayStrings), Description = nameof(OptionsDisplayStrings.DisplayAttributeDescription_CollectLiveMetricsOptions_Meters))] - public EventMetricsMeter[] Meters { get; set; } + public EventMetricsMeter[]? Meters { get; set; } [Display( ResourceType = typeof(OptionsDisplayStrings), @@ -52,6 +54,6 @@ internal sealed partial record class CollectLiveMetricsOptions : BaseRecordOptio #if !UNITTEST && !SCHEMAGEN [ValidateEgressProvider] #endif - public string Egress { get; set; } + public string Egress { get; set; } = string.Empty; } } diff --git a/src/Tools/dotnet-monitor/CollectionRules/Options/Actions/CollectLogsOptions.cs b/src/Tools/dotnet-monitor/CollectionRules/Options/Actions/CollectLogsOptions.cs index c10c5820eb8..5241c1a357f 100644 --- a/src/Tools/dotnet-monitor/CollectionRules/Options/Actions/CollectLogsOptions.cs +++ b/src/Tools/dotnet-monitor/CollectionRules/Options/Actions/CollectLogsOptions.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.Diagnostics.Monitoring.Options; using Microsoft.Diagnostics.Monitoring.WebApi; using Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.CollectionRuleDefaultsInterfaces; @@ -32,7 +34,7 @@ internal sealed partial record class CollectLogsOptions : BaseRecordOptions, IEg [Display( ResourceType = typeof(OptionsDisplayStrings), Description = nameof(OptionsDisplayStrings.DisplayAttributeDescription_CollectLogsOptions_FilterSpecs))] - public Dictionary FilterSpecs { get; set; } + public Dictionary? FilterSpecs { get; set; } [Display( ResourceType = typeof(OptionsDisplayStrings), @@ -56,7 +58,7 @@ internal sealed partial record class CollectLogsOptions : BaseRecordOptions, IEg #if !UNITTEST && !SCHEMAGEN [ValidateEgressProvider] #endif - public string Egress { get; set; } + public string Egress { get; set; } = string.Empty; [Display( ResourceType = typeof(OptionsDisplayStrings), diff --git a/src/Tools/dotnet-monitor/CollectionRules/Options/Actions/CollectStacksOptions.cs b/src/Tools/dotnet-monitor/CollectionRules/Options/Actions/CollectStacksOptions.cs index dd1aeda5a35..1276386f0a4 100644 --- a/src/Tools/dotnet-monitor/CollectionRules/Options/Actions/CollectStacksOptions.cs +++ b/src/Tools/dotnet-monitor/CollectionRules/Options/Actions/CollectStacksOptions.cs @@ -31,7 +31,7 @@ internal sealed partial record class CollectStacksOptions : BaseRecordOptions, I #if !UNITTEST && !SCHEMAGEN [ValidateEgressProvider] #endif - public string Egress { get; set; } + public string Egress { get; set; } = string.Empty; [Display( ResourceType = typeof(OptionsDisplayStrings), diff --git a/src/Tools/dotnet-monitor/CollectionRules/Options/Actions/CollectTraceOptions.cs b/src/Tools/dotnet-monitor/CollectionRules/Options/Actions/CollectTraceOptions.cs index dfe4c50a888..267ff9b76ca 100644 --- a/src/Tools/dotnet-monitor/CollectionRules/Options/Actions/CollectTraceOptions.cs +++ b/src/Tools/dotnet-monitor/CollectionRules/Options/Actions/CollectTraceOptions.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.Diagnostics.Monitoring.WebApi; using Microsoft.Diagnostics.Monitoring.WebApi.Models; using Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.CollectionRuleDefaultsInterfaces; @@ -30,7 +32,7 @@ internal sealed partial record class CollectTraceOptions : BaseRecordOptions, IE [Display( ResourceType = typeof(OptionsDisplayStrings), Description = nameof(OptionsDisplayStrings.DisplayAttributeDescription_CollectTraceOptions_Providers))] - public List Providers { get; set; } + public List? Providers { get; set; } [Display( ResourceType = typeof(OptionsDisplayStrings), @@ -61,11 +63,11 @@ internal sealed partial record class CollectTraceOptions : BaseRecordOptions, IE #if !UNITTEST && !SCHEMAGEN [ValidateEgressProvider] #endif - public string Egress { get; set; } + public string Egress { get; set; } = string.Empty; [Display( ResourceType = typeof(OptionsDisplayStrings), Description = nameof(OptionsDisplayStrings.DisplayAttributeDescription_CollectTraceOptions_StoppingEvent))] - public TraceEventFilter StoppingEvent { get; set; } + public TraceEventFilter? StoppingEvent { get; set; } } } diff --git a/src/Tools/dotnet-monitor/CollectionRules/Options/Actions/ExecuteOptions.cs b/src/Tools/dotnet-monitor/CollectionRules/Options/Actions/ExecuteOptions.cs index f855a589882..f62f665430f 100644 --- a/src/Tools/dotnet-monitor/CollectionRules/Options/Actions/ExecuteOptions.cs +++ b/src/Tools/dotnet-monitor/CollectionRules/Options/Actions/ExecuteOptions.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.Diagnostics.Monitoring.WebApi; using System.ComponentModel; using System.ComponentModel.DataAnnotations; @@ -21,13 +23,13 @@ internal sealed record class ExecuteOptions : BaseRecordOptions ResourceType = typeof(OptionsDisplayStrings), Description = nameof(OptionsDisplayStrings.DisplayAttributeDescription_ExecuteOptions_Path))] [Required] - public string Path { get; set; } + public string Path { get; set; } = string.Empty; [Display( ResourceType = typeof(OptionsDisplayStrings), Description = nameof(OptionsDisplayStrings.DisplayAttributeDescription_ExecuteOptions_Arguments))] [ActionOptionsDependencyProperty] - public string Arguments { get; set; } + public string? Arguments { get; set; } [DefaultValue(ExecuteOptionsDefaults.IgnoreExitCode)] public bool? IgnoreExitCode { get; set; } diff --git a/src/Tools/dotnet-monitor/CollectionRules/Options/Actions/GetEnvironmentVariableOptions.cs b/src/Tools/dotnet-monitor/CollectionRules/Options/Actions/GetEnvironmentVariableOptions.cs index ff7ad9592f8..67da644add3 100644 --- a/src/Tools/dotnet-monitor/CollectionRules/Options/Actions/GetEnvironmentVariableOptions.cs +++ b/src/Tools/dotnet-monitor/CollectionRules/Options/Actions/GetEnvironmentVariableOptions.cs @@ -20,6 +20,6 @@ internal sealed record class GetEnvironmentVariableOptions : BaseRecordOptions ResourceType = typeof(OptionsDisplayStrings), Description = nameof(OptionsDisplayStrings.DisplayAttributeDescription_GetEnvironmentVariableOptions_Name))] [Required] - public string Name { get; set; } + public string Name { get; set; } = string.Empty; } } diff --git a/src/Tools/dotnet-monitor/CollectionRules/Options/Actions/LoadProfilerOptions.cs b/src/Tools/dotnet-monitor/CollectionRules/Options/Actions/LoadProfilerOptions.cs index 6084293da0f..d3f2fadba13 100644 --- a/src/Tools/dotnet-monitor/CollectionRules/Options/Actions/LoadProfilerOptions.cs +++ b/src/Tools/dotnet-monitor/CollectionRules/Options/Actions/LoadProfilerOptions.cs @@ -21,7 +21,7 @@ internal sealed record class LoadProfilerOptions : BaseRecordOptions ResourceType = typeof(OptionsDisplayStrings), Description = nameof(OptionsDisplayStrings.DisplayAttributeDescription_LoadProfilerOptions_Path))] [Required] - public string Path { get; set; } + public string Path { get; set; } = string.Empty; [Display( ResourceType = typeof(OptionsDisplayStrings), diff --git a/src/Tools/dotnet-monitor/CollectionRules/Options/Actions/SetEnvironmentVariableOptions.cs b/src/Tools/dotnet-monitor/CollectionRules/Options/Actions/SetEnvironmentVariableOptions.cs index 31c3412a745..d9323b29bcc 100644 --- a/src/Tools/dotnet-monitor/CollectionRules/Options/Actions/SetEnvironmentVariableOptions.cs +++ b/src/Tools/dotnet-monitor/CollectionRules/Options/Actions/SetEnvironmentVariableOptions.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.Diagnostics.Monitoring.WebApi; using System.ComponentModel.DataAnnotations; using System.Diagnostics; @@ -20,11 +22,11 @@ internal sealed record class SetEnvironmentVariableOptions : BaseRecordOptions ResourceType = typeof(OptionsDisplayStrings), Description = nameof(OptionsDisplayStrings.DisplayAttributeDescription_SetEnvironmentVariableOptions_Name))] [Required] - public string Name { get; set; } + public string Name { get; set; } = string.Empty; [Display( ResourceType = typeof(OptionsDisplayStrings), Description = nameof(OptionsDisplayStrings.DisplayAttributeDescription_SetEnvironmentVariableOptions_Value))] - public string Value { get; set; } + public string? Value { get; set; } } } diff --git a/src/Tools/dotnet-monitor/CollectionRules/Options/Actions/TraceEventFilter.cs b/src/Tools/dotnet-monitor/CollectionRules/Options/Actions/TraceEventFilter.cs index 7f9e7e5d5c6..ab7e874fc9f 100644 --- a/src/Tools/dotnet-monitor/CollectionRules/Options/Actions/TraceEventFilter.cs +++ b/src/Tools/dotnet-monitor/CollectionRules/Options/Actions/TraceEventFilter.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.Diagnostics.Monitoring.WebApi; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; @@ -21,17 +23,17 @@ internal sealed record class TraceEventFilter : BaseRecordOptions ResourceType = typeof(OptionsDisplayStrings), Description = nameof(OptionsDisplayStrings.DisplayAttributeDescription_TraceEventFilter_ProviderName))] [Required] - public string ProviderName { get; set; } + public string ProviderName { get; set; } = string.Empty; [Display( ResourceType = typeof(OptionsDisplayStrings), Description = nameof(OptionsDisplayStrings.DisplayAttributeDescription_TraceEventFilter_EventName))] [Required] - public string EventName { get; set; } + public string EventName { get; set; } = string.Empty; [Display( ResourceType = typeof(OptionsDisplayStrings), Description = nameof(OptionsDisplayStrings.DisplayAttributeDescription_TraceEventFilter_PayloadFilter))] - public IDictionary PayloadFilter { get; set; } + public IDictionary? PayloadFilter { get; set; } } } diff --git a/src/Tools/dotnet-monitor/CollectionRules/Options/CollectionRuleActionDefaultsOptions.cs b/src/Tools/dotnet-monitor/CollectionRules/Options/CollectionRuleActionDefaultsOptions.cs index 0eb8d329059..f9978705d0b 100644 --- a/src/Tools/dotnet-monitor/CollectionRules/Options/CollectionRuleActionDefaultsOptions.cs +++ b/src/Tools/dotnet-monitor/CollectionRules/Options/CollectionRuleActionDefaultsOptions.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.Diagnostics.Monitoring.WebApi; using System.ComponentModel.DataAnnotations; @@ -11,6 +13,6 @@ internal sealed class CollectionRuleActionDefaultsOptions [Display( ResourceType = typeof(OptionsDisplayStrings), Description = nameof(OptionsDisplayStrings.DisplayAttributeDescription_CollectionRuleActionDefaultsOptions_Egress))] - public string Egress { get; set; } + public string? Egress { get; set; } } } diff --git a/src/Tools/dotnet-monitor/CollectionRules/Options/CollectionRuleActionOptions.cs b/src/Tools/dotnet-monitor/CollectionRules/Options/CollectionRuleActionOptions.cs index 085708a7682..66e29494f0a 100644 --- a/src/Tools/dotnet-monitor/CollectionRules/Options/CollectionRuleActionOptions.cs +++ b/src/Tools/dotnet-monitor/CollectionRules/Options/CollectionRuleActionOptions.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.Diagnostics.Monitoring.WebApi; using System.ComponentModel; using System.ComponentModel.DataAnnotations; @@ -17,18 +19,18 @@ internal sealed partial class CollectionRuleActionOptions [Display( ResourceType = typeof(OptionsDisplayStrings), Description = nameof(OptionsDisplayStrings.DisplayAttributeDescription_CollectionRuleActionOptions_Name))] - public string Name { get; set; } + public string? Name { get; set; } [Display( ResourceType = typeof(OptionsDisplayStrings), Description = nameof(OptionsDisplayStrings.DisplayAttributeDescription_CollectionRuleActionOptions_Type))] [Required] - public string Type { get; set; } + public string Type { get; set; } = string.Empty; [Display( ResourceType = typeof(OptionsDisplayStrings), Description = nameof(OptionsDisplayStrings.DisplayAttributeDescription_CollectionRuleActionOptions_Settings))] - public object Settings { get; internal set; } + public object? Settings { get; internal set; } [Display( ResourceType = typeof(OptionsDisplayStrings), diff --git a/src/Tools/dotnet-monitor/CollectionRules/Options/CollectionRuleDefaultsOptions.cs b/src/Tools/dotnet-monitor/CollectionRules/Options/CollectionRuleDefaultsOptions.cs index 57d6a637cc4..064d4ab8f9b 100644 --- a/src/Tools/dotnet-monitor/CollectionRules/Options/CollectionRuleDefaultsOptions.cs +++ b/src/Tools/dotnet-monitor/CollectionRules/Options/CollectionRuleDefaultsOptions.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.Diagnostics.Monitoring.WebApi; using System.ComponentModel.DataAnnotations; @@ -11,16 +13,16 @@ internal sealed class CollectionRuleDefaultsOptions [Display( ResourceType = typeof(OptionsDisplayStrings), Description = nameof(OptionsDisplayStrings.DisplayAttributeDescription_CollectionRuleDefaultsOptions_Triggers))] - public CollectionRuleTriggerDefaultsOptions Triggers { get; set; } + public CollectionRuleTriggerDefaultsOptions? Triggers { get; set; } [Display( ResourceType = typeof(OptionsDisplayStrings), Description = nameof(OptionsDisplayStrings.DisplayAttributeDescription_CollectionRuleDefaultsOptions_Actions))] - public CollectionRuleActionDefaultsOptions Actions { get; set; } + public CollectionRuleActionDefaultsOptions? Actions { get; set; } [Display( ResourceType = typeof(OptionsDisplayStrings), Description = nameof(OptionsDisplayStrings.DisplayAttributeDescription_CollectionRuleDefaultsOptions_Limits))] - public CollectionRuleLimitsDefaultsOptions Limits { get; set; } + public CollectionRuleLimitsDefaultsOptions? Limits { get; set; } } } diff --git a/src/Tools/dotnet-monitor/CollectionRules/Options/CollectionRuleOptions.cs b/src/Tools/dotnet-monitor/CollectionRules/Options/CollectionRuleOptions.cs index 95b8f9562a6..791c81f801d 100644 --- a/src/Tools/dotnet-monitor/CollectionRules/Options/CollectionRuleOptions.cs +++ b/src/Tools/dotnet-monitor/CollectionRules/Options/CollectionRuleOptions.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.Diagnostics.Monitoring.WebApi; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; @@ -15,23 +17,23 @@ internal sealed partial class CollectionRuleOptions [Display( ResourceType = typeof(OptionsDisplayStrings), Description = nameof(OptionsDisplayStrings.DisplayAttributeDescription_CollectionRuleOptions_Filters))] - public List Filters { get; } = new List(0); + public List? Filters { get; } = new List(0); [Display( ResourceType = typeof(OptionsDisplayStrings), Description = nameof(OptionsDisplayStrings.DisplayAttributeDescription_CollectionRuleOptions_Trigger))] [Required] - public CollectionRuleTriggerOptions Trigger { get; set; } + public CollectionRuleTriggerOptions Trigger { get; set; } = new(); [Display( ResourceType = typeof(OptionsDisplayStrings), Description = nameof(OptionsDisplayStrings.DisplayAttributeDescription_CollectionRuleOptions_Actions))] - public List Actions { get; } = new List(0); + public List? Actions { get; } = new List(0); [Display( ResourceType = typeof(OptionsDisplayStrings), Description = nameof(OptionsDisplayStrings.DisplayAttributeDescription_CollectionRuleOptions_Limits))] - public CollectionRuleLimitsOptions Limits { get; set; } + public CollectionRuleLimitsOptions? Limits { get; set; } internal List ErrorList { get; } = new List(); } diff --git a/src/Tools/dotnet-monitor/CollectionRules/Options/CollectionRuleTriggerOptions.cs b/src/Tools/dotnet-monitor/CollectionRules/Options/CollectionRuleTriggerOptions.cs index 1ea171a3219..6abf18ab2d0 100644 --- a/src/Tools/dotnet-monitor/CollectionRules/Options/CollectionRuleTriggerOptions.cs +++ b/src/Tools/dotnet-monitor/CollectionRules/Options/CollectionRuleTriggerOptions.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.Diagnostics.Monitoring.WebApi; using System.ComponentModel.DataAnnotations; using System.Diagnostics; @@ -17,11 +19,11 @@ internal sealed partial class CollectionRuleTriggerOptions ResourceType = typeof(OptionsDisplayStrings), Description = nameof(OptionsDisplayStrings.DisplayAttributeDescription_CollectionRuleTriggerOptions_Type))] [Required] - public string Type { get; set; } + public string Type { get; set; } = string.Empty; [Display( ResourceType = typeof(OptionsDisplayStrings), Description = nameof(OptionsDisplayStrings.DisplayAttributeDescription_CollectionRuleTriggerOptions_Settings))] - public object Settings { get; internal set; } + public object? Settings { get; internal set; } } } diff --git a/src/Tools/dotnet-monitor/CollectionRules/Options/RegularExpressionsAttribute.cs b/src/Tools/dotnet-monitor/CollectionRules/Options/RegularExpressionsAttribute.cs index adbb53c620b..1188ed42326 100644 --- a/src/Tools/dotnet-monitor/CollectionRules/Options/RegularExpressionsAttribute.cs +++ b/src/Tools/dotnet-monitor/CollectionRules/Options/RegularExpressionsAttribute.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.ComponentModel.DataAnnotations; @@ -13,7 +15,7 @@ public RegularExpressionsAttribute(string pattern) : base(pattern) { } - public override bool IsValid(object value) + public override bool IsValid(object? value) { if (value is string[] values) { diff --git a/src/Tools/dotnet-monitor/CollectionRules/Options/TemplateOptions.cs b/src/Tools/dotnet-monitor/CollectionRules/Options/TemplateOptions.cs index bb28aebd736..40b91ff4282 100644 --- a/src/Tools/dotnet-monitor/CollectionRules/Options/TemplateOptions.cs +++ b/src/Tools/dotnet-monitor/CollectionRules/Options/TemplateOptions.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.Diagnostics.Monitoring.WebApi; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; @@ -15,21 +17,21 @@ internal sealed partial class TemplateOptions [Display( ResourceType = typeof(OptionsDisplayStrings), Description = nameof(OptionsDisplayStrings.DisplayAttributeDescription_CollectionRuleOptions_Filters))] - public IDictionary CollectionRuleFilters { get; set; } = new Dictionary(); + public IDictionary? CollectionRuleFilters { get; set; } = new Dictionary(); [Display( ResourceType = typeof(OptionsDisplayStrings), Description = nameof(OptionsDisplayStrings.DisplayAttributeDescription_CollectionRuleOptions_Trigger))] - public IDictionary CollectionRuleTriggers { get; set; } = new Dictionary(); + public IDictionary? CollectionRuleTriggers { get; set; } = new Dictionary(); [Display( ResourceType = typeof(OptionsDisplayStrings), Description = nameof(OptionsDisplayStrings.DisplayAttributeDescription_CollectionRuleOptions_Actions))] - public IDictionary CollectionRuleActions { get; set; } = new Dictionary(); + public IDictionary? CollectionRuleActions { get; set; } = new Dictionary(); [Display( ResourceType = typeof(OptionsDisplayStrings), Description = nameof(OptionsDisplayStrings.DisplayAttributeDescription_CollectionRuleOptions_Limits))] - public IDictionary CollectionRuleLimits { get; set; } = new Dictionary(); + public IDictionary? CollectionRuleLimits { get; set; } = new Dictionary(); } } diff --git a/src/Tools/dotnet-monitor/CollectionRules/Options/Triggers/AspNetRequestCountOptions.cs b/src/Tools/dotnet-monitor/CollectionRules/Options/Triggers/AspNetRequestCountOptions.cs index cfe312de124..adb6868e8fa 100644 --- a/src/Tools/dotnet-monitor/CollectionRules/Options/Triggers/AspNetRequestCountOptions.cs +++ b/src/Tools/dotnet-monitor/CollectionRules/Options/Triggers/AspNetRequestCountOptions.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.Diagnostics.Monitoring.WebApi; using Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.CollectionRuleDefaultsInterfaces; using System; @@ -35,13 +37,13 @@ internal sealed class AspNetRequestCountOptions : [Display( ResourceType = typeof(OptionsDisplayStrings), Description = nameof(OptionsDisplayStrings.DisplayAttributeDescription_AspNetRequestCountOptions_IncludePaths))] - public string[] IncludePaths { get; set; } + public string[]? IncludePaths { get; set; } // CONSIDER: Currently described that paths have to exactly match one item in the list. // Consider allowing for wildcard/globbing to simplify list of matchable paths. [Display( ResourceType = typeof(OptionsDisplayStrings), Description = nameof(OptionsDisplayStrings.DisplayAttributeDescription_AspNetRequestCountOptions_ExcludePaths))] - public string[] ExcludePaths { get; set; } + public string[]? ExcludePaths { get; set; } } } diff --git a/src/Tools/dotnet-monitor/CollectionRules/Options/Triggers/AspNetRequestDurationOptions.cs b/src/Tools/dotnet-monitor/CollectionRules/Options/Triggers/AspNetRequestDurationOptions.cs index b9c4f28388f..1967a34f1f8 100644 --- a/src/Tools/dotnet-monitor/CollectionRules/Options/Triggers/AspNetRequestDurationOptions.cs +++ b/src/Tools/dotnet-monitor/CollectionRules/Options/Triggers/AspNetRequestDurationOptions.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.Diagnostics.Monitoring.WebApi; using Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.CollectionRuleDefaultsInterfaces; using System; @@ -46,13 +48,13 @@ internal sealed class AspNetRequestDurationOptions : [Display( ResourceType = typeof(OptionsDisplayStrings), Description = nameof(OptionsDisplayStrings.DisplayAttributeDescription_AspNetRequestDurationOptions_IncludePaths))] - public string[] IncludePaths { get; set; } + public string[]? IncludePaths { get; set; } // CONSIDER: Currently described that paths have to exactly match one item in the list. // Consider allowing for wildcard/globbing to simplify list of matchable paths. [Display( ResourceType = typeof(OptionsDisplayStrings), Description = nameof(OptionsDisplayStrings.DisplayAttributeDescription_AspNetRequestDurationOptions_ExcludePaths))] - public string[] ExcludePaths { get; set; } + public string[]? ExcludePaths { get; set; } } } diff --git a/src/Tools/dotnet-monitor/CollectionRules/Options/Triggers/AspNetResponseStatusOptions.cs b/src/Tools/dotnet-monitor/CollectionRules/Options/Triggers/AspNetResponseStatusOptions.cs index d124033b2b8..01f85593abf 100644 --- a/src/Tools/dotnet-monitor/CollectionRules/Options/Triggers/AspNetResponseStatusOptions.cs +++ b/src/Tools/dotnet-monitor/CollectionRules/Options/Triggers/AspNetResponseStatusOptions.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.Diagnostics.Monitoring.WebApi; using Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.CollectionRuleDefaultsInterfaces; using System; @@ -25,7 +27,7 @@ internal sealed class AspNetResponseStatusOptions : [RegularExpressions(StatusCodesRegex, ErrorMessageResourceType = typeof(OptionsDisplayStrings), ErrorMessageResourceName = nameof(OptionsDisplayStrings.ErrorMessage_StatusCodesRegularExpressionDoesNotMatch))] - public string[] StatusCodes { get; set; } + public string[] StatusCodes { get; set; } = []; [Display( ResourceType = typeof(OptionsDisplayStrings), @@ -48,13 +50,13 @@ internal sealed class AspNetResponseStatusOptions : [Display( ResourceType = typeof(OptionsDisplayStrings), Description = nameof(OptionsDisplayStrings.DisplayAttributeDescription_AspNetResponseStatusOptions_IncludePaths))] - public string[] IncludePaths { get; set; } + public string[]? IncludePaths { get; set; } // CONSIDER: Currently described that paths have to exactly match one item in the list. // Consider allowing for wildcard/globbing to simplify list of matchable paths. [Display( ResourceType = typeof(OptionsDisplayStrings), Description = nameof(OptionsDisplayStrings.DisplayAttributeDescription_AspNetResponseStatusOptions_ExcludePaths))] - public string[] ExcludePaths { get; set; } + public string[]? ExcludePaths { get; set; } } } diff --git a/src/Tools/dotnet-monitor/CollectionRules/Options/Triggers/EventCounterOptions.cs b/src/Tools/dotnet-monitor/CollectionRules/Options/Triggers/EventCounterOptions.cs index 3546b3ff123..3c02bcd03cf 100644 --- a/src/Tools/dotnet-monitor/CollectionRules/Options/Triggers/EventCounterOptions.cs +++ b/src/Tools/dotnet-monitor/CollectionRules/Options/Triggers/EventCounterOptions.cs @@ -17,13 +17,13 @@ internal sealed partial class EventCounterOptions : ISlidingWindowDurationProper ResourceType = typeof(OptionsDisplayStrings), Description = nameof(OptionsDisplayStrings.DisplayAttributeDescription_EventCounterOptions_ProviderName))] [Required] - public string ProviderName { get; set; } + public string ProviderName { get; set; } = string.Empty; [Display( ResourceType = typeof(OptionsDisplayStrings), Description = nameof(OptionsDisplayStrings.DisplayAttributeDescription_EventCounterOptions_CounterName))] [Required] - public string CounterName { get; set; } + public string CounterName { get; set; } = string.Empty; [Display( ResourceType = typeof(OptionsDisplayStrings), diff --git a/src/Tools/dotnet-monitor/CollectionRules/Options/Triggers/EventMeterOptions.cs b/src/Tools/dotnet-monitor/CollectionRules/Options/Triggers/EventMeterOptions.cs index c5288203f6b..cc22561940f 100644 --- a/src/Tools/dotnet-monitor/CollectionRules/Options/Triggers/EventMeterOptions.cs +++ b/src/Tools/dotnet-monitor/CollectionRules/Options/Triggers/EventMeterOptions.cs @@ -17,13 +17,13 @@ internal sealed partial class EventMeterOptions : ISlidingWindowDurationProperti ResourceType = typeof(OptionsDisplayStrings), Description = nameof(OptionsDisplayStrings.DisplayAttributeDescription_EventMeterOptions_MeterName))] [Required] - public string MeterName { get; set; } + public string MeterName { get; set; } = string.Empty; [Display( ResourceType = typeof(OptionsDisplayStrings), Description = nameof(OptionsDisplayStrings.DisplayAttributeDescription_EventMeterOptions_InstrumentName))] [Required] - public string InstrumentName { get; set; } + public string InstrumentName { get; set; } = string.Empty; [Display( ResourceType = typeof(OptionsDisplayStrings), diff --git a/src/Tools/dotnet-monitor/CollectionRules/Options/Triggers/IAspNetActionPathFilters.cs b/src/Tools/dotnet-monitor/CollectionRules/Options/Triggers/IAspNetActionPathFilters.cs index 723073aaeff..28657b2c5d6 100644 --- a/src/Tools/dotnet-monitor/CollectionRules/Options/Triggers/IAspNetActionPathFilters.cs +++ b/src/Tools/dotnet-monitor/CollectionRules/Options/Triggers/IAspNetActionPathFilters.cs @@ -1,12 +1,14 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +#nullable enable + namespace Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Triggers { internal interface IAspNetActionPathFilters { - public string[] IncludePaths { get; } + public string[]? IncludePaths { get; } - public string[] ExcludePaths { get; } + public string[]? ExcludePaths { get; } } } diff --git a/src/Tools/dotnet-monitor/RootOptions.cs b/src/Tools/dotnet-monitor/RootOptions.cs index 526ee2d8acf..f3a42b42575 100644 --- a/src/Tools/dotnet-monitor/RootOptions.cs +++ b/src/Tools/dotnet-monitor/RootOptions.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.Diagnostics.Monitoring.Options; using Microsoft.Diagnostics.Monitoring.WebApi; using Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options; @@ -10,32 +12,32 @@ namespace Microsoft.Diagnostics.Tools.Monitor { internal sealed partial class RootOptions { - public AuthenticationOptions Authentication { get; set; } + public AuthenticationOptions? Authentication { get; set; } - public IDictionary CollectionRules { get; set; } + public IDictionary? CollectionRules { get; set; } = new Dictionary(0); - public GlobalCounterOptions GlobalCounter { get; set; } + public GlobalCounterOptions? GlobalCounter { get; set; } - public InProcessFeaturesOptions InProcessFeatures { get; set; } + public InProcessFeaturesOptions? InProcessFeatures { get; set; } - public CorsConfigurationOptions CorsConfiguration { get; set; } + public CorsConfigurationOptions? CorsConfiguration { get; set; } - public DiagnosticPortOptions DiagnosticPort { get; set; } + public DiagnosticPortOptions? DiagnosticPort { get; set; } - public EgressOptions Egress { get; set; } + public EgressOptions? Egress { get; set; } - public MetricsOptions Metrics { get; set; } + public MetricsOptions? Metrics { get; set; } - public StorageOptions Storage { get; set; } + public StorageOptions? Storage { get; set; } - public ProcessFilterOptions DefaultProcess { get; set; } + public ProcessFilterOptions? DefaultProcess { get; set; } - public CollectionRuleDefaultsOptions CollectionRuleDefaults { get; set; } + public CollectionRuleDefaultsOptions? CollectionRuleDefaults { get; set; } - public TemplateOptions Templates { get; set; } + public TemplateOptions? Templates { get; set; } - public DotnetMonitorDebugOptions DotnetMonitorDebug { get; set; } + public DotnetMonitorDebugOptions? DotnetMonitorDebug { get; set; } } } From 75cb74a2809842511287942087b51e34ef78db83 Mon Sep 17 00:00:00 2001 From: Joe Schmitt Date: Mon, 1 Jul 2024 15:17:11 -0700 Subject: [PATCH 02/20] Enable nullability context --- .../AuthenticationOptions.cs | 4 ++-- .../AzureAdOptions.cs | 10 ++++----- .../CollectionRuleMetadata.cs | 4 ++-- .../CorsConfigurationOptions.cs | 4 ++-- .../DiagnosticPortOptions.cs | 2 +- .../DotnetMonitorDebugOptions.cs | 2 +- .../EgressOptions.cs | 4 ++-- .../ExceptionsConfiguration.cs | 17 ++++++++------ .../ExceptionsOptions.cs | 2 +- .../FileSystemEgressProviderOptions.cs | 4 ++-- .../GlobalCounterOptions.cs | 22 +++++++++++-------- .../InProcessFeaturesOptions.cs | 6 ++--- .../MetricsOptions.cs | 14 ++++++------ ...soft.Diagnostics.Monitoring.Options.csproj | 1 + .../MonitorApiKeyOptions.cs | 6 ++--- .../ProcessFilterOptions.cs | 10 ++++----- .../StorageOptions.cs | 6 ++--- .../Controllers/DiagController.cs | 4 ++-- .../DiagProcessFilter.cs | 11 +++++----- .../DumpService.cs | 3 ++- .../Exceptions/ExceptionsSettingsFactory.cs | 4 ++-- .../ProfilerChannel.cs | 4 ++-- 22 files changed, 77 insertions(+), 67 deletions(-) diff --git a/src/Microsoft.Diagnostics.Monitoring.Options/AuthenticationOptions.cs b/src/Microsoft.Diagnostics.Monitoring.Options/AuthenticationOptions.cs index 776080b8ca7..8b2b8567588 100644 --- a/src/Microsoft.Diagnostics.Monitoring.Options/AuthenticationOptions.cs +++ b/src/Microsoft.Diagnostics.Monitoring.Options/AuthenticationOptions.cs @@ -11,11 +11,11 @@ internal sealed partial class AuthenticationOptions [Display( ResourceType = typeof(OptionsDisplayStrings), Description = nameof(OptionsDisplayStrings.DisplayAttributeDescription_AuthenticationOptions_MonitorApiKey))] - public MonitorApiKeyOptions MonitorApiKey { get; set; } + public MonitorApiKeyOptions? MonitorApiKey { get; set; } [Display( ResourceType = typeof(OptionsDisplayStrings), Description = nameof(OptionsDisplayStrings.DisplayAttributeDescription_AuthenticationOptions_AzureAd))] - public AzureAdOptions AzureAd { get; set; } + public AzureAdOptions? AzureAd { get; set; } } } diff --git a/src/Microsoft.Diagnostics.Monitoring.Options/AzureAdOptions.cs b/src/Microsoft.Diagnostics.Monitoring.Options/AzureAdOptions.cs index a696a70bdd2..b40304057e1 100644 --- a/src/Microsoft.Diagnostics.Monitoring.Options/AzureAdOptions.cs +++ b/src/Microsoft.Diagnostics.Monitoring.Options/AzureAdOptions.cs @@ -14,29 +14,29 @@ internal sealed partial class AzureAdOptions ResourceType = typeof(OptionsDisplayStrings), Description = nameof(OptionsDisplayStrings.DisplayAttributeDescription_AzureAdOptions_Instance))] [DefaultValue(AzureAdOptionsDefaults.DefaultInstance)] - public Uri Instance { get; set; } + public Uri? Instance { get; set; } [Display( ResourceType = typeof(OptionsDisplayStrings), Description = nameof(OptionsDisplayStrings.DisplayAttributeDescription_AzureAdOptions_TenantId))] [DefaultValue(AzureAdOptionsDefaults.DefaultTenantId)] - public string TenantId { get; set; } + public string? TenantId { get; set; } [Display( ResourceType = typeof(OptionsDisplayStrings), Description = nameof(OptionsDisplayStrings.DisplayAttributeDescription_AzureAdOptions_ClientId))] [Required] - public string ClientId { get; set; } + public string ClientId { get; set; } = string.Empty; [Display( ResourceType = typeof(OptionsDisplayStrings), Description = nameof(OptionsDisplayStrings.DisplayAttributeDescription_AzureAdOptions_AppIdUri))] - public Uri AppIdUri { get; set; } + public Uri? AppIdUri { get; set; } [Display( ResourceType = typeof(OptionsDisplayStrings), Description = nameof(OptionsDisplayStrings.DisplayAttributeDescription_AzureAdOptions_RequiredRole))] [Required] - public string RequiredRole { get; set; } + public string RequiredRole { get; set; } = string.Empty; } } diff --git a/src/Microsoft.Diagnostics.Monitoring.Options/CollectionRuleMetadata.cs b/src/Microsoft.Diagnostics.Monitoring.Options/CollectionRuleMetadata.cs index b8f93b77ded..5f385e4a8eb 100644 --- a/src/Microsoft.Diagnostics.Monitoring.Options/CollectionRuleMetadata.cs +++ b/src/Microsoft.Diagnostics.Monitoring.Options/CollectionRuleMetadata.cs @@ -5,10 +5,10 @@ namespace Microsoft.Diagnostics.Monitoring.WebApi { internal class CollectionRuleMetadata { - public string CollectionRuleName { get; set; } + public string CollectionRuleName { get; set; } = string.Empty; // JSFIX public int ActionListIndex { get; set; } - public string ActionName { get; set; } + public string? ActionName { get; set; } } } diff --git a/src/Microsoft.Diagnostics.Monitoring.Options/CorsConfigurationOptions.cs b/src/Microsoft.Diagnostics.Monitoring.Options/CorsConfigurationOptions.cs index 3d0973cdc07..325293a3454 100644 --- a/src/Microsoft.Diagnostics.Monitoring.Options/CorsConfigurationOptions.cs +++ b/src/Microsoft.Diagnostics.Monitoring.Options/CorsConfigurationOptions.cs @@ -11,8 +11,8 @@ public class CorsConfigurationOptions ResourceType = typeof(OptionsDisplayStrings), Description = nameof(OptionsDisplayStrings.DisplayAttributeDescription_CorsConfiguration_AllowedOrigins))] [Required] - public string AllowedOrigins { get; set; } + 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/DiagnosticPortOptions.cs b/src/Microsoft.Diagnostics.Monitoring.Options/DiagnosticPortOptions.cs index 24f71cbf722..cb6d4431ca4 100644 --- a/src/Microsoft.Diagnostics.Monitoring.Options/DiagnosticPortOptions.cs +++ b/src/Microsoft.Diagnostics.Monitoring.Options/DiagnosticPortOptions.cs @@ -17,7 +17,7 @@ public class DiagnosticPortOptions [Display( ResourceType = typeof(OptionsDisplayStrings), Description = nameof(OptionsDisplayStrings.DisplayAttributeDescription_DiagnosticPortOptions_EndpointName))] - public string EndpointName { get; set; } + public string? EndpointName { get; set; } [Display( ResourceType = typeof(OptionsDisplayStrings), diff --git a/src/Microsoft.Diagnostics.Monitoring.Options/DotnetMonitorDebugOptions.cs b/src/Microsoft.Diagnostics.Monitoring.Options/DotnetMonitorDebugOptions.cs index f0ed54fb1af..b8ca50a529e 100644 --- a/src/Microsoft.Diagnostics.Monitoring.Options/DotnetMonitorDebugOptions.cs +++ b/src/Microsoft.Diagnostics.Monitoring.Options/DotnetMonitorDebugOptions.cs @@ -9,6 +9,6 @@ namespace Microsoft.Diagnostics.Monitoring.Options /// internal sealed class DotnetMonitorDebugOptions { - public ExceptionsDebugOptions Exceptions { get; set; } + public ExceptionsDebugOptions? Exceptions { get; set; } } } diff --git a/src/Microsoft.Diagnostics.Monitoring.Options/EgressOptions.cs b/src/Microsoft.Diagnostics.Monitoring.Options/EgressOptions.cs index 2120c2e0335..b0b07ca343e 100644 --- a/src/Microsoft.Diagnostics.Monitoring.Options/EgressOptions.cs +++ b/src/Microsoft.Diagnostics.Monitoring.Options/EgressOptions.cs @@ -13,11 +13,11 @@ internal sealed class EgressOptions [Display( ResourceType = typeof(OptionsDisplayStrings), Description = nameof(OptionsDisplayStrings.DisplayAttributeDescription_EgressOptions_FileSystem))] - public IDictionary FileSystem { get; set; } + public IDictionary? FileSystem { get; set; } [Display( ResourceType = typeof(OptionsDisplayStrings), Description = nameof(OptionsDisplayStrings.DisplayAttributeDescription_EgressOptions_Properties))] - public IDictionary Properties { get; set; } + public IDictionary? Properties { get; set; } } } diff --git a/src/Microsoft.Diagnostics.Monitoring.Options/ExceptionsConfiguration.cs b/src/Microsoft.Diagnostics.Monitoring.Options/ExceptionsConfiguration.cs index e47bb3953cd..8a44b0c7ae1 100644 --- a/src/Microsoft.Diagnostics.Monitoring.Options/ExceptionsConfiguration.cs +++ b/src/Microsoft.Diagnostics.Monitoring.Options/ExceptionsConfiguration.cs @@ -13,25 +13,28 @@ public sealed class ExceptionsConfiguration /// Each configuration is a logical OR, so if any of the configurations match, the exception is shown. /// [JsonPropertyName("include")] - public List Include { get; set; } = new(); + public List? Include { get; set; } = new(); /// /// The list of exception configurations that determine which exceptions should be shown. /// Each configuration is a logical OR, so if any of the configurations match, the exception isn't shown. /// [JsonPropertyName("exclude")] - public List Exclude { get; set; } = new(); + public List? Exclude { get; set; } = new(); } - public sealed class ExceptionFilter : IMethodDescription + public sealed class ExceptionFilter { [JsonPropertyName("exceptionType")] - public string ExceptionType { get; set; } + public string? ExceptionType { get; set; } - public string ModuleName { get; set; } + [JsonPropertyName("moduleName")] + public string? ModuleName { get; set; } - public string TypeName { get; set; } + [JsonPropertyName("typeName")] + public string? TypeName { get; set; } - public string MethodName { get; set; } + [JsonPropertyName("methodName")] + public string? MethodName { get; set; } } } diff --git a/src/Microsoft.Diagnostics.Monitoring.Options/ExceptionsOptions.cs b/src/Microsoft.Diagnostics.Monitoring.Options/ExceptionsOptions.cs index ed638f0c0a0..547c125916f 100644 --- a/src/Microsoft.Diagnostics.Monitoring.Options/ExceptionsOptions.cs +++ b/src/Microsoft.Diagnostics.Monitoring.Options/ExceptionsOptions.cs @@ -26,6 +26,6 @@ internal sealed class ExceptionsOptions : [Display( ResourceType = typeof(OptionsDisplayStrings), Description = nameof(OptionsDisplayStrings.DisplayAttributeDescription_ExceptionsOptions_CollectionFilters))] - public ExceptionsConfiguration CollectionFilters { get; set; } + public ExceptionsConfiguration? CollectionFilters { get; set; } } } diff --git a/src/Microsoft.Diagnostics.Monitoring.Options/FileSystemEgressProviderOptions.cs b/src/Microsoft.Diagnostics.Monitoring.Options/FileSystemEgressProviderOptions.cs index d6ceffc2673..0caee405036 100644 --- a/src/Microsoft.Diagnostics.Monitoring.Options/FileSystemEgressProviderOptions.cs +++ b/src/Microsoft.Diagnostics.Monitoring.Options/FileSystemEgressProviderOptions.cs @@ -18,12 +18,12 @@ internal sealed class FileSystemEgressProviderOptions ResourceType = typeof(OptionsDisplayStrings), Description = nameof(OptionsDisplayStrings.DisplayAttributeDescription_FileSystemEgressProviderOptions_DirectoryPath))] [Required] - public string DirectoryPath { get; set; } + public string DirectoryPath { get; set; } = string.Empty; [Display( ResourceType = typeof(OptionsDisplayStrings), Description = nameof(OptionsDisplayStrings.DisplayAttributeDescription_FileSystemEgressProviderOptions_IntermediateDirectoryPath))] - public string IntermediateDirectoryPath { get; set; } + public string? IntermediateDirectoryPath { get; set; } [Display( ResourceType = typeof(OptionsDisplayStrings), diff --git a/src/Microsoft.Diagnostics.Monitoring.Options/GlobalCounterOptions.cs b/src/Microsoft.Diagnostics.Monitoring.Options/GlobalCounterOptions.cs index ccb83017e09..c360b5184d1 100644 --- a/src/Microsoft.Diagnostics.Monitoring.Options/GlobalCounterOptions.cs +++ b/src/Microsoft.Diagnostics.Monitoring.Options/GlobalCounterOptions.cs @@ -39,7 +39,7 @@ public partial class GlobalCounterOptions [Display( ResourceType = typeof(OptionsDisplayStrings), Description = nameof(OptionsDisplayStrings.DisplayAttributeDescription_GlobalCounterOptions_Providers))] - public System.Collections.Generic.IDictionary Providers { get; set; } = new Dictionary(StringComparer.OrdinalIgnoreCase); + public System.Collections.Generic.IDictionary? Providers { get; set; } = new Dictionary(StringComparer.OrdinalIgnoreCase); } public class GlobalProviderOptions @@ -53,15 +53,19 @@ partial class GlobalCounterOptions : IValidatableObject public IEnumerable Validate(ValidationContext validationContext) { var results = new List(); - var providerResults = new List(); - foreach ((string provider, GlobalProviderOptions options) in Providers) + + if (Providers != null) { - providerResults.Clear(); - if (!Validator.TryValidateObject(options, new ValidationContext(options), providerResults, true)) + var providerResults = new List(); + foreach ((string provider, GlobalProviderOptions options) in Providers) { - // We prefix the validation error with the provider. - results.AddRange(providerResults.Select(r => new ValidationResult( - string.Format(CultureInfo.CurrentCulture, OptionsDisplayStrings.ErrorMessage_NestedProviderValidationError, provider, r.ErrorMessage)))); + providerResults.Clear(); + if (!Validator.TryValidateObject(options, new ValidationContext(options), providerResults, true)) + { + // We prefix the validation error with the provider. + results.AddRange(providerResults.Select(r => new ValidationResult( + string.Format(CultureInfo.CurrentCulture, OptionsDisplayStrings.ErrorMessage_NestedProviderValidationError, provider, r.ErrorMessage)))); + } } } @@ -81,6 +85,6 @@ public static int GetMaxTimeSeries(this GlobalCounterOptions options) => options.MaxTimeSeries.GetValueOrDefault(GlobalCounterOptionsDefaults.MaxTimeSeries); public static float GetProviderSpecificInterval(this GlobalCounterOptions options, string providerName) => - options.Providers.TryGetValue(providerName, out GlobalProviderOptions providerOptions) ? providerOptions.IntervalSeconds ?? options.GetIntervalSeconds() : options.GetIntervalSeconds(); + options.Providers?.TryGetValue(providerName, out GlobalProviderOptions? providerOptions) == true ? providerOptions.IntervalSeconds ?? options.GetIntervalSeconds() : options.GetIntervalSeconds(); } } diff --git a/src/Microsoft.Diagnostics.Monitoring.Options/InProcessFeaturesOptions.cs b/src/Microsoft.Diagnostics.Monitoring.Options/InProcessFeaturesOptions.cs index 63be112f872..0d7dadbd92f 100644 --- a/src/Microsoft.Diagnostics.Monitoring.Options/InProcessFeaturesOptions.cs +++ b/src/Microsoft.Diagnostics.Monitoring.Options/InProcessFeaturesOptions.cs @@ -21,17 +21,17 @@ internal sealed class InProcessFeaturesOptions [Display( ResourceType = typeof(OptionsDisplayStrings), Description = nameof(OptionsDisplayStrings.DisplayAttributeDescription_InProcessFeaturesOptions_CallStacks))] - public CallStacksOptions CallStacks { get; set; } + public CallStacksOptions? CallStacks { get; set; } [Display( ResourceType = typeof(OptionsDisplayStrings), Description = nameof(OptionsDisplayStrings.DisplayAttributeDescription_InProcessFeaturesOptions_Exceptions))] - public ExceptionsOptions Exceptions { get; set; } + public ExceptionsOptions? Exceptions { get; set; } [Display( ResourceType = typeof(OptionsDisplayStrings), Description = nameof(OptionsDisplayStrings.DisplayAttributeDescription_InProcessFeaturesOptions_ParameterCapturing))] [Experimental] - public ParameterCapturingOptions ParameterCapturing { get; set; } + public ParameterCapturingOptions? ParameterCapturing { get; set; } } } diff --git a/src/Microsoft.Diagnostics.Monitoring.Options/MetricsOptions.cs b/src/Microsoft.Diagnostics.Monitoring.Options/MetricsOptions.cs index a3bb75c6246..1450284480e 100644 --- a/src/Microsoft.Diagnostics.Monitoring.Options/MetricsOptions.cs +++ b/src/Microsoft.Diagnostics.Monitoring.Options/MetricsOptions.cs @@ -25,7 +25,7 @@ public class MetricsOptions [Display( ResourceType = typeof(OptionsDisplayStrings), Description = nameof(OptionsDisplayStrings.DisplayAttributeDescription_MetricsOptions_Endpoints))] - public string Endpoints { get; set; } + public string? Endpoints { get; set; } [Display( ResourceType = typeof(OptionsDisplayStrings), @@ -43,12 +43,12 @@ public class MetricsOptions [Display( ResourceType = typeof(OptionsDisplayStrings), Description = nameof(OptionsDisplayStrings.DisplayAttributeDescription_MetricsOptions_Providers))] - public List Providers { get; set; } = new List(0); + public List? Providers { get; set; } = new List(0); [Display( ResourceType = typeof(OptionsDisplayStrings), Description = nameof(OptionsDisplayStrings.DisplayAttributeDescription_MetricsOptions_Meters))] - public List Meters { get; set; } = new List(0); + public List? Meters { get; set; } = new List(0); } public class MetricProvider @@ -57,12 +57,12 @@ public class MetricProvider ResourceType = typeof(OptionsDisplayStrings), Description = nameof(OptionsDisplayStrings.DisplayAttributeDescription_MetricProvider_ProviderName))] [Required] - public string ProviderName { get; set; } + public string ProviderName { get; set; } = string.Empty; [Display( ResourceType = typeof(OptionsDisplayStrings), Description = nameof(OptionsDisplayStrings.DisplayAttributeDescription_MetricProvider_CounterNames))] - public List CounterNames { get; set; } = new List(0); + public List? CounterNames { get; set; } = new List(0); } public class MeterConfiguration @@ -70,11 +70,11 @@ public class MeterConfiguration [Display( ResourceType = typeof(OptionsDisplayStrings), Description = nameof(OptionsDisplayStrings.DisplayAttributeDescription_MeterConfiguration_MeterName))] - public string MeterName { get; set; } + public string? MeterName { get; set; } [Display( ResourceType = typeof(OptionsDisplayStrings), Description = nameof(OptionsDisplayStrings.DisplayAttributeDescription_MeterConfiguration_InstrumentNames))] - public List InstrumentNames { get; set; } = new List(0); + public List? InstrumentNames { get; set; } = new List(0); } } diff --git a/src/Microsoft.Diagnostics.Monitoring.Options/Microsoft.Diagnostics.Monitoring.Options.csproj b/src/Microsoft.Diagnostics.Monitoring.Options/Microsoft.Diagnostics.Monitoring.Options.csproj index 14275961c91..f11b2d63e0e 100644 --- a/src/Microsoft.Diagnostics.Monitoring.Options/Microsoft.Diagnostics.Monitoring.Options.csproj +++ b/src/Microsoft.Diagnostics.Monitoring.Options/Microsoft.Diagnostics.Monitoring.Options.csproj @@ -8,6 +8,7 @@ $(TestTargetFrameworks) true Library + enable diff --git a/src/Microsoft.Diagnostics.Monitoring.Options/MonitorApiKeyOptions.cs b/src/Microsoft.Diagnostics.Monitoring.Options/MonitorApiKeyOptions.cs index 8f54cce9111..d37c2c6449d 100644 --- a/src/Microsoft.Diagnostics.Monitoring.Options/MonitorApiKeyOptions.cs +++ b/src/Microsoft.Diagnostics.Monitoring.Options/MonitorApiKeyOptions.cs @@ -12,18 +12,18 @@ internal sealed class MonitorApiKeyOptions ResourceType = typeof(OptionsDisplayStrings), Description = nameof(OptionsDisplayStrings.DisplayAttributeDescription_MonitorApiKeyOptions_Subject))] [Required] - public string Subject { get; set; } + public string Subject { get; set; } = string.Empty; [Display( ResourceType = typeof(OptionsDisplayStrings), Description = nameof(OptionsDisplayStrings.DisplayAttributeDescription_MonitorApiKeyOptions_PublicKey))] [RegularExpression("[0-9a-zA-Z_-]+")] [Required] - public string PublicKey { get; set; } + public string PublicKey { get; set; } = string.Empty; [Display( ResourceType = typeof(OptionsDisplayStrings), Description = nameof(OptionsDisplayStrings.DisplayAttributeDescription_MonitorApiKeyOptions_Issuer))] - public string Issuer { get; set; } + public string? Issuer { get; set; } } } diff --git a/src/Microsoft.Diagnostics.Monitoring.Options/ProcessFilterOptions.cs b/src/Microsoft.Diagnostics.Monitoring.Options/ProcessFilterOptions.cs index 572de62c486..cc6f88ab22b 100644 --- a/src/Microsoft.Diagnostics.Monitoring.Options/ProcessFilterOptions.cs +++ b/src/Microsoft.Diagnostics.Monitoring.Options/ProcessFilterOptions.cs @@ -41,7 +41,7 @@ public sealed class ProcessFilterOptions [Display( ResourceType = typeof(OptionsDisplayStrings), Description = nameof(OptionsDisplayStrings.DisplayAttributeDescription_ProcessFilterOptions_Filters))] - public List Filters { get; set; } = new List(0); + public List? Filters { get; set; } = new List(0); } public sealed partial class ProcessFilterDescriptor @@ -54,7 +54,7 @@ public sealed partial class ProcessFilterDescriptor [Display( ResourceType = typeof(OptionsDisplayStrings), Description = nameof(OptionsDisplayStrings.DisplayAttributeDescription_ProcessFilterDescriptor_Value))] - public string Value { get; set; } + public string? Value { get; set; } [Display( ResourceType = typeof(OptionsDisplayStrings), @@ -65,17 +65,17 @@ public sealed partial class ProcessFilterDescriptor [Display( ResourceType = typeof(OptionsDisplayStrings), Description = nameof(OptionsDisplayStrings.DisplayAttributeDescription_ProcessFilterDescriptor_ProcessName))] - public string ProcessName { get; set; } + public string? ProcessName { get; set; } [Display( ResourceType = typeof(OptionsDisplayStrings), Description = nameof(OptionsDisplayStrings.DisplayAttributeDescription_ProcessFilterDescriptor_ProcessId))] - public string ProcessId { get; set; } + public string? ProcessId { get; set; } [Display( ResourceType = typeof(OptionsDisplayStrings), Description = nameof(OptionsDisplayStrings.DisplayAttributeDescription_ProcessFilterDescriptor_CommandLine))] - public string CommandLine { get; set; } + public string? CommandLine { get; set; } } partial class ProcessFilterDescriptor : IValidatableObject diff --git a/src/Microsoft.Diagnostics.Monitoring.Options/StorageOptions.cs b/src/Microsoft.Diagnostics.Monitoring.Options/StorageOptions.cs index aaf9240cbbc..39c925fee41 100644 --- a/src/Microsoft.Diagnostics.Monitoring.Options/StorageOptions.cs +++ b/src/Microsoft.Diagnostics.Monitoring.Options/StorageOptions.cs @@ -11,17 +11,17 @@ public class StorageOptions [Display( ResourceType = typeof(OptionsDisplayStrings), Description = nameof(OptionsDisplayStrings.DisplayAttributeDescription_StorageOptions_DefaultSharedPath))] - public string DefaultSharedPath { get; set; } + public string? DefaultSharedPath { get; set; } [Display( ResourceType = typeof(OptionsDisplayStrings), Description = nameof(OptionsDisplayStrings.DisplayAttributeDescription_StorageOptions_DumpTempFolder))] - public string DumpTempFolder { get; set; } + public string? DumpTempFolder { get; set; } [Experimental] [Display( ResourceType = typeof(OptionsDisplayStrings), Description = nameof(OptionsDisplayStrings.DisplayAttributeDescription_StorageOptions_SharedLibraryPath))] - public string SharedLibraryPath { get; set; } + public string? SharedLibraryPath { get; set; } } } diff --git a/src/Microsoft.Diagnostics.Monitoring.WebApi/Controllers/DiagController.cs b/src/Microsoft.Diagnostics.Monitoring.WebApi/Controllers/DiagController.cs index 60bea0b1635..ea42067a86b 100644 --- a/src/Microsoft.Diagnostics.Monitoring.WebApi/Controllers/DiagController.cs +++ b/src/Microsoft.Diagnostics.Monitoring.WebApi/Controllers/DiagController.cs @@ -500,7 +500,7 @@ public ActionResult GetInfo() string? version = Assembly.GetExecutingAssembly().GetInformationalVersionString(); string runtimeVersion = Environment.Version.ToString(); DiagnosticPortConnectionMode diagnosticPortMode = _diagnosticPortOptions.Value.GetConnectionMode(); - string diagnosticPortName = GetDiagnosticPortName(); + string? diagnosticPortName = GetDiagnosticPortName(); DotnetMonitorInfo dotnetMonitorInfo = new() { @@ -653,7 +653,7 @@ public Task CaptureStacks( }, processKey, Utilities.ArtifactType_Stacks); } - private string GetDiagnosticPortName() + private string? GetDiagnosticPortName() { return _diagnosticPortOptions.Value.EndpointName; } diff --git a/src/Microsoft.Diagnostics.Monitoring.WebApi/DiagProcessFilter.cs b/src/Microsoft.Diagnostics.Monitoring.WebApi/DiagProcessFilter.cs index 09159e22762..9ac54121e81 100644 --- a/src/Microsoft.Diagnostics.Monitoring.WebApi/DiagProcessFilter.cs +++ b/src/Microsoft.Diagnostics.Monitoring.WebApi/DiagProcessFilter.cs @@ -36,10 +36,10 @@ public static DiagProcessFilter FromConfiguration(ProcessFilterOptions options) return FromConfiguration(options.Filters); } - public static DiagProcessFilter FromConfiguration(IEnumerable filters) + public static DiagProcessFilter FromConfiguration(IEnumerable? filters) { var filter = new DiagProcessFilter(); - foreach (ProcessFilterDescriptor processFilter in filters) + foreach (ProcessFilterDescriptor processFilter in filters ?? []) { filter.Filters.Add(TransformDescriptor(processFilter)); } @@ -96,23 +96,24 @@ private static DiagProcessFilterEntry TransformDescriptor(ProcessFilterDescripto }; } + string filterValue = processFilterDescriptor.Value!; // Guarenteed not to be null by ProcessFilterDescriptor.Validate. https://github.com/dotnet/dotnet-monitor/issues/6929. switch (processFilterDescriptor.Key) { case ProcessFilterKey.ProcessId: - return new DiagProcessFilterEntry { Criteria = DiagProcessFilterCriteria.ProcessId, MatchType = DiagProcessFilterMatchType.Exact, Value = processFilterDescriptor.Value }; + return new DiagProcessFilterEntry { Criteria = DiagProcessFilterCriteria.ProcessId, MatchType = DiagProcessFilterMatchType.Exact, Value = filterValue }; case ProcessFilterKey.ProcessName: return new DiagProcessFilterEntry { Criteria = DiagProcessFilterCriteria.ProcessName, MatchType = (processFilterDescriptor.MatchType == ProcessFilterType.Exact) ? DiagProcessFilterMatchType.Exact : DiagProcessFilterMatchType.Contains, - Value = processFilterDescriptor.Value + Value = filterValue }; case ProcessFilterKey.CommandLine: return new DiagProcessFilterEntry { Criteria = DiagProcessFilterCriteria.CommandLine, MatchType = (processFilterDescriptor.MatchType == ProcessFilterType.Exact) ? DiagProcessFilterMatchType.Exact : DiagProcessFilterMatchType.Contains, - Value = processFilterDescriptor.Value + Value = filterValue }; default: throw new ArgumentException( diff --git a/src/Microsoft.Diagnostics.Monitoring.WebApi/DumpService.cs b/src/Microsoft.Diagnostics.Monitoring.WebApi/DumpService.cs index 337ff58c6a6..aff4d8c2a62 100644 --- a/src/Microsoft.Diagnostics.Monitoring.WebApi/DumpService.cs +++ b/src/Microsoft.Diagnostics.Monitoring.WebApi/DumpService.cs @@ -36,7 +36,8 @@ public async Task DumpAsync(IEndpointInfo endpointInfo, Models.DumpType throw new ArgumentNullException(nameof(endpointInfo)); } - string dumpTempFolder = _storageOptions.CurrentValue.DumpTempFolder; + // Guarenteed to not be null by StoragePostConfigureOptions.PostConfigure. https://github.com/dotnet/dotnet-monitor/issues/6929. + string dumpTempFolder = _storageOptions.CurrentValue.DumpTempFolder!; // Ensure folder exists before issue command. if (!Directory.Exists(dumpTempFolder)) diff --git a/src/Microsoft.Diagnostics.Monitoring.WebApi/Exceptions/ExceptionsSettingsFactory.cs b/src/Microsoft.Diagnostics.Monitoring.WebApi/Exceptions/ExceptionsSettingsFactory.cs index 465f1bce77d..92011a5354d 100644 --- a/src/Microsoft.Diagnostics.Monitoring.WebApi/Exceptions/ExceptionsSettingsFactory.cs +++ b/src/Microsoft.Diagnostics.Monitoring.WebApi/Exceptions/ExceptionsSettingsFactory.cs @@ -19,12 +19,12 @@ public static ExceptionsConfigurationSettings ConvertExceptionsConfiguration(Exc return configurationSettings; } - foreach (var filter in configuration.Include) + foreach (var filter in configuration.Include ?? []) { configurationSettings.Include.Add(ConvertExceptionFilter(filter)); } - foreach (var filter in configuration.Exclude) + foreach (var filter in configuration.Exclude ?? []) { configurationSettings.Exclude.Add(ConvertExceptionFilter(filter)); } diff --git a/src/Microsoft.Diagnostics.Monitoring.WebApi/ProfilerChannel.cs b/src/Microsoft.Diagnostics.Monitoring.WebApi/ProfilerChannel.cs index ce07974f9e1..ddbd9d40bb5 100644 --- a/src/Microsoft.Diagnostics.Monitoring.WebApi/ProfilerChannel.cs +++ b/src/Microsoft.Diagnostics.Monitoring.WebApi/ProfilerChannel.cs @@ -119,8 +119,8 @@ private static async Task ReceiveStatusMessageAsync(Socket socket, Cancella private string ComputeChannelPath(IEndpointInfo endpointInfo) { - string defaultSharedPath = _storageOptions.CurrentValue.DefaultSharedPath; - if (string.IsNullOrEmpty(_storageOptions.CurrentValue.DefaultSharedPath)) + string? defaultSharedPath = _storageOptions.CurrentValue.DefaultSharedPath; + if (string.IsNullOrEmpty(defaultSharedPath)) { //Note this fallback does not work well for sidecar scenarios. defaultSharedPath = Path.GetTempPath(); From 678291f7109e5671e42d62d8ef67cbe8996f289c Mon Sep 17 00:00:00 2001 From: Joe Schmitt Date: Mon, 1 Jul 2024 15:19:21 -0700 Subject: [PATCH 03/20] Remove placeholder --- .../CollectionRuleMetadata.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.Diagnostics.Monitoring.Options/CollectionRuleMetadata.cs b/src/Microsoft.Diagnostics.Monitoring.Options/CollectionRuleMetadata.cs index 5f385e4a8eb..8b22ceac2be 100644 --- a/src/Microsoft.Diagnostics.Monitoring.Options/CollectionRuleMetadata.cs +++ b/src/Microsoft.Diagnostics.Monitoring.Options/CollectionRuleMetadata.cs @@ -5,7 +5,7 @@ namespace Microsoft.Diagnostics.Monitoring.WebApi { internal class CollectionRuleMetadata { - public string CollectionRuleName { get; set; } = string.Empty; // JSFIX + public string CollectionRuleName { get; set; } = string.Empty; public int ActionListIndex { get; set; } From 8ba4691daa740356cbd11fd52bc27b53178255d4 Mon Sep 17 00:00:00 2001 From: Joe Schmitt Date: Mon, 1 Jul 2024 15:19:52 -0700 Subject: [PATCH 04/20] Spelling --- .../DiagProcessFilter.cs | 2 +- src/Microsoft.Diagnostics.Monitoring.WebApi/DumpService.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Microsoft.Diagnostics.Monitoring.WebApi/DiagProcessFilter.cs b/src/Microsoft.Diagnostics.Monitoring.WebApi/DiagProcessFilter.cs index 9ac54121e81..59416a11175 100644 --- a/src/Microsoft.Diagnostics.Monitoring.WebApi/DiagProcessFilter.cs +++ b/src/Microsoft.Diagnostics.Monitoring.WebApi/DiagProcessFilter.cs @@ -96,7 +96,7 @@ private static DiagProcessFilterEntry TransformDescriptor(ProcessFilterDescripto }; } - string filterValue = processFilterDescriptor.Value!; // Guarenteed not to be null by ProcessFilterDescriptor.Validate. https://github.com/dotnet/dotnet-monitor/issues/6929. + string filterValue = processFilterDescriptor.Value!; // Guaranteed not to be null by ProcessFilterDescriptor.Validate. https://github.com/dotnet/dotnet-monitor/issues/6929. switch (processFilterDescriptor.Key) { case ProcessFilterKey.ProcessId: diff --git a/src/Microsoft.Diagnostics.Monitoring.WebApi/DumpService.cs b/src/Microsoft.Diagnostics.Monitoring.WebApi/DumpService.cs index aff4d8c2a62..37f374e2e88 100644 --- a/src/Microsoft.Diagnostics.Monitoring.WebApi/DumpService.cs +++ b/src/Microsoft.Diagnostics.Monitoring.WebApi/DumpService.cs @@ -36,7 +36,7 @@ public async Task DumpAsync(IEndpointInfo endpointInfo, Models.DumpType throw new ArgumentNullException(nameof(endpointInfo)); } - // Guarenteed to not be null by StoragePostConfigureOptions.PostConfigure. https://github.com/dotnet/dotnet-monitor/issues/6929. + // Guaranteed to not be null by StoragePostConfigureOptions.PostConfigure. https://github.com/dotnet/dotnet-monitor/issues/6929. string dumpTempFolder = _storageOptions.CurrentValue.DumpTempFolder!; // Ensure folder exists before issue command. From f08aefb15d62e3e22fc6a698a530de6cf4c58313 Mon Sep 17 00:00:00 2001 From: Joe Schmitt Date: Mon, 1 Jul 2024 15:57:32 -0700 Subject: [PATCH 05/20] Fix build --- .../CollectionRules/Options/CollectionRuleOptions.cs | 4 +++- .../Options/Triggers/AspNetResponseStatusOptions.cs | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/Tools/dotnet-monitor/CollectionRules/Options/CollectionRuleOptions.cs b/src/Tools/dotnet-monitor/CollectionRules/Options/CollectionRuleOptions.cs index 791c81f801d..607f9e735a5 100644 --- a/src/Tools/dotnet-monitor/CollectionRules/Options/CollectionRuleOptions.cs +++ b/src/Tools/dotnet-monitor/CollectionRules/Options/CollectionRuleOptions.cs @@ -19,11 +19,13 @@ internal sealed partial class CollectionRuleOptions Description = nameof(OptionsDisplayStrings.DisplayAttributeDescription_CollectionRuleOptions_Filters))] public List? Filters { get; } = new List(0); +#nullable disable [Display( ResourceType = typeof(OptionsDisplayStrings), Description = nameof(OptionsDisplayStrings.DisplayAttributeDescription_CollectionRuleOptions_Trigger))] [Required] - public CollectionRuleTriggerOptions Trigger { get; set; } = new(); + public CollectionRuleTriggerOptions Trigger { get; set; } +#nullable enable [Display( ResourceType = typeof(OptionsDisplayStrings), diff --git a/src/Tools/dotnet-monitor/CollectionRules/Options/Triggers/AspNetResponseStatusOptions.cs b/src/Tools/dotnet-monitor/CollectionRules/Options/Triggers/AspNetResponseStatusOptions.cs index 01f85593abf..9f998a007cf 100644 --- a/src/Tools/dotnet-monitor/CollectionRules/Options/Triggers/AspNetResponseStatusOptions.cs +++ b/src/Tools/dotnet-monitor/CollectionRules/Options/Triggers/AspNetResponseStatusOptions.cs @@ -19,6 +19,7 @@ internal sealed class AspNetResponseStatusOptions : private const string StatusCodeRegex = "[1-5][0-9]{2}"; private const string StatusCodesRegex = StatusCodeRegex + "(-" + StatusCodeRegex + ")?"; +#nullable disable [Display( ResourceType = typeof(OptionsDisplayStrings), Description = nameof(OptionsDisplayStrings.DisplayAttributeDescription_AspNetResponseStatusOptions_StatusCodes))] @@ -27,7 +28,8 @@ internal sealed class AspNetResponseStatusOptions : [RegularExpressions(StatusCodesRegex, ErrorMessageResourceType = typeof(OptionsDisplayStrings), ErrorMessageResourceName = nameof(OptionsDisplayStrings.ErrorMessage_StatusCodesRegularExpressionDoesNotMatch))] - public string[] StatusCodes { get; set; } = []; + public string[] StatusCodes { get; set; } +#nullable enable [Display( ResourceType = typeof(OptionsDisplayStrings), From 7da8781b75d7c054034e4727ae1453571a22d8d1 Mon Sep 17 00:00:00 2001 From: Joe Schmitt Date: Mon, 1 Jul 2024 16:01:01 -0700 Subject: [PATCH 06/20] Fix build --- .../Metrics/MetricsSettingsFactory.cs | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/Microsoft.Diagnostics.Monitoring.WebApi/Metrics/MetricsSettingsFactory.cs b/src/Microsoft.Diagnostics.Monitoring.WebApi/Metrics/MetricsSettingsFactory.cs index 06cbe409fa4..3deb2d8d3dc 100644 --- a/src/Microsoft.Diagnostics.Monitoring.WebApi/Metrics/MetricsSettingsFactory.cs +++ b/src/Microsoft.Diagnostics.Monitoring.WebApi/Metrics/MetricsSettingsFactory.cs @@ -54,7 +54,7 @@ public static MetricsPipelineSettings CreateSettings(GlobalCounterOptions counte private static MetricsPipelineSettings CreateSettings(bool includeDefaults, int durationSeconds, float counterInterval, - IDictionary intervalMap, + IDictionary? intervalMap, int maxHistograms, int maxTimeSeries, Func> createCounterGroups) @@ -68,12 +68,15 @@ private static MetricsPipelineSettings CreateSettings(bool includeDefaults, eventPipeCounterGroups.Add(new EventPipeCounterGroup { ProviderName = MonitoringSourceConfiguration.GrpcAspNetCoreServer, Type = CounterGroupType.EventCounter }); } - foreach (EventPipeCounterGroup counterGroup in eventPipeCounterGroups) + if (intervalMap != null) { - if (intervalMap.TryGetValue(counterGroup.ProviderName, out GlobalProviderOptions? providerInterval)) + foreach (EventPipeCounterGroup counterGroup in eventPipeCounterGroups) { - Debug.Assert(counterGroup.IntervalSeconds == null, "Unexpected value for provider interval"); - counterGroup.IntervalSeconds = providerInterval.IntervalSeconds; + if (intervalMap.TryGetValue(counterGroup.ProviderName, out GlobalProviderOptions? providerInterval)) + { + Debug.Assert(counterGroup.IntervalSeconds == null, "Unexpected value for provider interval"); + counterGroup.IntervalSeconds = providerInterval.IntervalSeconds; + } } } @@ -87,7 +90,7 @@ private static MetricsPipelineSettings CreateSettings(bool includeDefaults, }; } - private static List ConvertCounterGroups(IList providers, IList meters) + private static List ConvertCounterGroups(IList? providers, IList? meters) { List counterGroups = new(); From 014c52f7fa544bacc123132ad873a22471cd8566 Mon Sep 17 00:00:00 2001 From: Joe Schmitt Date: Mon, 1 Jul 2024 16:02:52 -0700 Subject: [PATCH 07/20] Remove comments --- .../DiagProcessFilter.cs | 2 +- src/Microsoft.Diagnostics.Monitoring.WebApi/DumpService.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Microsoft.Diagnostics.Monitoring.WebApi/DiagProcessFilter.cs b/src/Microsoft.Diagnostics.Monitoring.WebApi/DiagProcessFilter.cs index 59416a11175..3a0bd01b849 100644 --- a/src/Microsoft.Diagnostics.Monitoring.WebApi/DiagProcessFilter.cs +++ b/src/Microsoft.Diagnostics.Monitoring.WebApi/DiagProcessFilter.cs @@ -96,7 +96,7 @@ private static DiagProcessFilterEntry TransformDescriptor(ProcessFilterDescripto }; } - string filterValue = processFilterDescriptor.Value!; // Guaranteed not to be null by ProcessFilterDescriptor.Validate. https://github.com/dotnet/dotnet-monitor/issues/6929. + string filterValue = processFilterDescriptor.Value!; // Guaranteed not to be null by ProcessFilterDescriptor.Validate. switch (processFilterDescriptor.Key) { case ProcessFilterKey.ProcessId: diff --git a/src/Microsoft.Diagnostics.Monitoring.WebApi/DumpService.cs b/src/Microsoft.Diagnostics.Monitoring.WebApi/DumpService.cs index 37f374e2e88..358ee7745d7 100644 --- a/src/Microsoft.Diagnostics.Monitoring.WebApi/DumpService.cs +++ b/src/Microsoft.Diagnostics.Monitoring.WebApi/DumpService.cs @@ -36,7 +36,7 @@ public async Task DumpAsync(IEndpointInfo endpointInfo, Models.DumpType throw new ArgumentNullException(nameof(endpointInfo)); } - // Guaranteed to not be null by StoragePostConfigureOptions.PostConfigure. https://github.com/dotnet/dotnet-monitor/issues/6929. + // Guaranteed to not be null by StoragePostConfigureOptions.PostConfigure. string dumpTempFolder = _storageOptions.CurrentValue.DumpTempFolder!; // Ensure folder exists before issue command. From ca3e8981104e0c044272465619ddc2c7cdcbcd9c Mon Sep 17 00:00:00 2001 From: Joe Schmitt Date: Mon, 1 Jul 2024 16:18:03 -0700 Subject: [PATCH 08/20] Fix GetOrigins --- .../CorsConfigurationOptions.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.Diagnostics.Monitoring.Options/CorsConfigurationOptions.cs b/src/Microsoft.Diagnostics.Monitoring.Options/CorsConfigurationOptions.cs index 325293a3454..86398d68b90 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(';'); } } From 8b400c9d1b7575cfc030367109407dfefab2e7ed Mon Sep 17 00:00:00 2001 From: Joe Schmitt Date: Tue, 2 Jul 2024 11:21:05 -0700 Subject: [PATCH 09/20] Port dotnet-monitor tool --- .../CorsConfigurationOptions.cs | 2 +- .../ExceptionsDebugOptionsExtensions.cs | 2 +- .../Controllers/DiagController.cs | 4 +- .../Exceptions/ExceptionInstance.cs | 2 +- .../Exceptions/ExceptionsSettingsFactory.cs | 2 +- .../ICollectionRuleService.cs | 2 +- .../ITraceOperationFactory.cs | 2 +- ...ics.Monitoring.Tool.FunctionalTests.csproj | 1 + .../EgressExtensibilityTests.cs | 9 +++-- .../dotnet-monitor/ActivityExtensions.cs | 6 +-- .../dotnet-monitor/AddressListenResults.cs | 4 +- .../AddressListenResultsStartupLogger.cs | 5 ++- .../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 | 12 +++--- .../Auth/AuthConfiguratorFactory.cs | 4 +- .../CollectionRules/ActionListExecutor.cs | 13 +++--- .../ActionOptionsDependencyAnalyzer.cs | 31 +++++++++----- .../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 | 15 +++---- .../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 +++- .../IEgressProviderProperties.cs | 2 + .../Options/CollectionRuleOptions.Validate.cs | 2 + ...faultCollectionRulePostConfigureOptions.cs | 16 ++++---- .../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 | 10 ++--- src/Tools/dotnet-monitor/ConvertUtils.cs | 17 ++++++++ .../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 | 2 + .../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 | 8 ++-- .../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 | 17 ++++++++ .../dotnet-monitor/dotnet-monitor.csproj | 1 + 128 files changed, 501 insertions(+), 312 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/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 92011a5354d..3b7f6d99924 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/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/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/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..3f18083fb41 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,10 +54,10 @@ public void Log() } } +#nullable disable private void OnStarted() { IServerAddressesFeature serverAddresses = _server.Features.Get(); - // This logging allows the tool to differentiate which addresses // are default address and which are metrics addresses. @@ -69,5 +71,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..b7e7bb9507f 100644 --- a/src/Tools/dotnet-monitor/Auth/ApiKey/UserAuthorizationHandler.cs +++ b/src/Tools/dotnet-monitor/Auth/ApiKey/UserAuthorizationHandler.cs @@ -26,18 +26,20 @@ public UserAuthorizationHandler(IOptionsMonitor apiK protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, AuthorizedUserRequirement requirement) { - if (context.User.Identity.AuthenticationType == AuthConstants.FederationAuthType) + 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) || - (context.User.Identity.AuthenticationType == AuthConstants.NegotiateSchema)) + else if ((context.User?.Identity?.AuthenticationType == AuthConstants.NtlmSchema) || + (context.User?.Identity?.AuthenticationType == AuthConstants.KerberosSchema) || + (context.User?.Identity?.AuthenticationType == AuthConstants.NegotiateSchema)) { // Only supported on Windows if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) @@ -57,7 +59,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..f95a18e0fd1 100644 --- a/src/Tools/dotnet-monitor/CollectionRules/ActionListExecutor.cs +++ b/src/Tools/dotnet-monitor/CollectionRules/ActionListExecutor.cs @@ -46,8 +46,9 @@ public async Task> ExecuteAction }; int actionIndex = 0; +#nullable disable List deferredCompletions = new(context.Options.Actions.Count); - +#nullable restore var actionResults = new Dictionary(StringComparer.Ordinal); var dependencyAnalyzer = ActionOptionsDependencyAnalyzer.Create(context); @@ -58,7 +59,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 +92,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 +159,7 @@ public async Task> ExecuteAction } private async Task WaitForCompletion(CollectionRuleContext context, - Action startCallback, + Action? startCallback, IDictionary allResults, ICollectionRuleAction action, CollectionRuleActionOptions actionOption, @@ -178,7 +179,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..f72314e6336 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,6 +156,7 @@ 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..83a593a59ed 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,7 @@ protected override EgressOperation CreateArtifactOperation(CollectionRuleMetadat } else { - EventPipeProvider[] optionsProviders = Options.Providers.ToArray(); + EventPipeProvider[] optionsProviders = Options.Providers?.ToArray() ?? []; 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..5d7616b61cb 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,18 +164,19 @@ 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); @@ -242,7 +243,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 +252,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/CollectionRuleDefaultsInterfaces/IEgressProviderProperties.cs b/src/Tools/dotnet-monitor/CollectionRules/Options/CollectionRuleDefaultsInterfaces/IEgressProviderProperties.cs index 56c906eed69..16a18f8aafe 100644 --- a/src/Tools/dotnet-monitor/CollectionRules/Options/CollectionRuleDefaultsInterfaces/IEgressProviderProperties.cs +++ b/src/Tools/dotnet-monitor/CollectionRules/Options/CollectionRuleDefaultsInterfaces/IEgressProviderProperties.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 + namespace Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.CollectionRuleDefaultsInterfaces { internal interface IEgressProviderProperties 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..b1118abee5c 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,20 +32,22 @@ 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) { return; } - foreach (var action in options.Actions) + foreach (var action in options.Actions ?? []) { if (action.Settings is IEgressProviderProperties egressProviderProperties) { 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..75e4e2cc25e 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) { @@ -105,7 +105,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..4ea815bb8ed --- /dev/null +++ b/src/Tools/dotnet-monitor/ConvertUtils.cs @@ -0,0 +1,17 @@ +// 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.Diagnostics.CodeAnalysis; + +namespace Microsoft.Diagnostics.Tools.Monitor; + +internal static class ConvertUtils +{ + public static string ToString([NotNull] 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..10aa3ef46df 100644 --- a/src/Tools/dotnet-monitor/LoggingExtensions.cs +++ b/src/Tools/dotnet-monitor/LoggingExtensions.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 // JSFIX + using Microsoft.Diagnostics.Tools.Monitor.Extensibility; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; diff --git a/src/Tools/dotnet-monitor/MetricsPortsProvider.cs b/src/Tools/dotnet-monitor/MetricsPortsProvider.cs index 2ed061d420e..26fdc85a295 100644 --- a/src/Tools/dotnet-monitor/MetricsPortsProvider.cs +++ b/src/Tools/dotnet-monitor/MetricsPortsProvider.cs @@ -14,7 +14,9 @@ namespace Microsoft.Diagnostics.Tools.Monitor internal class MetricsPortsProvider : IMetricsPortsProvider { private readonly AddressListenResults _results; +#nullable disable private readonly IServerAddressesFeature _serverAddresses; +#nullable restore public MetricsPortsProvider(AddressListenResults results, IServer server) { diff --git a/src/Tools/dotnet-monitor/ParameterCapturing/CaptureParametersOperation.cs b/src/Tools/dotnet-monitor/ParameterCapturing/CaptureParametersOperation.cs index 12c32830bf8..5691e60fe95 100644 --- a/src/Tools/dotnet-monitor/ParameterCapturing/CaptureParametersOperation.cs +++ b/src/Tools/dotnet-monitor/ParameterCapturing/CaptureParametersOperation.cs @@ -94,20 +94,20 @@ static Exception getNotAvailableException(string reason) IDictionary 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..0adb77be4ae 100644 --- a/src/Tools/dotnet-monitor/StartupHook/StartupHookApplicator.cs +++ b/src/Tools/dotnet-monitor/StartupHook/StartupHookApplicator.cs @@ -49,13 +49,13 @@ public async Task ApplyAsync(string tfm, string fileName, CancellationToke } - if (_endpointInfo.RuntimeVersion.Major < 8) + if (_endpointInfo?.RuntimeVersion?.Major < 8) { _logger.StartupHookInstructions(_endpointInfo.ProcessId, fileInfo.Name, fileInfo.PhysicalPath); return false; } - 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 +66,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..7fae84a3467 --- /dev/null +++ b/src/Tools/dotnet-monitor/ValidationResultExtensions.cs @@ -0,0 +1,17 @@ +// 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 1e2ac9acd0c808994738ddececa66fe5160a4ed8 Mon Sep 17 00:00:00 2001 From: Joe Schmitt Date: Tue, 2 Jul 2024 11:34:31 -0700 Subject: [PATCH 10/20] Fix endpoint info --- .../DiagProcessFilter.cs | 6 +++--- .../IDiagnosticServices.cs | 6 +++--- .../CollectionRules/ActionOptionsDependencyAnalyzer.cs | 10 +++++----- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/Microsoft.Diagnostics.Monitoring.WebApi/DiagProcessFilter.cs b/src/Microsoft.Diagnostics.Monitoring.WebApi/DiagProcessFilter.cs index 3a0bd01b849..f0b6c7818b4 100644 --- a/src/Microsoft.Diagnostics.Monitoring.WebApi/DiagProcessFilter.cs +++ b/src/Microsoft.Diagnostics.Monitoring.WebApi/DiagProcessFilter.cs @@ -155,7 +155,7 @@ public bool MatchFilter(IProcessInfo processInfo) return false; } - private bool Compare(string value) + private bool Compare(string? value) { if (MatchType == DiagProcessFilterMatchType.Exact) { @@ -170,12 +170,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/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/Tools/dotnet-monitor/CollectionRules/ActionOptionsDependencyAnalyzer.cs b/src/Tools/dotnet-monitor/CollectionRules/ActionOptionsDependencyAnalyzer.cs index f72314e6336..dcfab2c920b 100644 --- a/src/Tools/dotnet-monitor/CollectionRules/ActionOptionsDependencyAnalyzer.cs +++ b/src/Tools/dotnet-monitor/CollectionRules/ActionOptionsDependencyAnalyzer.cs @@ -158,15 +158,15 @@ public IList GetActionDependencies(int actionIndex) } #nullable restore } - string commandLine = _ruleContext.EndpointInfo?.CommandLine ?? string.Empty; + string? commandLine = _ruleContext.EndpointInfo.CommandLine; settings = _tokenParser.SubstituteOptionValues(settings, new TokenContext { CloneOnSubstitution = ReferenceEquals(originalSettings, settings), - RuntimeId = _ruleContext.EndpointInfo?.RuntimeInstanceCookie ?? Guid.Empty, - ProcessId = _ruleContext.EndpointInfo?.ProcessId ?? 0, - CommandLine = commandLine, - ProcessName = _ruleContext.ProcessInfo?.ProcessName ?? string.Empty + RuntimeId = _ruleContext.EndpointInfo.RuntimeInstanceCookie, + ProcessId = _ruleContext.EndpointInfo.ProcessId, + CommandLine = commandLine ?? string.Empty, + ProcessName = _ruleContext.ProcessInfo.ProcessName ?? string.Empty }); return settings; From 0d254a7de5c7e5e67f6fc47d0928a33465252fd0 Mon Sep 17 00:00:00 2001 From: Joe Schmitt Date: Tue, 2 Jul 2024 11:37:01 -0700 Subject: [PATCH 11/20] Fix tests --- .../ActionDependencyAnalyzerTests.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) 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); From 21946801187ee088898e833e6908cd881e51008d Mon Sep 17 00:00:00 2001 From: Joe Schmitt Date: Tue, 2 Jul 2024 11:57:39 -0700 Subject: [PATCH 12/20] Port logger --- src/Tools/dotnet-monitor/LoggingExtensions.cs | 146 +++++++++--------- .../StartupHook/StartupHookApplicator.cs | 2 +- 2 files changed, 74 insertions(+), 74 deletions(-) diff --git a/src/Tools/dotnet-monitor/LoggingExtensions.cs b/src/Tools/dotnet-monitor/LoggingExtensions.cs index 10aa3ef46df..22523777625 100644 --- a/src/Tools/dotnet-monitor/LoggingExtensions.cs +++ b/src/Tools/dotnet-monitor/LoggingExtensions.cs @@ -1,8 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -#nullable disable // JSFIX - using Microsoft.Diagnostics.Tools.Monitor.Extensibility; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; @@ -16,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, @@ -382,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, @@ -406,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, @@ -418,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, @@ -442,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, @@ -484,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, @@ -590,7 +588,9 @@ public static void ApiKeyValidationFailures(this ILogger logger, IEnumerable ApplyAsync(string tfm, string fileName, CancellationToke } - if (_endpointInfo?.RuntimeVersion?.Major < 8) + if (_endpointInfo.RuntimeVersion?.Major < 8) { _logger.StartupHookInstructions(_endpointInfo.ProcessId, fileInfo.Name, fileInfo.PhysicalPath); return false; From fbf5ca20b97fd4ae071ac8b8810c7167f9de03c1 Mon Sep 17 00:00:00 2001 From: Joe Schmitt Date: Tue, 2 Jul 2024 14:13:22 -0700 Subject: [PATCH 13/20] Fix build --- src/Tools/dotnet-monitor/ConfigurationTokenParser.cs | 2 ++ src/Tools/dotnet-monitor/StartupHook/StartupHookApplicator.cs | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/Tools/dotnet-monitor/ConfigurationTokenParser.cs b/src/Tools/dotnet-monitor/ConfigurationTokenParser.cs index 75e4e2cc25e..6fce6ead540 100644 --- a/src/Tools/dotnet-monitor/ConfigurationTokenParser.cs +++ b/src/Tools/dotnet-monitor/ConfigurationTokenParser.cs @@ -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; } diff --git a/src/Tools/dotnet-monitor/StartupHook/StartupHookApplicator.cs b/src/Tools/dotnet-monitor/StartupHook/StartupHookApplicator.cs index a91e63a48ad..1077f4ffe4a 100644 --- a/src/Tools/dotnet-monitor/StartupHook/StartupHookApplicator.cs +++ b/src/Tools/dotnet-monitor/StartupHook/StartupHookApplicator.cs @@ -51,7 +51,9 @@ public async Task ApplyAsync(string tfm, string fileName, CancellationToke if (_endpointInfo.RuntimeVersion?.Major < 8) { +#nullable disable _logger.StartupHookInstructions(_endpointInfo.ProcessId, fileInfo.Name, fileInfo.PhysicalPath); +#nullable restore return false; } From 63f0fdbd431b38657a0e043f030b62deb30e7cb8 Mon Sep 17 00:00:00 2001 From: Joe Schmitt Date: Tue, 2 Jul 2024 14:26:19 -0700 Subject: [PATCH 14/20] Fix test --- .../ActionListExecutorTests.cs | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) 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++; From e912ca5bd8752436f2c4e97cac5eeb515319792b Mon Sep 17 00:00:00 2001 From: Joe Schmitt Date: Tue, 2 Jul 2024 15:29:13 -0700 Subject: [PATCH 15/20] PR feedback --- .../DiagProcessFilter.cs | 8 ++++++-- .../Exceptions/ExceptionsSettingsFactory.cs | 14 ++++++++++---- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/src/Microsoft.Diagnostics.Monitoring.WebApi/DiagProcessFilter.cs b/src/Microsoft.Diagnostics.Monitoring.WebApi/DiagProcessFilter.cs index 3a0bd01b849..3a417960008 100644 --- a/src/Microsoft.Diagnostics.Monitoring.WebApi/DiagProcessFilter.cs +++ b/src/Microsoft.Diagnostics.Monitoring.WebApi/DiagProcessFilter.cs @@ -39,10 +39,14 @@ public static DiagProcessFilter FromConfiguration(ProcessFilterOptions options) public static DiagProcessFilter FromConfiguration(IEnumerable? filters) { var filter = new DiagProcessFilter(); - foreach (ProcessFilterDescriptor processFilter in filters ?? []) + if (filters != null) { - filter.Filters.Add(TransformDescriptor(processFilter)); + foreach (ProcessFilterDescriptor processFilter in filters) + { + filter.Filters.Add(TransformDescriptor(processFilter)); + } } + return filter; } diff --git a/src/Microsoft.Diagnostics.Monitoring.WebApi/Exceptions/ExceptionsSettingsFactory.cs b/src/Microsoft.Diagnostics.Monitoring.WebApi/Exceptions/ExceptionsSettingsFactory.cs index 92011a5354d..55a6ff5b25c 100644 --- a/src/Microsoft.Diagnostics.Monitoring.WebApi/Exceptions/ExceptionsSettingsFactory.cs +++ b/src/Microsoft.Diagnostics.Monitoring.WebApi/Exceptions/ExceptionsSettingsFactory.cs @@ -19,14 +19,20 @@ public static ExceptionsConfigurationSettings ConvertExceptionsConfiguration(Exc return configurationSettings; } - foreach (var filter in configuration.Include ?? []) + if (configuration.Include != null) { - configurationSettings.Include.Add(ConvertExceptionFilter(filter)); + foreach (var filter in configuration.Include) + { + configurationSettings.Include.Add(ConvertExceptionFilter(filter)); + } } - foreach (var filter in configuration.Exclude ?? []) + if (configuration.Exclude != null) { - configurationSettings.Exclude.Add(ConvertExceptionFilter(filter)); + foreach (var filter in configuration.Exclude) + { + configurationSettings.Exclude.Add(ConvertExceptionFilter(filter)); + } } return configurationSettings; From bd9f95ea3f8cf845533dbca172057dbb73ae3553 Mon Sep 17 00:00:00 2001 From: Joe Schmitt Date: Tue, 2 Jul 2024 16:04:48 -0700 Subject: [PATCH 16/20] PR feedback --- .../CollectionRules/Options/CollectionRuleOptions.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Tools/dotnet-monitor/CollectionRules/Options/CollectionRuleOptions.cs b/src/Tools/dotnet-monitor/CollectionRules/Options/CollectionRuleOptions.cs index 607f9e735a5..835d57e7d49 100644 --- a/src/Tools/dotnet-monitor/CollectionRules/Options/CollectionRuleOptions.cs +++ b/src/Tools/dotnet-monitor/CollectionRules/Options/CollectionRuleOptions.cs @@ -17,7 +17,7 @@ internal sealed partial class CollectionRuleOptions [Display( ResourceType = typeof(OptionsDisplayStrings), Description = nameof(OptionsDisplayStrings.DisplayAttributeDescription_CollectionRuleOptions_Filters))] - public List? Filters { get; } = new List(0); + public List Filters { get; } = new List(0); #nullable disable [Display( @@ -30,7 +30,7 @@ internal sealed partial class CollectionRuleOptions [Display( ResourceType = typeof(OptionsDisplayStrings), Description = nameof(OptionsDisplayStrings.DisplayAttributeDescription_CollectionRuleOptions_Actions))] - public List? Actions { get; } = new List(0); + public List Actions { get; } = new List(0); [Display( ResourceType = typeof(OptionsDisplayStrings), From c8102baf2a78bef22396f3e9a05fe40e41ed46e4 Mon Sep 17 00:00:00 2001 From: Joe Schmitt Date: Tue, 2 Jul 2024 16:30:22 -0700 Subject: [PATCH 17/20] Reconcile merge --- .../CollectionRules/ActionListExecutor.cs | 3 +-- .../CollectionRuleContainer.cs | 21 ++++++++----------- 2 files changed, 10 insertions(+), 14 deletions(-) diff --git a/src/Tools/dotnet-monitor/CollectionRules/ActionListExecutor.cs b/src/Tools/dotnet-monitor/CollectionRules/ActionListExecutor.cs index f95a18e0fd1..bafe19a5390 100644 --- a/src/Tools/dotnet-monitor/CollectionRules/ActionListExecutor.cs +++ b/src/Tools/dotnet-monitor/CollectionRules/ActionListExecutor.cs @@ -46,9 +46,8 @@ public async Task> ExecuteAction }; int actionIndex = 0; -#nullable disable List deferredCompletions = new(context.Options.Actions.Count); -#nullable restore + var actionResults = new Dictionary(StringComparer.Ordinal); var dependencyAnalyzer = ActionOptionsDependencyAnalyzer.Create(context); diff --git a/src/Tools/dotnet-monitor/CollectionRules/CollectionRuleContainer.cs b/src/Tools/dotnet-monitor/CollectionRules/CollectionRuleContainer.cs index 5d7616b61cb..2565190a5a9 100644 --- a/src/Tools/dotnet-monitor/CollectionRules/CollectionRuleContainer.cs +++ b/src/Tools/dotnet-monitor/CollectionRules/CollectionRuleContainer.cs @@ -181,21 +181,18 @@ private async Task RunRuleAsync( { 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); From ac3b6b82b7ca6fa29e2db20f9fee3b038fedee90 Mon Sep 17 00:00:00 2001 From: Joe Schmitt Date: Wed, 3 Jul 2024 10:13:43 -0700 Subject: [PATCH 18/20] Standardize schema --- documentation/schema.json | 45 ++++--------------- .../ExceptionsConfiguration.cs | 4 +- .../MetricsOptions.cs | 8 ++-- .../ProcessFilterOptions.cs | 2 +- .../Exceptions/ExceptionsSettingsFactory.cs | 14 ++---- .../Options/CollectionRuleOptions.cs | 4 +- 6 files changed, 22 insertions(+), 55 deletions(-) diff --git a/documentation/schema.json b/documentation/schema.json index 6d29cb04540..36cff6187fc 100644 --- a/documentation/schema.json +++ b/documentation/schema.json @@ -513,10 +513,7 @@ ], "properties": { "Filters": { - "type": [ - "array", - "null" - ], + "type": "array", "description": "Process filters used to determine to which process(es) the collection rule is applied. All filters must match. If no filters are specified, the rule is applied to all discovered processes.", "items": { "$ref": "#/definitions/ProcessFilterDescriptor" @@ -531,10 +528,7 @@ ] }, "Actions": { - "type": [ - "array", - "null" - ], + "type": "array", "description": "The list of actions to be executed when the trigger raises its notification.", "items": { "$ref": "#/definitions/CollectionRuleActionOptions" @@ -1130,20 +1124,14 @@ "additionalProperties": false, "properties": { "Include": { - "type": [ - "array", - "null" - ], + "type": "array", "description": "The list of exception configurations that determine which exceptions should be shown.\nEach configuration is a logical OR, so if any of the configurations match, the exception is shown.", "items": { "$ref": "#/definitions/ExceptionFilter" } }, "Exclude": { - "type": [ - "array", - "null" - ], + "type": "array", "description": "The list of exception configurations that determine which exceptions should be shown.\nEach configuration is a logical OR, so if any of the configurations match, the exception isn't shown.", "items": { "$ref": "#/definitions/ExceptionFilter" @@ -1384,20 +1372,14 @@ "default": true }, "Providers": { - "type": [ - "array", - "null" - ], + "type": "array", "description": "Providers for custom metrics.", "items": { "$ref": "#/definitions/MetricProvider" } }, "Meters": { - "type": [ - "array", - "null" - ], + "type": "array", "description": "Names of meters to collect from the System.Diagnostics.Metrics provider.", "items": { "$ref": "#/definitions/MeterConfiguration" @@ -1418,10 +1400,7 @@ "minLength": 1 }, "CounterNames": { - "type": [ - "array", - "null" - ], + "type": "array", "description": "Name of custom metrics counters.", "items": { "type": "string" @@ -1441,10 +1420,7 @@ "description": "Name of the custom meter." }, "InstrumentNames": { - "type": [ - "array", - "null" - ], + "type": "array", "description": "Names of the custom instruments.", "items": { "type": "string" @@ -1484,10 +1460,7 @@ "additionalProperties": false, "properties": { "Filters": { - "type": [ - "array", - "null" - ], + "type": "array", "description": "Process filters used to determine which process to use if one is not explicitly specified. All filters must match.", "items": { "$ref": "#/definitions/ProcessFilterDescriptor" diff --git a/src/Microsoft.Diagnostics.Monitoring.Options/ExceptionsConfiguration.cs b/src/Microsoft.Diagnostics.Monitoring.Options/ExceptionsConfiguration.cs index 8a44b0c7ae1..709562981f4 100644 --- a/src/Microsoft.Diagnostics.Monitoring.Options/ExceptionsConfiguration.cs +++ b/src/Microsoft.Diagnostics.Monitoring.Options/ExceptionsConfiguration.cs @@ -13,14 +13,14 @@ public sealed class ExceptionsConfiguration /// Each configuration is a logical OR, so if any of the configurations match, the exception is shown. /// [JsonPropertyName("include")] - public List? Include { get; set; } = new(); + public List Include { get; set; } = []; /// /// The list of exception configurations that determine which exceptions should be shown. /// Each configuration is a logical OR, so if any of the configurations match, the exception isn't shown. /// [JsonPropertyName("exclude")] - public List? Exclude { get; set; } = new(); + public List Exclude { get; set; } = []; } public sealed class ExceptionFilter diff --git a/src/Microsoft.Diagnostics.Monitoring.Options/MetricsOptions.cs b/src/Microsoft.Diagnostics.Monitoring.Options/MetricsOptions.cs index 1450284480e..faa647690f3 100644 --- a/src/Microsoft.Diagnostics.Monitoring.Options/MetricsOptions.cs +++ b/src/Microsoft.Diagnostics.Monitoring.Options/MetricsOptions.cs @@ -43,12 +43,12 @@ public class MetricsOptions [Display( ResourceType = typeof(OptionsDisplayStrings), Description = nameof(OptionsDisplayStrings.DisplayAttributeDescription_MetricsOptions_Providers))] - public List? Providers { get; set; } = new List(0); + public List Providers { get; set; } = []; [Display( ResourceType = typeof(OptionsDisplayStrings), Description = nameof(OptionsDisplayStrings.DisplayAttributeDescription_MetricsOptions_Meters))] - public List? Meters { get; set; } = new List(0); + public List Meters { get; set; } = []; } public class MetricProvider @@ -62,7 +62,7 @@ public class MetricProvider [Display( ResourceType = typeof(OptionsDisplayStrings), Description = nameof(OptionsDisplayStrings.DisplayAttributeDescription_MetricProvider_CounterNames))] - public List? CounterNames { get; set; } = new List(0); + public List CounterNames { get; set; } = []; } public class MeterConfiguration @@ -75,6 +75,6 @@ public class MeterConfiguration [Display( ResourceType = typeof(OptionsDisplayStrings), Description = nameof(OptionsDisplayStrings.DisplayAttributeDescription_MeterConfiguration_InstrumentNames))] - public List? InstrumentNames { get; set; } = new List(0); + public List InstrumentNames { get; set; } = []; } } diff --git a/src/Microsoft.Diagnostics.Monitoring.Options/ProcessFilterOptions.cs b/src/Microsoft.Diagnostics.Monitoring.Options/ProcessFilterOptions.cs index cc6f88ab22b..f8a90738658 100644 --- a/src/Microsoft.Diagnostics.Monitoring.Options/ProcessFilterOptions.cs +++ b/src/Microsoft.Diagnostics.Monitoring.Options/ProcessFilterOptions.cs @@ -41,7 +41,7 @@ public sealed class ProcessFilterOptions [Display( ResourceType = typeof(OptionsDisplayStrings), Description = nameof(OptionsDisplayStrings.DisplayAttributeDescription_ProcessFilterOptions_Filters))] - public List? Filters { get; set; } = new List(0); + public List Filters { get; set; } = []; } public sealed partial class ProcessFilterDescriptor diff --git a/src/Microsoft.Diagnostics.Monitoring.WebApi/Exceptions/ExceptionsSettingsFactory.cs b/src/Microsoft.Diagnostics.Monitoring.WebApi/Exceptions/ExceptionsSettingsFactory.cs index 55a6ff5b25c..465f1bce77d 100644 --- a/src/Microsoft.Diagnostics.Monitoring.WebApi/Exceptions/ExceptionsSettingsFactory.cs +++ b/src/Microsoft.Diagnostics.Monitoring.WebApi/Exceptions/ExceptionsSettingsFactory.cs @@ -19,20 +19,14 @@ public static ExceptionsConfigurationSettings ConvertExceptionsConfiguration(Exc return configurationSettings; } - if (configuration.Include != null) + foreach (var filter in configuration.Include) { - foreach (var filter in configuration.Include) - { - configurationSettings.Include.Add(ConvertExceptionFilter(filter)); - } + configurationSettings.Include.Add(ConvertExceptionFilter(filter)); } - if (configuration.Exclude != null) + foreach (var filter in configuration.Exclude) { - foreach (var filter in configuration.Exclude) - { - configurationSettings.Exclude.Add(ConvertExceptionFilter(filter)); - } + configurationSettings.Exclude.Add(ConvertExceptionFilter(filter)); } return configurationSettings; diff --git a/src/Tools/dotnet-monitor/CollectionRules/Options/CollectionRuleOptions.cs b/src/Tools/dotnet-monitor/CollectionRules/Options/CollectionRuleOptions.cs index 607f9e735a5..128848d3bd3 100644 --- a/src/Tools/dotnet-monitor/CollectionRules/Options/CollectionRuleOptions.cs +++ b/src/Tools/dotnet-monitor/CollectionRules/Options/CollectionRuleOptions.cs @@ -17,7 +17,7 @@ internal sealed partial class CollectionRuleOptions [Display( ResourceType = typeof(OptionsDisplayStrings), Description = nameof(OptionsDisplayStrings.DisplayAttributeDescription_CollectionRuleOptions_Filters))] - public List? Filters { get; } = new List(0); + public List Filters { get; set; } = []; #nullable disable [Display( @@ -30,7 +30,7 @@ internal sealed partial class CollectionRuleOptions [Display( ResourceType = typeof(OptionsDisplayStrings), Description = nameof(OptionsDisplayStrings.DisplayAttributeDescription_CollectionRuleOptions_Actions))] - public List? Actions { get; } = new List(0); + public List Actions { get; set; } = []; [Display( ResourceType = typeof(OptionsDisplayStrings), From c855da015aabbc4b212a2998938e168bb549f023 Mon Sep 17 00:00:00 2001 From: Joe Schmitt Date: Wed, 3 Jul 2024 10:56:51 -0700 Subject: [PATCH 19/20] Fixes --- src/Tools/dotnet-monitor/ConvertUtils.cs | 3 +-- src/Tools/dotnet-monitor/ValidationResultExtensions.cs | 1 - 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/Tools/dotnet-monitor/ConvertUtils.cs b/src/Tools/dotnet-monitor/ConvertUtils.cs index 4ea815bb8ed..f386b149580 100644 --- a/src/Tools/dotnet-monitor/ConvertUtils.cs +++ b/src/Tools/dotnet-monitor/ConvertUtils.cs @@ -4,13 +4,12 @@ #nullable enable using System; -using System.Diagnostics.CodeAnalysis; namespace Microsoft.Diagnostics.Tools.Monitor; internal static class ConvertUtils { - public static string ToString([NotNull] object value, IFormatProvider? provider) + 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/ValidationResultExtensions.cs b/src/Tools/dotnet-monitor/ValidationResultExtensions.cs index 7fae84a3467..308cd1074d9 100644 --- a/src/Tools/dotnet-monitor/ValidationResultExtensions.cs +++ b/src/Tools/dotnet-monitor/ValidationResultExtensions.cs @@ -4,7 +4,6 @@ using System.ComponentModel.DataAnnotations; using System.Diagnostics.CodeAnalysis; - namespace Microsoft.Diagnostics.Tools.Monitor { internal static class ValidationResultExtensions From 4f2b9b6955a259b67326fdd2a999f4904f7992e1 Mon Sep 17 00:00:00 2001 From: Joe Schmitt Date: Wed, 3 Jul 2024 11:12:53 -0700 Subject: [PATCH 20/20] Fixes --- .../AddressListenResultsStartupLogger.cs | 1 + .../Auth/ApiKey/UserAuthorizationHandler.cs | 13 +++++++++---- .../IEgressProviderProperties.cs | 2 -- .../DefaultCollectionRulePostConfigureOptions.cs | 2 +- .../StartupHook/StartupHookApplicator.cs | 5 ++--- 5 files changed, 13 insertions(+), 10 deletions(-) diff --git a/src/Tools/dotnet-monitor/AddressListenResultsStartupLogger.cs b/src/Tools/dotnet-monitor/AddressListenResultsStartupLogger.cs index 3f18083fb41..e1ab2d915d6 100644 --- a/src/Tools/dotnet-monitor/AddressListenResultsStartupLogger.cs +++ b/src/Tools/dotnet-monitor/AddressListenResultsStartupLogger.cs @@ -58,6 +58,7 @@ public void Log() private void OnStarted() { IServerAddressesFeature serverAddresses = _server.Features.Get(); + // This logging allows the tool to differentiate which addresses // are default address and which are metrics addresses. diff --git a/src/Tools/dotnet-monitor/Auth/ApiKey/UserAuthorizationHandler.cs b/src/Tools/dotnet-monitor/Auth/ApiKey/UserAuthorizationHandler.cs index b7e7bb9507f..bac15350948 100644 --- a/src/Tools/dotnet-monitor/Auth/ApiKey/UserAuthorizationHandler.cs +++ b/src/Tools/dotnet-monitor/Auth/ApiKey/UserAuthorizationHandler.cs @@ -26,7 +26,12 @@ public UserAuthorizationHandler(IOptionsMonitor apiK protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, AuthorizedUserRequirement requirement) { - if (context.User?.Identity?.AuthenticationType == AuthConstants.FederationAuthType) + 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; @@ -37,9 +42,9 @@ protected override Task HandleRequirementAsync(AuthorizationHandlerContext conte } #nullable restore } - else if ((context.User?.Identity?.AuthenticationType == AuthConstants.NtlmSchema) || - (context.User?.Identity?.AuthenticationType == AuthConstants.KerberosSchema) || - (context.User?.Identity?.AuthenticationType == AuthConstants.NegotiateSchema)) + else if ((context.User.Identity.AuthenticationType == AuthConstants.NtlmSchema) || + (context.User.Identity.AuthenticationType == AuthConstants.KerberosSchema) || + (context.User.Identity.AuthenticationType == AuthConstants.NegotiateSchema)) { // Only supported on Windows if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) diff --git a/src/Tools/dotnet-monitor/CollectionRules/Options/CollectionRuleDefaultsInterfaces/IEgressProviderProperties.cs b/src/Tools/dotnet-monitor/CollectionRules/Options/CollectionRuleDefaultsInterfaces/IEgressProviderProperties.cs index 16a18f8aafe..56c906eed69 100644 --- a/src/Tools/dotnet-monitor/CollectionRules/Options/CollectionRuleDefaultsInterfaces/IEgressProviderProperties.cs +++ b/src/Tools/dotnet-monitor/CollectionRules/Options/CollectionRuleDefaultsInterfaces/IEgressProviderProperties.cs @@ -1,8 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -#nullable enable - namespace Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.CollectionRuleDefaultsInterfaces { internal interface IEgressProviderProperties diff --git a/src/Tools/dotnet-monitor/CollectionRules/Options/DefaultCollectionRulePostConfigureOptions.cs b/src/Tools/dotnet-monitor/CollectionRules/Options/DefaultCollectionRulePostConfigureOptions.cs index b1118abee5c..879941d066c 100644 --- a/src/Tools/dotnet-monitor/CollectionRules/Options/DefaultCollectionRulePostConfigureOptions.cs +++ b/src/Tools/dotnet-monitor/CollectionRules/Options/DefaultCollectionRulePostConfigureOptions.cs @@ -39,7 +39,7 @@ private void ConfigureEgress(CollectionRuleOptions options) return; } - foreach (var action in options.Actions ?? []) + foreach (var action in options.Actions) { if (action.Settings is IEgressProviderProperties egressProviderProperties) { diff --git a/src/Tools/dotnet-monitor/StartupHook/StartupHookApplicator.cs b/src/Tools/dotnet-monitor/StartupHook/StartupHookApplicator.cs index 1077f4ffe4a..6623bc1e351 100644 --- a/src/Tools/dotnet-monitor/StartupHook/StartupHookApplicator.cs +++ b/src/Tools/dotnet-monitor/StartupHook/StartupHookApplicator.cs @@ -48,14 +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); }