Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -191,4 +191,20 @@ public partial class ProtocolClientOptions : Azure.Core.ClientOptions
{
public ProtocolClientOptions() { }
}
public sealed partial class ResponseError
{
internal ResponseError() { }
public string? Code { get { throw null; } }
public System.Collections.Generic.IReadOnlyList<Azure.Core.ResponseError> Details { get { throw null; } }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's a bit strange that details of X is a collection of X.

Copy link
Member

@tg-msft tg-msft Jun 24, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

public Azure.Core.ResponseInnerError? InnerError { get { throw null; } }
public string? Message { get { throw null; } }
public string? Target { get { throw null; } }
}
public sealed partial class ResponseInnerError
{
internal ResponseInnerError() { }
public string? Code { get { throw null; } }
public Azure.Core.ResponseInnerError? InnerError { get { throw null; } }
public string? Message { get { throw null; } }
}
}
115 changes: 115 additions & 0 deletions sdk/core/Azure.Core.Experimental/src/ResponseError.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using System;
using System.Collections.Generic;
using System.Text.Json;
using System.Text.Json.Serialization;

namespace Azure.Core
{
/// <summary>
/// Represents an error returned by an Azure Service.
/// </summary>
[JsonConverter(typeof(Converter))]
public sealed class ResponseError
{
internal ResponseError(string? code, string? message, ResponseInnerError? innerError, string? target, IReadOnlyList<ResponseError>? details)
{
Code = code;
Message = message;
InnerError = innerError;
Target = target;
Details = details ?? Array.Empty<ResponseError>();
}

/// <summary>
/// Gets the error code.
/// </summary>
public string? Code { get; }

/// <summary>
/// Gets the error message.
/// </summary>
public string? Message { get; }

/// <summary>
/// Gets the inner error.
/// </summary>
public ResponseInnerError? InnerError { get; }

/// <summary>
/// Gets the error target.
/// </summary>
public string? Target { get; }

/// <summary>
/// Gets the list of related errors.
/// </summary>
public IReadOnlyList<ResponseError> Details { get; }

private class Converter : JsonConverter<ResponseError?>
{
public override ResponseError? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
using var document = JsonDocument.ParseValue(ref reader);
var element = document.RootElement;
return Read(element);
}

private static ResponseError? Read(JsonElement element)
{
if (element.ValueKind == JsonValueKind.Null)
{
return null;
}

string? code = null;
if (element.TryGetProperty("code", out var property))
{
code = property.GetString();
}

string? message = null;
if (element.TryGetProperty("message", out property))
{
message = property.GetString();
}

string? target = null;
if (element.TryGetProperty("target", out property))
{
target = property.GetString();
}

ResponseInnerError? innererror = null;
if (element.TryGetProperty("innererror", out property))
{
innererror = ResponseInnerError.Converter.Read(property);
}

List<ResponseError>? details = null;
if (element.TryGetProperty("details", out property) &&
property.ValueKind == JsonValueKind.Array)
{
foreach (var item in property.EnumerateArray())
{
var detail = Read(item);
if (detail != null)
{
details ??= new();
details.Add(detail);
}
}
}

return new ResponseError(code, message, innererror, target, details);
}

public override void Write(Utf8JsonWriter writer, ResponseError? value, JsonSerializerOptions options)
{
throw new NotImplementedException();
}
}
}
}
81 changes: 81 additions & 0 deletions sdk/core/Azure.Core.Experimental/src/ResponseInnerError.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using System;
using System.Text.Json;
using System.Text.Json.Serialization;

namespace Azure.Core
{
/// <summary>
/// Represents an inner error.
/// </summary>
[JsonConverter(typeof(Converter))]
public sealed class ResponseInnerError
{
internal ResponseInnerError(string? code, string? message, ResponseInnerError? innerError)
{
Code = code;
Message = message;
InnerError = innerError;
}

/// <summary>
/// Gets the error code.
/// </summary>
public string? Code { get; }

/// <summary>
/// Gets the error message.
/// </summary>
public string? Message { get; }

/// <summary>
/// Gets the inner error.
/// </summary>
public ResponseInnerError? InnerError { get; }

internal class Converter : JsonConverter<ResponseInnerError?>
{
public override ResponseInnerError? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
using var document = JsonDocument.ParseValue(ref reader);
var element = document.RootElement;
return Read(element);
}

internal static ResponseInnerError? Read(JsonElement element)
{
if (element.ValueKind == JsonValueKind.Null)
{
return null;
}

string? code = null;
if (element.TryGetProperty("code", out var property))
{
code = property.GetString();
}

string? message = null;
if (element.TryGetProperty("message", out property))
{
message = property.GetString();
}

ResponseInnerError? innererror = null;
if (element.TryGetProperty("innererror", out property))
{
innererror = Read(property);
}

return new ResponseInnerError(code, message, innererror);
}

public override void Write(Utf8JsonWriter writer, ResponseInnerError? value, JsonSerializerOptions options)
{
throw new NotImplementedException();
}
}
}
}
85 changes: 85 additions & 0 deletions sdk/core/Azure.Core.Experimental/tests/ResponseErrorTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using System.Text.Json;
using NUnit.Framework;

namespace Azure.Core.Tests
{
public class ResponseErrorTests
{
[Test]
public void CanDeserializeNull()
{
Assert.Null(JsonSerializer.Deserialize<ResponseError>("null"));
}

[Test]
public void CanDeserializeSimple()
{
var error = JsonSerializer.Deserialize<ResponseError>(
"{" +
"\"code\":\"BadError\"," +
"\"message\":\"Something wasn't awesome\"," +
"\"target\":\"Error target\"," +
"\"innererror\":" +
"{" +
"\"code\":\"MoreDetailedBadError\"," +
"\"message\":\"Inner message\"" +
"}}");

Assert.AreEqual("BadError", error.Code);
Assert.AreEqual("Something wasn't awesome", error.Message);
Assert.AreEqual("Error target", error.Target);

Assert.AreEqual("MoreDetailedBadError", error.InnerError.Code);
Assert.AreEqual("Inner message", error.InnerError.Message);
Assert.Null(error.InnerError.InnerError);
}

[Test]
public void CanDeserializeComplex()
{
var error = JsonSerializer.Deserialize<ResponseError>(
"{" +
"\"code\":\"BadError\"," +
"\"message\":\"Something wasn't awesome\"," +
"\"target\":\"Error target\"," +
"\"details\": [" +
"{\"code\":\"Code 1\",\"message\":\"Message 1\"}," +
"{\"code\":\"Code 2\",\"message\":\"Message 2\"}," +
"null" +
"]," +
"\"innererror\":" +
"{" +
"\"code\":\"MoreDetailedBadError\"," +
"\"message\":\"Inner message\"," +
"\"innererror\":" +
"{" +
"\"code\":\"InnerMoreDetailedBadError\"," +
"\"message\":\"Inner Inner message\"" +
"}"+
"}}");

Assert.AreEqual("BadError", error.Code);
Assert.AreEqual("Something wasn't awesome", error.Message);
Assert.AreEqual("Error target", error.Target);

Assert.AreEqual("MoreDetailedBadError", error.InnerError.Code);
Assert.AreEqual("Inner message", error.InnerError.Message);

Assert.AreEqual("InnerMoreDetailedBadError", error.InnerError.InnerError.Code);
Assert.AreEqual("Inner Inner message", error.InnerError.InnerError.Message);

Assert.AreEqual("Code 1", error.Details[0].Code);
Assert.AreEqual("Message 1", error.Details[0].Message);

Assert.AreEqual("Code 2", error.Details[1].Code);
Assert.AreEqual("Message 2", error.Details[1].Message);

Assert.AreEqual(2, error.Details.Count);

Assert.Null(error.InnerError.InnerError.InnerError);
}
}
}
2 changes: 1 addition & 1 deletion sdk/monitor/Azure.Monitor.Query/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ LogsBatchQuery batch = new LogsBatchQuery();
string countQueryId = batch.AddQuery(workspaceId, "AzureActivity | count", TimeSpan.FromDays(1));
string topQueryId = batch.AddQuery(workspaceId, "AzureActivity | summarize Count = count() by ResourceGroup | top 10 by Count", TimeSpan.FromDays(1));

Response<LogsBatchQueryResult> response = await client.QueryBatchAsync(batch);
Response<LogsBatchQueryResults> response = await client.QueryBatchAsync(batch);

var count = response.Value.GetResult<int>(countQueryId).Single();
var topEntries = response.Value.GetResult<MyLogEntryModel>(topQueryId);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ public LogsQueryClient(System.Uri endpoint, Azure.Core.TokenCredential credentia
public virtual Azure.Response<Azure.Monitor.Query.Models.LogsQueryResult> Query(string workspace, string query, Azure.Core.DateTimeRange timeRange, Azure.Monitor.Query.LogsQueryOptions options = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; }
public virtual System.Threading.Tasks.Task<Azure.Response<Azure.Monitor.Query.Models.LogsQueryResult>> QueryAsync(string workspace, string query, Azure.Core.DateTimeRange timeRange, Azure.Monitor.Query.LogsQueryOptions options = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; }
public virtual System.Threading.Tasks.Task<Azure.Response<System.Collections.Generic.IReadOnlyList<T>>> QueryAsync<T>(string workspace, string query, Azure.Core.DateTimeRange timeRange, Azure.Monitor.Query.LogsQueryOptions options = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; }
public virtual Azure.Response<Azure.Monitor.Query.Models.LogsBatchQueryResult> QueryBatch(Azure.Monitor.Query.LogsBatchQuery batch, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; }
public virtual System.Threading.Tasks.Task<Azure.Response<Azure.Monitor.Query.Models.LogsBatchQueryResult>> QueryBatchAsync(Azure.Monitor.Query.LogsBatchQuery batch, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; }
public virtual Azure.Response<Azure.Monitor.Query.Models.LogsBatchQueryResults> QueryBatch(Azure.Monitor.Query.LogsBatchQuery batch, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; }
public virtual System.Threading.Tasks.Task<Azure.Response<Azure.Monitor.Query.Models.LogsBatchQueryResults>> QueryBatchAsync(Azure.Monitor.Query.LogsBatchQuery batch, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; }
public virtual Azure.Response<System.Collections.Generic.IReadOnlyList<T>> Query<T>(string workspace, string query, Azure.Core.DateTimeRange timeRange, Azure.Monitor.Query.LogsQueryOptions options = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; }
}
public partial class LogsQueryClientOptions : Azure.Core.ClientOptions
Expand Down Expand Up @@ -70,7 +70,7 @@ public MetricsQueryOptions() { }
}
public static partial class QueryModelFactory
{
public static Azure.Monitor.Query.Models.LogsQueryResult LogsQueryResult(System.Collections.Generic.IReadOnlyList<Azure.Monitor.Query.Models.LogsQueryResultTable> tables = null, System.Text.Json.JsonElement Statistics = default(System.Text.Json.JsonElement), System.Text.Json.JsonElement Visualization = default(System.Text.Json.JsonElement)) { throw null; }
public static Azure.Monitor.Query.Models.LogsQueryResult LogsQueryResult(System.Collections.Generic.IReadOnlyList<Azure.Monitor.Query.Models.LogsQueryResultTable> tables = null, System.Text.Json.JsonElement Statistics = default(System.Text.Json.JsonElement), System.Text.Json.JsonElement Error = default(System.Text.Json.JsonElement), System.Text.Json.JsonElement Visualization = default(System.Text.Json.JsonElement)) { throw null; }
public static Azure.Monitor.Query.Models.LogsQueryResultColumn LogsQueryResultColumn(string name = null, Azure.Monitor.Query.Models.LogColumnTypes type = default(Azure.Monitor.Query.Models.LogColumnTypes)) { throw null; }
public static Azure.Monitor.Query.Models.LogsQueryResultTable LogsQueryResultTable(string name = null, System.Collections.Generic.IReadOnlyList<Azure.Monitor.Query.Models.LogsQueryResultColumn> columns = null, System.Text.Json.JsonElement internalRows = default(System.Text.Json.JsonElement)) { throw null; }
public static Azure.Monitor.Query.Models.MetricAvailability MetricAvailability(System.TimeSpan? timeGrain = default(System.TimeSpan?), System.TimeSpan? retention = default(System.TimeSpan?)) { throw null; }
Expand Down Expand Up @@ -103,15 +103,23 @@ namespace Azure.Monitor.Query.Models
public static bool operator !=(Azure.Monitor.Query.Models.LogColumnTypes left, Azure.Monitor.Query.Models.LogColumnTypes right) { throw null; }
public override string ToString() { throw null; }
}
public partial class LogsBatchQueryResult
public partial class LogsBatchQueryResult : Azure.Monitor.Query.Models.LogsQueryResult
{
internal LogsBatchQueryResult() { }
public bool HasFailed { get { throw null; } }
public string Id { get { throw null; } }
}
public partial class LogsBatchQueryResults
{
internal LogsBatchQueryResults() { }
public System.Collections.Generic.IReadOnlyList<Azure.Monitor.Query.Models.LogsBatchQueryResult> Results { get { throw null; } }
public Azure.Monitor.Query.Models.LogsQueryResult GetResult(string queryId) { throw null; }
public System.Collections.Generic.IReadOnlyList<T> GetResult<T>(string queryId) { throw null; }
}
public partial class LogsQueryResult
{
internal LogsQueryResult() { }
public Azure.Core.ResponseError Error { get { throw null; } }
public Azure.Monitor.Query.Models.LogsQueryResultTable PrimaryTable { get { throw null; } }
public System.BinaryData Statistics { get { throw null; } }
public System.Collections.Generic.IReadOnlyList<Azure.Monitor.Query.Models.LogsQueryResultTable> Tables { get { throw null; } }
Expand Down Expand Up @@ -160,6 +168,7 @@ internal LogsQueryResultTable() { }
public System.Collections.Generic.IReadOnlyList<Azure.Monitor.Query.Models.LogsQueryResultColumn> Columns { get { throw null; } }
public string Name { get { throw null; } }
public System.Collections.Generic.IReadOnlyList<Azure.Monitor.Query.Models.LogsQueryResultRow> Rows { get { throw null; } }
public System.Collections.Generic.IReadOnlyList<T> Deserialize<T>() { throw null; }
}
public partial class Metric
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,12 @@

<ItemGroup>
<PackageReference Include="System.Text.Json" />
<PackageReference Include="Azure.Core" />
<PackageReference Include="Azure.Core.Experimental" />
<!--
<PackageReference Include="Azure.Core" />
<PackageReference Include="Azure.Core.Experimental" />
-->
<ProjectReference Include="..\..\..\core\Azure.Core\src\Azure.Core.csproj" />
<ProjectReference Include="..\..\..\core\Azure.Core.Experimental\src\Azure.Core.Experimental.csproj" />
</ItemGroup>

<!-- Shared source from Azure.Core -->
Expand Down
Loading