Azure / autorest.csharp

Extension for AutoRest (https://github.com/Azure/autorest) that generates C# code
MIT License
142 stars 165 forks source link

Improve crash reports to include better logging #1082

Open chamons opened 3 years ago

chamons commented 3 years ago

As we process the yaml output of autorest core \ m4, we may not be able to get the exact swagger lines like

 https://github.com/Azure/autorest/issues/3559

But we need to do better. When you get a crash like this:

    file:///C:/src/azure-sdk-for-net/sdk/containerregistry/Azure.Containers.ContainerRegistry/src/swagger/containerregistry-jeremy.json#/components/schemas/paths┬╖v9pjtw┬╖v2-name-manifests-reference┬╖put┬╖responses┬╖201┬╖content┬╖application-json┬╖schema
  INFORMATION: Options {​​​​​"input":["prechecker"],"always-create-content-type-parameter":true,"flatten-models":true,"flatten-payloads":true,"group-parameters":true,"always-create-accept-parameter":true,"naming":{​​​​​"override":{​​​​​"cmyk":"CMYK","$host":"$host"}​​​​​}​​​​​}​​​​​
  INFORMATION: Accept-param true
  INFORMATION: Options {​​​​​"input":["prechecker"],"always-create-content-type-parameter":true,"flatten-models":true,"flatten-payloads":true,"group-parameters":true,"always-create-accept-parameter":true,"naming":{​​​​​"override":{​​​​​"cmyk":"CMYK","$host":"$host"}​​​​​}​​​​​}​​​​​
  INFORMATION: Accept-param true
  FATAL: System.Collections.Generic.KeyNotFoundException: The given key 'reference' was not present in the dictionary.
     at System.Collections.Generic.Dictionary`2.get_Item(TKey key)
     at AutoRest.CSharp.Output.Models.RestClient.GetPathSegments(String httpRequestUri, Dictionary`2 parameters, Boolean isRaw)+MoveNext() in D:\a\1\s\autorest.csharp\src\AutoRest.CSharp\Output\Models\RestClient.cs:line 462
     at System.Collections.Generic.LargeArrayBuilder1.AddRange(IEnumerable1 items)
     at System.Collections.Generic.SparseArrayBuilder1.AddRange(IEnumerable1 items)
     at System.Collections.Generic.SparseArrayBuilder1.ReserveOrAdd(IEnumerable1 items)
     at System.Linq.Enumerable.Concat2Iterator`1.ToArray()
     at System.Linq.Enumerable.ToArray[TSource](IEnumerable`1 source)
     at AutoRest.CSharp.Output.Models.RestClient.BuildMethod(Operation operation, HttpRequest httpRequest, ICollection`1 requestParameters, ResponseHeaderGroupType responseHeaderModel) in D:\a\1\s\autorest.csharp\src\AutoRest.CSharp\Output\Models\RestClient.cs:line 353
     at AutoRest.CSharp.Output.Models.RestClient.EnsureNormalMethods() in D:\a\1\s\autorest.csharp\src\AutoRest.CSharp\Output\Models\RestClient.cs:line 116
     at AutoRest.CSharp.Output.Models.RestClient.GetOperationMethod(ServiceRequest request) in D:\a\1\s\autorest.csharp\src\AutoRest.CSharp\Output\Models\RestClient.cs:line 551
     at AutoRest.CSharp.Output.Models.RestClient.BuildAllMethods()+MoveNext() in D:\a\1\s\autorest.csharp\src\AutoRest.CSharp\Output\Models\RestClient.cs:line 77
     at System.Collections.Generic.LargeArrayBuilder1.AddRange(IEnumerable1 items)
     at System.Collections.Generic.EnumerableHelpers.ToArray[T](IEnumerable`1 source)
     at System.Linq.Enumerable.ToArray[TSource](IEnumerable`1 source)
     at AutoRest.CSharp.Output.Models.RestClient.get_Methods() in D:\a\1\s\autorest.csharp\src\AutoRest.CSharp\Output\Models\RestClient.cs:line 66
     at AutoRest.CSharp.Generation.Writers.RestClientWriter.WriteClient(CodeWriter writer, RestClient restClient) in D:\a\1\s\autorest.csharp\src\AutoRest.CSharp\Generation\Writers\RestClientWriter.cs:line 42
     at AutoRest.CSharp.AutoRest.Plugins.CSharpGen.ExecuteAsync(Task`1 codeModelTask, Configuration configuration) in D:\a\1\s\autorest.csharp\src\AutoRest.CSharp\AutoRest\Plugins\CSharpGen.cs:line 64
     at AutoRest.CSharp.AutoRest.Plugins.CSharpGen.Execute(IPluginCommunication autoRest) in D:\a\1\s\autorest.csharp\src\AutoRest.CSharp\AutoRest\Plugins\CSharpGen.cs:line 152
     at AutoRest.CSharp.AutoRest.Plugins.PluginProcessor.Start(IPluginCommunication autoRest) in D:\a\1\s\autorest.csharp\src\AutoRest.CSharp\AutoRest\Plugins\PluginProcessor.cs:line 36
EXEC : error : Plugin csharpgen reported failure. [C:\src\azure-sdk-for-net\sdk\containerregistry\Azure.Containers.ContainerRegistry\src\Azure.Containers.ContainerRegistry.csproj]

it is not possible to know what part of the swagger we were generated (What method in BuildMethod?)

chamons commented 3 years ago

Example:

input-file: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/53574efb3c9199b9dcec21bd8e7ca5b9e8d4f9b9/specification/deviceupdate/data-plane/Microsoft.DeviceUpdate/preview/2020-09-01/deviceupdate.json
low-level-client: true

Knowing we are generating 'GetUpdate' and parameter 'ifNoneMatch' would be super useful.

Possible Design

My idea is to have a static ConcurrentDictionary<ThreadID, Stack> that gets context information pushed onto it as generation continues. Maybe a cute using statement that pushing on start and pops on dispose? On crash, we look up our thread and output each entry like a stack trace.

We need to measure performance, and if more than a few % off we likely need to add a new configuration option "debug-crash" or something. In that mode, we actually do this work. Then we can update the crash log to have a note "re-run with --debug-crash or whatever for a more detailed description of the problem."