diff --git a/Directory.Packages.props b/Directory.Packages.props index f37bd594e4c..7923f760fc8 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -7,8 +7,9 @@ - + + diff --git a/src/Directory.Build.targets b/src/Directory.Build.targets index b75f72b30b1..f79f7d13d44 100644 --- a/src/Directory.Build.targets +++ b/src/Directory.Build.targets @@ -126,4 +126,13 @@ + + + + + + + diff --git a/src/Microsoft.Diagnostics.Monitoring.Extension.Common/Microsoft.Diagnostics.Monitoring.Extension.Common.csproj b/src/Microsoft.Diagnostics.Monitoring.Extension.Common/Microsoft.Diagnostics.Monitoring.Extension.Common.csproj index 8879d6f8eb6..f9ada28f3cc 100644 --- a/src/Microsoft.Diagnostics.Monitoring.Extension.Common/Microsoft.Diagnostics.Monitoring.Extension.Common.csproj +++ b/src/Microsoft.Diagnostics.Monitoring.Extension.Common/Microsoft.Diagnostics.Monitoring.Extension.Common.csproj @@ -1,4 +1,4 @@ - + Library @@ -11,6 +11,7 @@ + diff --git a/src/Microsoft.Diagnostics.Monitoring.Options/AuthenticationOptions.Validate.cs b/src/Microsoft.Diagnostics.Monitoring.Options/AuthenticationOptions.Validate.cs index d684f739526..6b11722b7a1 100644 --- a/src/Microsoft.Diagnostics.Monitoring.Options/AuthenticationOptions.Validate.cs +++ b/src/Microsoft.Diagnostics.Monitoring.Options/AuthenticationOptions.Validate.cs @@ -20,7 +20,7 @@ IEnumerable IValidatableObject.Validate(ValidationContext vali results.Add( new ValidationResult( string.Format( - OptionsDisplayStrings.ErrorMessage_MultipleAuthenticationModesSpecified))); + OptionsDisplayStrings.ErrorMessage_MultipleAuthenticationModesSpecified), [nameof(MonitorApiKey), nameof(AzureAd)])); } return results; diff --git a/src/Microsoft.Diagnostics.Monitoring.Options/GlobalCounterOptions.cs b/src/Microsoft.Diagnostics.Monitoring.Options/GlobalCounterOptions.cs index c360b5184d1..ff3c222d629 100644 --- a/src/Microsoft.Diagnostics.Monitoring.Options/GlobalCounterOptions.cs +++ b/src/Microsoft.Diagnostics.Monitoring.Options/GlobalCounterOptions.cs @@ -64,7 +64,8 @@ public IEnumerable Validate(ValidationContext validationContex { // 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)))); + string.Format(CultureInfo.CurrentCulture, OptionsDisplayStrings.ErrorMessage_NestedProviderValidationError, provider, r.ErrorMessage), + [nameof(Providers)]))); } } } diff --git a/src/Tests/CollectionRuleActions.UnitTests/CollectionRuleActions.UnitTests.csproj b/src/Tests/CollectionRuleActions.UnitTests/CollectionRuleActions.UnitTests.csproj index aa0591b54fc..f98166d3e64 100644 --- a/src/Tests/CollectionRuleActions.UnitTests/CollectionRuleActions.UnitTests.csproj +++ b/src/Tests/CollectionRuleActions.UnitTests/CollectionRuleActions.UnitTests.csproj @@ -7,6 +7,7 @@ + @@ -14,6 +15,7 @@ + diff --git a/src/Tests/CollectionRuleActions.UnitTests/ExecuteActionTests.cs b/src/Tests/CollectionRuleActions.UnitTests/ExecuteActionTests.cs index e5bf473507b..5c062e23516 100644 --- a/src/Tests/CollectionRuleActions.UnitTests/ExecuteActionTests.cs +++ b/src/Tests/CollectionRuleActions.UnitTests/ExecuteActionTests.cs @@ -1,11 +1,15 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using Microsoft.AspNetCore.Http.Validation; +using Microsoft.AspNetCore.Mvc.Testing; using Microsoft.Diagnostics.Monitoring.TestCommon; using Microsoft.Diagnostics.Tools.Monitor; using Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Actions; using Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Exceptions; using Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Actions; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; using System; using System.Globalization; using System.IO; @@ -18,17 +22,23 @@ namespace CollectionRuleActions.UnitTests { + public class ExecuteActionFixture : WebApplicationFactory + { + } + [TargetFrameworkMonikerTrait(TargetFrameworkMonikerExtensions.CurrentTargetFrameworkMoniker)] [Collection(TestCollections.CollectionRuleActions)] - public sealed class ExecuteActionTests + public sealed class ExecuteActionTests : IClassFixture { private static readonly TimeSpan DefaultTimeout = TimeSpan.FromSeconds(30); private readonly ITestOutputHelper _outputHelper; + private readonly ExecuteActionFixture _fixture; - public ExecuteActionTests(ITestOutputHelper outputHelper) + public ExecuteActionTests(ITestOutputHelper outputHelper, ExecuteActionFixture fixture) { _outputHelper = outputHelper; + _fixture = fixture; } [Fact] @@ -173,9 +183,10 @@ private static void ValidateActionResult(CollectionRuleActionResult result, stri Assert.Equal(expectedExitCode, actualExitCode); } - private static async Task ValidateAction(Action optionsCallback, Func actionCallback) + private async Task ValidateAction(Action optionsCallback, Func actionCallback) { - ExecuteActionFactory factory = new(); + var validationOptions = _fixture.Services.GetService>(); + ExecuteActionFactory factory = new(_fixture.Services, validationOptions); ExecuteOptions options = new(); diff --git a/src/Tests/Microsoft.Diagnostics.Monitoring.Tool.FunctionalTests/AuthenticationTests.cs b/src/Tests/Microsoft.Diagnostics.Monitoring.Tool.FunctionalTests/AuthenticationTests.cs index e13ae742e76..555348cba9d 100644 --- a/src/Tests/Microsoft.Diagnostics.Monitoring.Tool.FunctionalTests/AuthenticationTests.cs +++ b/src/Tests/Microsoft.Diagnostics.Monitoring.Tool.FunctionalTests/AuthenticationTests.cs @@ -472,9 +472,6 @@ public async Task AllowsConfiguredIssuer() [Theory] // Guids that don't match should get rejected [InlineData("980d2b17-71e1-4313-a084-c077e962680c", "10253b7a-454d-41bb-a3f5-5f2e6b26ed93", HttpStatusCode.Forbidden)] - // Empty string isn't valid even when signed and configured correctly - [InlineData("", "", HttpStatusCode.Unauthorized)] - [InlineData("10253b7a-454d-41bb-a3f5-5f2e6b26ed93", "", HttpStatusCode.Unauthorized)] [InlineData("", "10253b7a-454d-41bb-a3f5-5f2e6b26ed93", HttpStatusCode.Forbidden)] public async Task RejectsBadSubject(string jwtSubject, string configSubject, HttpStatusCode expectedError) { @@ -501,6 +498,25 @@ public async Task RejectsBadSubject(string jwtSubject, string configSubject, Htt Assert.Equal(expectedError, statusCodeException.StatusCode); } + /// + /// This tests that an empty configured subject fails on startup. + /// + [Fact] + public async Task DoesNotStart_With_EmptySubject() + { + var configSubject = ""; + await using MonitorCollectRunner toolRunner = new(_outputHelper); + toolRunner.DisableMetricsViaCommandLine = true; + + _outputHelper.WriteLine("Generating API key."); + + JwtPayload newPayload = GetJwtPayload(AuthConstants.ApiKeyJwtAudience, configSubject, AuthConstants.ApiKeyJwtInternalIssuer, AuthConstants.ApiKeyJwtDefaultExpiration); + + toolRunner.ConfigurationFromEnvironment.UseApiKey(SecurityAlgorithms.EcdsaSha384, configSubject, newPayload, out string token); + + await Assert.ThrowsAsync(toolRunner.StartAsync); + } + [Fact] public async Task RejectsMissingExpiration() { diff --git a/src/Tests/Microsoft.Diagnostics.Monitoring.Tool.UnitTestCommon/Microsoft.Diagnostics.Monitoring.Tool.UnitTestCommon.csproj b/src/Tests/Microsoft.Diagnostics.Monitoring.Tool.UnitTestCommon/Microsoft.Diagnostics.Monitoring.Tool.UnitTestCommon.csproj index d8db2356aea..5f0b9f3f651 100644 --- a/src/Tests/Microsoft.Diagnostics.Monitoring.Tool.UnitTestCommon/Microsoft.Diagnostics.Monitoring.Tool.UnitTestCommon.csproj +++ b/src/Tests/Microsoft.Diagnostics.Monitoring.Tool.UnitTestCommon/Microsoft.Diagnostics.Monitoring.Tool.UnitTestCommon.csproj @@ -3,6 +3,7 @@ $(ToolTargetFrameworks) true + true diff --git a/src/Tests/Microsoft.Diagnostics.Monitoring.Tool.UnitTestCommon/TestHostHelper.cs b/src/Tests/Microsoft.Diagnostics.Monitoring.Tool.UnitTestCommon/TestHostHelper.cs index 02c48fa9433..795b4fb01e9 100644 --- a/src/Tests/Microsoft.Diagnostics.Monitoring.Tool.UnitTestCommon/TestHostHelper.cs +++ b/src/Tests/Microsoft.Diagnostics.Monitoring.Tool.UnitTestCommon/TestHostHelper.cs @@ -124,6 +124,8 @@ public static IHost CreateHost( services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); + ValidatableTypes.AddValidation(services); + TestValidatableTypes.AddValidation(services); servicesCallback?.Invoke(services); }) .Build(); diff --git a/src/Tests/Microsoft.Diagnostics.Monitoring.Tool.UnitTestCommon/TestValidatableType.cs b/src/Tests/Microsoft.Diagnostics.Monitoring.Tool.UnitTestCommon/TestValidatableType.cs new file mode 100644 index 00000000000..f2b2bd4ead0 --- /dev/null +++ b/src/Tests/Microsoft.Diagnostics.Monitoring.Tool.UnitTestCommon/TestValidatableType.cs @@ -0,0 +1,20 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Microsoft.AspNetCore.Http.Validation; +using Microsoft.AspNetCore.Http.Validation.Generated; +using Microsoft.Extensions.DependencyInjection; + +namespace Microsoft.Diagnostics.Monitoring.TestCommon +{ + [ValidatableType] + internal sealed class TestValidatableTypes + { + public required PassThroughOptions PassThroughOptions { get; init; } + + public static void AddValidation(IServiceCollection services) + { + TestGeneratedServiceCollectionExtensions.AddValidation(services); + } + } +} diff --git a/src/Tests/Microsoft.Diagnostics.Monitoring.Tool.UnitTestCommon/ValidatableInfoResolver.cs b/src/Tests/Microsoft.Diagnostics.Monitoring.Tool.UnitTestCommon/ValidatableInfoResolver.cs new file mode 100644 index 00000000000..06509a455b9 --- /dev/null +++ b/src/Tests/Microsoft.Diagnostics.Monitoring.Tool.UnitTestCommon/ValidatableInfoResolver.cs @@ -0,0 +1,743 @@ +#nullable enable annotations +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ +#nullable enable + +namespace System.Runtime.CompilerServices +{ + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.Http.ValidationsGenerator, Version=10.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60", "10.0.0.0")] + [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)] + file sealed class InterceptsLocationAttribute : System.Attribute + { + public InterceptsLocationAttribute(int version, string data) + { + } + } +} + +namespace Microsoft.AspNetCore.Http.Validation.Generated +{ + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.Http.ValidationsGenerator, Version=10.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60", "10.0.0.0")] + file sealed class GeneratedValidatablePropertyInfo : global::Microsoft.AspNetCore.Http.Validation.ValidatablePropertyInfo + { + public GeneratedValidatablePropertyInfo( + [param: global::System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembers(global::System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicProperties)] + global::System.Type containingType, + global::System.Type propertyType, + string name, + string displayName) : base(containingType, propertyType, name, displayName) + { + ContainingType = containingType; + Name = name; + } + + internal global::System.Type ContainingType { get; } + internal string Name { get; } + + protected override global::System.ComponentModel.DataAnnotations.ValidationAttribute[] GetValidationAttributes() + => ValidationAttributeCache.GetValidationAttributes(ContainingType, Name); + } + + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.Http.ValidationsGenerator, Version=10.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60", "10.0.0.0")] + file sealed class GeneratedValidatableTypeInfo : global::Microsoft.AspNetCore.Http.Validation.ValidatableTypeInfo + { + public GeneratedValidatableTypeInfo( + [param: global::System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembers(global::System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.Interfaces)] + global::System.Type type, + ValidatablePropertyInfo[] members) : base(type, members) { } + } + + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.Http.ValidationsGenerator, Version=10.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60", "10.0.0.0")] + file class GeneratedValidatableInfoResolver : global::Microsoft.AspNetCore.Http.Validation.IValidatableInfoResolver + { + public bool TryGetValidatableTypeInfo(global::System.Type type, [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] out global::Microsoft.AspNetCore.Http.Validation.IValidatableInfo? validatableInfo) + { + validatableInfo = null; + if (type == typeof(global::System.Reflection.MethodBase)) + { + validatableInfo = CreateMethodBase(); + return true; + } + if (type == typeof(global::System.Reflection.ConstructorInfo)) + { + validatableInfo = CreateConstructorInfo(); + return true; + } + if (type == typeof(global::System.Reflection.CustomAttributeTypedArgument)) + { + validatableInfo = CreateCustomAttributeTypedArgument(); + return true; + } + if (type == typeof(global::System.Reflection.CustomAttributeNamedArgument)) + { + validatableInfo = CreateCustomAttributeNamedArgument(); + return true; + } + if (type == typeof(global::System.Reflection.CustomAttributeData)) + { + validatableInfo = CreateCustomAttributeData(); + return true; + } + if (type == typeof(global::System.Reflection.ParameterInfo)) + { + validatableInfo = CreateParameterInfo(); + return true; + } + if (type == typeof(global::System.Reflection.MethodInfo)) + { + validatableInfo = CreateMethodInfo(); + return true; + } + if (type == typeof(global::System.Reflection.EventInfo)) + { + validatableInfo = CreateEventInfo(); + return true; + } + if (type == typeof(global::System.Reflection.FieldInfo)) + { + validatableInfo = CreateFieldInfo(); + return true; + } + if (type == typeof(global::System.Reflection.PropertyInfo)) + { + validatableInfo = CreatePropertyInfo(); + return true; + } + if (type == typeof(global::System.Reflection.TypeInfo)) + { + validatableInfo = CreateTypeInfo(); + return true; + } + if (type == typeof(global::System.Reflection.Assembly)) + { + validatableInfo = CreateAssembly(); + return true; + } + if (type == typeof(global::System.Guid)) + { + validatableInfo = CreateGuid(); + return true; + } + if (type == typeof(global::System.Reflection.Module)) + { + validatableInfo = CreateModule(); + return true; + } + if (type == typeof(global::System.Reflection.MemberInfo)) + { + validatableInfo = CreateMemberInfo(); + return true; + } + if (type == typeof(global::System.Type)) + { + validatableInfo = CreateType(); + return true; + } + if (type == typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Actions.BaseRecordOptions)) + { + validatableInfo = CreateBaseRecordOptions(); + return true; + } + if (type == typeof(global::Microsoft.Diagnostics.Monitoring.TestCommon.PassThroughOptions)) + { + validatableInfo = CreatePassThroughOptions(); + return true; + } + if (type == typeof(global::Microsoft.Diagnostics.Monitoring.TestCommon.TestValidatableTypes)) + { + validatableInfo = CreateTestValidatableTypes(); + return true; + } + + return false; + } + + // No-ops, rely on runtime code for ParameterInfo-based resolution + public bool TryGetValidatableParameterInfo(global::System.Reflection.ParameterInfo parameterInfo, [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] out global::Microsoft.AspNetCore.Http.Validation.IValidatableInfo? validatableInfo) + { + validatableInfo = null; + return false; + } + + private ValidatableTypeInfo CreateMethodBase() + { + return new GeneratedValidatableTypeInfo( + type: typeof(global::System.Reflection.MethodBase), + members: [] + ); + } + private ValidatableTypeInfo CreateConstructorInfo() + { + return new GeneratedValidatableTypeInfo( + type: typeof(global::System.Reflection.ConstructorInfo), + members: [] + ); + } + private ValidatableTypeInfo CreateCustomAttributeTypedArgument() + { + return new GeneratedValidatableTypeInfo( + type: typeof(global::System.Reflection.CustomAttributeTypedArgument), + members: [ + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::System.Reflection.CustomAttributeTypedArgument), + propertyType: typeof(global::System.Type), + name: "ArgumentType", + displayName: "ArgumentType" + ), + ] + ); + } + private ValidatableTypeInfo CreateCustomAttributeNamedArgument() + { + return new GeneratedValidatableTypeInfo( + type: typeof(global::System.Reflection.CustomAttributeNamedArgument), + members: [ + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::System.Reflection.CustomAttributeNamedArgument), + propertyType: typeof(global::System.Reflection.MemberInfo), + name: "MemberInfo", + displayName: "MemberInfo" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::System.Reflection.CustomAttributeNamedArgument), + propertyType: typeof(global::System.Reflection.CustomAttributeTypedArgument), + name: "TypedValue", + displayName: "TypedValue" + ), + ] + ); + } + private ValidatableTypeInfo CreateCustomAttributeData() + { + return new GeneratedValidatableTypeInfo( + type: typeof(global::System.Reflection.CustomAttributeData), + members: [ + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::System.Reflection.CustomAttributeData), + propertyType: typeof(global::System.Type), + name: "AttributeType", + displayName: "AttributeType" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::System.Reflection.CustomAttributeData), + propertyType: typeof(global::System.Reflection.ConstructorInfo), + name: "Constructor", + displayName: "Constructor" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::System.Reflection.CustomAttributeData), + propertyType: typeof(global::System.Collections.Generic.IList), + name: "ConstructorArguments", + displayName: "ConstructorArguments" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::System.Reflection.CustomAttributeData), + propertyType: typeof(global::System.Collections.Generic.IList), + name: "NamedArguments", + displayName: "NamedArguments" + ), + ] + ); + } + private ValidatableTypeInfo CreateParameterInfo() + { + return new GeneratedValidatableTypeInfo( + type: typeof(global::System.Reflection.ParameterInfo), + members: [ + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::System.Reflection.ParameterInfo), + propertyType: typeof(global::System.Collections.Generic.IEnumerable), + name: "CustomAttributes", + displayName: "CustomAttributes" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::System.Reflection.ParameterInfo), + propertyType: typeof(global::System.Reflection.MemberInfo), + name: "Member", + displayName: "Member" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::System.Reflection.ParameterInfo), + propertyType: typeof(global::System.Type), + name: "ParameterType", + displayName: "ParameterType" + ), + ] + ); + } + private ValidatableTypeInfo CreateMethodInfo() + { + return new GeneratedValidatableTypeInfo( + type: typeof(global::System.Reflection.MethodInfo), + members: [ + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::System.Reflection.MethodInfo), + propertyType: typeof(global::System.Reflection.MemberTypes), + name: "MemberType", + displayName: "MemberType" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::System.Reflection.MethodInfo), + propertyType: typeof(global::System.Reflection.ParameterInfo), + name: "ReturnParameter", + displayName: "ReturnParameter" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::System.Reflection.MethodInfo), + propertyType: typeof(global::System.Type), + name: "ReturnType", + displayName: "ReturnType" + ), + ] + ); + } + private ValidatableTypeInfo CreateEventInfo() + { + return new GeneratedValidatableTypeInfo( + type: typeof(global::System.Reflection.EventInfo), + members: [ + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::System.Reflection.EventInfo), + propertyType: typeof(global::System.Reflection.MethodInfo), + name: "AddMethod", + displayName: "AddMethod" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::System.Reflection.EventInfo), + propertyType: typeof(global::System.Type), + name: "EventHandlerType", + displayName: "EventHandlerType" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::System.Reflection.EventInfo), + propertyType: typeof(global::System.Reflection.MemberTypes), + name: "MemberType", + displayName: "MemberType" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::System.Reflection.EventInfo), + propertyType: typeof(global::System.Reflection.MethodInfo), + name: "RaiseMethod", + displayName: "RaiseMethod" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::System.Reflection.EventInfo), + propertyType: typeof(global::System.Reflection.MethodInfo), + name: "RemoveMethod", + displayName: "RemoveMethod" + ), + ] + ); + } + private ValidatableTypeInfo CreateFieldInfo() + { + return new GeneratedValidatableTypeInfo( + type: typeof(global::System.Reflection.FieldInfo), + members: [ + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::System.Reflection.FieldInfo), + propertyType: typeof(global::System.Type), + name: "FieldType", + displayName: "FieldType" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::System.Reflection.FieldInfo), + propertyType: typeof(global::System.Reflection.MemberTypes), + name: "MemberType", + displayName: "MemberType" + ), + ] + ); + } + private ValidatableTypeInfo CreatePropertyInfo() + { + return new GeneratedValidatableTypeInfo( + type: typeof(global::System.Reflection.PropertyInfo), + members: [ + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::System.Reflection.PropertyInfo), + propertyType: typeof(global::System.Reflection.MethodInfo), + name: "GetMethod", + displayName: "GetMethod" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::System.Reflection.PropertyInfo), + propertyType: typeof(global::System.Reflection.MemberTypes), + name: "MemberType", + displayName: "MemberType" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::System.Reflection.PropertyInfo), + propertyType: typeof(global::System.Type), + name: "PropertyType", + displayName: "PropertyType" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::System.Reflection.PropertyInfo), + propertyType: typeof(global::System.Reflection.MethodInfo), + name: "SetMethod", + displayName: "SetMethod" + ), + ] + ); + } + private ValidatableTypeInfo CreateTypeInfo() + { + return new GeneratedValidatableTypeInfo( + type: typeof(global::System.Reflection.TypeInfo), + members: [ + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::System.Reflection.TypeInfo), + propertyType: typeof(global::System.Collections.Generic.IEnumerable), + name: "DeclaredConstructors", + displayName: "DeclaredConstructors" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::System.Reflection.TypeInfo), + propertyType: typeof(global::System.Collections.Generic.IEnumerable), + name: "DeclaredEvents", + displayName: "DeclaredEvents" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::System.Reflection.TypeInfo), + propertyType: typeof(global::System.Collections.Generic.IEnumerable), + name: "DeclaredFields", + displayName: "DeclaredFields" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::System.Reflection.TypeInfo), + propertyType: typeof(global::System.Collections.Generic.IEnumerable), + name: "DeclaredMembers", + displayName: "DeclaredMembers" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::System.Reflection.TypeInfo), + propertyType: typeof(global::System.Collections.Generic.IEnumerable), + name: "DeclaredMethods", + displayName: "DeclaredMethods" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::System.Reflection.TypeInfo), + propertyType: typeof(global::System.Collections.Generic.IEnumerable), + name: "DeclaredNestedTypes", + displayName: "DeclaredNestedTypes" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::System.Reflection.TypeInfo), + propertyType: typeof(global::System.Collections.Generic.IEnumerable), + name: "DeclaredProperties", + displayName: "DeclaredProperties" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::System.Reflection.TypeInfo), + propertyType: typeof(global::System.Collections.Generic.IEnumerable), + name: "ImplementedInterfaces", + displayName: "ImplementedInterfaces" + ), + ] + ); + } + private ValidatableTypeInfo CreateAssembly() + { + return new GeneratedValidatableTypeInfo( + type: typeof(global::System.Reflection.Assembly), + members: [ + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::System.Reflection.Assembly), + propertyType: typeof(global::System.Collections.Generic.IEnumerable), + name: "CustomAttributes", + displayName: "CustomAttributes" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::System.Reflection.Assembly), + propertyType: typeof(global::System.Collections.Generic.IEnumerable), + name: "DefinedTypes", + displayName: "DefinedTypes" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::System.Reflection.Assembly), + propertyType: typeof(global::System.Reflection.MethodInfo), + name: "EntryPoint", + displayName: "EntryPoint" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::System.Reflection.Assembly), + propertyType: typeof(global::System.Collections.Generic.IEnumerable), + name: "ExportedTypes", + displayName: "ExportedTypes" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::System.Reflection.Assembly), + propertyType: typeof(global::System.Reflection.Module), + name: "ManifestModule", + displayName: "ManifestModule" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::System.Reflection.Assembly), + propertyType: typeof(global::System.Collections.Generic.IEnumerable), + name: "Modules", + displayName: "Modules" + ), + ] + ); + } + private ValidatableTypeInfo CreateGuid() + { + return new GeneratedValidatableTypeInfo( + type: typeof(global::System.Guid), + members: [ + // https://github.com/dotnet/aspnetcore/issues/61525 + // new GeneratedValidatablePropertyInfo( + // containingType: typeof(global::System.Guid), + // propertyType: typeof(global::System.Guid), + // name: "AllBitsSet", + // displayName: "AllBitsSet" + // ), + ] + ); + } + private ValidatableTypeInfo CreateModule() + { + return new GeneratedValidatableTypeInfo( + type: typeof(global::System.Reflection.Module), + members: [ + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::System.Reflection.Module), + propertyType: typeof(global::System.Reflection.Assembly), + name: "Assembly", + displayName: "Assembly" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::System.Reflection.Module), + propertyType: typeof(global::System.Collections.Generic.IEnumerable), + name: "CustomAttributes", + displayName: "CustomAttributes" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::System.Reflection.Module), + propertyType: typeof(global::System.Guid), + name: "ModuleVersionId", + displayName: "ModuleVersionId" + ), + ] + ); + } + private ValidatableTypeInfo CreateMemberInfo() + { + return new GeneratedValidatableTypeInfo( + type: typeof(global::System.Reflection.MemberInfo), + members: [ + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::System.Reflection.MemberInfo), + propertyType: typeof(global::System.Collections.Generic.IEnumerable), + name: "CustomAttributes", + displayName: "CustomAttributes" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::System.Reflection.MemberInfo), + propertyType: typeof(global::System.Type), + name: "DeclaringType", + displayName: "DeclaringType" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::System.Reflection.MemberInfo), + propertyType: typeof(global::System.Reflection.MemberTypes), + name: "MemberType", + displayName: "MemberType" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::System.Reflection.MemberInfo), + propertyType: typeof(global::System.Reflection.Module), + name: "Module", + displayName: "Module" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::System.Reflection.MemberInfo), + propertyType: typeof(global::System.Type), + name: "ReflectedType", + displayName: "ReflectedType" + ), + ] + ); + } + private ValidatableTypeInfo CreateType() + { + return new GeneratedValidatableTypeInfo( + type: typeof(global::System.Type), + members: [ + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::System.Type), + propertyType: typeof(global::System.Reflection.Assembly), + name: "Assembly", + displayName: "Assembly" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::System.Type), + propertyType: typeof(global::System.Type), + name: "BaseType", + displayName: "BaseType" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::System.Type), + propertyType: typeof(global::System.Reflection.MethodBase), + name: "DeclaringMethod", + displayName: "DeclaringMethod" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::System.Type), + propertyType: typeof(global::System.Type), + name: "DeclaringType", + displayName: "DeclaringType" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::System.Type), + propertyType: typeof(global::System.Type[]), + name: "GenericTypeArguments", + displayName: "GenericTypeArguments" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::System.Type), + propertyType: typeof(global::System.Guid), + name: "GUID", + displayName: "GUID" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::System.Type), + propertyType: typeof(global::System.Reflection.MemberTypes), + name: "MemberType", + displayName: "MemberType" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::System.Type), + propertyType: typeof(global::System.Reflection.Module), + name: "Module", + displayName: "Module" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::System.Type), + propertyType: typeof(global::System.Type), + name: "ReflectedType", + displayName: "ReflectedType" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::System.Type), + propertyType: typeof(global::System.Reflection.ConstructorInfo), + name: "TypeInitializer", + displayName: "TypeInitializer" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::System.Type), + propertyType: typeof(global::System.Type), + name: "UnderlyingSystemType", + displayName: "UnderlyingSystemType" + ), + ] + ); + } + private ValidatableTypeInfo CreateBaseRecordOptions() + { + return new GeneratedValidatableTypeInfo( + type: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Actions.BaseRecordOptions), + members: [ + // https://github.com/dotnet/aspnetcore/issues/61379 + // new GeneratedValidatablePropertyInfo( + // containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Actions.BaseRecordOptions), + // propertyType: typeof(global::System.Type), + // name: "EqualityContract", + // displayName: "EqualityContract" + // ), + ] + ); + } + private ValidatableTypeInfo CreatePassThroughOptions() + { + return new GeneratedValidatableTypeInfo( + type: typeof(global::Microsoft.Diagnostics.Monitoring.TestCommon.PassThroughOptions), + members: [ + // https://github.com/dotnet/aspnetcore/issues/61379 + // new GeneratedValidatablePropertyInfo( + // containingType: typeof(global::Microsoft.Diagnostics.Monitoring.TestCommon.PassThroughOptions), + // propertyType: typeof(global::System.Type), + // name: "EqualityContract", + // displayName: "EqualityContract" + // ), + ] + ); + } + private ValidatableTypeInfo CreateTestValidatableTypes() + { + return new GeneratedValidatableTypeInfo( + type: typeof(global::Microsoft.Diagnostics.Monitoring.TestCommon.TestValidatableTypes), + members: [ + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Monitoring.TestCommon.TestValidatableTypes), + propertyType: typeof(global::Microsoft.Diagnostics.Monitoring.TestCommon.PassThroughOptions), + name: "PassThroughOptions", + displayName: "PassThroughOptions" + ), + ] + ); + } + + } + + // Added internal wrapper to let the generated extension method be accessed from test code + // without conflicting with GeneratedServiceCollectionExtensions in product code. + internal static class TestGeneratedServiceCollectionExtensions + { + public static global::Microsoft.Extensions.DependencyInjection.IServiceCollection AddValidation(global::Microsoft.Extensions.DependencyInjection.IServiceCollection services) + { + return GeneratedServiceCollectionExtensions.AddValidation(services); + } + } + + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.Http.ValidationsGenerator, Version=10.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60", "10.0.0.0")] + file static class GeneratedServiceCollectionExtensions + { + // [global::System.Runtime.CompilerServices.InterceptsLocationAttribute(1, "8vl1G447Wi3Pc94851ZKGx+IAABWYWxpZGF0YWJsZUluZm9SZXNvbHZlci5jcw==")] + // Removed InterceptsLocation since we are calling the extension method directly from a checked-in copy of the + // generated code, and interceptors are not designed for use in checked-in code. + public static global::Microsoft.Extensions.DependencyInjection.IServiceCollection AddValidation(this global::Microsoft.Extensions.DependencyInjection.IServiceCollection services, global::System.Action? configureOptions = null) + { + // Use non-extension method to avoid infinite recursion. + return global::Microsoft.Extensions.DependencyInjection.ValidationServiceCollectionExtensions.AddValidation(services, options => + { + options.Resolvers.Insert(0, new GeneratedValidatableInfoResolver()); + if (configureOptions is not null) + { + configureOptions(options); + } + }); + } + } + + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.Http.ValidationsGenerator, Version=10.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60", "10.0.0.0")] + file static class ValidationAttributeCache + { + private sealed record CacheKey(global::System.Type ContainingType, string PropertyName); + private static readonly global::System.Collections.Concurrent.ConcurrentDictionary _cache = new(); + + public static global::System.ComponentModel.DataAnnotations.ValidationAttribute[] GetValidationAttributes( + global::System.Type containingType, + string propertyName) + { + var key = new CacheKey(containingType, propertyName); + return _cache.GetOrAdd(key, static k => + { + var property = k.ContainingType.GetProperty(k.PropertyName); + if (property == null) + { + return []; + } + + return [.. global::System.Reflection.CustomAttributeExtensions.GetCustomAttributes(property, inherit: true)]; + }); + } + } +} diff --git a/src/Tests/Microsoft.Diagnostics.Monitoring.Tool.UnitTests/CollectionRuleOptionsTests.cs b/src/Tests/Microsoft.Diagnostics.Monitoring.Tool.UnitTests/CollectionRuleOptionsTests.cs index 31cbb996d67..ed3ba328fda 100644 --- a/src/Tests/Microsoft.Diagnostics.Monitoring.Tool.UnitTests/CollectionRuleOptionsTests.cs +++ b/src/Tests/Microsoft.Diagnostics.Monitoring.Tool.UnitTests/CollectionRuleOptionsTests.cs @@ -195,14 +195,12 @@ public Task CollectionRuleOptions_EventCounterTrigger_PropertyValidation() ex => { string[] failures = ex.Failures.ToArray(); - // Property validation failures will short-circuit the remainder of the validation - // rules, thus only observe 3 errors when one might expect 4 (the fourth being that - // either GreaterThan or LessThan should be specified). - Assert.Equal(3, failures.Length); + Assert.Equal(4, failures.Length); VerifyRequiredMessage(failures, 0, nameof(EventCounterOptions.ProviderName)); VerifyRequiredMessage(failures, 1, nameof(EventCounterOptions.CounterName)); VerifyRangeMessage(failures, 2, nameof(EventCounterOptions.SlidingWindowDuration), TriggerOptionsConstants.SlidingWindowDuration_MinValue, TriggerOptionsConstants.SlidingWindowDuration_MaxValue); + VerifyEitherRequiredMessage(failures, 3, nameof(EventCounterOptions.GreaterThan), nameof(EventCounterOptions.LessThan)); }); } @@ -362,13 +360,12 @@ public Task CollectionRuleOptions_EventMeterTrigger_PropertyValidation() ex => { string[] failures = ex.Failures.ToArray(); - // Property validation failures will short-circuit the remainder of the validation - // rules, thus only observe 3 errors when one might expect 4 (GreaterThan or LessThan should be specified). - Assert.Equal(3, failures.Length); + Assert.Equal(4, failures.Length); VerifyRequiredMessage(failures, 0, nameof(EventMeterOptions.MeterName)); VerifyRequiredMessage(failures, 1, nameof(EventMeterOptions.InstrumentName)); VerifyRangeMessage(failures, 2, nameof(EventMeterOptions.SlidingWindowDuration), TriggerOptionsConstants.SlidingWindowDuration_MinValue, TriggerOptionsConstants.SlidingWindowDuration_MaxValue); + VerifyEitherRequiredMessage(failures, 3, nameof(EventMeterOptions.GreaterThan), nameof(EventMeterOptions.LessThan)); }); } diff --git a/src/Tests/Microsoft.Diagnostics.Monitoring.Tool.UnitTests/CollectionRulePipelineTests.cs b/src/Tests/Microsoft.Diagnostics.Monitoring.Tool.UnitTests/CollectionRulePipelineTests.cs index 75ca11aca3d..a3889d34d03 100644 --- a/src/Tests/Microsoft.Diagnostics.Monitoring.Tool.UnitTests/CollectionRulePipelineTests.cs +++ b/src/Tests/Microsoft.Diagnostics.Monitoring.Tool.UnitTests/CollectionRulePipelineTests.cs @@ -473,8 +473,8 @@ public Task CollectionRulePipeline_ActionCountLimitSlidingDurationTest(TargetFra { const int IterationCount = 5; const int ExpectedActionExecutionCount = 3; - TimeSpan SlidingWindowDuration = TimeSpan.FromMilliseconds(100); - TimeSpan ClockIncrementDuration = TimeSpan.FromMilliseconds(10); + TimeSpan SlidingWindowDuration = TimeSpan.FromMilliseconds(1000); + TimeSpan ClockIncrementDuration = TimeSpan.FromMilliseconds(100); MockTimeProvider timeProvider = new(); ManualTriggerService triggerService = new(); diff --git a/src/Tests/Microsoft.Diagnostics.Monitoring.Tool.UnitTests/ExtensionManifestTests.cs b/src/Tests/Microsoft.Diagnostics.Monitoring.Tool.UnitTests/ExtensionManifestTests.cs index b3794d70476..1dd630b3384 100644 --- a/src/Tests/Microsoft.Diagnostics.Monitoring.Tool.UnitTests/ExtensionManifestTests.cs +++ b/src/Tests/Microsoft.Diagnostics.Monitoring.Tool.UnitTests/ExtensionManifestTests.cs @@ -1,8 +1,12 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using Microsoft.AspNetCore.Http.Validation; using Microsoft.Diagnostics.Monitoring.TestCommon; using Microsoft.Diagnostics.Tools.Monitor.Extensibility; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; +using Microsoft.AspNetCore.Mvc.Testing; using System.IO; using System.Text.Json; using Xunit; @@ -10,18 +14,24 @@ namespace Microsoft.Diagnostics.Monitoring.Tool.UnitTests { + public class ExtensionManifestFixture : WebApplicationFactory + { + } + [TargetFrameworkMonikerTrait(TargetFrameworkMonikerExtensions.CurrentTargetFrameworkMoniker)] - public sealed class ExtensionManifestTests + public sealed class ExtensionManifestTests : IClassFixture { private const string ExpectedName = "CustomEgress"; private const string ExpectedExecutableName = "CustomExecutable"; private const string ExpectedAssemblyName = "CustomAssembly"; private readonly ITestOutputHelper _outputHelper; + private readonly ExtensionManifestFixture _fixture; - public ExtensionManifestTests(ITestOutputHelper outputHelper) + public ExtensionManifestTests(ITestOutputHelper outputHelper, ExtensionManifestFixture fixture) { _outputHelper = outputHelper; + _fixture = fixture; } [Fact] @@ -91,7 +101,8 @@ public void ExtensionManifest_EmptyObject_ThrowOnValidate() Assert.Null(manifest.AssemblyFileName); Assert.Null(manifest.ExecutableFileName); - ExtensionException ex = Assert.Throws(manifest.Validate); + var validationOptions = _fixture.Services.GetRequiredService>().Value; + ExtensionException ex = Assert.Throws(() => manifest.Validate(_fixture.Services, validationOptions)); Assert.Null(ex.InnerException); } @@ -115,7 +126,8 @@ public void ExtensionManifest_NameOnly_ThrowOnValidate() Assert.Null(manifest.AssemblyFileName); Assert.Null(manifest.ExecutableFileName); - ExtensionException ex = Assert.Throws(manifest.Validate); + var validationOptions = _fixture.Services.GetRequiredService>().Value; + ExtensionException ex = Assert.Throws(() => manifest.Validate(_fixture.Services, validationOptions)); Assert.Null(ex.InnerException); } @@ -141,7 +153,8 @@ public void ExtensionManifest_ExecutableAndAssembly_ThrowOnValidate() Assert.Equal(ExpectedAssemblyName, manifest.AssemblyFileName); Assert.Equal(ExpectedExecutableName, manifest.ExecutableFileName); - ExtensionException ex = Assert.Throws(manifest.Validate); + var validationOptions = _fixture.Services.GetRequiredService>().Value; + ExtensionException ex = Assert.Throws(() => manifest.Validate(_fixture.Services, validationOptions)); Assert.Null(ex.InnerException); } @@ -166,7 +179,8 @@ public void ExtensionManifest_NameAndAssembly_Valid() Assert.Equal(ExpectedAssemblyName, manifest.AssemblyFileName); Assert.Null(manifest.ExecutableFileName); - manifest.Validate(); + var validationOptions = _fixture.Services.GetRequiredService>().Value; + manifest.Validate(_fixture.Services, validationOptions); } [Fact] @@ -190,7 +204,8 @@ public void ExtensionManifest_NameAndExecutable_Valid() Assert.Null(manifest.AssemblyFileName); Assert.Equal(ExpectedExecutableName, manifest.ExecutableFileName); - manifest.Validate(); + var validationOptions = _fixture.Services.GetRequiredService>().Value; + manifest.Validate(_fixture.Services, validationOptions); } private static Stream CreateManifestStream(TemporaryDirectory dir, out string path) diff --git a/src/Tests/Microsoft.Diagnostics.Monitoring.Tool.UnitTests/FileSystemEgressExtensionTests.cs b/src/Tests/Microsoft.Diagnostics.Monitoring.Tool.UnitTests/FileSystemEgressExtensionTests.cs index 9a9ba33bf8b..5989905b166 100644 --- a/src/Tests/Microsoft.Diagnostics.Monitoring.Tool.UnitTests/FileSystemEgressExtensionTests.cs +++ b/src/Tests/Microsoft.Diagnostics.Monitoring.Tool.UnitTests/FileSystemEgressExtensionTests.cs @@ -1,12 +1,15 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using Microsoft.AspNetCore.Http.Validation; +using Microsoft.AspNetCore.Mvc.Testing; using Microsoft.Diagnostics.Monitoring.TestCommon; using Microsoft.Diagnostics.Tools.Monitor; using Microsoft.Diagnostics.Tools.Monitor.Egress; using Microsoft.Diagnostics.Tools.Monitor.Egress.Configuration; using Microsoft.Diagnostics.Tools.Monitor.Egress.FileSystem; using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Moq; @@ -22,8 +25,12 @@ namespace Microsoft.Diagnostics.Monitoring.Tool.UnitTests { + public class FileSystemEgressExtensionFixture : WebApplicationFactory + { + } + [TargetFrameworkMonikerTrait(TargetFrameworkMonikerExtensions.CurrentTargetFrameworkMoniker)] - public sealed class FileSystemEgressExtensionTests + public sealed class FileSystemEgressExtensionTests : IClassFixture { const string ProviderName = "TestProvider"; const string ExpectedFileName = "EgressedData.txt"; @@ -35,10 +42,12 @@ public sealed class FileSystemEgressExtensionTests FileSystemEgressProviderOptions.CopyBufferSize_MaxValue.ToString()); private readonly ITestOutputHelper _outputHelper; + private readonly FileSystemEgressExtensionFixture _fixture; - public FileSystemEgressExtensionTests(ITestOutputHelper outputHelper) + public FileSystemEgressExtensionTests(ITestOutputHelper outputHelper, FileSystemEgressExtensionFixture fixture) { _outputHelper = outputHelper; + _fixture = fixture; } [Fact] @@ -145,7 +154,7 @@ public async Task FileSystemEgressExtension_IntermediateDirectoryPath_Success() Assert.False(intermediateDirInfo.EnumerateFiles().Any(), "Intermediate directory should not contain any files."); } - private static IEgressExtension CreateExtension(Action callback = null) + private IEgressExtension CreateExtension(Action callback = null) { List configProviders = new() { @@ -163,6 +172,8 @@ private static IEgressExtension CreateExtension(Action cal Mock> mockLogger = new(); Mock mockServiceProvider = new(); + mockServiceProvider.Setup(provider => provider.GetService(typeof(IOptions))) + .Returns(_fixture.Services.GetRequiredService>()); return new FileSystemEgressExtension(mockServiceProvider.Object, mockConfigurationProvider.Object, mockLogger.Object); } diff --git a/src/Tests/Microsoft.Diagnostics.Monitoring.Tool.UnitTests/Microsoft.Diagnostics.Monitoring.Tool.UnitTests.csproj b/src/Tests/Microsoft.Diagnostics.Monitoring.Tool.UnitTests/Microsoft.Diagnostics.Monitoring.Tool.UnitTests.csproj index cb44deedb4b..43d46599cc9 100644 --- a/src/Tests/Microsoft.Diagnostics.Monitoring.Tool.UnitTests/Microsoft.Diagnostics.Monitoring.Tool.UnitTests.csproj +++ b/src/Tests/Microsoft.Diagnostics.Monitoring.Tool.UnitTests/Microsoft.Diagnostics.Monitoring.Tool.UnitTests.csproj @@ -8,6 +8,7 @@ + @@ -15,6 +16,7 @@ + diff --git a/src/Tests/Microsoft.Diagnostics.Monitoring.Tool.UnitTests/Options/AzureAdOptionsTests.cs b/src/Tests/Microsoft.Diagnostics.Monitoring.Tool.UnitTests/Options/AzureAdOptionsTests.cs index 95966d09f04..3ab0b08d058 100644 --- a/src/Tests/Microsoft.Diagnostics.Monitoring.Tool.UnitTests/Options/AzureAdOptionsTests.cs +++ b/src/Tests/Microsoft.Diagnostics.Monitoring.Tool.UnitTests/Options/AzureAdOptionsTests.cs @@ -1,8 +1,13 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using Microsoft.AspNetCore.Http.Validation; +using Microsoft.AspNetCore.Mvc.Testing; using Microsoft.Diagnostics.Monitoring.TestCommon; using Microsoft.Diagnostics.Tools.Monitor; +using Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; @@ -10,9 +15,20 @@ namespace Microsoft.Diagnostics.Monitoring.Tool.UnitTests.Options { + public class AzureAdOptionsTestsFixture : WebApplicationFactory + { + } + [TargetFrameworkMonikerTrait(TargetFrameworkMonikerExtensions.CurrentTargetFrameworkMoniker)] - public class AzureAdOptionsTests + public class AzureAdOptionsTests : IClassFixture { + private readonly AzureAdOptionsTestsFixture _fixture; + + public AzureAdOptionsTests(AzureAdOptionsTestsFixture fixture) + { + _fixture = fixture; + } + private static AzureAdOptions GetDefaultOptions() { return new AzureAdOptions @@ -32,9 +48,10 @@ public void AzureAdOptions_Requires_Role() options.RequiredRole = null; List results = new(); + var validationOptions = _fixture.Services.GetRequiredService>().Value; // Act - bool isValid = Validator.TryValidateObject(options, new(options), results, validateAllProperties: true); + bool isValid = ValidationHelper.TryValidateObject(options, typeof(AzureAdOptions), validationOptions, _fixture.Services, results); // Assert Assert.False(isValid); @@ -50,9 +67,10 @@ public void AzureAdOptions_Requires_TenantId() options.TenantId = null; List results = new(); + var validationOptions = _fixture.Services.GetRequiredService>().Value; // Act - bool isValid = Validator.TryValidateObject(options, new(options), results, validateAllProperties: true); + bool isValid = ValidationHelper.TryValidateObject(options, typeof(AzureAdOptions), validationOptions, _fixture.Services, results); // Assert Assert.False(isValid); @@ -68,9 +86,10 @@ public void AzureAdOptions_Requires_ClientId() options.ClientId = null; List results = new(); + var validationOptions = _fixture.Services.GetRequiredService>().Value; // Act - bool isValid = Validator.TryValidateObject(options, new(options), results, validateAllProperties: true); + bool isValid = ValidationHelper.TryValidateObject(options, typeof(AzureAdOptions), validationOptions, _fixture.Services, results); // Assert Assert.False(isValid); diff --git a/src/Tests/Microsoft.Diagnostics.Monitoring.Tool.UnitTestsSample/Microsoft.Diagnostics.Monitoring.Tool.UnitTestsSample.csproj b/src/Tests/Microsoft.Diagnostics.Monitoring.Tool.UnitTestsSample/Microsoft.Diagnostics.Monitoring.Tool.UnitTestsSample.csproj new file mode 100644 index 00000000000..6b94db64edf --- /dev/null +++ b/src/Tests/Microsoft.Diagnostics.Monitoring.Tool.UnitTestsSample/Microsoft.Diagnostics.Monitoring.Tool.UnitTestsSample.csproj @@ -0,0 +1,13 @@ + + + + $(ToolTargetFrameworks) + enable + enable + + + + + + + diff --git a/src/Tests/Microsoft.Diagnostics.Monitoring.Tool.UnitTestsSample/Program.cs b/src/Tests/Microsoft.Diagnostics.Monitoring.Tool.UnitTestsSample/Program.cs new file mode 100644 index 00000000000..00b3a88b98f --- /dev/null +++ b/src/Tests/Microsoft.Diagnostics.Monitoring.Tool.UnitTestsSample/Program.cs @@ -0,0 +1,14 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Microsoft.Diagnostics.Tools.Monitor; + +var builder = WebApplication.CreateBuilder(new WebApplicationOptions +{ + ContentRootPath = AppContext.BaseDirectory +}); + +ValidatableTypes.AddValidation(builder.Services); +builder.Build(); + +public partial class Program {} diff --git a/src/Tools/dotnet-monitor/Auth/ApiKey/MonitorApiKeyPostConfigure.cs b/src/Tools/dotnet-monitor/Auth/ApiKey/MonitorApiKeyPostConfigure.cs index 2cae0a91b75..1746ba63581 100644 --- a/src/Tools/dotnet-monitor/Auth/ApiKey/MonitorApiKeyPostConfigure.cs +++ b/src/Tools/dotnet-monitor/Auth/ApiKey/MonitorApiKeyPostConfigure.cs @@ -1,7 +1,10 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using Microsoft.AspNetCore.Http.Validation; using Microsoft.Diagnostics.Monitoring.WebApi; +using Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Microsoft.IdentityModel.Tokens; @@ -21,20 +24,25 @@ internal sealed class MonitorApiKeyPostConfigure : { private readonly ILogger _logger; private readonly IOptionsMonitor _apiKeyOptions; + private readonly IServiceProvider _serviceProvider; + private readonly ValidationOptions _validationOptions; public MonitorApiKeyPostConfigure( + IServiceProvider serviceProvider, ILogger logger, IOptionsMonitor apiKeyOptions) { _logger = logger; _apiKeyOptions = apiKeyOptions; + _serviceProvider = serviceProvider ?? throw new ArgumentNullException(nameof(serviceProvider)); + _validationOptions = serviceProvider.GetRequiredService>().Value; } public void PostConfigure(string? name, MonitorApiKeyConfiguration options) { MonitorApiKeyOptions sourceOptions = _apiKeyOptions.CurrentValue; - IList errors = new List(); + List errors = new List(); // If nothing is set, lets not attach an error and instead pass along the blank config if (sourceOptions.Subject == null && sourceOptions.PublicKey == null) @@ -48,11 +56,12 @@ public void PostConfigure(string? name, MonitorApiKeyConfiguration options) // Some options are configured (but may not be valid) options.Configured = true; - Validator.TryValidateObject( + ValidationHelper.TryValidateObject( sourceOptions, - new ValidationContext(sourceOptions, null, null), - errors, - validateAllProperties: true); + typeof(MonitorApiKeyOptions), + _validationOptions, + _serviceProvider, + errors); string? jwkJson = null; try diff --git a/src/Tools/dotnet-monitor/Auth/AuthConfiguratorFactory.cs b/src/Tools/dotnet-monitor/Auth/AuthConfiguratorFactory.cs index a16e1aa9216..983499440da 100644 --- a/src/Tools/dotnet-monitor/Auth/AuthConfiguratorFactory.cs +++ b/src/Tools/dotnet-monitor/Auth/AuthConfiguratorFactory.cs @@ -1,12 +1,16 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using Microsoft.AspNetCore.Http.Validation; using Microsoft.Diagnostics.Tools.Monitor.Auth.ApiKey; using Microsoft.Diagnostics.Tools.Monitor.Auth.AzureAd; using Microsoft.Diagnostics.Tools.Monitor.Auth.NoAuth; +using Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration.Binder.SourceGeneration; using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Options; +using Microsoft.Extensions.DependencyInjection; using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; @@ -22,7 +26,7 @@ internal enum StartupAuthenticationMode internal static class AuthConfiguratorFactory { - public static IAuthenticationConfigurator Create(StartupAuthenticationMode startupAuthMode, HostBuilderContext context) + public static IAuthenticationConfigurator Create(StartupAuthenticationMode startupAuthMode, HostBuilderContext context, IServiceProvider services) { switch (startupAuthMode) { @@ -47,12 +51,12 @@ public static IAuthenticationConfigurator Create(StartupAuthenticationMode start if (authConfigSection.Exists()) { authConfigSection.Bind_AuthenticationOptions(authOptions); - ValidateAuthConfigSection(authOptions, authConfigSection.Path); + ValidateAuthConfigSection(authOptions, authConfigSection.Path, services); } if (authOptions.AzureAd != null) { - ValidateAuthConfigSection(authOptions.AzureAd, ConfigurationPath.Combine(authConfigSection.Path, ConfigurationKeys.AzureAd)); + ValidateAuthConfigSection(authOptions.AzureAd, ConfigurationPath.Combine(authConfigSection.Path, ConfigurationKeys.AzureAd), services); return new AzureAdAuthConfigurator(authOptions.AzureAd); } @@ -63,10 +67,11 @@ public static IAuthenticationConfigurator Create(StartupAuthenticationMode start } } - private static void ValidateAuthConfigSection(T options, string configurationPath) where T : notnull + private static void ValidateAuthConfigSection(T options, string configurationPath, IServiceProvider services) where T : notnull { + var validationOptions = services.GetRequiredService>().Value; List results = new(); - if (!Validator.TryValidateObject(options, new ValidationContext(options), results, validateAllProperties: true)) + if (!ValidationHelper.TryValidateObject(options, typeof(T), validationOptions, services, results)) { throw new DeferredAuthenticationValidationException(configurationPath, results); } diff --git a/src/Tools/dotnet-monitor/CollectionRules/Actions/CollectDumpAction.cs b/src/Tools/dotnet-monitor/CollectionRules/Actions/CollectDumpAction.cs index 9647ee347a0..be3c7f8fc1c 100644 --- a/src/Tools/dotnet-monitor/CollectionRules/Actions/CollectDumpAction.cs +++ b/src/Tools/dotnet-monitor/CollectionRules/Actions/CollectDumpAction.cs @@ -1,15 +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 Microsoft.AspNetCore.Http.Validation; using Microsoft.Diagnostics.Monitoring.WebApi; using Microsoft.Diagnostics.Monitoring.WebApi.Models; +using Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options; using Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Configuration; using Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Actions; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration.Binder.SourceGeneration; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; using System; -using System.ComponentModel.DataAnnotations; using Utils = Microsoft.Diagnostics.Monitoring.WebApi.Utilities; namespace Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Actions @@ -18,10 +20,12 @@ internal sealed class CollectDumpActionFactory : ICollectionRuleActionFactory { private readonly IServiceProvider _serviceProvider; + private readonly ValidationOptions _validationOptions; public CollectDumpActionFactory(IServiceProvider serviceProvider) { _serviceProvider = serviceProvider ?? throw new ArgumentNullException(nameof(serviceProvider)); + _validationOptions = serviceProvider.GetRequiredService>().Value; } public ICollectionRuleAction Create(IProcessInfo processInfo, CollectDumpOptions options) @@ -31,8 +35,7 @@ public ICollectionRuleAction Create(IProcessInfo processInfo, CollectDumpOptions throw new ArgumentNullException(nameof(options)); } - ValidationContext context = new(options, _serviceProvider, items: null); - Validator.ValidateObject(options, context, validateAllProperties: true); + ValidationHelper.ValidateObject(options, typeof(CollectDumpOptions), _validationOptions, _serviceProvider); return new CollectDumpAction(_serviceProvider, processInfo, options); } diff --git a/src/Tools/dotnet-monitor/CollectionRules/Actions/CollectExceptionsAction.cs b/src/Tools/dotnet-monitor/CollectionRules/Actions/CollectExceptionsAction.cs index e6aacfd4a99..feb71ba2177 100644 --- a/src/Tools/dotnet-monitor/CollectionRules/Actions/CollectExceptionsAction.cs +++ b/src/Tools/dotnet-monitor/CollectionRules/Actions/CollectExceptionsAction.cs @@ -1,20 +1,31 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using Microsoft.AspNetCore.Http.Validation; using Microsoft.Diagnostics.Monitoring.WebApi; +using Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options; using Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Actions; using Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Configuration; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration.Binder.SourceGeneration; using System; -using System.ComponentModel.DataAnnotations; using Utils = Microsoft.Diagnostics.Monitoring.WebApi.Utilities; namespace Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Actions { internal sealed class CollectExceptionsActionFactory : ICollectionRuleActionFactory { + private readonly IServiceProvider _serviceProvider; + private readonly ValidationOptions _validationOptions; + + public CollectExceptionsActionFactory(IServiceProvider serviceProvider, IOptions validationOptions) + { + _serviceProvider = serviceProvider ?? throw new ArgumentNullException(nameof(serviceProvider)); + _validationOptions = validationOptions?.Value ?? throw new ArgumentNullException(nameof(validationOptions)); + } + public ICollectionRuleAction Create(IProcessInfo processInfo, CollectExceptionsOptions options) { if (null == options) @@ -22,8 +33,7 @@ public ICollectionRuleAction Create(IProcessInfo processInfo, CollectExceptionsO throw new ArgumentNullException(nameof(options)); } - ValidationContext context = new(options, processInfo.EndpointInfo.ServiceProvider, items: null); - Validator.ValidateObject(options, context, validateAllProperties: true); + ValidationHelper.ValidateObject(options, typeof(CollectExceptionsOptions), _validationOptions, _serviceProvider); return new CollectExceptionsAction(processInfo, options); } diff --git a/src/Tools/dotnet-monitor/CollectionRules/Actions/CollectGCDumpAction.cs b/src/Tools/dotnet-monitor/CollectionRules/Actions/CollectGCDumpAction.cs index 525be20357c..5d7c0388409 100644 --- a/src/Tools/dotnet-monitor/CollectionRules/Actions/CollectGCDumpAction.cs +++ b/src/Tools/dotnet-monitor/CollectionRules/Actions/CollectGCDumpAction.cs @@ -6,9 +6,11 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration.Binder.SourceGeneration; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; +using Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options; using System; -using System.ComponentModel.DataAnnotations; using Utils = Microsoft.Diagnostics.Monitoring.WebApi.Utilities; +using Microsoft.AspNetCore.Http.Validation; using Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Configuration; namespace Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Actions @@ -17,10 +19,12 @@ internal sealed class CollectGCDumpActionFactory : ICollectionRuleActionFactory { private readonly IServiceProvider _serviceProvider; + private readonly ValidationOptions _validationOptions; public CollectGCDumpActionFactory(IServiceProvider serviceProvider) { _serviceProvider = serviceProvider ?? throw new ArgumentNullException(nameof(serviceProvider)); + _validationOptions = serviceProvider.GetRequiredService>().Value; } public ICollectionRuleAction Create(IProcessInfo processInfo, CollectGCDumpOptions options) @@ -29,9 +33,7 @@ public ICollectionRuleAction Create(IProcessInfo processInfo, CollectGCDumpOptio { throw new ArgumentNullException(nameof(options)); } - - ValidationContext context = new(options, _serviceProvider, items: null); - Validator.ValidateObject(options, context, validateAllProperties: true); + ValidationHelper.ValidateObject(options, typeof(CollectGCDumpOptions), _validationOptions, _serviceProvider); return new CollectGCDumpAction(_serviceProvider, processInfo, options); } diff --git a/src/Tools/dotnet-monitor/CollectionRules/Actions/CollectLiveMetricsAction.cs b/src/Tools/dotnet-monitor/CollectionRules/Actions/CollectLiveMetricsAction.cs index d1c0d85be70..f29ca44a407 100644 --- a/src/Tools/dotnet-monitor/CollectionRules/Actions/CollectLiveMetricsAction.cs +++ b/src/Tools/dotnet-monitor/CollectionRules/Actions/CollectLiveMetricsAction.cs @@ -1,9 +1,11 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using Microsoft.AspNetCore.Http.Validation; using Microsoft.Diagnostics.Monitoring.EventPipe; using Microsoft.Diagnostics.Monitoring.WebApi; using Microsoft.Diagnostics.Monitoring.WebApi.Models; +using Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options; using Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Actions; using Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Configuration; using Microsoft.Extensions.Configuration; @@ -11,7 +13,6 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; using System; -using System.ComponentModel.DataAnnotations; using Utils = Microsoft.Diagnostics.Monitoring.WebApi.Utilities; namespace Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Actions @@ -20,10 +21,12 @@ internal sealed class CollectLiveMetricsActionFactory : ICollectionRuleActionFactory { private readonly IServiceProvider _serviceProvider; + private readonly ValidationOptions _validationOptions; public CollectLiveMetricsActionFactory(IServiceProvider serviceProvider) { _serviceProvider = serviceProvider ?? throw new ArgumentNullException(nameof(serviceProvider)); + _validationOptions = serviceProvider.GetRequiredService>().Value; } public ICollectionRuleAction Create(IProcessInfo processInfo, CollectLiveMetricsOptions options) @@ -33,8 +36,7 @@ public ICollectionRuleAction Create(IProcessInfo processInfo, CollectLiveMetrics throw new ArgumentNullException(nameof(options)); } - ValidationContext context = new(options, _serviceProvider, items: null); - Validator.ValidateObject(options, context, validateAllProperties: true); + ValidationHelper.ValidateObject(options, typeof(CollectLiveMetricsOptions), _validationOptions, _serviceProvider); return new CollectLiveMetricsAction(_serviceProvider, processInfo, options); } diff --git a/src/Tools/dotnet-monitor/CollectionRules/Actions/CollectLogsAction.cs b/src/Tools/dotnet-monitor/CollectionRules/Actions/CollectLogsAction.cs index 8b85db24af2..b6c76c66eda 100644 --- a/src/Tools/dotnet-monitor/CollectionRules/Actions/CollectLogsAction.cs +++ b/src/Tools/dotnet-monitor/CollectionRules/Actions/CollectLogsAction.cs @@ -1,18 +1,20 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using Microsoft.AspNetCore.Http.Validation; using Microsoft.Diagnostics.Monitoring.EventPipe; using Microsoft.Diagnostics.Monitoring.Options; using Microsoft.Diagnostics.Monitoring.WebApi; +using Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options; using Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Actions; using Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Configuration; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration.Binder.SourceGeneration; using System; using System.Collections.Generic; -using System.ComponentModel.DataAnnotations; using Utils = Microsoft.Diagnostics.Monitoring.WebApi.Utilities; namespace Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Actions @@ -21,10 +23,12 @@ internal sealed class CollectLogsActionFactory : ICollectionRuleActionFactory { private readonly IServiceProvider _serviceProvider; + private readonly ValidationOptions _validationOptions; public CollectLogsActionFactory(IServiceProvider serviceProvider) { _serviceProvider = serviceProvider ?? throw new ArgumentNullException(nameof(serviceProvider)); + _validationOptions = serviceProvider.GetRequiredService>().Value; } public ICollectionRuleAction Create(IProcessInfo processInfo, CollectLogsOptions options) @@ -34,8 +38,7 @@ public ICollectionRuleAction Create(IProcessInfo processInfo, CollectLogsOptions throw new ArgumentNullException(nameof(options)); } - ValidationContext context = new(options, _serviceProvider, items: null); - Validator.ValidateObject(options, context, validateAllProperties: true); + ValidationHelper.ValidateObject(options, typeof(CollectLogsOptions), _validationOptions, _serviceProvider); return new CollectLogsAction(_serviceProvider, processInfo, options); } diff --git a/src/Tools/dotnet-monitor/CollectionRules/Actions/CollectStacksAction.cs b/src/Tools/dotnet-monitor/CollectionRules/Actions/CollectStacksAction.cs index e0cfb15b4b3..2bcc4084994 100644 --- a/src/Tools/dotnet-monitor/CollectionRules/Actions/CollectStacksAction.cs +++ b/src/Tools/dotnet-monitor/CollectionRules/Actions/CollectStacksAction.cs @@ -1,14 +1,16 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using Microsoft.AspNetCore.Http.Validation; using Microsoft.Diagnostics.Monitoring.WebApi; +using Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options; using Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Actions; using Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Configuration; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration.Binder.SourceGeneration; using System; -using System.ComponentModel.DataAnnotations; using Utils = Microsoft.Diagnostics.Monitoring.WebApi.Utilities; namespace Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Actions @@ -16,10 +18,12 @@ namespace Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Actions internal sealed class CollectStacksActionFactory : ICollectionRuleActionFactory { private readonly IServiceProvider _serviceProvider; + private readonly ValidationOptions _validationOptions; public CollectStacksActionFactory(IServiceProvider serviceProvider) { _serviceProvider = serviceProvider ?? throw new ArgumentNullException(nameof(serviceProvider)); + _validationOptions = serviceProvider.GetRequiredService>().Value; } public ICollectionRuleAction Create(IProcessInfo processInfo, CollectStacksOptions options) @@ -29,8 +33,7 @@ public ICollectionRuleAction Create(IProcessInfo processInfo, CollectStacksOptio throw new ArgumentNullException(nameof(options)); } - ValidationContext context = new(options, _serviceProvider, items: null); - Validator.ValidateObject(options, context, validateAllProperties: true); + ValidationHelper.ValidateObject(options, typeof(CollectStacksOptions), _validationOptions, _serviceProvider); return new CollectStacksAction(_serviceProvider, processInfo, options); } diff --git a/src/Tools/dotnet-monitor/CollectionRules/Actions/CollectTraceAction.cs b/src/Tools/dotnet-monitor/CollectionRules/Actions/CollectTraceAction.cs index a3c53868d36..fb3b69d8940 100644 --- a/src/Tools/dotnet-monitor/CollectionRules/Actions/CollectTraceAction.cs +++ b/src/Tools/dotnet-monitor/CollectionRules/Actions/CollectTraceAction.cs @@ -1,9 +1,11 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using Microsoft.AspNetCore.Http.Validation; using Microsoft.Diagnostics.Monitoring.EventPipe; using Microsoft.Diagnostics.Monitoring.WebApi; using Microsoft.Diagnostics.Monitoring.WebApi.Models; +using Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options; using Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Actions; using Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Configuration; using Microsoft.Extensions.DependencyInjection; @@ -11,7 +13,6 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration.Binder.SourceGeneration; using System; -using System.ComponentModel.DataAnnotations; using Utils = Microsoft.Diagnostics.Monitoring.WebApi.Utilities; namespace Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Actions @@ -20,6 +21,7 @@ internal sealed class CollectTraceActionFactory : ICollectionRuleActionFactory { private readonly IServiceProvider _serviceProvider; + private readonly ValidationOptions _validationOptions; public ICollectionRuleAction Create(IProcessInfo processInfo, CollectTraceOptions options) { @@ -28,8 +30,7 @@ public ICollectionRuleAction Create(IProcessInfo processInfo, CollectTraceOption throw new ArgumentNullException(nameof(options)); } - ValidationContext context = new(options, _serviceProvider, items: null); - Validator.ValidateObject(options, context, validateAllProperties: true); + ValidationHelper.ValidateObject(options, typeof(CollectTraceOptions), _validationOptions, _serviceProvider); return new CollectTraceAction(_serviceProvider, processInfo, options); } @@ -37,6 +38,7 @@ public ICollectionRuleAction Create(IProcessInfo processInfo, CollectTraceOption public CollectTraceActionFactory(IServiceProvider serviceProvider) { _serviceProvider = serviceProvider ?? throw new ArgumentNullException(nameof(serviceProvider)); + _validationOptions = serviceProvider.GetRequiredService>().Value; } private sealed class CollectTraceAction : diff --git a/src/Tools/dotnet-monitor/CollectionRules/Actions/CollectionRuleActionOperations.cs b/src/Tools/dotnet-monitor/CollectionRules/Actions/CollectionRuleActionOperations.cs index 746af4f906a..e92f1510ff9 100644 --- a/src/Tools/dotnet-monitor/CollectionRules/Actions/CollectionRuleActionOperations.cs +++ b/src/Tools/dotnet-monitor/CollectionRules/Actions/CollectionRuleActionOperations.cs @@ -89,7 +89,7 @@ public bool TryValidateOptions( } else { - results.Add(new ValidationResult(string.Format(CultureInfo.InvariantCulture, Strings.ErrorMessage_UnknownActionType, actionName))); + results.Add(new ValidationResult(string.Format(CultureInfo.InvariantCulture, Strings.ErrorMessage_UnknownActionType, actionName), [actionName])); return false; } } diff --git a/src/Tools/dotnet-monitor/CollectionRules/Actions/ExecuteAction.cs b/src/Tools/dotnet-monitor/CollectionRules/Actions/ExecuteAction.cs index 072bb23241b..67daa210c87 100644 --- a/src/Tools/dotnet-monitor/CollectionRules/Actions/ExecuteAction.cs +++ b/src/Tools/dotnet-monitor/CollectionRules/Actions/ExecuteAction.cs @@ -1,15 +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 Microsoft.AspNetCore.Http.Validation; using Microsoft.Diagnostics.Monitoring.EventPipe; using Microsoft.Diagnostics.Monitoring.WebApi; +using Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options; using Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Actions; +using Microsoft.Extensions.Options; using Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Configuration; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration.Binder.SourceGeneration; using System; using System.Collections.Generic; -using System.ComponentModel.DataAnnotations; using System.Diagnostics; using System.Globalization; using System.IO; @@ -21,6 +23,15 @@ namespace Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Actions internal sealed class ExecuteActionFactory : ICollectionRuleActionFactory { + private readonly IServiceProvider _serviceProvider; + private readonly ValidationOptions _validationOptions; + + public ExecuteActionFactory(IServiceProvider serviceProvider, IOptions validationOptions) + { + _serviceProvider = serviceProvider ?? throw new ArgumentNullException(nameof(serviceProvider)); + _validationOptions = validationOptions?.Value ?? throw new ArgumentNullException(nameof(validationOptions)); + } + public ICollectionRuleAction Create(IProcessInfo processInfo, ExecuteOptions options) { if (null == options) @@ -28,8 +39,7 @@ public ICollectionRuleAction Create(IProcessInfo processInfo, ExecuteOptions opt throw new ArgumentNullException(nameof(options)); } - ValidationContext context = new(options, null, items: null); - Validator.ValidateObject(options, context, validateAllProperties: true); + ValidationHelper.ValidateObject(options, typeof(ExecuteOptions), _validationOptions, _serviceProvider); return new ExecuteAction(processInfo, options); } diff --git a/src/Tools/dotnet-monitor/CollectionRules/Actions/GetEnvironmentVariableAction.cs b/src/Tools/dotnet-monitor/CollectionRules/Actions/GetEnvironmentVariableAction.cs index da2c1a777b7..6af2b909470 100644 --- a/src/Tools/dotnet-monitor/CollectionRules/Actions/GetEnvironmentVariableAction.cs +++ b/src/Tools/dotnet-monitor/CollectionRules/Actions/GetEnvironmentVariableAction.cs @@ -1,16 +1,19 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using Microsoft.AspNetCore.Http.Validation; using Microsoft.Diagnostics.Monitoring.WebApi; using Microsoft.Diagnostics.NETCore.Client; -using Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Configuration; +using Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options; using Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Actions; using Microsoft.Extensions.Logging; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; +using Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Configuration; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration.Binder.SourceGeneration; using System; using System.Collections.Generic; -using System.ComponentModel.DataAnnotations; using System.Threading; using System.Threading.Tasks; @@ -21,11 +24,13 @@ internal sealed partial class GetEnvironmentVariableActionFactory : { private readonly IServiceProvider _serviceProvider; private readonly ILogger _logger; + private readonly ValidationOptions _validationOptions; public GetEnvironmentVariableActionFactory(IServiceProvider serviceProvider, ILogger logger) { _serviceProvider = serviceProvider ?? throw new ArgumentNullException(nameof(serviceProvider)); _logger = logger ?? throw new ArgumentNullException(nameof(serviceProvider)); + _validationOptions = serviceProvider.GetRequiredService>().Value; } public ICollectionRuleAction Create(IProcessInfo processInfo, GetEnvironmentVariableOptions options) @@ -35,8 +40,7 @@ public ICollectionRuleAction Create(IProcessInfo processInfo, GetEnvironmentVari throw new ArgumentNullException(nameof(options)); } - ValidationContext context = new(options, _serviceProvider, items: null); - Validator.ValidateObject(options, context, validateAllProperties: true); + ValidationHelper.ValidateObject(options, typeof(GetEnvironmentVariableOptions), _validationOptions, _serviceProvider); return new GetEnvironmentVariableAction(_logger, processInfo, options); } diff --git a/src/Tools/dotnet-monitor/CollectionRules/Actions/LoadProfilerAction.cs b/src/Tools/dotnet-monitor/CollectionRules/Actions/LoadProfilerAction.cs index 46f336a90f5..4ec1a9b8d18 100644 --- a/src/Tools/dotnet-monitor/CollectionRules/Actions/LoadProfilerAction.cs +++ b/src/Tools/dotnet-monitor/CollectionRules/Actions/LoadProfilerAction.cs @@ -1,15 +1,18 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using Microsoft.AspNetCore.Http.Validation; using Microsoft.Diagnostics.Monitoring.WebApi; using Microsoft.Diagnostics.NETCore.Client; +using Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options; using Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Actions; using Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Configuration; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration.Binder.SourceGeneration; using System; -using System.ComponentModel.DataAnnotations; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; using System.Threading; using System.Threading.Tasks; @@ -20,11 +23,13 @@ internal sealed class LoadProfilerActionFactory : { private readonly IServiceProvider _serviceProvider; private readonly ILogger _logger; + private readonly ValidationOptions _validationOptions; public LoadProfilerActionFactory(IServiceProvider serviceProvider, ILogger logger) { _serviceProvider = serviceProvider ?? throw new ArgumentNullException(nameof(serviceProvider)); _logger = logger ?? throw new ArgumentNullException(nameof(serviceProvider)); + _validationOptions = serviceProvider.GetRequiredService>().Value; } public ICollectionRuleAction Create(IProcessInfo processInfo, LoadProfilerOptions options) @@ -34,8 +39,7 @@ public ICollectionRuleAction Create(IProcessInfo processInfo, LoadProfilerOption throw new ArgumentNullException(nameof(options)); } - ValidationContext context = new(options, _serviceProvider, items: null); - Validator.ValidateObject(options, context, validateAllProperties: true); + ValidationHelper.ValidateObject(options, typeof(LoadProfilerOptions), _validationOptions, _serviceProvider); return new LoadProfilerAction(_logger, processInfo, options); } diff --git a/src/Tools/dotnet-monitor/CollectionRules/Actions/SetEnvironmentVariableAction.cs b/src/Tools/dotnet-monitor/CollectionRules/Actions/SetEnvironmentVariableAction.cs index 66101ea2cdc..c501057751b 100644 --- a/src/Tools/dotnet-monitor/CollectionRules/Actions/SetEnvironmentVariableAction.cs +++ b/src/Tools/dotnet-monitor/CollectionRules/Actions/SetEnvironmentVariableAction.cs @@ -1,15 +1,18 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using Microsoft.AspNetCore.Http.Validation; using Microsoft.Diagnostics.Monitoring.WebApi; using Microsoft.Diagnostics.NETCore.Client; +using Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options; using Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Actions; -using Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Configuration; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; +using Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Configuration; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration.Binder.SourceGeneration; using System; -using System.ComponentModel.DataAnnotations; using System.Threading; using System.Threading.Tasks; @@ -20,11 +23,13 @@ internal sealed partial class SetEnvironmentVariableActionFactory : { private readonly IServiceProvider _serviceProvider; private readonly ILogger _logger; + private readonly ValidationOptions _validationOptions; public SetEnvironmentVariableActionFactory(IServiceProvider serviceProvider, ILogger logger) { _serviceProvider = serviceProvider ?? throw new ArgumentNullException(nameof(serviceProvider)); _logger = logger ?? throw new ArgumentNullException(nameof(logger)); + _validationOptions = serviceProvider.GetRequiredService>().Value; } public ICollectionRuleAction Create(IProcessInfo processInfo, SetEnvironmentVariableOptions options) @@ -34,8 +39,7 @@ public ICollectionRuleAction Create(IProcessInfo processInfo, SetEnvironmentVari throw new ArgumentNullException(nameof(options)); } - ValidationContext context = new(options, _serviceProvider, items: null); - Validator.ValidateObject(options, context, validateAllProperties: true); + ValidationHelper.ValidateObject(options, typeof(SetEnvironmentVariableOptions), _validationOptions, _serviceProvider); return new SetEnvironmentVariableAction(_logger, processInfo, options); } diff --git a/src/Tools/dotnet-monitor/CollectionRules/Configuration/CollectionRulePostConfigureNamedOptions.cs b/src/Tools/dotnet-monitor/CollectionRules/Configuration/CollectionRulePostConfigureNamedOptions.cs index 46a5ab241f5..d992fb085c4 100644 --- a/src/Tools/dotnet-monitor/CollectionRules/Configuration/CollectionRulePostConfigureNamedOptions.cs +++ b/src/Tools/dotnet-monitor/CollectionRules/Configuration/CollectionRulePostConfigureNamedOptions.cs @@ -56,7 +56,8 @@ private void ResolveActionList(CollectionRuleOptions ruleOptions, IConfiguration // The Section Key is the action index; the value (if present) is the name of the template if (SectionHasValue(actionSection)) { - TryGetTemplate(ruleOptions, nameof(ruleOptions.Actions), _templateOptions.CollectionRuleActions, actionSection.Value, out CollectionRuleActionOptions templateActionOptions); + var memberName = nameof(ruleOptions.Actions) + "[" + ruleOptions.Actions.Count.ToString(CultureInfo.InvariantCulture) + "]"; + TryGetTemplate(ruleOptions, memberName, _templateOptions.CollectionRuleActions, actionSection.Value, out CollectionRuleActionOptions templateActionOptions); ruleOptions.Actions.Add(templateActionOptions); } @@ -100,7 +101,7 @@ private void ResolveFilterList(CollectionRuleOptions ruleOptions, IConfiguration // The Section Key is the filter index; the value (if present) is the name of the template if (SectionHasValue(filterSection)) { - TryGetTemplate(ruleOptions, nameof(ruleOptions.Filters), _templateOptions.CollectionRuleFilters, filterSection.Value, out ProcessFilterDescriptor templateFilterOptions); + TryGetTemplate(ruleOptions, nameof(ruleOptions.Filters), _templateOptions.CollectionRuleFilters, filterSection.Value, out ProcessFilterDescriptor templateFilterOptions); ruleOptions.Filters.Add(templateFilterOptions); } diff --git a/src/Tools/dotnet-monitor/CollectionRules/Options/Actions/CollectExceptionsOptions.Validate.cs b/src/Tools/dotnet-monitor/CollectionRules/Options/Actions/CollectExceptionsOptions.Validate.cs index 05cf725f5f4..01f2d44124d 100644 --- a/src/Tools/dotnet-monitor/CollectionRules/Options/Actions/CollectExceptionsOptions.Validate.cs +++ b/src/Tools/dotnet-monitor/CollectionRules/Options/Actions/CollectExceptionsOptions.Validate.cs @@ -27,7 +27,7 @@ IEnumerable IValidatableObject.Validate(ValidationContext vali string.Format( CultureInfo.InvariantCulture, Strings.ErrorMessage_DisabledFeature, - nameof(CollectExceptionsAction)))); + nameof(CollectExceptionsAction)), [nameof(CollectExceptionsAction)])); } return results; 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 e8ede3ded8c..624db8b4c86 100644 --- a/src/Tools/dotnet-monitor/CollectionRules/Options/Actions/CollectLogsOptions.Validate.cs +++ b/src/Tools/dotnet-monitor/CollectionRules/Options/Actions/CollectLogsOptions.Validate.cs @@ -1,4 +1,4 @@ -// Licensed to the .NET Foundation under one or more agreements. +// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using Microsoft.Extensions.Logging; @@ -23,7 +23,7 @@ IEnumerable IValidatableObject.Validate(ValidationContext vali RequiredAttribute requiredAttribute = new(); EnumDataTypeAttribute enumValidationAttribute = new(typeof(LogLevel)); - ValidationContext filterSpecsContext = new(FilterSpecs, validationContext, validationContext.Items); + ValidationContext filterSpecsContext = new(FilterSpecs, nameof(FilterSpecs), validationContext, validationContext.Items); filterSpecsContext.MemberName = nameof(FilterSpecs); // Validate that the category is not null and that the level is a valid level value. diff --git a/src/Tools/dotnet-monitor/CollectionRules/Options/Actions/CollectStacksOptions.Validate.cs b/src/Tools/dotnet-monitor/CollectionRules/Options/Actions/CollectStacksOptions.Validate.cs index 362985a54c8..27eee18bf69 100644 --- a/src/Tools/dotnet-monitor/CollectionRules/Options/Actions/CollectStacksOptions.Validate.cs +++ b/src/Tools/dotnet-monitor/CollectionRules/Options/Actions/CollectStacksOptions.Validate.cs @@ -26,7 +26,7 @@ IEnumerable IValidatableObject.Validate(ValidationContext vali string.Format( CultureInfo.InvariantCulture, Strings.ErrorMessage_DisabledFeature, - nameof(CollectionRules.Actions.CollectStacksAction)))); + nameof(CollectionRules.Actions.CollectStacksAction)), [nameof(CollectionRules.Actions.CollectStacksAction)])); } return results; 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 6874ec2354b..9107de46d08 100644 --- a/src/Tools/dotnet-monitor/CollectionRules/Options/Actions/CollectTraceOptions.Validate.cs +++ b/src/Tools/dotnet-monitor/CollectionRules/Options/Actions/CollectTraceOptions.Validate.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using Microsoft.AspNetCore.Http.Validation; using Microsoft.Diagnostics.Monitoring.WebApi; using Microsoft.Diagnostics.Monitoring.WebApi.Models; using Microsoft.Diagnostics.Monitoring.WebApi.Validation; @@ -53,7 +54,7 @@ IEnumerable IValidatableObject.Validate(ValidationContext vali CultureInfo.InvariantCulture, Strings.ErrorMessage_TwoFieldsCannotBeSpecified, nameof(Profile), - nameof(StoppingEvent)))); + nameof(StoppingEvent)), [nameof(Profile), nameof(StoppingEvent)])); } if (HasProviders()) @@ -66,7 +67,7 @@ IEnumerable IValidatableObject.Validate(ValidationContext vali CultureInfo.InvariantCulture, Strings.ErrorMessage_TwoFieldsCannotBeSpecified, nameof(Profile), - nameof(Providers)))); + nameof(Providers)), [nameof(Profile), nameof(Providers)])); } } else if (HasProviders()) @@ -80,17 +81,20 @@ IEnumerable IValidatableObject.Validate(ValidationContext vali } catch (OptionsValidationException e) { - results.AddRange(e.Failures.Select((string failure) => new ValidationResult(e.Message))); + results.AddRange(e.Failures.Select((string failure) => new ValidationResult(e.Message, [e.OptionsType.Name]))); } // Validate that each provider is valid. + // Necessary to work around the generated validation code not recursing into List? members: + // https://github.com/dotnet/aspnetcore/issues/61737 int index = 0; foreach (EventPipeProvider provider in Providers) { - ValidationContext providerContext = new(provider, validationContext, validationContext.Items); + ValidationContext providerContext = new(provider, nameof(Providers), validationContext, validationContext.Items); providerContext.MemberName = nameof(Providers) + "[" + index.ToString(CultureInfo.InvariantCulture) + "]"; - Validator.TryValidateObject(provider, providerContext, results, validateAllProperties: true); + var validationOptions = validationContext.GetRequiredService>().Value; + ValidationHelper.TryValidateObject(provider, typeof(EventPipeProvider), validationOptions, providerContext, results); if (counterOptions != null && !CounterValidator.ValidateProvider(counterOptions, provider, out string? errorMessage)) { @@ -108,7 +112,7 @@ IEnumerable IValidatableObject.Validate(ValidationContext vali CultureInfo.InvariantCulture, Strings.ErrorMessage_TwoFieldsMissing, nameof(Profile), - nameof(Providers)))); + nameof(Providers)), [nameof(Profile), nameof(Providers)])); } if (HasStoppingEvent()) @@ -124,7 +128,7 @@ IEnumerable IValidatableObject.Validate(ValidationContext vali Strings.ErrorMessage_MissingStoppingEventProvider, nameof(StoppingEvent), StoppingEvent.ProviderName, - nameof(Providers)))); + nameof(Providers)), [nameof(StoppingEvent), nameof(Providers)])); } } diff --git a/src/Tools/dotnet-monitor/CollectionRules/Options/Actions/RequiredGuidAttribute.cs b/src/Tools/dotnet-monitor/CollectionRules/Options/Actions/RequiredGuidAttribute.cs index e23e9a230a4..117674c27f1 100644 --- a/src/Tools/dotnet-monitor/CollectionRules/Options/Actions/RequiredGuidAttribute.cs +++ b/src/Tools/dotnet-monitor/CollectionRules/Options/Actions/RequiredGuidAttribute.cs @@ -20,10 +20,14 @@ public override string FormatErrorMessage(string name) protected override ValidationResult? IsValid(object? value, ValidationContext validationContext) { + if (validationContext.MemberName is null) + { + throw new ArgumentNullException(nameof(validationContext.MemberName)); + } if (!(value is Guid)) { return new ValidationResult( - FormatErrorMessage(validationContext.DisplayName)); + FormatErrorMessage(validationContext.DisplayName), [validationContext.MemberName]); } Guid guidVal = (Guid)value; @@ -31,7 +35,7 @@ public override string FormatErrorMessage(string name) if (guidVal == Guid.Empty) { return new ValidationResult( - FormatErrorMessage(validationContext.DisplayName)); + FormatErrorMessage(validationContext.DisplayName), [validationContext.MemberName]); } return ValidationResult.Success; diff --git a/src/Tools/dotnet-monitor/CollectionRules/Options/Actions/ValidateEgressProviderAttribute.cs b/src/Tools/dotnet-monitor/CollectionRules/Options/Actions/ValidateEgressProviderAttribute.cs index 5e77e45e06c..6743a5395a0 100644 --- a/src/Tools/dotnet-monitor/CollectionRules/Options/Actions/ValidateEgressProviderAttribute.cs +++ b/src/Tools/dotnet-monitor/CollectionRules/Options/Actions/ValidateEgressProviderAttribute.cs @@ -14,10 +14,14 @@ internal sealed class ValidateEgressProviderAttribute : { protected override ValidationResult? IsValid(object? value, ValidationContext validationContext) { + if (validationContext.MemberName is null) + { + throw new ArgumentNullException(nameof(validationContext.MemberName)); + } if (!(value is string)) { return new ValidationResult( - FormatErrorMessage(validationContext.DisplayName)); + FormatErrorMessage(validationContext.DisplayName), [validationContext.MemberName]); } string egressProvider = (string)value; @@ -33,7 +37,7 @@ internal sealed class ValidateEgressProviderAttribute : string.Format( CultureInfo.InvariantCulture, Strings.ErrorMessage_EgressProviderDoesNotExist, - egressProvider)); + egressProvider), [validationContext.MemberName]); } return ValidationResult.Success; diff --git a/src/Tools/dotnet-monitor/CollectionRules/Options/CollectionRuleActionOptions.Validate.cs b/src/Tools/dotnet-monitor/CollectionRules/Options/CollectionRuleActionOptions.Validate.cs index 45d41c6977a..ede73aff565 100644 --- a/src/Tools/dotnet-monitor/CollectionRules/Options/CollectionRuleActionOptions.Validate.cs +++ b/src/Tools/dotnet-monitor/CollectionRules/Options/CollectionRuleActionOptions.Validate.cs @@ -18,6 +18,10 @@ IEnumerable IValidatableObject.Validate(ValidationContext vali if (!string.IsNullOrEmpty(Type)) { + validationContext = new ValidationContext(this, displayName: nameof(Settings), validationContext, items: null) + { + MemberName = nameof(Settings) + }; actionOperations.TryValidateOptions(Type, Settings, validationContext, results); } diff --git a/src/Tools/dotnet-monitor/CollectionRules/Options/CollectionRuleOptions.Validate.cs b/src/Tools/dotnet-monitor/CollectionRules/Options/CollectionRuleOptions.Validate.cs index 2af986cc1a8..60e5949f33a 100644 --- a/src/Tools/dotnet-monitor/CollectionRules/Options/CollectionRuleOptions.Validate.cs +++ b/src/Tools/dotnet-monitor/CollectionRules/Options/CollectionRuleOptions.Validate.cs @@ -1,4 +1,4 @@ -// Licensed to the .NET Foundation under one or more agreements. +// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. #nullable disable @@ -27,21 +27,6 @@ IEnumerable IValidatableObject.Validate(ValidationContext vali return results; } - ValidationContext filtersContext = new(Filters, validationContext, validationContext.Items); - filtersContext.MemberName = nameof(Filters); - ValidationHelper.TryValidateItems(Filters, filtersContext, results); - - if (null != Trigger) - { - ValidationContext triggerContext = new(Trigger, validationContext, validationContext.Items); - triggerContext.MemberName = nameof(Trigger); - Validator.TryValidateObject(Trigger, triggerContext, results); - } - - ValidationContext actionsContext = new(Actions, validationContext, validationContext.Items); - actionsContext.MemberName = nameof(Actions); - ValidationHelper.TryValidateItems(Actions, actionsContext, results); - var actionNames = new HashSet(StringComparer.Ordinal); foreach (CollectionRuleActionOptions option in Actions) { diff --git a/src/Tools/dotnet-monitor/CollectionRules/Options/Triggers/EventCounterOptions.Validate.cs b/src/Tools/dotnet-monitor/CollectionRules/Options/Triggers/EventCounterOptions.Validate.cs index 44c132c45ee..689ba328238 100644 --- a/src/Tools/dotnet-monitor/CollectionRules/Options/Triggers/EventCounterOptions.Validate.cs +++ b/src/Tools/dotnet-monitor/CollectionRules/Options/Triggers/EventCounterOptions.Validate.cs @@ -19,7 +19,7 @@ IEnumerable IValidatableObject.Validate(ValidationContext vali string.Format( Strings.ErrorMessage_TwoFieldsMissing, nameof(GreaterThan), - nameof(LessThan)))); + nameof(LessThan)), [nameof(GreaterThan), nameof(LessThan)])); } else if (GreaterThan.HasValue && LessThan.HasValue && LessThan.Value < GreaterThan.Value) { @@ -28,7 +28,7 @@ IEnumerable IValidatableObject.Validate(ValidationContext vali string.Format( Strings.ErrorMessage_FieldMustBeLessThanOtherField, nameof(GreaterThan), - nameof(LessThan)))); + nameof(LessThan)), [nameof(GreaterThan), nameof(LessThan)])); } return results; diff --git a/src/Tools/dotnet-monitor/CollectionRules/Options/Triggers/EventCounterShortcuts/IEventCounterShortcuts.Validate.cs b/src/Tools/dotnet-monitor/CollectionRules/Options/Triggers/EventCounterShortcuts/IEventCounterShortcuts.Validate.cs index 5f81bfb93ca..8081f9df8d3 100644 --- a/src/Tools/dotnet-monitor/CollectionRules/Options/Triggers/EventCounterShortcuts/IEventCounterShortcuts.Validate.cs +++ b/src/Tools/dotnet-monitor/CollectionRules/Options/Triggers/EventCounterShortcuts/IEventCounterShortcuts.Validate.cs @@ -19,7 +19,7 @@ IEnumerable IValidatableObject.Validate(ValidationContext vali string.Format( Strings.ErrorMessage_FieldMustBeLessThanOtherField, nameof(GreaterThan), - nameof(LessThan)))); + nameof(LessThan)), [nameof(GreaterThan), nameof(LessThan)])); } return results; diff --git a/src/Tools/dotnet-monitor/CollectionRules/Options/Triggers/EventMeterOptions.Validate.cs b/src/Tools/dotnet-monitor/CollectionRules/Options/Triggers/EventMeterOptions.Validate.cs index 3ac644373fb..30952baf8dd 100644 --- a/src/Tools/dotnet-monitor/CollectionRules/Options/Triggers/EventMeterOptions.Validate.cs +++ b/src/Tools/dotnet-monitor/CollectionRules/Options/Triggers/EventMeterOptions.Validate.cs @@ -19,7 +19,7 @@ IEnumerable IValidatableObject.Validate(ValidationContext vali string.Format( Strings.ErrorMessage_TwoFieldsMissing, nameof(GreaterThan), - nameof(LessThan)))); + nameof(LessThan)), [nameof(GreaterThan), nameof(LessThan)])); } else if (GreaterThan.HasValue && LessThan.HasValue && LessThan.Value < GreaterThan.Value) { @@ -28,7 +28,7 @@ IEnumerable IValidatableObject.Validate(ValidationContext vali string.Format( Strings.ErrorMessage_FieldMustBeLessThanOtherField, nameof(GreaterThan), - nameof(LessThan)))); + nameof(LessThan)), [nameof(GreaterThan), nameof(LessThan)])); } return results; diff --git a/src/Tools/dotnet-monitor/CollectionRules/Options/ValidationHelper.cs b/src/Tools/dotnet-monitor/CollectionRules/Options/ValidationHelper.cs index c99543df9c0..c6fd02c9f80 100644 --- a/src/Tools/dotnet-monitor/CollectionRules/Options/ValidationHelper.cs +++ b/src/Tools/dotnet-monitor/CollectionRules/Options/ValidationHelper.cs @@ -1,31 +1,23 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using Microsoft.AspNetCore.Http.Validation; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Reflection; +using System.Threading; +#if EXTENSION +namespace Microsoft.Diagnostics.Monitoring.Extension.Common +#else namespace Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options +#endif { internal static class ValidationHelper { - public static void TryValidateItems(IEnumerable items, ValidationContext validationContext, ICollection results) - { - int index = 0; - foreach (object item in items) - { - ValidationContext itemContext = new(item, validationContext, validationContext.Items); - itemContext.MemberName = validationContext.MemberName + "[" + index.ToString() + "]"; - - Validator.TryValidateObject(item, itemContext, results); - - index++; - } - } - #nullable disable public static bool TryValidateOptions(Type optionsType, object options, ValidationContext validationContext, ICollection results) { @@ -45,7 +37,7 @@ public static bool TryValidateOptions(Type optionsType, object options, Validati { foreach (string failure in validateResult.Failures) { - results.Add(new ValidationResult(failure)); + results.Add(new ValidationResult(failure, [validationContext.MemberName])); hasFailedResults = true; } } @@ -59,6 +51,58 @@ public static bool TryValidateOptions(Type optionsType, object options, Validati return false; } } -#nullable restore +#nullable enable + + public static bool TryValidateObject(object options, Type type, ValidationOptions validationOptions, ValidationContext validationContext, ICollection results) + { + return TryValidateObject(options, type, validationOptions, validationContext, results); + } + + public static bool TryValidateObject(object options, Type type, ValidationOptions validationOptions, IServiceProvider serviceProvider, List results) + { + var validationContext = new ValidationContext(options, type.Name, serviceProvider, items: null) { + MemberName = type.Name + }; + return TryValidateObject(options, type, validationOptions, validationContext, results); + } + + public static bool TryValidateObject(object options, Type type, ValidationOptions validationOptions, ValidationContext validationContext, List results) + { + if (!validationOptions.TryGetValidatableTypeInfo(type, out IValidatableInfo? validatableTypeInfo)) + { + throw new Exception("No type info found for type " + type.FullName); + } + if (validationContext.MemberName is null) + { + throw new ArgumentNullException(nameof(validationContext.MemberName)); + } + var validateContext = new ValidateContext() + { + ValidationOptions = validationOptions, + ValidationContext = validationContext + }; + validatableTypeInfo.ValidateAsync(options, validateContext, CancellationToken.None).GetAwaiter().GetResult(); + if (validateContext.ValidationErrors is Dictionary validationErrors) + { + foreach (var (name, errors) in validationErrors) + { + foreach (var error in errors) + { + results.Add(new ValidationResult(error, [name])); + } + } + return false; + } + return true; + } + + public static void ValidateObject(object options, Type type, ValidationOptions validationOptions, IServiceProvider serviceProvider) + { + List results = new(); + if (!TryValidateObject(options, type, validationOptions, serviceProvider, results)) + { + throw new ValidationException(string.Join(Environment.NewLine, results.ConvertAll(r => r.ErrorMessage))); + } + } } } diff --git a/src/Tools/dotnet-monitor/CollectionRules/Triggers/CollectionRuleTriggerOperations.cs b/src/Tools/dotnet-monitor/CollectionRules/Triggers/CollectionRuleTriggerOperations.cs index efdf694c883..2c2ccc7d03b 100644 --- a/src/Tools/dotnet-monitor/CollectionRules/Triggers/CollectionRuleTriggerOperations.cs +++ b/src/Tools/dotnet-monitor/CollectionRules/Triggers/CollectionRuleTriggerOperations.cs @@ -107,7 +107,7 @@ public bool TryValidateOptions( } else { - results.Add(new ValidationResult(string.Format(CultureInfo.InvariantCulture, Strings.ErrorMessage_UnknownTriggerType, triggerName))); + results.Add(new ValidationResult(string.Format(CultureInfo.InvariantCulture, Strings.ErrorMessage_UnknownTriggerType, triggerName), [validationContext.MemberName])); return false; } } diff --git a/src/Tools/dotnet-monitor/Commands/CollectCommandHandler.cs b/src/Tools/dotnet-monitor/Commands/CollectCommandHandler.cs index cd1e585887f..1463b2afb1c 100644 --- a/src/Tools/dotnet-monitor/Commands/CollectCommandHandler.cs +++ b/src/Tools/dotnet-monitor/Commands/CollectCommandHandler.cs @@ -85,7 +85,7 @@ private static IHostBuilder Configure(this IHostBuilder builder, StartupAuthenti { return builder.ConfigureServices((HostBuilderContext context, IServiceCollection services) => { - IAuthenticationConfigurator authConfigurator = AuthConfiguratorFactory.Create(startupAuthMode, context); + IAuthenticationConfigurator authConfigurator = AuthConfiguratorFactory.Create(startupAuthMode, context, services.BuildServiceProvider()); services.AddSingleton(authConfigurator); //TODO Many of these service additions should be done through extension methods diff --git a/src/Tools/dotnet-monitor/CustomValidationInfo.cs b/src/Tools/dotnet-monitor/CustomValidationInfo.cs new file mode 100644 index 00000000000..3ecc73149d5 --- /dev/null +++ b/src/Tools/dotnet-monitor/CustomValidationInfo.cs @@ -0,0 +1,271 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Microsoft.AspNetCore.Http.Validation; +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Linq; +using System.Reflection; +using System.Threading.Tasks; +using System.Threading; + +#nullable enable + +namespace Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options +{ + public class CustomValidatableInfoResolver : IValidatableInfoResolver + { + public bool TryGetValidatableTypeInfo(Type type, [NotNullWhen(true)] out IValidatableInfo? validatableInfo) + { + if (type == typeof(CollectionRuleOptions)) + { + validatableInfo = new CollectionRuleOptionsTypeInfo(); + return true; + } + + validatableInfo = null; + return false; + } + + public bool TryGetValidatableParameterInfo(ParameterInfo parameterInfo, [NotNullWhen(true)] out IValidatableInfo? validatableInfo) + { + validatableInfo = null; + return false; + } + + sealed class CollectionRuleOptionsTypeInfo : ValidatableTypeInfo + { + public CollectionRuleOptionsTypeInfo() + : this( + [ + new CustomValidatablePropertyInfo( + containingType: typeof(CollectionRuleOptions), + propertyType: typeof(CollectionRuleTriggerOptions), + name: "Trigger", + displayName: "Trigger" + ), + new CustomValidatablePropertyInfo( + containingType: typeof(CollectionRuleOptions), + propertyType: typeof(List), + name: "Actions", + displayName: "Actions" + ), + new CustomValidatablePropertyInfo( + containingType: typeof(CollectionRuleOptions), + propertyType: typeof(CollectionRuleLimitsOptions), + name: "Limits", + displayName: "Limits" + ) + ]) + { + } + + private CollectionRuleOptionsTypeInfo(ValidatablePropertyInfo[] members) + : base(typeof(CollectionRuleOptions), members) + { + Members = members; + _membersCount = members.Length; + } + + private readonly int _membersCount; + + internal IReadOnlyList Members { get; } + + public override async Task ValidateAsync(object? value, ValidateContext context, CancellationToken cancellationToken) + { + Debug.Assert(context.ValidationContext is not null); + if (value == null) + { + return; + } + + // Check if we've exceeded the maximum depth + if (context.CurrentDepth >= context.ValidationOptions.MaxDepth) + { + throw new InvalidOperationException( + $"Maximum validation depth of {context.ValidationOptions.MaxDepth} exceeded at '{context.CurrentValidationPath}' in '{nameof(CollectionRuleOptions)}'. " + + "This is likely caused by a circular reference in the object graph. " + + "Consider increasing the MaxDepth in ValidationOptions if deeper validation is required."); + } + + var originalPrefix = context.CurrentValidationPath; + + try + { + // Finally validate IValidatableObject if implemented + if (value is IValidatableObject validatable) + { + // Important: Set the DisplayName to the type name for top-level validations + // and restore the original validation context properties + var originalDisplayName = context.ValidationContext.DisplayName; + var originalMemberName = context.ValidationContext.MemberName; + + // Set the display name to the class name for IValidatableObject validation + context.ValidationContext.DisplayName = nameof(CollectionRuleOptions); + context.ValidationContext.MemberName = null; + + var validationResults = validatable.Validate(context.ValidationContext); + bool hasErrors = false; + foreach (var validationResult in validationResults) + { + if (validationResult != ValidationResult.Success && validationResult.ErrorMessage is not null) + { + var memberName = validationResult.MemberNames.First(); + var key = string.IsNullOrEmpty(originalPrefix) ? + memberName : + $"{originalPrefix}.{memberName}"; + + context.AddOrExtendValidationError(key, validationResult.ErrorMessage); + hasErrors = true; + } + } + + // Restore the original validation context properties + context.ValidationContext.DisplayName = originalDisplayName; + context.ValidationContext.MemberName = originalMemberName; + if (hasErrors) + { + return; + } + } + + // Validate members + for (var i = 0; i < _membersCount; i++) + { + await Members[i].ValidateAsync(value, context, cancellationToken); + context.CurrentValidationPath = originalPrefix; + } + } + finally + { + context.CurrentValidationPath = originalPrefix; + } + } + } + + sealed class CustomValidatablePropertyInfo : ValidatablePropertyInfo + { + public CustomValidatablePropertyInfo( + Type containingType, + Type propertyType, + string name, + string displayName) : base(containingType, propertyType, name, displayName) + { + ContainingType = containingType; + Name = name; + } + + internal Type ContainingType { get; } + internal string Name { get; } + + protected override ValidationAttribute[] GetValidationAttributes() + => ValidationAttributeCache.GetValidationAttributes(ContainingType, Name); + } + + static class ValidationAttributeCache + { + private sealed record CacheKey(Type ContainingType, string PropertyName); + private static readonly ConcurrentDictionary _cache = new(); + + public static ValidationAttribute[] GetValidationAttributes(Type containingType, string propertyName) + { + var key = new CacheKey(containingType, propertyName); + return _cache.GetOrAdd(key, static k => + { + var results = new List(); + + // Get attributes from the property + var property = k.ContainingType.GetProperty(k.PropertyName); + if (property != null) + { + var propertyAttributes = CustomAttributeExtensions.GetCustomAttributes(property, inherit: true); + + results.AddRange(propertyAttributes); + } + + // Check constructors for parameters that match the property name + // to handle record scenarios + foreach (var constructor in k.ContainingType.GetConstructors()) + { + // Look for parameter with matching name (case insensitive) + var parameter = Enumerable.FirstOrDefault( + constructor.GetParameters(), + p => string.Equals(p.Name, k.PropertyName, global::System.StringComparison.OrdinalIgnoreCase)); + + if (parameter != null) + { + var paramAttributes = CustomAttributeExtensions.GetCustomAttributes(parameter, inherit: true); + + results.AddRange(paramAttributes); + + break; + } + } + + return results.ToArray(); + }); + } + } + } + + internal static class TypeExtensions + { + public static List GetAllImplementedTypes([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.Interfaces)] this Type type) + { + ArgumentNullException.ThrowIfNull(type); + + var implementedTypes = new List(); + + // Yield all interfaces directly and indirectly implemented by this type + foreach (var interfaceType in type.GetInterfaces()) + { + implementedTypes.Add(interfaceType); + } + + // Finally, walk up the inheritance chain + var baseType = type.BaseType; + while (baseType != null && baseType != typeof(object)) + { + implementedTypes.Add(baseType); + baseType = baseType.BaseType; + } + + return implementedTypes; + } + + public static bool ImplementsInterface(this Type type, Type interfaceType) + { + ArgumentNullException.ThrowIfNull(type); + ArgumentNullException.ThrowIfNull(interfaceType); + + // Check if interfaceType is actually an interface + if (!interfaceType.IsInterface) + { + throw new ArgumentException($"Type {interfaceType.FullName} is not an interface.", nameof(interfaceType)); + } + + return interfaceType.IsAssignableFrom(type); + } + } + + internal static class ValidateContextExtensions + { + internal static void AddOrExtendValidationError(this ValidateContext context, string key, string error) + { + context.ValidationErrors ??= []; + + if (context.ValidationErrors.TryGetValue(key, out var existingErrors) && !existingErrors.Contains(error)) + { + context.ValidationErrors[key] = [.. existingErrors, error]; + } + else + { + context.ValidationErrors[key] = [error]; + } + } + } +} diff --git a/src/Tools/dotnet-monitor/DataAnnotationValidateOptions.cs b/src/Tools/dotnet-monitor/DataAnnotationValidateOptions.cs index 2b6548a03b3..56c1583a83c 100644 --- a/src/Tools/dotnet-monitor/DataAnnotationValidateOptions.cs +++ b/src/Tools/dotnet-monitor/DataAnnotationValidateOptions.cs @@ -3,11 +3,15 @@ #nullable enable +using Microsoft.AspNetCore.Http.Validation; using Microsoft.Extensions.Options; +using Microsoft.Extensions.DependencyInjection; using System; using System.Collections.Generic; -using System.Collections.ObjectModel; using System.ComponentModel.DataAnnotations; +#if !EXTENSION +using Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options; +#endif #if EXTENSION namespace Microsoft.Diagnostics.Monitoring.Extension.Common @@ -20,33 +24,30 @@ internal sealed class DataAnnotationValidateOptions : where TOptions : class { private readonly IServiceProvider _serviceProvider; + private readonly ValidationOptions _validationOptions; public DataAnnotationValidateOptions(IServiceProvider serviceProvider) { _serviceProvider = serviceProvider; + _validationOptions = serviceProvider.GetRequiredService>().Value; } public ValidateOptionsResult Validate(string? name, TOptions options) { - ValidationContext validationContext = new(options, _serviceProvider, null); - ICollection results = new Collection(); - if (!Validator.TryValidateObject(options, validationContext, results, validateAllProperties: true)) + var results = new List(); + if (!ValidationHelper.TryValidateObject(options, typeof(TOptions), _validationOptions, _serviceProvider, results)) { IList failures = new List(); foreach (ValidationResult result in results) { - if (ValidationResult.Success != result) + if (result.ErrorMessage is null) { -#nullable disable - failures.Add(result.ErrorMessage); -#nullable restore + throw new ArgumentNullException(nameof(result.ErrorMessage)); } + failures.Add(result.ErrorMessage); } - if (failures.Count > 0) - { - return ValidateOptionsResult.Fail(failures); - } + return ValidateOptionsResult.Fail(failures); } return ValidateOptionsResult.Success; diff --git a/src/Tools/dotnet-monitor/Egress/Extension/EgressExtension.cs b/src/Tools/dotnet-monitor/Egress/Extension/EgressExtension.cs index fdcf814c0ac..aebb2074656 100644 --- a/src/Tools/dotnet-monitor/Egress/Extension/EgressExtension.cs +++ b/src/Tools/dotnet-monitor/Egress/Extension/EgressExtension.cs @@ -3,9 +3,12 @@ #nullable disable +using Microsoft.AspNetCore.Http.Validation; using Microsoft.Diagnostics.Tools.Monitor.Egress.Configuration; using Microsoft.Diagnostics.Tools.Monitor.Extensibility; using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; using System; @@ -29,6 +32,8 @@ internal partial class EgressExtension : IExtension, IEgressExtension private readonly string _extensionPath; private readonly ILogger _logger; private readonly ExtensionManifest _manifest; + private readonly IServiceProvider _serviceProvider; + private readonly ValidationOptions _validationOptions; private readonly IDictionary _processEnvironmentVariables = new Dictionary(); private const int PayloadProtocolVersion = 1; @@ -38,12 +43,15 @@ public EgressExtension( ExtensionManifest manifest, string extensionPath, IEgressConfigurationProvider configurationProvider, - ILogger logger) + ILogger logger, + IServiceProvider serviceProvider) { _configurationProvider = configurationProvider ?? throw new ArgumentNullException(nameof(configurationProvider)); _extensionPath = extensionPath ?? throw new ArgumentNullException(nameof(extensionPath)); _logger = logger ?? throw new ArgumentNullException(nameof(logger)); _manifest = manifest ?? throw new ArgumentNullException(nameof(manifest)); + _serviceProvider = serviceProvider ?? throw new ArgumentNullException(nameof(serviceProvider)); + _validationOptions = serviceProvider.GetRequiredService>().Value; } /// @@ -107,7 +115,7 @@ public async Task EgressArtifact( ExtensionMode mode, CancellationToken token) { - _manifest.Validate(); + _manifest.Validate(_serviceProvider, _validationOptions); ProcessStartInfo pStart = new ProcessStartInfo() { diff --git a/src/Tools/dotnet-monitor/Egress/Extension/EgressExtensionFactory.cs b/src/Tools/dotnet-monitor/Egress/Extension/EgressExtensionFactory.cs index dbc690c5bd5..eafe34882e3 100644 --- a/src/Tools/dotnet-monitor/Egress/Extension/EgressExtensionFactory.cs +++ b/src/Tools/dotnet-monitor/Egress/Extension/EgressExtensionFactory.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System; using Microsoft.Diagnostics.Tools.Monitor.Egress.Configuration; using Microsoft.Diagnostics.Tools.Monitor.Extensibility; using Microsoft.Extensions.Logging; @@ -11,18 +12,21 @@ internal sealed class EgressExtensionFactory { private readonly IEgressConfigurationProvider _configurationProvider; private readonly ILogger _logger; + private readonly IServiceProvider _serviceProvider; public EgressExtensionFactory( IEgressConfigurationProvider configurationProvider, - ILogger logger) + ILogger logger, + IServiceProvider serviceProvider) { _configurationProvider = configurationProvider; _logger = logger; + _serviceProvider = serviceProvider; } public IEgressExtension Create(ExtensionManifest manifest, string path) { - return new EgressExtension(manifest, path, _configurationProvider, _logger); + return new EgressExtension(manifest, path, _configurationProvider, _logger, _serviceProvider); } } } diff --git a/src/Tools/dotnet-monitor/Extensibility/ExtensionManifest.cs b/src/Tools/dotnet-monitor/Extensibility/ExtensionManifest.cs index 4af5efa5c31..faaab28ac3f 100644 --- a/src/Tools/dotnet-monitor/Extensibility/ExtensionManifest.cs +++ b/src/Tools/dotnet-monitor/Extensibility/ExtensionManifest.cs @@ -3,6 +3,8 @@ #nullable disable +using Microsoft.AspNetCore.Http.Validation; +using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Globalization; @@ -10,6 +12,7 @@ using System.Linq; using System.Text.Json; using System.Text.Json.Serialization; +using Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options; namespace Microsoft.Diagnostics.Tools.Monitor.Extensibility { @@ -70,11 +73,10 @@ public static ExtensionManifest FromPath(string path) } } - public void Validate() + public void Validate(IServiceProvider serviceProvider, ValidationOptions validationOptions) { List results = new(); - if (!Validator.TryValidateObject(this, new ValidationContext(this), results, validateAllProperties: true) && - results.Count > 0) + if (!ValidationHelper.TryValidateObject(this, typeof(ExtensionManifest), validationOptions, serviceProvider, results)) { ExtensionException.ThrowInvalidManifest(results.First().ErrorMessage); } @@ -95,7 +97,8 @@ public IEnumerable Validate(ValidationContext validationContex CultureInfo.InvariantCulture, Strings.ErrorMessage_TwoFieldsCannotBeSpecified, nameof(AssemblyFileName), - nameof(ExecutableFileName)))); + nameof(ExecutableFileName)), + [nameof(AssemblyFileName), nameof(ExecutableFileName)])); } if (!hasAssemblyFileName && !hasExecutableFileName) @@ -106,7 +109,8 @@ public IEnumerable Validate(ValidationContext validationContex CultureInfo.InvariantCulture, Strings.ErrorMessage_TwoFieldsMissing, nameof(AssemblyFileName), - nameof(ExecutableFileName)))); + nameof(ExecutableFileName)), + [nameof(AssemblyFileName), nameof(ExecutableFileName)])); } return results; diff --git a/src/Tools/dotnet-monitor/HostBuilder/HostBuilderHelper.cs b/src/Tools/dotnet-monitor/HostBuilder/HostBuilderHelper.cs index 07df5e4bb3a..052d6284661 100644 --- a/src/Tools/dotnet-monitor/HostBuilder/HostBuilderHelper.cs +++ b/src/Tools/dotnet-monitor/HostBuilder/HostBuilderHelper.cs @@ -132,6 +132,7 @@ public static IHostBuilder CreateHostBuilder(HostBuilderSettings settings) services.AddSingleton(listenResults); services.AddSingleton(); services.AddHostedService(); + ValidatableTypes.AddValidation(services); }) .ConfigureKestrel((context, options) => { diff --git a/src/Tools/dotnet-monitor/ValidatableInfoResolver.cs b/src/Tools/dotnet-monitor/ValidatableInfoResolver.cs new file mode 100644 index 00000000000..0297dd3896a --- /dev/null +++ b/src/Tools/dotnet-monitor/ValidatableInfoResolver.cs @@ -0,0 +1,2231 @@ +#nullable enable annotations +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ +#nullable enable + +namespace System.Runtime.CompilerServices +{ + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.Http.ValidationsGenerator, Version=10.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60", "10.0.0.0")] + [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)] + file sealed class InterceptsLocationAttribute : System.Attribute + { + public InterceptsLocationAttribute(int version, string data) + { + } + } +} + +namespace Microsoft.AspNetCore.Http.Validation.Generated +{ + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.Http.ValidationsGenerator, Version=10.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60", "10.0.0.0")] + file sealed class GeneratedValidatablePropertyInfo : global::Microsoft.AspNetCore.Http.Validation.ValidatablePropertyInfo + { + public GeneratedValidatablePropertyInfo( + [param: global::System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembers(global::System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicProperties)] + global::System.Type containingType, + global::System.Type propertyType, + string name, + string displayName) : base(containingType, propertyType, name, displayName) + { + ContainingType = containingType; + Name = name; + } + + internal global::System.Type ContainingType { get; } + internal string Name { get; } + + protected override global::System.ComponentModel.DataAnnotations.ValidationAttribute[] GetValidationAttributes() + => ValidationAttributeCache.GetValidationAttributes(ContainingType, Name); + } + + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.Http.ValidationsGenerator, Version=10.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60", "10.0.0.0")] + file sealed class GeneratedValidatableTypeInfo : global::Microsoft.AspNetCore.Http.Validation.ValidatableTypeInfo + { + public GeneratedValidatableTypeInfo( + [param: global::System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembers(global::System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.Interfaces)] + global::System.Type type, + ValidatablePropertyInfo[] members) : base(type, members) { } + } + + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.Http.ValidationsGenerator, Version=10.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60", "10.0.0.0")] + file class GeneratedValidatableInfoResolver : global::Microsoft.AspNetCore.Http.Validation.IValidatableInfoResolver + { + public bool TryGetValidatableTypeInfo(global::System.Type type, [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] out global::Microsoft.AspNetCore.Http.Validation.IValidatableInfo? validatableInfo) + { + validatableInfo = null; + if (type == typeof(global::Microsoft.Diagnostics.Tools.Monitor.MonitorApiKeyOptions)) + { + validatableInfo = CreateMonitorApiKeyOptions(); + return true; + } + if (type == typeof(global::Microsoft.Diagnostics.Tools.Monitor.AzureAdOptions)) + { + validatableInfo = CreateAzureAdOptions(); + return true; + } + if (type == typeof(global::Microsoft.Diagnostics.Tools.Monitor.AuthenticationOptions)) + { + validatableInfo = CreateAuthenticationOptions(); + return true; + } + // https://github.com/dotnet/aspnetcore/issues/61388 + // if (type == typeof(global::System.Collections.Generic.IDictionary)) + // { + // validatableInfo = CreateIDictionary`2(); + // return true; + // } + if (type == typeof(global::Microsoft.Diagnostics.Monitoring.WebApi.GlobalCounterOptions)) + { + validatableInfo = CreateGlobalCounterOptions(); + return true; + } + if (type == typeof(global::Microsoft.Diagnostics.Monitoring.Options.ExceptionsConfiguration)) + { + validatableInfo = CreateExceptionsConfiguration(); + return true; + } + if (type == typeof(global::Microsoft.Diagnostics.Monitoring.Options.ExceptionsOptions)) + { + validatableInfo = CreateExceptionsOptions(); + return true; + } + if (type == typeof(global::Microsoft.Diagnostics.Monitoring.Options.InProcessFeaturesOptions)) + { + validatableInfo = CreateInProcessFeaturesOptions(); + return true; + } + if (type == typeof(global::Microsoft.Diagnostics.Monitoring.WebApi.CorsConfigurationOptions)) + { + validatableInfo = CreateCorsConfigurationOptions(); + return true; + } + if (type == typeof(global::Microsoft.Diagnostics.Tools.Monitor.EgressOptions)) + { + validatableInfo = CreateEgressOptions(); + return true; + } + if (type == typeof(global::Microsoft.Diagnostics.Monitoring.WebApi.MetricProvider)) + { + validatableInfo = CreateMetricProvider(); + return true; + } + if (type == typeof(global::Microsoft.Diagnostics.Monitoring.WebApi.MetricsOptions)) + { + validatableInfo = CreateMetricsOptions(); + return true; + } + if (type == typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.CollectionRuleTriggerDefaultsOptions)) + { + validatableInfo = CreateCollectionRuleTriggerDefaultsOptions(); + return true; + } + if (type == typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.CollectionRuleLimitsDefaultsOptions)) + { + validatableInfo = CreateCollectionRuleLimitsDefaultsOptions(); + return true; + } + if (type == typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.CollectionRuleDefaultsOptions)) + { + validatableInfo = CreateCollectionRuleDefaultsOptions(); + return true; + } + if (type == typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.TemplateOptions)) + { + validatableInfo = CreateTemplateOptions(); + return true; + } + if (type == typeof(global::Microsoft.Diagnostics.Tools.Monitor.RootOptions)) + { + validatableInfo = CreateRootOptions(); + return true; + } + if (type == typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.CollectionRuleTriggerOptions)) + { + validatableInfo = CreateCollectionRuleTriggerOptions(); + return true; + } + if (type == typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.CollectionRuleActionOptions)) + { + validatableInfo = CreateCollectionRuleActionOptions(); + return true; + } + if (type == typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.CollectionRuleLimitsOptions)) + { + validatableInfo = CreateCollectionRuleLimitsOptions(); + return true; + } + if (type == typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.CollectionRuleOptions)) + { + validatableInfo = CreateCollectionRuleOptions(); + return true; + } + if (type == typeof(global::System.Reflection.MethodBase)) + { + validatableInfo = CreateMethodBase(); + return true; + } + if (type == typeof(global::System.Reflection.ConstructorInfo)) + { + validatableInfo = CreateConstructorInfo(); + return true; + } + if (type == typeof(global::System.Reflection.CustomAttributeTypedArgument)) + { + validatableInfo = CreateCustomAttributeTypedArgument(); + return true; + } + if (type == typeof(global::System.Reflection.CustomAttributeNamedArgument)) + { + validatableInfo = CreateCustomAttributeNamedArgument(); + return true; + } + if (type == typeof(global::System.Reflection.CustomAttributeData)) + { + validatableInfo = CreateCustomAttributeData(); + return true; + } + if (type == typeof(global::System.Reflection.ParameterInfo)) + { + validatableInfo = CreateParameterInfo(); + return true; + } + if (type == typeof(global::System.Reflection.MethodInfo)) + { + validatableInfo = CreateMethodInfo(); + return true; + } + if (type == typeof(global::System.Reflection.EventInfo)) + { + validatableInfo = CreateEventInfo(); + return true; + } + if (type == typeof(global::System.Reflection.FieldInfo)) + { + validatableInfo = CreateFieldInfo(); + return true; + } + if (type == typeof(global::System.Reflection.PropertyInfo)) + { + validatableInfo = CreatePropertyInfo(); + return true; + } + if (type == typeof(global::System.Reflection.TypeInfo)) + { + validatableInfo = CreateTypeInfo(); + return true; + } + if (type == typeof(global::System.Reflection.Assembly)) + { + validatableInfo = CreateAssembly(); + return true; + } + if (type == typeof(global::System.Guid)) + { + validatableInfo = CreateGuid(); + return true; + } + if (type == typeof(global::System.Reflection.Module)) + { + validatableInfo = CreateModule(); + return true; + } + if (type == typeof(global::System.Reflection.MemberInfo)) + { + validatableInfo = CreateMemberInfo(); + return true; + } + if (type == typeof(global::System.Type)) + { + validatableInfo = CreateType(); + return true; + } + if (type == typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Actions.BaseRecordOptions)) + { + validatableInfo = CreateBaseRecordOptions(); + return true; + } + if (type == typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Actions.CollectDumpOptions)) + { + validatableInfo = CreateCollectDumpOptions(); + return true; + } + if (type == typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Actions.CollectExceptionsOptions)) + { + validatableInfo = CreateCollectExceptionsOptions(); + return true; + } + if (type == typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Actions.CollectGCDumpOptions)) + { + validatableInfo = CreateCollectGCDumpOptions(); + return true; + } + if (type == typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Actions.CollectLiveMetricsOptions)) + { + validatableInfo = CreateCollectLiveMetricsOptions(); + return true; + } + // https://github.com/dotnet/aspnetcore/issues/61388 + // if (type == typeof(global::System.Collections.Generic.Dictionary)) + // { + // validatableInfo = CreateDictionary`2(); + // return true; + // } + if (type == typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Actions.CollectLogsOptions)) + { + validatableInfo = CreateCollectLogsOptions(); + return true; + } + if (type == typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Actions.CollectStacksOptions)) + { + validatableInfo = CreateCollectStacksOptions(); + return true; + } + if (type == typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Actions.TraceEventFilter)) + { + validatableInfo = CreateTraceEventFilter(); + return true; + } + if (type == typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Actions.CollectTraceOptions)) + { + validatableInfo = CreateCollectTraceOptions(); + return true; + } + if (type == typeof(global::Microsoft.Diagnostics.Monitoring.WebApi.Models.EventPipeProvider)) + { + validatableInfo = CreateEventPipeProvider(); + return true; + } + if (type == typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Actions.ExecuteOptions)) + { + validatableInfo = CreateExecuteOptions(); + return true; + } + if (type == typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Actions.GetEnvironmentVariableOptions)) + { + validatableInfo = CreateGetEnvironmentVariableOptions(); + return true; + } + if (type == typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Actions.LoadProfilerOptions)) + { + validatableInfo = CreateLoadProfilerOptions(); + return true; + } + if (type == typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Actions.SetEnvironmentVariableOptions)) + { + validatableInfo = CreateSetEnvironmentVariableOptions(); + return true; + } + if (type == typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Triggers.EventCounterShortcuts.CPUUsageOptions)) + { + validatableInfo = CreateCPUUsageOptions(); + return true; + } + if (type == typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Triggers.EventCounterShortcuts.GCHeapSizeOptions)) + { + validatableInfo = CreateGCHeapSizeOptions(); + return true; + } + if (type == typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Triggers.EventCounterShortcuts.ThreadpoolQueueLengthOptions)) + { + validatableInfo = CreateThreadpoolQueueLengthOptions(); + return true; + } + if (type == typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Triggers.AspNetRequestCountOptions)) + { + validatableInfo = CreateAspNetRequestCountOptions(); + return true; + } + if (type == typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Triggers.AspNetRequestDurationOptions)) + { + validatableInfo = CreateAspNetRequestDurationOptions(); + return true; + } + if (type == typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Triggers.AspNetResponseStatusOptions)) + { + validatableInfo = CreateAspNetResponseStatusOptions(); + return true; + } + if (type == typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Triggers.EventCounterOptions)) + { + validatableInfo = CreateEventCounterOptions(); + return true; + } + if (type == typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Triggers.EventMeterOptions)) + { + validatableInfo = CreateEventMeterOptions(); + return true; + } + if (type == typeof(global::Microsoft.Diagnostics.Tools.Monitor.Egress.FileSystem.FileSystemEgressProviderOptions)) + { + validatableInfo = CreateFileSystemEgressProviderOptions(); + return true; + } + if (type == typeof(global::Microsoft.Diagnostics.Tools.Monitor.Extensibility.ExtensionManifest)) + { + validatableInfo = CreateExtensionManifest(); + return true; + } + if (type == typeof(global::Microsoft.Diagnostics.Tools.Monitor.ValidatableTypes)) + { + validatableInfo = CreateValidatableTypes(); + return true; + } + + return false; + } + + // No-ops, rely on runtime code for ParameterInfo-based resolution + public bool TryGetValidatableParameterInfo(global::System.Reflection.ParameterInfo parameterInfo, [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] out global::Microsoft.AspNetCore.Http.Validation.IValidatableInfo? validatableInfo) + { + validatableInfo = null; + return false; + } + + private ValidatableTypeInfo CreateMonitorApiKeyOptions() + { + return new GeneratedValidatableTypeInfo( + type: typeof(global::Microsoft.Diagnostics.Tools.Monitor.MonitorApiKeyOptions), + members: [ + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.MonitorApiKeyOptions), + propertyType: typeof(string), + name: "Subject", + displayName: "Subject" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.MonitorApiKeyOptions), + propertyType: typeof(string), + name: "PublicKey", + displayName: "PublicKey" + ), + ] + ); + } + private ValidatableTypeInfo CreateAzureAdOptions() + { + return new GeneratedValidatableTypeInfo( + type: typeof(global::Microsoft.Diagnostics.Tools.Monitor.AzureAdOptions), + members: [ + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.AzureAdOptions), + propertyType: typeof(string), + name: "TenantId", + displayName: "TenantId" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.AzureAdOptions), + propertyType: typeof(string), + name: "ClientId", + displayName: "ClientId" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.AzureAdOptions), + propertyType: typeof(global::System.Uri), + name: "AppIdUri", + displayName: "AppIdUri" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.AzureAdOptions), + propertyType: typeof(string), + name: "RequiredRole", + displayName: "RequiredRole" + ), + ] + ); + } + private ValidatableTypeInfo CreateAuthenticationOptions() + { + return new GeneratedValidatableTypeInfo( + type: typeof(global::Microsoft.Diagnostics.Tools.Monitor.AuthenticationOptions), + members: [ + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.AuthenticationOptions), + propertyType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.MonitorApiKeyOptions), + name: "MonitorApiKey", + displayName: "MonitorApiKey" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.AuthenticationOptions), + propertyType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.AzureAdOptions), + name: "AzureAd", + displayName: "AzureAd" + ), + ] + ); + } + private ValidatableTypeInfo CreateGlobalCounterOptions() + { + return new GeneratedValidatableTypeInfo( + type: typeof(global::Microsoft.Diagnostics.Monitoring.WebApi.GlobalCounterOptions), + members: [ + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Monitoring.WebApi.GlobalCounterOptions), + propertyType: typeof(float?), + name: "IntervalSeconds", + displayName: "IntervalSeconds" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Monitoring.WebApi.GlobalCounterOptions), + propertyType: typeof(int?), + name: "MaxHistograms", + displayName: "MaxHistograms" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Monitoring.WebApi.GlobalCounterOptions), + propertyType: typeof(int?), + name: "MaxTimeSeries", + displayName: "MaxTimeSeries" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Monitoring.WebApi.GlobalCounterOptions), + propertyType: typeof(global::System.Collections.Generic.IDictionary), + name: "Providers", + displayName: "Providers" + ), + ] + ); + } + private ValidatableTypeInfo CreateExceptionsConfiguration() + { + return new GeneratedValidatableTypeInfo( + type: typeof(global::Microsoft.Diagnostics.Monitoring.Options.ExceptionsConfiguration), + members: [ + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Monitoring.Options.ExceptionsConfiguration), + propertyType: typeof(global::System.Collections.Generic.List), + name: "Exclude", + displayName: "Exclude" + ), + ] + ); + } + private ValidatableTypeInfo CreateExceptionsOptions() + { + return new GeneratedValidatableTypeInfo( + type: typeof(global::Microsoft.Diagnostics.Monitoring.Options.ExceptionsOptions), + members: [ + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Monitoring.Options.ExceptionsOptions), + propertyType: typeof(int?), + name: "TopLevelLimit", + displayName: "TopLevelLimit" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Monitoring.Options.ExceptionsOptions), + propertyType: typeof(global::Microsoft.Diagnostics.Monitoring.Options.ExceptionsConfiguration), + name: "CollectionFilters", + displayName: "CollectionFilters" + ), + ] + ); + } + private ValidatableTypeInfo CreateInProcessFeaturesOptions() + { + return new GeneratedValidatableTypeInfo( + type: typeof(global::Microsoft.Diagnostics.Monitoring.Options.InProcessFeaturesOptions), + members: [ + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Monitoring.Options.InProcessFeaturesOptions), + propertyType: typeof(global::Microsoft.Diagnostics.Monitoring.Options.ExceptionsOptions), + name: "Exceptions", + displayName: "Exceptions" + ), + ] + ); + } + private ValidatableTypeInfo CreateCorsConfigurationOptions() + { + return new GeneratedValidatableTypeInfo( + type: typeof(global::Microsoft.Diagnostics.Monitoring.WebApi.CorsConfigurationOptions), + members: [ + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Monitoring.WebApi.CorsConfigurationOptions), + propertyType: typeof(string), + name: "AllowedOrigins", + displayName: "AllowedOrigins" + ), + ] + ); + } + private ValidatableTypeInfo CreateEgressOptions() + { + return new GeneratedValidatableTypeInfo( + type: typeof(global::Microsoft.Diagnostics.Tools.Monitor.EgressOptions), + members: [ + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.EgressOptions), + propertyType: typeof(global::System.Collections.Generic.IDictionary), + name: "FileSystem", + displayName: "FileSystem" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.EgressOptions), + propertyType: typeof(global::System.Collections.Generic.IDictionary), + name: "Properties", + displayName: "Properties" + ), + ] + ); + } + private ValidatableTypeInfo CreateMetricProvider() + { + return new GeneratedValidatableTypeInfo( + type: typeof(global::Microsoft.Diagnostics.Monitoring.WebApi.MetricProvider), + members: [ + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Monitoring.WebApi.MetricProvider), + propertyType: typeof(string), + name: "ProviderName", + displayName: "ProviderName" + ), + ] + ); + } + private ValidatableTypeInfo CreateMetricsOptions() + { + return new GeneratedValidatableTypeInfo( + type: typeof(global::Microsoft.Diagnostics.Monitoring.WebApi.MetricsOptions), + members: [ + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Monitoring.WebApi.MetricsOptions), + propertyType: typeof(int?), + name: "MetricCount", + displayName: "MetricCount" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Monitoring.WebApi.MetricsOptions), + propertyType: typeof(global::System.Collections.Generic.List), + name: "Providers", + displayName: "Providers" + ), + ] + ); + } + private ValidatableTypeInfo CreateCollectionRuleTriggerDefaultsOptions() + { + return new GeneratedValidatableTypeInfo( + type: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.CollectionRuleTriggerDefaultsOptions), + members: [ + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.CollectionRuleTriggerDefaultsOptions), + propertyType: typeof(int?), + name: "RequestCount", + displayName: "RequestCount" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.CollectionRuleTriggerDefaultsOptions), + propertyType: typeof(int?), + name: "ResponseCount", + displayName: "ResponseCount" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.CollectionRuleTriggerDefaultsOptions), + propertyType: typeof(global::System.TimeSpan?), + name: "SlidingWindowDuration", + displayName: "SlidingWindowDuration" + ), + ] + ); + } + private ValidatableTypeInfo CreateCollectionRuleLimitsDefaultsOptions() + { + return new GeneratedValidatableTypeInfo( + type: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.CollectionRuleLimitsDefaultsOptions), + members: [ + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.CollectionRuleLimitsDefaultsOptions), + propertyType: typeof(int?), + name: "ActionCount", + displayName: "ActionCount" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.CollectionRuleLimitsDefaultsOptions), + propertyType: typeof(global::System.TimeSpan?), + name: "ActionCountSlidingWindowDuration", + displayName: "ActionCountSlidingWindowDuration" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.CollectionRuleLimitsDefaultsOptions), + propertyType: typeof(global::System.TimeSpan?), + name: "RuleDuration", + displayName: "RuleDuration" + ), + ] + ); + } + private ValidatableTypeInfo CreateCollectionRuleDefaultsOptions() + { + return new GeneratedValidatableTypeInfo( + type: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.CollectionRuleDefaultsOptions), + members: [ + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.CollectionRuleDefaultsOptions), + propertyType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.CollectionRuleTriggerDefaultsOptions), + name: "Triggers", + displayName: "Triggers" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.CollectionRuleDefaultsOptions), + propertyType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.CollectionRuleLimitsDefaultsOptions), + name: "Limits", + displayName: "Limits" + ), + ] + ); + } + private ValidatableTypeInfo CreateTemplateOptions() + { + return new GeneratedValidatableTypeInfo( + type: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.TemplateOptions), + members: [ + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.TemplateOptions), + propertyType: typeof(global::System.Collections.Generic.IDictionary), + name: "CollectionRuleFilters", + displayName: "CollectionRuleFilters" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.TemplateOptions), + propertyType: typeof(global::System.Collections.Generic.IDictionary), + name: "CollectionRuleTriggers", + displayName: "CollectionRuleTriggers" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.TemplateOptions), + propertyType: typeof(global::System.Collections.Generic.IDictionary), + name: "CollectionRuleActions", + displayName: "CollectionRuleActions" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.TemplateOptions), + propertyType: typeof(global::System.Collections.Generic.IDictionary), + name: "CollectionRuleLimits", + displayName: "CollectionRuleLimits" + ), + ] + ); + } + private ValidatableTypeInfo CreateRootOptions() + { + return new GeneratedValidatableTypeInfo( + type: typeof(global::Microsoft.Diagnostics.Tools.Monitor.RootOptions), + members: [ + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.RootOptions), + propertyType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.AuthenticationOptions), + name: "Authentication", + displayName: "Authentication" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.RootOptions), + propertyType: typeof(global::System.Collections.Generic.IDictionary), + name: "CollectionRules", + displayName: "CollectionRules" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.RootOptions), + propertyType: typeof(global::Microsoft.Diagnostics.Monitoring.WebApi.GlobalCounterOptions), + name: "GlobalCounter", + displayName: "GlobalCounter" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.RootOptions), + propertyType: typeof(global::Microsoft.Diagnostics.Monitoring.Options.InProcessFeaturesOptions), + name: "InProcessFeatures", + displayName: "InProcessFeatures" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.RootOptions), + propertyType: typeof(global::Microsoft.Diagnostics.Monitoring.WebApi.CorsConfigurationOptions), + name: "CorsConfiguration", + displayName: "CorsConfiguration" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.RootOptions), + propertyType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.EgressOptions), + name: "Egress", + displayName: "Egress" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.RootOptions), + propertyType: typeof(global::Microsoft.Diagnostics.Monitoring.WebApi.MetricsOptions), + name: "Metrics", + displayName: "Metrics" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.RootOptions), + propertyType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.CollectionRuleDefaultsOptions), + name: "CollectionRuleDefaults", + displayName: "CollectionRuleDefaults" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.RootOptions), + propertyType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.TemplateOptions), + name: "Templates", + displayName: "Templates" + ), + ] + ); + } + private ValidatableTypeInfo CreateCollectionRuleTriggerOptions() + { + return new GeneratedValidatableTypeInfo( + type: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.CollectionRuleTriggerOptions), + members: [ + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.CollectionRuleTriggerOptions), + propertyType: typeof(string), + name: "Type", + displayName: "Type" + ), + ] + ); + } + private ValidatableTypeInfo CreateCollectionRuleActionOptions() + { + return new GeneratedValidatableTypeInfo( + type: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.CollectionRuleActionOptions), + members: [ + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.CollectionRuleActionOptions), + propertyType: typeof(string), + name: "Type", + displayName: "Type" + ), + ] + ); + } + private ValidatableTypeInfo CreateCollectionRuleLimitsOptions() + { + return new GeneratedValidatableTypeInfo( + type: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.CollectionRuleLimitsOptions), + members: [ + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.CollectionRuleLimitsOptions), + propertyType: typeof(int?), + name: "ActionCount", + displayName: "ActionCount" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.CollectionRuleLimitsOptions), + propertyType: typeof(global::System.TimeSpan?), + name: "ActionCountSlidingWindowDuration", + displayName: "ActionCountSlidingWindowDuration" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.CollectionRuleLimitsOptions), + propertyType: typeof(global::System.TimeSpan?), + name: "RuleDuration", + displayName: "RuleDuration" + ), + ] + ); + } + private ValidatableTypeInfo CreateCollectionRuleOptions() + { + return new GeneratedValidatableTypeInfo( + type: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.CollectionRuleOptions), + members: [ + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.CollectionRuleOptions), + propertyType: typeof(global::System.Collections.Generic.List), + name: "Filters", + displayName: "Filters" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.CollectionRuleOptions), + propertyType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.CollectionRuleTriggerOptions), + name: "Trigger", + displayName: "Trigger" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.CollectionRuleOptions), + propertyType: typeof(global::System.Collections.Generic.List), + name: "Actions", + displayName: "Actions" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.CollectionRuleOptions), + propertyType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.CollectionRuleLimitsOptions), + name: "Limits", + displayName: "Limits" + ), + ] + ); + } + private ValidatableTypeInfo CreateMethodBase() + { + return new GeneratedValidatableTypeInfo( + type: typeof(global::System.Reflection.MethodBase), + members: [] + ); + } + private ValidatableTypeInfo CreateConstructorInfo() + { + return new GeneratedValidatableTypeInfo( + type: typeof(global::System.Reflection.ConstructorInfo), + members: [] + ); + } + private ValidatableTypeInfo CreateCustomAttributeTypedArgument() + { + return new GeneratedValidatableTypeInfo( + type: typeof(global::System.Reflection.CustomAttributeTypedArgument), + members: [ + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::System.Reflection.CustomAttributeTypedArgument), + propertyType: typeof(global::System.Type), + name: "ArgumentType", + displayName: "ArgumentType" + ), + ] + ); + } + private ValidatableTypeInfo CreateCustomAttributeNamedArgument() + { + return new GeneratedValidatableTypeInfo( + type: typeof(global::System.Reflection.CustomAttributeNamedArgument), + members: [ + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::System.Reflection.CustomAttributeNamedArgument), + propertyType: typeof(global::System.Reflection.MemberInfo), + name: "MemberInfo", + displayName: "MemberInfo" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::System.Reflection.CustomAttributeNamedArgument), + propertyType: typeof(global::System.Reflection.CustomAttributeTypedArgument), + name: "TypedValue", + displayName: "TypedValue" + ), + ] + ); + } + private ValidatableTypeInfo CreateCustomAttributeData() + { + return new GeneratedValidatableTypeInfo( + type: typeof(global::System.Reflection.CustomAttributeData), + members: [ + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::System.Reflection.CustomAttributeData), + propertyType: typeof(global::System.Type), + name: "AttributeType", + displayName: "AttributeType" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::System.Reflection.CustomAttributeData), + propertyType: typeof(global::System.Reflection.ConstructorInfo), + name: "Constructor", + displayName: "Constructor" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::System.Reflection.CustomAttributeData), + propertyType: typeof(global::System.Collections.Generic.IList), + name: "ConstructorArguments", + displayName: "ConstructorArguments" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::System.Reflection.CustomAttributeData), + propertyType: typeof(global::System.Collections.Generic.IList), + name: "NamedArguments", + displayName: "NamedArguments" + ), + ] + ); + } + private ValidatableTypeInfo CreateParameterInfo() + { + return new GeneratedValidatableTypeInfo( + type: typeof(global::System.Reflection.ParameterInfo), + members: [ + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::System.Reflection.ParameterInfo), + propertyType: typeof(global::System.Collections.Generic.IEnumerable), + name: "CustomAttributes", + displayName: "CustomAttributes" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::System.Reflection.ParameterInfo), + propertyType: typeof(global::System.Reflection.MemberInfo), + name: "Member", + displayName: "Member" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::System.Reflection.ParameterInfo), + propertyType: typeof(global::System.Type), + name: "ParameterType", + displayName: "ParameterType" + ), + ] + ); + } + private ValidatableTypeInfo CreateMethodInfo() + { + return new GeneratedValidatableTypeInfo( + type: typeof(global::System.Reflection.MethodInfo), + members: [ + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::System.Reflection.MethodInfo), + propertyType: typeof(global::System.Reflection.MemberTypes), + name: "MemberType", + displayName: "MemberType" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::System.Reflection.MethodInfo), + propertyType: typeof(global::System.Reflection.ParameterInfo), + name: "ReturnParameter", + displayName: "ReturnParameter" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::System.Reflection.MethodInfo), + propertyType: typeof(global::System.Type), + name: "ReturnType", + displayName: "ReturnType" + ), + ] + ); + } + private ValidatableTypeInfo CreateEventInfo() + { + return new GeneratedValidatableTypeInfo( + type: typeof(global::System.Reflection.EventInfo), + members: [ + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::System.Reflection.EventInfo), + propertyType: typeof(global::System.Reflection.MethodInfo), + name: "AddMethod", + displayName: "AddMethod" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::System.Reflection.EventInfo), + propertyType: typeof(global::System.Type), + name: "EventHandlerType", + displayName: "EventHandlerType" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::System.Reflection.EventInfo), + propertyType: typeof(global::System.Reflection.MemberTypes), + name: "MemberType", + displayName: "MemberType" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::System.Reflection.EventInfo), + propertyType: typeof(global::System.Reflection.MethodInfo), + name: "RaiseMethod", + displayName: "RaiseMethod" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::System.Reflection.EventInfo), + propertyType: typeof(global::System.Reflection.MethodInfo), + name: "RemoveMethod", + displayName: "RemoveMethod" + ), + ] + ); + } + private ValidatableTypeInfo CreateFieldInfo() + { + return new GeneratedValidatableTypeInfo( + type: typeof(global::System.Reflection.FieldInfo), + members: [ + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::System.Reflection.FieldInfo), + propertyType: typeof(global::System.Type), + name: "FieldType", + displayName: "FieldType" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::System.Reflection.FieldInfo), + propertyType: typeof(global::System.Reflection.MemberTypes), + name: "MemberType", + displayName: "MemberType" + ), + ] + ); + } + private ValidatableTypeInfo CreatePropertyInfo() + { + return new GeneratedValidatableTypeInfo( + type: typeof(global::System.Reflection.PropertyInfo), + members: [ + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::System.Reflection.PropertyInfo), + propertyType: typeof(global::System.Reflection.MethodInfo), + name: "GetMethod", + displayName: "GetMethod" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::System.Reflection.PropertyInfo), + propertyType: typeof(global::System.Reflection.MemberTypes), + name: "MemberType", + displayName: "MemberType" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::System.Reflection.PropertyInfo), + propertyType: typeof(global::System.Type), + name: "PropertyType", + displayName: "PropertyType" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::System.Reflection.PropertyInfo), + propertyType: typeof(global::System.Reflection.MethodInfo), + name: "SetMethod", + displayName: "SetMethod" + ), + ] + ); + } + private ValidatableTypeInfo CreateTypeInfo() + { + return new GeneratedValidatableTypeInfo( + type: typeof(global::System.Reflection.TypeInfo), + members: [ + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::System.Reflection.TypeInfo), + propertyType: typeof(global::System.Collections.Generic.IEnumerable), + name: "DeclaredConstructors", + displayName: "DeclaredConstructors" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::System.Reflection.TypeInfo), + propertyType: typeof(global::System.Collections.Generic.IEnumerable), + name: "DeclaredEvents", + displayName: "DeclaredEvents" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::System.Reflection.TypeInfo), + propertyType: typeof(global::System.Collections.Generic.IEnumerable), + name: "DeclaredFields", + displayName: "DeclaredFields" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::System.Reflection.TypeInfo), + propertyType: typeof(global::System.Collections.Generic.IEnumerable), + name: "DeclaredMembers", + displayName: "DeclaredMembers" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::System.Reflection.TypeInfo), + propertyType: typeof(global::System.Collections.Generic.IEnumerable), + name: "DeclaredMethods", + displayName: "DeclaredMethods" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::System.Reflection.TypeInfo), + propertyType: typeof(global::System.Collections.Generic.IEnumerable), + name: "DeclaredNestedTypes", + displayName: "DeclaredNestedTypes" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::System.Reflection.TypeInfo), + propertyType: typeof(global::System.Collections.Generic.IEnumerable), + name: "DeclaredProperties", + displayName: "DeclaredProperties" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::System.Reflection.TypeInfo), + propertyType: typeof(global::System.Collections.Generic.IEnumerable), + name: "ImplementedInterfaces", + displayName: "ImplementedInterfaces" + ), + ] + ); + } + private ValidatableTypeInfo CreateAssembly() + { + return new GeneratedValidatableTypeInfo( + type: typeof(global::System.Reflection.Assembly), + members: [ + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::System.Reflection.Assembly), + propertyType: typeof(global::System.Collections.Generic.IEnumerable), + name: "CustomAttributes", + displayName: "CustomAttributes" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::System.Reflection.Assembly), + propertyType: typeof(global::System.Collections.Generic.IEnumerable), + name: "DefinedTypes", + displayName: "DefinedTypes" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::System.Reflection.Assembly), + propertyType: typeof(global::System.Reflection.MethodInfo), + name: "EntryPoint", + displayName: "EntryPoint" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::System.Reflection.Assembly), + propertyType: typeof(global::System.Collections.Generic.IEnumerable), + name: "ExportedTypes", + displayName: "ExportedTypes" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::System.Reflection.Assembly), + propertyType: typeof(global::System.Reflection.Module), + name: "ManifestModule", + displayName: "ManifestModule" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::System.Reflection.Assembly), + propertyType: typeof(global::System.Collections.Generic.IEnumerable), + name: "Modules", + displayName: "Modules" + ), + ] + ); + } + private ValidatableTypeInfo CreateGuid() + { + return new GeneratedValidatableTypeInfo( + type: typeof(global::System.Guid), + members: [ + // https://github.com/dotnet/aspnetcore/issues/61525 + // new GeneratedValidatablePropertyInfo( + // containingType: typeof(global::System.Guid), + // propertyType: typeof(global::System.Guid), + // name: "AllBitsSet", + // displayName: "AllBitsSet" + // ), + ] + ); + } + private ValidatableTypeInfo CreateModule() + { + return new GeneratedValidatableTypeInfo( + type: typeof(global::System.Reflection.Module), + members: [ + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::System.Reflection.Module), + propertyType: typeof(global::System.Reflection.Assembly), + name: "Assembly", + displayName: "Assembly" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::System.Reflection.Module), + propertyType: typeof(global::System.Collections.Generic.IEnumerable), + name: "CustomAttributes", + displayName: "CustomAttributes" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::System.Reflection.Module), + propertyType: typeof(global::System.Guid), + name: "ModuleVersionId", + displayName: "ModuleVersionId" + ), + ] + ); + } + private ValidatableTypeInfo CreateMemberInfo() + { + return new GeneratedValidatableTypeInfo( + type: typeof(global::System.Reflection.MemberInfo), + members: [ + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::System.Reflection.MemberInfo), + propertyType: typeof(global::System.Collections.Generic.IEnumerable), + name: "CustomAttributes", + displayName: "CustomAttributes" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::System.Reflection.MemberInfo), + propertyType: typeof(global::System.Type), + name: "DeclaringType", + displayName: "DeclaringType" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::System.Reflection.MemberInfo), + propertyType: typeof(global::System.Reflection.MemberTypes), + name: "MemberType", + displayName: "MemberType" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::System.Reflection.MemberInfo), + propertyType: typeof(global::System.Reflection.Module), + name: "Module", + displayName: "Module" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::System.Reflection.MemberInfo), + propertyType: typeof(global::System.Type), + name: "ReflectedType", + displayName: "ReflectedType" + ), + ] + ); + } + private ValidatableTypeInfo CreateType() + { + return new GeneratedValidatableTypeInfo( + type: typeof(global::System.Type), + members: [ + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::System.Type), + propertyType: typeof(global::System.Reflection.Assembly), + name: "Assembly", + displayName: "Assembly" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::System.Type), + propertyType: typeof(global::System.Type), + name: "BaseType", + displayName: "BaseType" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::System.Type), + propertyType: typeof(global::System.Reflection.MethodBase), + name: "DeclaringMethod", + displayName: "DeclaringMethod" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::System.Type), + propertyType: typeof(global::System.Type), + name: "DeclaringType", + displayName: "DeclaringType" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::System.Type), + propertyType: typeof(global::System.Type[]), + name: "GenericTypeArguments", + displayName: "GenericTypeArguments" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::System.Type), + propertyType: typeof(global::System.Guid), + name: "GUID", + displayName: "GUID" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::System.Type), + propertyType: typeof(global::System.Reflection.MemberTypes), + name: "MemberType", + displayName: "MemberType" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::System.Type), + propertyType: typeof(global::System.Reflection.Module), + name: "Module", + displayName: "Module" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::System.Type), + propertyType: typeof(global::System.Type), + name: "ReflectedType", + displayName: "ReflectedType" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::System.Type), + propertyType: typeof(global::System.Reflection.ConstructorInfo), + name: "TypeInitializer", + displayName: "TypeInitializer" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::System.Type), + propertyType: typeof(global::System.Type), + name: "UnderlyingSystemType", + displayName: "UnderlyingSystemType" + ), + ] + ); + } + private ValidatableTypeInfo CreateBaseRecordOptions() + { + return new GeneratedValidatableTypeInfo( + type: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Actions.BaseRecordOptions), + members: [ + // https://github.com/dotnet/aspnetcore/issues/61379 + // new GeneratedValidatablePropertyInfo( + // containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Actions.BaseRecordOptions), + // propertyType: typeof(global::System.Type), + // name: "EqualityContract", + // displayName: "EqualityContract" + // ), + ] + ); + } + private ValidatableTypeInfo CreateCollectDumpOptions() + { + return new GeneratedValidatableTypeInfo( + type: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Actions.CollectDumpOptions), + members: [ + // https://github.com/dotnet/aspnetcore/issues/61379 + // new GeneratedValidatablePropertyInfo( + // containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Actions.CollectDumpOptions), + // propertyType: typeof(global::System.Type), + // name: "EqualityContract", + // displayName: "EqualityContract" + // ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Actions.CollectDumpOptions), + propertyType: typeof(global::Microsoft.Diagnostics.Monitoring.WebApi.Models.DumpType?), + name: "Type", + displayName: "Type" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Actions.CollectDumpOptions), + propertyType: typeof(string), + name: "Egress", + displayName: "Egress" + ), + ] + ); + } + private ValidatableTypeInfo CreateCollectExceptionsOptions() + { + return new GeneratedValidatableTypeInfo( + type: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Actions.CollectExceptionsOptions), + members: [ + // https://github.com/dotnet/aspnetcore/issues/61379 + // new GeneratedValidatablePropertyInfo( + // containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Actions.CollectExceptionsOptions), + // propertyType: typeof(global::System.Type), + // name: "EqualityContract", + // displayName: "EqualityContract" + // ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Actions.CollectExceptionsOptions), + propertyType: typeof(string), + name: "Egress", + displayName: "Egress" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Actions.CollectExceptionsOptions), + propertyType: typeof(global::Microsoft.Diagnostics.Monitoring.Options.ExceptionsConfiguration), + name: "Filters", + displayName: "Filters" + ), + ] + ); + } + private ValidatableTypeInfo CreateCollectGCDumpOptions() + { + return new GeneratedValidatableTypeInfo( + type: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Actions.CollectGCDumpOptions), + members: [ + // https://github.com/dotnet/aspnetcore/issues/61379 + // new GeneratedValidatablePropertyInfo( + // containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Actions.CollectGCDumpOptions), + // propertyType: typeof(global::System.Type), + // name: "EqualityContract", + // displayName: "EqualityContract" + // ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Actions.CollectGCDumpOptions), + propertyType: typeof(string), + name: "Egress", + displayName: "Egress" + ), + ] + ); + } + private ValidatableTypeInfo CreateCollectLiveMetricsOptions() + { + return new GeneratedValidatableTypeInfo( + type: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Actions.CollectLiveMetricsOptions), + members: [ + // https://github.com/dotnet/aspnetcore/issues/61379 + // new GeneratedValidatablePropertyInfo( + // containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Actions.CollectLiveMetricsOptions), + // propertyType: typeof(global::System.Type), + // name: "EqualityContract", + // displayName: "EqualityContract" + // ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Actions.CollectLiveMetricsOptions), + propertyType: typeof(global::System.TimeSpan?), + name: "Duration", + displayName: "Duration" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Actions.CollectLiveMetricsOptions), + propertyType: typeof(string), + name: "Egress", + displayName: "Egress" + ), + ] + ); + } + // https://github.com/dotnet/aspnetcore/issues/61388 + // private ValidatableTypeInfo CreateDictionary`2() + // { + // return new GeneratedValidatableTypeInfo( + // type: typeof(global::System.Collections.Generic.Dictionary), + // members: [ + // new GeneratedValidatablePropertyInfo( + // containingType: typeof(global::System.Collections.Generic.Dictionary), + // propertyType: typeof(global::System.Collections.Generic.ICollection), + // name: "System.Collections.Generic.IDictionary.Values", + // displayName: "System.Collections.Generic.IDictionary.Values" + // ), + // new GeneratedValidatablePropertyInfo( + // containingType: typeof(global::System.Collections.Generic.Dictionary), + // propertyType: typeof(global::System.Collections.Generic.IEnumerable), + // name: "System.Collections.Generic.IReadOnlyDictionary.Keys", + // displayName: "System.Collections.Generic.IReadOnlyDictionary.Keys" + // ), + // new GeneratedValidatablePropertyInfo( + // containingType: typeof(global::System.Collections.Generic.Dictionary), + // propertyType: typeof(global::System.Collections.Generic.IEnumerable), + // name: "System.Collections.Generic.IReadOnlyDictionary.Values", + // displayName: "System.Collections.Generic.IReadOnlyDictionary.Values" + // ), + // new GeneratedValidatablePropertyInfo( + // containingType: typeof(global::System.Collections.Generic.Dictionary), + // propertyType: typeof(global::System.Collections.ICollection), + // name: "System.Collections.IDictionary.Values", + // displayName: "System.Collections.IDictionary.Values" + // ), + // ] + // ); + // } + private ValidatableTypeInfo CreateCollectLogsOptions() + { + return new GeneratedValidatableTypeInfo( + type: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Actions.CollectLogsOptions), + members: [ + // https://github.com/dotnet/aspnetcore/issues/61379 + // new GeneratedValidatablePropertyInfo( + // containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Actions.CollectLogsOptions), + // propertyType: typeof(global::System.Type), + // name: "EqualityContract", + // displayName: "EqualityContract" + // ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Actions.CollectLogsOptions), + propertyType: typeof(global::Microsoft.Extensions.Logging.LogLevel?), + name: "DefaultLevel", + displayName: "DefaultLevel" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Actions.CollectLogsOptions), + propertyType: typeof(global::System.Collections.Generic.Dictionary), + name: "FilterSpecs", + displayName: "FilterSpecs" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Actions.CollectLogsOptions), + propertyType: typeof(global::System.TimeSpan?), + name: "Duration", + displayName: "Duration" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Actions.CollectLogsOptions), + propertyType: typeof(string), + name: "Egress", + displayName: "Egress" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Actions.CollectLogsOptions), + propertyType: typeof(global::Microsoft.Diagnostics.Monitoring.Options.LogFormat?), + name: "Format", + displayName: "Format" + ), + ] + ); + } + private ValidatableTypeInfo CreateCollectStacksOptions() + { + return new GeneratedValidatableTypeInfo( + type: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Actions.CollectStacksOptions), + members: [ + // https://github.com/dotnet/aspnetcore/issues/61379 + // new GeneratedValidatablePropertyInfo( + // containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Actions.CollectStacksOptions), + // propertyType: typeof(global::System.Type), + // name: "EqualityContract", + // displayName: "EqualityContract" + // ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Actions.CollectStacksOptions), + propertyType: typeof(string), + name: "Egress", + displayName: "Egress" + ), + ] + ); + } + private ValidatableTypeInfo CreateTraceEventFilter() + { + return new GeneratedValidatableTypeInfo( + type: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Actions.TraceEventFilter), + members: [ + // https://github.com/dotnet/aspnetcore/issues/61379 + // new GeneratedValidatablePropertyInfo( + // containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Actions.TraceEventFilter), + // propertyType: typeof(global::System.Type), + // name: "EqualityContract", + // displayName: "EqualityContract" + // ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Actions.TraceEventFilter), + propertyType: typeof(string), + name: "ProviderName", + displayName: "ProviderName" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Actions.TraceEventFilter), + propertyType: typeof(string), + name: "EventName", + displayName: "EventName" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Actions.TraceEventFilter), + propertyType: typeof(global::System.Collections.Generic.IDictionary), + name: "PayloadFilter", + displayName: "PayloadFilter" + ), + ] + ); + } + private ValidatableTypeInfo CreateCollectTraceOptions() + { + return new GeneratedValidatableTypeInfo( + type: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Actions.CollectTraceOptions), + members: [ + // https://github.com/dotnet/aspnetcore/issues/61379 + // new GeneratedValidatablePropertyInfo( + // containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Actions.CollectTraceOptions), + // propertyType: typeof(global::System.Type), + // name: "EqualityContract", + // displayName: "EqualityContract" + // ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Actions.CollectTraceOptions), + propertyType: typeof(global::Microsoft.Diagnostics.Monitoring.WebApi.Models.TraceProfile?), + name: "Profile", + displayName: "Profile" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Actions.CollectTraceOptions), + propertyType: typeof(int?), + name: "BufferSizeMegabytes", + displayName: "BufferSizeMegabytes" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Actions.CollectTraceOptions), + propertyType: typeof(global::System.TimeSpan?), + name: "Duration", + displayName: "Duration" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Actions.CollectTraceOptions), + propertyType: typeof(string), + name: "Egress", + displayName: "Egress" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Actions.CollectTraceOptions), + propertyType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Actions.TraceEventFilter), + name: "StoppingEvent", + displayName: "StoppingEvent" + ), + ] + ); + } + private ValidatableTypeInfo CreateEventPipeProvider() + { + return new GeneratedValidatableTypeInfo( + type: typeof(global::Microsoft.Diagnostics.Monitoring.WebApi.Models.EventPipeProvider), + members: [ + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Monitoring.WebApi.Models.EventPipeProvider), + propertyType: typeof(string), + name: "Name", + displayName: "Name" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Monitoring.WebApi.Models.EventPipeProvider), + propertyType: typeof(string), + name: "Keywords", + displayName: "Keywords" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Monitoring.WebApi.Models.EventPipeProvider), + propertyType: typeof(global::System.Diagnostics.Tracing.EventLevel), + name: "EventLevel", + displayName: "EventLevel" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Monitoring.WebApi.Models.EventPipeProvider), + propertyType: typeof(global::System.Collections.Generic.IDictionary), + name: "Arguments", + displayName: "Arguments" + ), + ] + ); + } + private ValidatableTypeInfo CreateExecuteOptions() + { + return new GeneratedValidatableTypeInfo( + type: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Actions.ExecuteOptions), + members: [ + // https://github.com/dotnet/aspnetcore/issues/61379 + // new GeneratedValidatablePropertyInfo( + // containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Actions.ExecuteOptions), + // propertyType: typeof(global::System.Type), + // name: "EqualityContract", + // displayName: "EqualityContract" + // ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Actions.ExecuteOptions), + propertyType: typeof(string), + name: "Path", + displayName: "Path" + ), + ] + ); + } + private ValidatableTypeInfo CreateGetEnvironmentVariableOptions() + { + return new GeneratedValidatableTypeInfo( + type: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Actions.GetEnvironmentVariableOptions), + members: [ + // https://github.com/dotnet/aspnetcore/issues/61379 + // new GeneratedValidatablePropertyInfo( + // containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Actions.GetEnvironmentVariableOptions), + // propertyType: typeof(global::System.Type), + // name: "EqualityContract", + // displayName: "EqualityContract" + // ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Actions.GetEnvironmentVariableOptions), + propertyType: typeof(string), + name: "Name", + displayName: "Name" + ), + ] + ); + } + private ValidatableTypeInfo CreateLoadProfilerOptions() + { + return new GeneratedValidatableTypeInfo( + type: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Actions.LoadProfilerOptions), + members: [ + // https://github.com/dotnet/aspnetcore/issues/61379 + // new GeneratedValidatablePropertyInfo( + // containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Actions.LoadProfilerOptions), + // propertyType: typeof(global::System.Type), + // name: "EqualityContract", + // displayName: "EqualityContract" + // ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Actions.LoadProfilerOptions), + propertyType: typeof(string), + name: "Path", + displayName: "Path" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Actions.LoadProfilerOptions), + propertyType: typeof(global::System.Guid), + name: "Clsid", + displayName: "Clsid" + ), + ] + ); + } + private ValidatableTypeInfo CreateSetEnvironmentVariableOptions() + { + return new GeneratedValidatableTypeInfo( + type: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Actions.SetEnvironmentVariableOptions), + members: [ + // https://github.com/dotnet/aspnetcore/issues/61379 + // new GeneratedValidatablePropertyInfo( + // containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Actions.SetEnvironmentVariableOptions), + // propertyType: typeof(global::System.Type), + // name: "EqualityContract", + // displayName: "EqualityContract" + // ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Actions.SetEnvironmentVariableOptions), + propertyType: typeof(string), + name: "Name", + displayName: "Name" + ), + ] + ); + } + private ValidatableTypeInfo CreateCPUUsageOptions() + { + return new GeneratedValidatableTypeInfo( + type: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Triggers.EventCounterShortcuts.CPUUsageOptions), + members: [ + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Triggers.EventCounterShortcuts.CPUUsageOptions), + propertyType: typeof(double?), + name: "GreaterThan", + displayName: "GreaterThan" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Triggers.EventCounterShortcuts.CPUUsageOptions), + propertyType: typeof(double?), + name: "LessThan", + displayName: "LessThan" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Triggers.EventCounterShortcuts.CPUUsageOptions), + propertyType: typeof(global::System.TimeSpan?), + name: "SlidingWindowDuration", + displayName: "SlidingWindowDuration" + ), + ] + ); + } + private ValidatableTypeInfo CreateGCHeapSizeOptions() + { + return new GeneratedValidatableTypeInfo( + type: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Triggers.EventCounterShortcuts.GCHeapSizeOptions), + members: [ + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Triggers.EventCounterShortcuts.GCHeapSizeOptions), + propertyType: typeof(double?), + name: "GreaterThan", + displayName: "GreaterThan" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Triggers.EventCounterShortcuts.GCHeapSizeOptions), + propertyType: typeof(double?), + name: "LessThan", + displayName: "LessThan" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Triggers.EventCounterShortcuts.GCHeapSizeOptions), + propertyType: typeof(global::System.TimeSpan?), + name: "SlidingWindowDuration", + displayName: "SlidingWindowDuration" + ), + ] + ); + } + private ValidatableTypeInfo CreateThreadpoolQueueLengthOptions() + { + return new GeneratedValidatableTypeInfo( + type: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Triggers.EventCounterShortcuts.ThreadpoolQueueLengthOptions), + members: [ + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Triggers.EventCounterShortcuts.ThreadpoolQueueLengthOptions), + propertyType: typeof(double?), + name: "GreaterThan", + displayName: "GreaterThan" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Triggers.EventCounterShortcuts.ThreadpoolQueueLengthOptions), + propertyType: typeof(double?), + name: "LessThan", + displayName: "LessThan" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Triggers.EventCounterShortcuts.ThreadpoolQueueLengthOptions), + propertyType: typeof(global::System.TimeSpan?), + name: "SlidingWindowDuration", + displayName: "SlidingWindowDuration" + ), + ] + ); + } + private ValidatableTypeInfo CreateAspNetRequestCountOptions() + { + return new GeneratedValidatableTypeInfo( + type: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Triggers.AspNetRequestCountOptions), + members: [ + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Triggers.AspNetRequestCountOptions), + propertyType: typeof(int), + name: "RequestCount", + displayName: "RequestCount" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Triggers.AspNetRequestCountOptions), + propertyType: typeof(global::System.TimeSpan?), + name: "SlidingWindowDuration", + displayName: "SlidingWindowDuration" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Triggers.AspNetRequestCountOptions), + propertyType: typeof(string[]), + name: "IncludePaths", + displayName: "IncludePaths" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Triggers.AspNetRequestCountOptions), + propertyType: typeof(string[]), + name: "ExcludePaths", + displayName: "ExcludePaths" + ), + ] + ); + } + private ValidatableTypeInfo CreateAspNetRequestDurationOptions() + { + return new GeneratedValidatableTypeInfo( + type: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Triggers.AspNetRequestDurationOptions), + members: [ + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Triggers.AspNetRequestDurationOptions), + propertyType: typeof(int), + name: "RequestCount", + displayName: "RequestCount" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Triggers.AspNetRequestDurationOptions), + propertyType: typeof(global::System.TimeSpan?), + name: "RequestDuration", + displayName: "RequestDuration" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Triggers.AspNetRequestDurationOptions), + propertyType: typeof(global::System.TimeSpan?), + name: "SlidingWindowDuration", + displayName: "SlidingWindowDuration" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Triggers.AspNetRequestDurationOptions), + propertyType: typeof(string[]), + name: "IncludePaths", + displayName: "IncludePaths" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Triggers.AspNetRequestDurationOptions), + propertyType: typeof(string[]), + name: "ExcludePaths", + displayName: "ExcludePaths" + ), + ] + ); + } + private ValidatableTypeInfo CreateAspNetResponseStatusOptions() + { + return new GeneratedValidatableTypeInfo( + type: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Triggers.AspNetResponseStatusOptions), + members: [ + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Triggers.AspNetResponseStatusOptions), + propertyType: typeof(string[]), + name: "StatusCodes", + displayName: "StatusCodes" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Triggers.AspNetResponseStatusOptions), + propertyType: typeof(int), + name: "ResponseCount", + displayName: "ResponseCount" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Triggers.AspNetResponseStatusOptions), + propertyType: typeof(global::System.TimeSpan?), + name: "SlidingWindowDuration", + displayName: "SlidingWindowDuration" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Triggers.AspNetResponseStatusOptions), + propertyType: typeof(string[]), + name: "IncludePaths", + displayName: "IncludePaths" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Triggers.AspNetResponseStatusOptions), + propertyType: typeof(string[]), + name: "ExcludePaths", + displayName: "ExcludePaths" + ), + ] + ); + } + private ValidatableTypeInfo CreateEventCounterOptions() + { + return new GeneratedValidatableTypeInfo( + type: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Triggers.EventCounterOptions), + members: [ + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Triggers.EventCounterOptions), + propertyType: typeof(string), + name: "ProviderName", + displayName: "ProviderName" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Triggers.EventCounterOptions), + propertyType: typeof(string), + name: "CounterName", + displayName: "CounterName" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Triggers.EventCounterOptions), + propertyType: typeof(global::System.TimeSpan?), + name: "SlidingWindowDuration", + displayName: "SlidingWindowDuration" + ), + ] + ); + } + private ValidatableTypeInfo CreateEventMeterOptions() + { + return new GeneratedValidatableTypeInfo( + type: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Triggers.EventMeterOptions), + members: [ + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Triggers.EventMeterOptions), + propertyType: typeof(string), + name: "MeterName", + displayName: "MeterName" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Triggers.EventMeterOptions), + propertyType: typeof(string), + name: "InstrumentName", + displayName: "InstrumentName" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Triggers.EventMeterOptions), + propertyType: typeof(global::System.TimeSpan?), + name: "SlidingWindowDuration", + displayName: "SlidingWindowDuration" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Triggers.EventMeterOptions), + propertyType: typeof(int?), + name: "HistogramPercentile", + displayName: "HistogramPercentile" + ), + ] + ); + } + private ValidatableTypeInfo CreateFileSystemEgressProviderOptions() + { + return new GeneratedValidatableTypeInfo( + type: typeof(global::Microsoft.Diagnostics.Tools.Monitor.Egress.FileSystem.FileSystemEgressProviderOptions), + members: [ + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.Egress.FileSystem.FileSystemEgressProviderOptions), + propertyType: typeof(string), + name: "DirectoryPath", + displayName: "DirectoryPath" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.Egress.FileSystem.FileSystemEgressProviderOptions), + propertyType: typeof(int?), + name: "CopyBufferSize", + displayName: "CopyBufferSize" + ), + ] + ); + } + private ValidatableTypeInfo CreateExtensionManifest() + { + return new GeneratedValidatableTypeInfo( + type: typeof(global::Microsoft.Diagnostics.Tools.Monitor.Extensibility.ExtensionManifest), + members: [ + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.Extensibility.ExtensionManifest), + propertyType: typeof(string), + name: "Name", + displayName: "Name" + ), + ] + ); + } + private ValidatableTypeInfo CreateValidatableTypes() + { + return new GeneratedValidatableTypeInfo( + type: typeof(global::Microsoft.Diagnostics.Tools.Monitor.ValidatableTypes), + members: [ + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.ValidatableTypes), + propertyType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.RootOptions), + name: "RootOptions", + displayName: "RootOptions" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.ValidatableTypes), + propertyType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.CollectionRuleOptions), + name: "CollectionRuleOptions", + displayName: "CollectionRuleOptions" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.ValidatableTypes), + propertyType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Actions.CollectDumpOptions), + name: "CollectDumpOptions", + displayName: "CollectDumpOptions" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.ValidatableTypes), + propertyType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Actions.CollectExceptionsOptions), + name: "CollectExceptionsOptions", + displayName: "CollectExceptionsOptions" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.ValidatableTypes), + propertyType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Actions.CollectGCDumpOptions), + name: "CollectGCDumpOptions", + displayName: "CollectGCDumpOptions" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.ValidatableTypes), + propertyType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Actions.CollectLiveMetricsOptions), + name: "CollectLiveMetricsOptions", + displayName: "CollectLiveMetricsOptions" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.ValidatableTypes), + propertyType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Actions.CollectLogsOptions), + name: "CollectLogsOptions", + displayName: "CollectLogsOptions" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.ValidatableTypes), + propertyType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Actions.CollectStacksOptions), + name: "CollectStacksOptions", + displayName: "CollectStacksOptions" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.ValidatableTypes), + propertyType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Actions.CollectTraceOptions), + name: "CollectTraceOptions", + displayName: "CollectTraceOptions" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.ValidatableTypes), + propertyType: typeof(global::Microsoft.Diagnostics.Monitoring.WebApi.Models.EventPipeProvider), + name: "EventPipeProvider", + displayName: "EventPipeProvider" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.ValidatableTypes), + propertyType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Actions.ExecuteOptions), + name: "ExecuteOptions", + displayName: "ExecuteOptions" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.ValidatableTypes), + propertyType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Actions.GetEnvironmentVariableOptions), + name: "GetEnvironmentVariableOptions", + displayName: "GetEnvironmentVariableOptions" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.ValidatableTypes), + propertyType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Actions.LoadProfilerOptions), + name: "LoadProfilerOptions", + displayName: "LoadProfilerOptions" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.ValidatableTypes), + propertyType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Actions.SetEnvironmentVariableOptions), + name: "SetEnvironmentVariableOptions", + displayName: "SetEnvironmentVariableOptions" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.ValidatableTypes), + propertyType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Triggers.EventCounterShortcuts.CPUUsageOptions), + name: "CPUUsageOptions", + displayName: "CPUUsageOptions" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.ValidatableTypes), + propertyType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Triggers.EventCounterShortcuts.GCHeapSizeOptions), + name: "GCHeapSizeOptions", + displayName: "GCHeapSizeOptions" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.ValidatableTypes), + propertyType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Triggers.EventCounterShortcuts.ThreadpoolQueueLengthOptions), + name: "ThreadpoolQueueLengthOptions", + displayName: "ThreadpoolQueueLengthOptions" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.ValidatableTypes), + propertyType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Triggers.AspNetRequestCountOptions), + name: "AspNetRequestCountOptions", + displayName: "AspNetRequestCountOptions" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.ValidatableTypes), + propertyType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Triggers.AspNetRequestDurationOptions), + name: "AspNetRequestDurationOptions", + displayName: "AspNetRequestDurationOptions" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.ValidatableTypes), + propertyType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Triggers.AspNetResponseStatusOptions), + name: "AspNetResponseStatusOptions", + displayName: "AspNetResponseStatusOptions" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.ValidatableTypes), + propertyType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Triggers.EventCounterOptions), + name: "EventCounterOptions", + displayName: "EventCounterOptions" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.ValidatableTypes), + propertyType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Triggers.EventMeterOptions), + name: "EventMeterOptions", + displayName: "EventMeterOptions" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.ValidatableTypes), + propertyType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.Egress.FileSystem.FileSystemEgressProviderOptions), + name: "FileSystemEgressProviderOptions", + displayName: "FileSystemEgressProviderOptions" + ), + new GeneratedValidatablePropertyInfo( + containingType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.ValidatableTypes), + propertyType: typeof(global::Microsoft.Diagnostics.Tools.Monitor.Extensibility.ExtensionManifest), + name: "ExtensionManifest", + displayName: "ExtensionManifest" + ), + ] + ); + } + + } + + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.Http.ValidationsGenerator, Version=10.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60", "10.0.0.0")] + // file static class GeneratedServiceCollectionExtensions + // Made internal to allow access within the same assembly + internal static class GeneratedServiceCollectionExtensions + { + // [global::System.Runtime.CompilerServices.InterceptsLocationAttribute(1, "o8z0Jzavd3bSTijvzqPfl8tVAQBWYWxpZGF0YWJsZUluZm9SZXNvbHZlci5jcw==")] + // Removed InterceptsLocation since we are calling the extension method directly from a checked-in copy of the + // generated code, and interceptors are not designed for use in checked-in code. + public static global::Microsoft.Extensions.DependencyInjection.IServiceCollection AddValidation(this global::Microsoft.Extensions.DependencyInjection.IServiceCollection services, global::System.Action? configureOptions = null) + { + // Use non-extension method to avoid infinite recursion. + return global::Microsoft.Extensions.DependencyInjection.ValidationServiceCollectionExtensions.AddValidation(services, options => + { + options.Resolvers.Insert(0, new GeneratedValidatableInfoResolver()); + if (configureOptions is not null) + { + configureOptions(options); + } + }); + } + } + + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.Http.ValidationsGenerator, Version=10.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60", "10.0.0.0")] + file static class ValidationAttributeCache + { + private sealed record CacheKey(global::System.Type ContainingType, string PropertyName); + private static readonly global::System.Collections.Concurrent.ConcurrentDictionary _cache = new(); + + public static global::System.ComponentModel.DataAnnotations.ValidationAttribute[] GetValidationAttributes( + global::System.Type containingType, + string propertyName) + { + var key = new CacheKey(containingType, propertyName); + return _cache.GetOrAdd(key, static k => + { + var property = k.ContainingType.GetProperty(k.PropertyName); + if (property == null) + { + return []; + } + + return [.. global::System.Reflection.CustomAttributeExtensions.GetCustomAttributes(property, inherit: true)]; + }); + } + } +} \ No newline at end of file diff --git a/src/Tools/dotnet-monitor/ValidatableTypes.cs b/src/Tools/dotnet-monitor/ValidatableTypes.cs new file mode 100644 index 00000000000..453dc745f55 --- /dev/null +++ b/src/Tools/dotnet-monitor/ValidatableTypes.cs @@ -0,0 +1,72 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Microsoft.AspNetCore.Http.Validation; +using Microsoft.AspNetCore.Http.Validation.Generated; +using Microsoft.Diagnostics.Monitoring.WebApi.Models; +using Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options; +using Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Actions; +using Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Triggers; +using Microsoft.Diagnostics.Tools.Monitor.CollectionRules.Options.Triggers.EventCounterShortcuts; +using Microsoft.Diagnostics.Tools.Monitor.Egress.FileSystem; +using Microsoft.Diagnostics.Tools.Monitor.Extensibility; +using Microsoft.Extensions.DependencyInjection; + +namespace Microsoft.Diagnostics.Tools.Monitor +{ + // The Validation source generator doesn't run for libraries that don't call AddValidation, + // so we can't generate IValidatableInfo by using [ValidatableType] directly on types defined + // in ProjectReferences. This is a workaround to force the generator running in this project to + // generate IValidatableInfo for the referenced types. The containing class is not used otherwise. + // We use the same pattern for all types, including those defined in the same project. + [ValidatableType] + internal class ValidatableTypes + { + public required RootOptions RootOptions { get; init; } + + // Necessary to work around the generated validation code not recursing into Dictionary? members: + // https://github.com/dotnet/aspnetcore/issues/61737 + public required CollectionRuleOptions CollectionRuleOptions { get; init; } + + // Action options + public required CollectDumpOptions CollectDumpOptions { get; init; } + public required CollectExceptionsOptions CollectExceptionsOptions { get; init; } + public required CollectGCDumpOptions CollectGCDumpOptions { get; init; } + public required CollectLiveMetricsOptions CollectLiveMetricsOptions { get; init; } + public required CollectLogsOptions CollectLogsOptions { get; init; } + public required CollectStacksOptions CollectStacksOptions { get; init; } + public required CollectTraceOptions CollectTraceOptions { get; init; } + // Necessary to work around the generated validation code not recursing into List? members: + // https://github.com/dotnet/aspnetcore/issues/61737 + public required EventPipeProvider EventPipeProvider { get; init; } + public required ExecuteOptions ExecuteOptions { get; init; } + public required GetEnvironmentVariableOptions GetEnvironmentVariableOptions { get; init; } + public required LoadProfilerOptions LoadProfilerOptions { get; init; } + public required SetEnvironmentVariableOptions SetEnvironmentVariableOptions { get; init; } + + + // Trigger options + // EventCounterShortcuts + public required CPUUsageOptions CPUUsageOptions { get; init; } + public required GCHeapSizeOptions GCHeapSizeOptions { get; init; } + public required ThreadpoolQueueLengthOptions ThreadpoolQueueLengthOptions { get; init; } + // Other trigger options + public required AspNetRequestCountOptions AspNetRequestCountOptions { get; init; } + public required AspNetRequestDurationOptions AspNetRequestDurationOptions { get; init; } + public required AspNetResponseStatusOptions AspNetResponseStatusOptions { get; init; } + public required EventCounterOptions EventCounterOptions { get; init; } + public required EventMeterOptions EventMeterOptions { get; init; } + + + public required FileSystemEgressProviderOptions FileSystemEgressProviderOptions { get; init; } + public required ExtensionManifest ExtensionManifest { get; init; } + + public static void AddValidation(IServiceCollection services) + { + GeneratedServiceCollectionExtensions.AddValidation(services, options => + { + options.Resolvers.Insert(0, new CustomValidatableInfoResolver()); + }); + } + } +} diff --git a/src/Tools/dotnet-monitor/dotnet-monitor.csproj b/src/Tools/dotnet-monitor/dotnet-monitor.csproj index 3d5349372f8..fdf8418f3fd 100644 --- a/src/Tools/dotnet-monitor/dotnet-monitor.csproj +++ b/src/Tools/dotnet-monitor/dotnet-monitor.csproj @@ -11,6 +11,8 @@ enable false true + true + $(InterceptorsNamespaces);Microsoft.AspNetCore.Http.Validation.Generated @@ -41,6 +43,7 @@ +