From b21cf25fc6ffe93927a8e703746ef4672e7a0351 Mon Sep 17 00:00:00 2001 From: Justin Anderson Date: Mon, 9 Aug 2021 17:32:18 -0700 Subject: [PATCH 1/4] Refactor schema gen to generically create discriminated subschemas. --- .../SchemaGenerator.cs | 130 +++++++++++------- 1 file changed, 84 insertions(+), 46 deletions(-) diff --git a/src/Tests/Microsoft.Diagnostics.Monitoring.ConfigurationSchema/SchemaGenerator.cs b/src/Tests/Microsoft.Diagnostics.Monitoring.ConfigurationSchema/SchemaGenerator.cs index 387654a6e15..7de7ac24015 100644 --- a/src/Tests/Microsoft.Diagnostics.Monitoring.ConfigurationSchema/SchemaGenerator.cs +++ b/src/Tests/Microsoft.Diagnostics.Monitoring.ConfigurationSchema/SchemaGenerator.cs @@ -17,27 +17,18 @@ internal sealed class SchemaGenerator { public string GenerateSchema() { - var settings = new JsonSchemaGeneratorSettings(); + var schema = new JsonSchema(); + var context = new GenerationContext(schema); + context.SetRoot(); - settings.SerializerSettings = new JsonSerializerSettings(); - settings.SerializerSettings.Converters.Add(new StringEnumConverter()); - - JsonSchema schema = JsonSchema.FromType(settings); schema.Id = @"https://www.github.com/dotnet/dotnet-monitor"; schema.Title = "DotnetMonitorConfiguration"; - JsonSchema jsonConsoleFormatterOptions = JsonSchema.FromType(); - schema.Definitions.Add(nameof(JsonConsoleFormatterOptions), jsonConsoleFormatterOptions); - - JsonSchema simpleConsoleFormatterOptions = JsonSchema.FromType(); - schema.Definitions.Add(nameof(SimpleConsoleFormatterOptions), simpleConsoleFormatterOptions); - - JsonSchema systemdConsoleFormatterOptions = JsonSchema.FromType(); - schema.Definitions.Add(nameof(ConsoleFormatterOptions), systemdConsoleFormatterOptions); - //Allow other properties in the schema. schema.AdditionalPropertiesSchema = JsonSchema.CreateAnySchema(); + AddConsoleLoggerFormatterSubSchemas(context); + //TODO Figure out a better way to add object defaults schema.Definitions[nameof(EgressOptions)].Properties[nameof(EgressOptions.AzureBlobStorage)].Default = JsonSchema.CreateAnySchema(); schema.Definitions[nameof(EgressOptions)].Properties[nameof(EgressOptions.FileSystem)].Default = JsonSchema.CreateAnySchema(); @@ -57,16 +48,6 @@ public string GenerateSchema() kvp.Value.Default = JsonSchema.CreateAnySchema(); } - JsonSchema jsonConsoleLoggerOptionsSchema = GenerateConsoleLoggerOptionsSchema(jsonConsoleFormatterOptions, ConsoleLoggerFormat.Json); - JsonSchema simpleConsoleLoggerOptionsSchema = GenerateConsoleLoggerOptionsSchema(simpleConsoleFormatterOptions, ConsoleLoggerFormat.Simple); - JsonSchema systemdConsoleLoggerOptionsSchema = GenerateConsoleLoggerOptionsSchema(systemdConsoleFormatterOptions, ConsoleLoggerFormat.Systemd); - JsonSchema defaultConsoleLoggerOptionsSchema = GenerateDefaultConsoleLoggerOptionsSchema(simpleConsoleFormatterOptions); - - schema.Definitions[nameof(ConsoleLoggerOptions)].OneOf.Add(jsonConsoleLoggerOptionsSchema); - schema.Definitions[nameof(ConsoleLoggerOptions)].OneOf.Add(simpleConsoleLoggerOptionsSchema); - schema.Definitions[nameof(ConsoleLoggerOptions)].OneOf.Add(systemdConsoleLoggerOptionsSchema); - schema.Definitions[nameof(ConsoleLoggerOptions)].OneOf.Add(defaultConsoleLoggerOptionsSchema); - string schemaPayload = schema.ToJson(); //Normalize newlines embedded into json @@ -74,39 +55,37 @@ public string GenerateSchema() return schemaPayload; } - public static JsonSchema GenerateConsoleLoggerOptionsSchema(JsonSchema consoleFormatterOptions, ConsoleLoggerFormat consoleLoggerFormat) + private static void AddConsoleLoggerFormatterSubSchemas(GenerationContext context) { - JsonSchema consoleLoggerOptionsSchema = new JsonSchema(); - - JsonSchemaProperty formatterNameProperty = new JsonSchemaProperty(); - JsonSchemaProperty formatterOptionsProperty = new JsonSchemaProperty(); - - JsonSchema formatterOptionsSchema = new JsonSchema(); - formatterOptionsSchema.Reference = consoleFormatterOptions; - - formatterOptionsProperty.Reference = formatterOptionsSchema; - - formatterNameProperty.ExtensionData = new Dictionary(); - formatterNameProperty.ExtensionData.Add("const", consoleLoggerFormat.ToString()); + AddConsoleLoggerOptionsSubSchema(context, ConsoleLoggerFormat.Json); + AddConsoleLoggerOptionsSubSchema(context, ConsoleLoggerFormat.Simple); + AddConsoleLoggerOptionsSubSchema(context, ConsoleLoggerFormat.Systemd); + AddDefaultConsoleLoggerOptionsSubSchema(context); + } - consoleLoggerOptionsSchema.Properties.Add(nameof(ConsoleLoggerOptions.FormatterName), formatterNameProperty); - consoleLoggerOptionsSchema.Properties.Add(nameof(ConsoleLoggerOptions.FormatterOptions), formatterOptionsProperty); + private static void AddConsoleLoggerOptionsSubSchema(GenerationContext context, ConsoleLoggerFormat consoleLoggerFormat) + { + JsonSchema consoleLoggerOptionsSchema = new JsonSchema(); consoleLoggerOptionsSchema.RequiredProperties.Add(nameof(ConsoleLoggerOptions.FormatterName)); - return consoleLoggerOptionsSchema; + JsonSchemaProperty formatterOptionsProperty = AddDiscriminatedSubSchema( + context.Schema.Definitions[nameof(ConsoleLoggerOptions)], + nameof(ConsoleLoggerOptions.FormatterName), + consoleLoggerFormat.ToString(), + nameof(ConsoleLoggerOptions.FormatterOptions), + consoleLoggerOptionsSchema); + + formatterOptionsProperty.Reference = context.AddTypeIfNotExist(); } - public static JsonSchema GenerateDefaultConsoleLoggerOptionsSchema(JsonSchema consoleFormatterOptions) + private static void AddDefaultConsoleLoggerOptionsSubSchema(GenerationContext context) { JsonSchema consoleLoggerOptionsSchema = new JsonSchema(); JsonSchemaProperty formatterNameProperty = new JsonSchemaProperty(); JsonSchemaProperty formatterOptionsProperty = new JsonSchemaProperty(); - - JsonSchema formatterOptionsSchema = new JsonSchema(); - formatterOptionsSchema.Reference = consoleFormatterOptions; - formatterOptionsProperty.Reference = formatterOptionsSchema; + formatterOptionsProperty.Reference = context.AddTypeIfNotExist(); formatterNameProperty.Type = JsonObjectType.Null; formatterNameProperty.Default = "Simple"; @@ -114,7 +93,66 @@ public static JsonSchema GenerateDefaultConsoleLoggerOptionsSchema(JsonSchema co consoleLoggerOptionsSchema.Properties.Add(nameof(ConsoleLoggerOptions.FormatterName), formatterNameProperty); consoleLoggerOptionsSchema.Properties.Add(nameof(ConsoleLoggerOptions.FormatterOptions), formatterOptionsProperty); - return consoleLoggerOptionsSchema; + context.Schema.Definitions[nameof(ConsoleLoggerOptions)].OneOf.Add(consoleLoggerOptionsSchema); + } + + private static JsonSchemaProperty AddDiscriminatedSubSchema( + JsonSchema parentSchema, + string descriminatingPropertyName, + string descriminatingPropertyValue, + string descriminatedPropertyName, + JsonSchema subSchema = null) + { + if (null == subSchema) + { + subSchema = new JsonSchema(); + } + + JsonSchemaProperty descriminatingProperty = new JsonSchemaProperty(); + descriminatingProperty.ExtensionData = new Dictionary(); + descriminatingProperty.ExtensionData.Add("const", descriminatingPropertyValue); + + subSchema.Properties.Add(descriminatingPropertyName, descriminatingProperty); + + JsonSchemaProperty descriminatedProperty = new JsonSchemaProperty(); + + subSchema.Properties.Add(descriminatedPropertyName, descriminatedProperty); + + parentSchema.OneOf.Add(subSchema); + + return descriminatedProperty; + } + + private class GenerationContext + { + private readonly JsonSchemaGenerator _generator; + private readonly JsonSchemaResolver _resolver; + private readonly JsonSchemaGeneratorSettings _settings; + + public GenerationContext(JsonSchema rootSchema) + { + Schema = rootSchema; + + _settings = new JsonSchemaGeneratorSettings(); + _settings.SerializerSettings = new JsonSerializerSettings(); + _settings.SerializerSettings.Converters.Add(new StringEnumConverter()); + + _resolver = new JsonSchemaResolver(rootSchema, _settings); + + _generator = new JsonSchemaGenerator(_settings); + } + + public JsonSchema AddTypeIfNotExist() + { + return _generator.Generate(typeof(T), _resolver); + } + + public void SetRoot() + { + _generator.Generate(Schema, typeof(T), _resolver); + } + + public JsonSchema Schema { get; } } } } \ No newline at end of file From 4019f5afc6d0f88bbd8dd9ece91aeb935acf9e91 Mon Sep 17 00:00:00 2001 From: Justin Anderson Date: Tue, 10 Aug 2021 11:20:43 -0700 Subject: [PATCH 2/4] Regenerate schema.json --- documentation/schema.json | 99 ++++++++++++++++++--------------------- 1 file changed, 46 insertions(+), 53 deletions(-) diff --git a/documentation/schema.json b/documentation/schema.json index a0e0c64244d..b7ce988a80a 100644 --- a/documentation/schema.json +++ b/documentation/schema.json @@ -716,7 +716,6 @@ ] }, "JsonConsoleFormatterOptions": { - "title": "JsonConsoleFormatterOptions", "type": "object", "additionalProperties": false, "properties": { @@ -724,7 +723,7 @@ "description": "Gets or sets JsonWriterOptions.", "oneOf": [ { - "$ref": "#/definitions/JsonConsoleFormatterOptions/definitions/JsonWriterOptions" + "$ref": "#/definitions/JsonWriterOptions" } ] }, @@ -744,51 +743,48 @@ "description": "Gets or sets whether or not UTC timezone should be used for timestamps in logging messages. Defaults to false.", "default": false } - }, - "definitions": { - "JsonWriterOptions": { - "type": "object", - "additionalProperties": false, - "properties": { - "Encoder": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/definitions/JsonConsoleFormatterOptions/definitions/JavaScriptEncoder" - } - ] - }, - "Indented": { - "type": "boolean" - }, - "SkipValidation": { - "type": "boolean" - } - } - }, - "JavaScriptEncoder": { - "allOf": [ + } + }, + "JsonWriterOptions": { + "type": "object", + "additionalProperties": false, + "properties": { + "Encoder": { + "oneOf": [ { - "$ref": "#/definitions/JsonConsoleFormatterOptions/definitions/TextEncoder" + "type": "null" }, { - "type": "object", - "x-abstract": true, - "additionalProperties": false + "$ref": "#/definitions/JavaScriptEncoder" } ] }, - "TextEncoder": { + "Indented": { + "type": "boolean" + }, + "SkipValidation": { + "type": "boolean" + } + } + }, + "JavaScriptEncoder": { + "allOf": [ + { + "$ref": "#/definitions/TextEncoder" + }, + { "type": "object", "x-abstract": true, "additionalProperties": false } - } + ] + }, + "TextEncoder": { + "type": "object", + "x-abstract": true, + "additionalProperties": false }, "SimpleConsoleFormatterOptions": { - "title": "SimpleConsoleFormatterOptions", "type": "object", "additionalProperties": false, "properties": { @@ -796,7 +792,7 @@ "description": "Determines when to use color when logging messages.", "oneOf": [ { - "$ref": "#/definitions/SimpleConsoleFormatterOptions/definitions/LoggerColorBehavior" + "$ref": "#/definitions/LoggerColorBehavior" } ] }, @@ -820,26 +816,23 @@ "description": "Gets or sets whether or not UTC timezone should be used for timestamps in logging messages. Defaults to false.", "default": false } - }, - "definitions": { - "LoggerColorBehavior": { - "type": "string", - "description": "", - "x-enumNames": [ - "Default", - "Enabled", - "Disabled" - ], - "enum": [ - "Default", - "Enabled", - "Disabled" - ] - } } }, + "LoggerColorBehavior": { + "type": "string", + "description": "", + "x-enumNames": [ + "Default", + "Enabled", + "Disabled" + ], + "enum": [ + "Default", + "Enabled", + "Disabled" + ] + }, "ConsoleFormatterOptions": { - "title": "ConsoleFormatterOptions", "type": "object", "additionalProperties": false, "properties": { From 1533dab5694170654bdf161f5f140c20b5483451 Mon Sep 17 00:00:00 2001 From: Justin Anderson Date: Tue, 10 Aug 2021 11:46:03 -0700 Subject: [PATCH 3/4] Fix spelling --- .../SchemaGenerator.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Tests/Microsoft.Diagnostics.Monitoring.ConfigurationSchema/SchemaGenerator.cs b/src/Tests/Microsoft.Diagnostics.Monitoring.ConfigurationSchema/SchemaGenerator.cs index 7de7ac24015..8f37806ecdc 100644 --- a/src/Tests/Microsoft.Diagnostics.Monitoring.ConfigurationSchema/SchemaGenerator.cs +++ b/src/Tests/Microsoft.Diagnostics.Monitoring.ConfigurationSchema/SchemaGenerator.cs @@ -98,9 +98,9 @@ private static void AddDefaultConsoleLoggerOptionsSubSchema(GenerationContext co private static JsonSchemaProperty AddDiscriminatedSubSchema( JsonSchema parentSchema, - string descriminatingPropertyName, - string descriminatingPropertyValue, - string descriminatedPropertyName, + string discriminatingPropertyName, + string discriminatingPropertyValue, + string discriminatedPropertyName, JsonSchema subSchema = null) { if (null == subSchema) @@ -110,13 +110,13 @@ private static JsonSchemaProperty AddDiscriminatedSubSchema( JsonSchemaProperty descriminatingProperty = new JsonSchemaProperty(); descriminatingProperty.ExtensionData = new Dictionary(); - descriminatingProperty.ExtensionData.Add("const", descriminatingPropertyValue); + descriminatingProperty.ExtensionData.Add("const", discriminatingPropertyValue); - subSchema.Properties.Add(descriminatingPropertyName, descriminatingProperty); + subSchema.Properties.Add(discriminatingPropertyName, descriminatingProperty); JsonSchemaProperty descriminatedProperty = new JsonSchemaProperty(); - subSchema.Properties.Add(descriminatedPropertyName, descriminatedProperty); + subSchema.Properties.Add(discriminatedPropertyName, descriminatedProperty); parentSchema.OneOf.Add(subSchema); From 95146fe63be81fc6509238ec8ce21bc91aa262fb Mon Sep 17 00:00:00 2001 From: Justin Anderson Date: Tue, 10 Aug 2021 12:42:21 -0700 Subject: [PATCH 4/4] Fix more spelling --- .../SchemaGenerator.cs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Tests/Microsoft.Diagnostics.Monitoring.ConfigurationSchema/SchemaGenerator.cs b/src/Tests/Microsoft.Diagnostics.Monitoring.ConfigurationSchema/SchemaGenerator.cs index 8f37806ecdc..b6a3416e7fa 100644 --- a/src/Tests/Microsoft.Diagnostics.Monitoring.ConfigurationSchema/SchemaGenerator.cs +++ b/src/Tests/Microsoft.Diagnostics.Monitoring.ConfigurationSchema/SchemaGenerator.cs @@ -108,19 +108,19 @@ private static JsonSchemaProperty AddDiscriminatedSubSchema( subSchema = new JsonSchema(); } - JsonSchemaProperty descriminatingProperty = new JsonSchemaProperty(); - descriminatingProperty.ExtensionData = new Dictionary(); - descriminatingProperty.ExtensionData.Add("const", discriminatingPropertyValue); + JsonSchemaProperty discriminatingProperty = new JsonSchemaProperty(); + discriminatingProperty.ExtensionData = new Dictionary(); + discriminatingProperty.ExtensionData.Add("const", discriminatingPropertyValue); - subSchema.Properties.Add(discriminatingPropertyName, descriminatingProperty); + subSchema.Properties.Add(discriminatingPropertyName, discriminatingProperty); - JsonSchemaProperty descriminatedProperty = new JsonSchemaProperty(); + JsonSchemaProperty discriminatedProperty = new JsonSchemaProperty(); - subSchema.Properties.Add(discriminatedPropertyName, descriminatedProperty); + subSchema.Properties.Add(discriminatedPropertyName, discriminatedProperty); parentSchema.OneOf.Add(subSchema); - return descriminatedProperty; + return discriminatedProperty; } private class GenerationContext