Skip to content

Commit aa44de3

Browse files
committed
Make service errors more discoverable.
1 parent 63e0fea commit aa44de3

File tree

3 files changed

+67
-6
lines changed

3 files changed

+67
-6
lines changed

src/readme.graph.md

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,27 @@ directive:
246246
}
247247
}
248248
}
249+
# Mark '@odata.id' as required properties for /$ref.
250+
- from: 'openapi-document'
251+
where: $.components.schemas['microsoft.graph.ODataErrors.InnerError']
252+
transform: >-
253+
return {
254+
"type": "object",
255+
"properties": {
256+
"date" : {
257+
"type" : 'string'
258+
},
259+
"request-id" : {
260+
"type" : 'string'
261+
},
262+
"client-request-id" : {
263+
"type" : 'string'
264+
}
265+
},
266+
"additionalProperties": {
267+
"type" : "object"
268+
}
269+
}
249270
# Mark '@odata.id' as required properties for /$ref.
250271
- from: 'openapi-document'
251272
where: $.components.schemas.ReferenceCreate
@@ -394,6 +415,10 @@ directive:
394415
}
395416
}
396417
418+
// Format error details.
419+
let errorDetailsRegex = /(ErrorDetails\s*=\s*)(new.*ErrorDetails\(message\).*)/gmi
420+
$ = $.replace(errorDetailsRegex, '$1this.GetErrorDetails((await response)?.Error, responseMessage)');
421+
397422
return $;
398423
}
399424
@@ -542,6 +567,21 @@ directive:
542567
return $;
543568
}
544569
570+
# Modify generated JsonObject class.
571+
- from: source-file-csharp
572+
where: $
573+
transform: >
574+
if (!$documentPath.match(/generated%2Fruntime%2FNodes%2FJsonObject.cs/gm))
575+
{
576+
return $;
577+
} else {
578+
// Make JsonObject's items dictionary case insensitive.
579+
let dictionaryInitRegex = /(\s*=\s*new\s*Dictionary<string,\s*JsonNode>\()(\);)/gm
580+
$ = $.replace(dictionaryInitRegex, '$1StringComparer.InvariantCultureIgnoreCase$2');
581+
582+
return $;
583+
}
584+
545585
# Modify API class.
546586
- from: source-file-csharp
547587
where: $

tools/Custom/HttpMessageLogFormatter.cs

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -63,9 +63,9 @@ public static async Task<string> GetHttpRequestLogAsync(HttpRequestMessage reque
6363

6464
StringBuilder stringBuilder = new StringBuilder();
6565
stringBuilder.AppendLine($"============================ HTTP REQUEST ============================{Environment.NewLine}");
66-
stringBuilder.AppendLine($"HTTP Method:{Environment.NewLine}{requestClone.Method.ToString()}{Environment.NewLine}");
67-
stringBuilder.AppendLine($"Absolute Uri:{Environment.NewLine}{requestClone.RequestUri.ToString()}{Environment.NewLine}");
68-
stringBuilder.AppendLine($"Headers:{Environment.NewLine}{HeadersToString(ConvertHttpHeadersToCollection(requestClone.Headers))}{Environment.NewLine}");
66+
stringBuilder.AppendLine($"HTTP Method:{Environment.NewLine}{requestClone.Method}{Environment.NewLine}");
67+
stringBuilder.AppendLine($"Absolute Uri:{Environment.NewLine}{requestClone.RequestUri}{Environment.NewLine}");
68+
stringBuilder.AppendLine($"Headers:{Environment.NewLine}{HeadersToString(requestClone.Headers)}{Environment.NewLine}");
6969
stringBuilder.AppendLine($"Body:{Environment.NewLine}{SanitizeBody(body)}{Environment.NewLine}");
7070
return stringBuilder.ToString();
7171
}
@@ -84,12 +84,17 @@ public static async Task<string> GetHttpResponseLogAsync(HttpResponseMessage res
8484
StringBuilder stringBuilder = new StringBuilder();
8585
stringBuilder.AppendLine($"============================ HTTP RESPONSE ============================{Environment.NewLine}");
8686
stringBuilder.AppendLine($"Status Code:{Environment.NewLine}{response.StatusCode}{Environment.NewLine}");
87-
stringBuilder.AppendLine($"Headers:{Environment.NewLine}{HeadersToString(ConvertHttpHeadersToCollection(response.Headers))}{Environment.NewLine}");
87+
stringBuilder.AppendLine($"Headers:{Environment.NewLine}{HeadersToString(response.Headers)}{Environment.NewLine}");
8888
stringBuilder.AppendLine($"Body:{Environment.NewLine}{SanitizeBody(body)}{Environment.NewLine}");
8989
return stringBuilder.ToString();
9090
}
9191

92-
private static Regex regexPattern = new Regex("(\\s*\"access_token\"\\s*:\\s*)\"[^\"]+\"", RegexOptions.Compiled);
92+
internal static string HeadersToString(HttpHeaders headers)
93+
{
94+
return HeadersToString(ConvertHttpHeadersToCollection(headers));
95+
}
96+
97+
private static readonly Regex regexPattern = new Regex("(\\s*\"access_token\"\\s*:\\s*)\"[^\"]+\"", RegexOptions.Compiled);
9398
private static object SanitizeBody(string body)
9499
{
95100
IList<Regex> regexList = new List<Regex>();
@@ -110,7 +115,7 @@ private static IDictionary<string, IEnumerable<string>> ConvertHttpHeadersToColl
110115
return headers.ToDictionary(a => a.Key, a => a.Value);
111116
}
112117

113-
private static object HeadersToString(IDictionary<string, IEnumerable<string>> headers)
118+
private static string HeadersToString(IDictionary<string, IEnumerable<string>> headers)
114119
{
115120
StringBuilder stringBuilder = headers.Aggregate(new StringBuilder(),
116121
(sb, kvp) => sb.AppendLine(string.Format("{0,-30}: {1}", kvp.Key, String.Join(",", kvp.Value.ToArray()))));

tools/Custom/PSCmdletExtensions.cs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ namespace NamespacePrefixPlaceholder.PowerShell
55
{
66
using Microsoft.Graph.PowerShell.Authentication;
77
using Microsoft.Graph.PowerShell.Authentication.Common;
8+
using NamespacePrefixPlaceholder.PowerShell.Models;
89
using System;
910
using System.Collections.ObjectModel;
1011
using System.IO;
@@ -105,6 +106,21 @@ internal static void WriteToFile(this PSCmdlet cmdlet, HttpResponseMessage respo
105106
}
106107
}
107108

109+
internal static ErrorDetails GetErrorDetails(this PSCmdlet cmdlet, IMicrosoftGraphODataErrorsMainError odataError, HttpResponseMessage responseMessage)
110+
{
111+
var serviceErrorDoc = "https://learn.microsoft.com/graph/errors";
112+
var recommendedAction = $"See service error codes: {serviceErrorDoc}";
113+
var requestUri = $"{responseMessage.RequestMessage?.Method} {responseMessage.RequestMessage?.RequestUri}";
114+
string date = odataError?.Innererror?.Date;
115+
string requestId = odataError?.Innererror?.RequestId;
116+
string clientRequestId = odataError?.Innererror?.ClientRequestId;
117+
string errorDetailsMessage = $"{odataError?.Message}\n\n{requestUri}\nStatusCode: {responseMessage.StatusCode}\nErrorCode: {odataError?.Code}\nDate: {date}\nRequestId: {requestId}\nClientRequestId: {clientRequestId}\n\n{recommendedAction}";
118+
return new ErrorDetails(errorDetailsMessage)
119+
{
120+
RecommendedAction = recommendedAction
121+
};
122+
}
123+
108124
/// <summary>
109125
/// Writes an input stream to an output stream.
110126
/// </summary>

0 commit comments

Comments
 (0)