diff --git a/sdk/core/Azure.Core.Experimental/api/Azure.Core.Experimental.netstandard2.0.cs b/sdk/core/Azure.Core.Experimental/api/Azure.Core.Experimental.netstandard2.0.cs index cce3e3c98654..6e88a212a3ec 100644 --- a/sdk/core/Azure.Core.Experimental/api/Azure.Core.Experimental.netstandard2.0.cs +++ b/sdk/core/Azure.Core.Experimental/api/Azure.Core.Experimental.netstandard2.0.cs @@ -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 Details { get { throw null; } } + 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; } } + } } diff --git a/sdk/core/Azure.Core.Experimental/src/ResponseError.cs b/sdk/core/Azure.Core.Experimental/src/ResponseError.cs new file mode 100644 index 000000000000..8b018d90e698 --- /dev/null +++ b/sdk/core/Azure.Core.Experimental/src/ResponseError.cs @@ -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 +{ + /// + /// Represents an error returned by an Azure Service. + /// + [JsonConverter(typeof(Converter))] + public sealed class ResponseError + { + internal ResponseError(string? code, string? message, ResponseInnerError? innerError, string? target, IReadOnlyList? details) + { + Code = code; + Message = message; + InnerError = innerError; + Target = target; + Details = details ?? Array.Empty(); + } + + /// + /// Gets the error code. + /// + public string? Code { get; } + + /// + /// Gets the error message. + /// + public string? Message { get; } + + /// + /// Gets the inner error. + /// + public ResponseInnerError? InnerError { get; } + + /// + /// Gets the error target. + /// + public string? Target { get; } + + /// + /// Gets the list of related errors. + /// + public IReadOnlyList Details { get; } + + private class Converter : JsonConverter + { + 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? 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(); + } + } + } +} \ No newline at end of file diff --git a/sdk/core/Azure.Core.Experimental/src/ResponseInnerError.cs b/sdk/core/Azure.Core.Experimental/src/ResponseInnerError.cs new file mode 100644 index 000000000000..822bcb5dbf45 --- /dev/null +++ b/sdk/core/Azure.Core.Experimental/src/ResponseInnerError.cs @@ -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 +{ + /// + /// Represents an inner error. + /// + [JsonConverter(typeof(Converter))] + public sealed class ResponseInnerError + { + internal ResponseInnerError(string? code, string? message, ResponseInnerError? innerError) + { + Code = code; + Message = message; + InnerError = innerError; + } + + /// + /// Gets the error code. + /// + public string? Code { get; } + + /// + /// Gets the error message. + /// + public string? Message { get; } + + /// + /// Gets the inner error. + /// + public ResponseInnerError? InnerError { get; } + + internal class Converter : JsonConverter + { + 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(); + } + } + } +} \ No newline at end of file diff --git a/sdk/core/Azure.Core.Experimental/tests/ResponseErrorTests.cs b/sdk/core/Azure.Core.Experimental/tests/ResponseErrorTests.cs new file mode 100644 index 000000000000..4e3002c574a5 --- /dev/null +++ b/sdk/core/Azure.Core.Experimental/tests/ResponseErrorTests.cs @@ -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("null")); + } + + [Test] + public void CanDeserializeSimple() + { + var error = JsonSerializer.Deserialize( + "{" + + "\"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( + "{" + + "\"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); + } + } +} \ No newline at end of file diff --git a/sdk/monitor/Azure.Monitor.Query/README.md b/sdk/monitor/Azure.Monitor.Query/README.md index 9ddf42f4e5fa..99a42cb474a8 100644 --- a/sdk/monitor/Azure.Monitor.Query/README.md +++ b/sdk/monitor/Azure.Monitor.Query/README.md @@ -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 response = await client.QueryBatchAsync(batch); +Response response = await client.QueryBatchAsync(batch); var count = response.Value.GetResult(countQueryId).Single(); var topEntries = response.Value.GetResult(topQueryId); diff --git a/sdk/monitor/Azure.Monitor.Query/api/Azure.Monitor.Query.netstandard2.0.cs b/sdk/monitor/Azure.Monitor.Query/api/Azure.Monitor.Query.netstandard2.0.cs index 68a475eb7c3e..c9826989b51d 100644 --- a/sdk/monitor/Azure.Monitor.Query/api/Azure.Monitor.Query.netstandard2.0.cs +++ b/sdk/monitor/Azure.Monitor.Query/api/Azure.Monitor.Query.netstandard2.0.cs @@ -16,8 +16,8 @@ public LogsQueryClient(System.Uri endpoint, Azure.Core.TokenCredential credentia public virtual Azure.Response 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> 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>> 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 Azure.Response QueryBatch(Azure.Monitor.Query.LogsBatchQuery batch, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } - public virtual System.Threading.Tasks.Task> QueryBatchAsync(Azure.Monitor.Query.LogsBatchQuery batch, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public virtual Azure.Response QueryBatch(Azure.Monitor.Query.LogsBatchQuery batch, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public virtual System.Threading.Tasks.Task> QueryBatchAsync(Azure.Monitor.Query.LogsBatchQuery batch, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } public virtual Azure.Response> 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 partial class LogsQueryClientOptions : Azure.Core.ClientOptions @@ -70,7 +70,7 @@ public MetricsQueryOptions() { } } public static partial class QueryModelFactory { - public static Azure.Monitor.Query.Models.LogsQueryResult LogsQueryResult(System.Collections.Generic.IReadOnlyList 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 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 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; } @@ -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 Results { get { throw null; } } public Azure.Monitor.Query.Models.LogsQueryResult GetResult(string queryId) { throw null; } public System.Collections.Generic.IReadOnlyList GetResult(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 Tables { get { throw null; } } @@ -160,6 +168,7 @@ internal LogsQueryResultTable() { } public System.Collections.Generic.IReadOnlyList Columns { get { throw null; } } public string Name { get { throw null; } } public System.Collections.Generic.IReadOnlyList Rows { get { throw null; } } + public System.Collections.Generic.IReadOnlyList Deserialize() { throw null; } } public partial class Metric { diff --git a/sdk/monitor/Azure.Monitor.Query/src/Azure.Monitor.Query.csproj b/sdk/monitor/Azure.Monitor.Query/src/Azure.Monitor.Query.csproj index 5925eea8a79b..a03e29c8492c 100644 --- a/sdk/monitor/Azure.Monitor.Query/src/Azure.Monitor.Query.csproj +++ b/sdk/monitor/Azure.Monitor.Query/src/Azure.Monitor.Query.csproj @@ -10,8 +10,12 @@ - - + + + diff --git a/sdk/monitor/Azure.Monitor.Query/src/Generated/Models/LogQueryResponse.Serialization.cs b/sdk/monitor/Azure.Monitor.Query/src/Generated/Models/LogQueryResponse.Serialization.cs index 3f5cbb561e1c..9122472e63b0 100644 --- a/sdk/monitor/Azure.Monitor.Query/src/Generated/Models/LogQueryResponse.Serialization.cs +++ b/sdk/monitor/Azure.Monitor.Query/src/Generated/Models/LogQueryResponse.Serialization.cs @@ -17,7 +17,7 @@ internal static LogQueryResponse DeserializeLogQueryResponse(JsonElement element { Optional id = default; Optional status = default; - Optional body = default; + Optional body = default; Optional> headers = default; foreach (var property in element.EnumerateObject()) { @@ -43,7 +43,7 @@ internal static LogQueryResponse DeserializeLogQueryResponse(JsonElement element property.ThrowNonNullablePropertyIsNull(); continue; } - body = LogsBatchQueryResultInternal.DeserializeLogsBatchQueryResultInternal(property.Value); + body = LogsBatchQueryResult.DeserializeLogsBatchQueryResult(property.Value); continue; } if (property.NameEquals("headers")) diff --git a/sdk/monitor/Azure.Monitor.Query/src/Generated/Models/LogQueryResponse.cs b/sdk/monitor/Azure.Monitor.Query/src/Generated/Models/LogQueryResponse.cs index e393be64297a..818ea441ffc5 100644 --- a/sdk/monitor/Azure.Monitor.Query/src/Generated/Models/LogQueryResponse.cs +++ b/sdk/monitor/Azure.Monitor.Query/src/Generated/Models/LogQueryResponse.cs @@ -22,20 +22,18 @@ internal LogQueryResponse() /// Initializes a new instance of LogQueryResponse. /// . /// . - /// Contains the tables, columns & rows resulting from the query or the error details if the query failed. + /// Contains the tables, columns & rows resulting from the query or the error details if the query failed. /// Dictionary of <string>. - internal LogQueryResponse(string id, int? status, LogsBatchQueryResultInternal body, IReadOnlyDictionary headers) + internal LogQueryResponse(string id, int? status, LogsBatchQueryResult Body, IReadOnlyDictionary headers) { Id = id; Status = status; - Body = body; + _body = Body; Headers = headers; } public string Id { get; } public int? Status { get; } - /// Contains the tables, columns & rows resulting from the query or the error details if the query failed. - public LogsBatchQueryResultInternal Body { get; } /// Dictionary of <string>. public IReadOnlyDictionary Headers { get; } } diff --git a/sdk/monitor/Azure.Monitor.Query/src/Generated/Models/LogsBatchQueryResult.Serialization.cs b/sdk/monitor/Azure.Monitor.Query/src/Generated/Models/LogsBatchQueryResult.Serialization.cs index b277657865a9..74dbab41c084 100644 --- a/sdk/monitor/Azure.Monitor.Query/src/Generated/Models/LogsBatchQueryResult.Serialization.cs +++ b/sdk/monitor/Azure.Monitor.Query/src/Generated/Models/LogsBatchQueryResult.Serialization.cs @@ -13,28 +13,5 @@ namespace Azure.Monitor.Query.Models { public partial class LogsBatchQueryResult { - internal static LogsBatchQueryResult DeserializeLogsBatchQueryResult(JsonElement element) - { - Optional> responses = default; - foreach (var property in element.EnumerateObject()) - { - if (property.NameEquals("responses")) - { - if (property.Value.ValueKind == JsonValueKind.Null) - { - property.ThrowNonNullablePropertyIsNull(); - continue; - } - List array = new List(); - foreach (var item in property.Value.EnumerateArray()) - { - array.Add(LogQueryResponse.DeserializeLogQueryResponse(item)); - } - responses = array; - continue; - } - } - return new LogsBatchQueryResult(Optional.ToList(responses)); - } } } diff --git a/sdk/monitor/Azure.Monitor.Query/src/Generated/Models/LogsBatchQueryResult.cs b/sdk/monitor/Azure.Monitor.Query/src/Generated/Models/LogsBatchQueryResult.cs index aa78c44ecf5b..9dad0a2679d5 100644 --- a/sdk/monitor/Azure.Monitor.Query/src/Generated/Models/LogsBatchQueryResult.cs +++ b/sdk/monitor/Azure.Monitor.Query/src/Generated/Models/LogsBatchQueryResult.cs @@ -5,25 +5,33 @@ #nullable disable +using System; using System.Collections.Generic; -using Azure.Core; +using System.Text.Json; namespace Azure.Monitor.Query.Models { - /// Response to a batch. - public partial class LogsBatchQueryResult + /// Contains the tables, columns & rows resulting from the query or the error details if the query failed. + public partial class LogsBatchQueryResult : LogsQueryResult { /// Initializes a new instance of LogsBatchQueryResult. - internal LogsBatchQueryResult() + /// The list of tables, columns and rows. + /// is null. + internal LogsBatchQueryResult(IEnumerable tables) : base(tables) { - Responses = new ChangeTrackingList(); + if (tables == null) + { + throw new ArgumentNullException(nameof(tables)); + } } /// Initializes a new instance of LogsBatchQueryResult. - /// An array of responses corresponding to each individual request in a batch. - internal LogsBatchQueryResult(IReadOnlyList responses) + /// The list of tables, columns and rows. + /// Any object. + /// Any object. + /// Any object. + internal LogsBatchQueryResult(IReadOnlyList tables, JsonElement Statistics, JsonElement Error, JsonElement Visualization) : base(tables, Statistics, Error, Visualization) { - Responses = responses; } } } diff --git a/sdk/monitor/Azure.Monitor.Query/src/Generated/Models/LogsBatchQueryResultInternal.Serialization.cs b/sdk/monitor/Azure.Monitor.Query/src/Generated/Models/LogsBatchQueryResultInternal.Serialization.cs deleted file mode 100644 index a303da3ae540..000000000000 --- a/sdk/monitor/Azure.Monitor.Query/src/Generated/Models/LogsBatchQueryResultInternal.Serialization.cs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -// - -#nullable disable - -using System.Collections.Generic; -using System.Text.Json; -using Azure.Core; - -namespace Azure.Monitor.Query.Models -{ - internal partial class LogsBatchQueryResultInternal - { - } -} diff --git a/sdk/monitor/Azure.Monitor.Query/src/Generated/Models/LogsBatchQueryResultInternal.cs b/sdk/monitor/Azure.Monitor.Query/src/Generated/Models/LogsBatchQueryResultInternal.cs deleted file mode 100644 index 2ae6a337beee..000000000000 --- a/sdk/monitor/Azure.Monitor.Query/src/Generated/Models/LogsBatchQueryResultInternal.cs +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -// - -#nullable disable - -using System; -using System.Collections.Generic; -using System.Text.Json; - -namespace Azure.Monitor.Query.Models -{ - /// Contains the tables, columns & rows resulting from the query or the error details if the query failed. - internal partial class LogsBatchQueryResultInternal : LogsQueryResult - { - /// Initializes a new instance of LogsBatchQueryResultInternal. - /// The list of tables, columns and rows. - /// is null. - internal LogsBatchQueryResultInternal(IEnumerable tables) : base(tables) - { - if (tables == null) - { - throw new ArgumentNullException(nameof(tables)); - } - } - - /// Initializes a new instance of LogsBatchQueryResultInternal. - /// The list of tables, columns and rows. - /// Any object. - /// Any object. - /// The code and message for an error. - internal LogsBatchQueryResultInternal(IReadOnlyList tables, JsonElement Statistics, JsonElement Visualization, ErrorInfo error) : base(tables, Statistics, Visualization) - { - Error = error; - } - } -} diff --git a/sdk/monitor/Azure.Monitor.Query/src/Generated/Models/LogsBatchQueryResults.Serialization.cs b/sdk/monitor/Azure.Monitor.Query/src/Generated/Models/LogsBatchQueryResults.Serialization.cs new file mode 100644 index 000000000000..48922dae3a72 --- /dev/null +++ b/sdk/monitor/Azure.Monitor.Query/src/Generated/Models/LogsBatchQueryResults.Serialization.cs @@ -0,0 +1,40 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System.Collections.Generic; +using System.Text.Json; +using Azure.Core; + +namespace Azure.Monitor.Query.Models +{ + public partial class LogsBatchQueryResults + { + internal static LogsBatchQueryResults DeserializeLogsBatchQueryResults(JsonElement element) + { + Optional> responses = default; + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("responses")) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + property.ThrowNonNullablePropertyIsNull(); + continue; + } + List array = new List(); + foreach (var item in property.Value.EnumerateArray()) + { + array.Add(LogQueryResponse.DeserializeLogQueryResponse(item)); + } + responses = array; + continue; + } + } + return new LogsBatchQueryResults(Optional.ToList(responses)); + } + } +} diff --git a/sdk/monitor/Azure.Monitor.Query/src/Generated/Models/LogsBatchQueryResults.cs b/sdk/monitor/Azure.Monitor.Query/src/Generated/Models/LogsBatchQueryResults.cs new file mode 100644 index 000000000000..401ce1a26fc7 --- /dev/null +++ b/sdk/monitor/Azure.Monitor.Query/src/Generated/Models/LogsBatchQueryResults.cs @@ -0,0 +1,29 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System.Collections.Generic; +using Azure.Core; + +namespace Azure.Monitor.Query.Models +{ + /// Response to a batch. + public partial class LogsBatchQueryResults + { + /// Initializes a new instance of LogsBatchQueryResults. + internal LogsBatchQueryResults() + { + Responses = new ChangeTrackingList(); + } + + /// Initializes a new instance of LogsBatchQueryResults. + /// An array of responses corresponding to each individual request in a batch. + internal LogsBatchQueryResults(IReadOnlyList responses) + { + Responses = responses; + } + } +} diff --git a/sdk/monitor/Azure.Monitor.Query/src/Generated/Models/LogsQueryResult.Serialization.cs b/sdk/monitor/Azure.Monitor.Query/src/Generated/Models/LogsQueryResult.Serialization.cs index aba2bccd3e5e..3bbf963169c2 100644 --- a/sdk/monitor/Azure.Monitor.Query/src/Generated/Models/LogsQueryResult.Serialization.cs +++ b/sdk/monitor/Azure.Monitor.Query/src/Generated/Models/LogsQueryResult.Serialization.cs @@ -17,6 +17,7 @@ internal static LogsQueryResult DeserializeLogsQueryResult(JsonElement element) { IReadOnlyList tables = default; Optional statistics = default; + Optional error = default; Optional render = default; foreach (var property in element.EnumerateObject()) { @@ -35,13 +36,18 @@ internal static LogsQueryResult DeserializeLogsQueryResult(JsonElement element) statistics = property.Value.Clone(); continue; } + if (property.NameEquals("error")) + { + error = property.Value.Clone(); + continue; + } if (property.NameEquals("render")) { render = property.Value.Clone(); continue; } } - return new LogsQueryResult(tables, statistics, render); + return new LogsQueryResult(tables, statistics, error, render); } } } diff --git a/sdk/monitor/Azure.Monitor.Query/src/Generated/Models/LogsQueryResult.cs b/sdk/monitor/Azure.Monitor.Query/src/Generated/Models/LogsQueryResult.cs index d934a9401739..5da705088b12 100644 --- a/sdk/monitor/Azure.Monitor.Query/src/Generated/Models/LogsQueryResult.cs +++ b/sdk/monitor/Azure.Monitor.Query/src/Generated/Models/LogsQueryResult.cs @@ -31,11 +31,13 @@ internal LogsQueryResult(IEnumerable tables) /// Initializes a new instance of LogsQueryResult. /// The list of tables, columns and rows. /// Any object. + /// Any object. /// Any object. - internal LogsQueryResult(IReadOnlyList tables, JsonElement Statistics, JsonElement Visualization) + internal LogsQueryResult(IReadOnlyList tables, JsonElement Statistics, JsonElement Error, JsonElement Visualization) { Tables = tables; _statistics = Statistics; + _error = Error; _visualization = Visualization; } diff --git a/sdk/monitor/Azure.Monitor.Query/src/Generated/QueryModelFactory.cs b/sdk/monitor/Azure.Monitor.Query/src/Generated/QueryModelFactory.cs index c86a514c7170..f0dff2a38602 100644 --- a/sdk/monitor/Azure.Monitor.Query/src/Generated/QueryModelFactory.cs +++ b/sdk/monitor/Azure.Monitor.Query/src/Generated/QueryModelFactory.cs @@ -18,12 +18,13 @@ public static partial class QueryModelFactory /// Initializes new instance of LogsQueryResult class. /// The list of tables, columns and rows. /// Any object. + /// Any object. /// Any object. /// A new instance for mocking. - public static LogsQueryResult LogsQueryResult(IReadOnlyList tables = default, JsonElement Statistics = default, JsonElement Visualization = default) + public static LogsQueryResult LogsQueryResult(IReadOnlyList tables = default, JsonElement Statistics = default, JsonElement Error = default, JsonElement Visualization = default) { tables ??= new List(); - return new LogsQueryResult(tables, Statistics, Visualization); + return new LogsQueryResult(tables, Statistics, Error, Visualization); } /// Initializes new instance of LogsQueryResultTable class. diff --git a/sdk/monitor/Azure.Monitor.Query/src/Generated/QueryRestClient.cs b/sdk/monitor/Azure.Monitor.Query/src/Generated/QueryRestClient.cs index c00044fa20cc..260597596edf 100644 --- a/sdk/monitor/Azure.Monitor.Query/src/Generated/QueryRestClient.cs +++ b/sdk/monitor/Azure.Monitor.Query/src/Generated/QueryRestClient.cs @@ -231,7 +231,7 @@ internal HttpMessage CreateBatchRequest(BatchRequest body) /// The batch request body. /// The cancellation token to use. /// is null. - public async Task> BatchAsync(BatchRequest body, CancellationToken cancellationToken = default) + public async Task> BatchAsync(BatchRequest body, CancellationToken cancellationToken = default) { if (body == null) { @@ -244,9 +244,9 @@ public async Task> BatchAsync(BatchRequest body, { case 200: { - LogsBatchQueryResult value = default; + LogsBatchQueryResults value = default; using var document = await JsonDocument.ParseAsync(message.Response.ContentStream, default, cancellationToken).ConfigureAwait(false); - value = LogsBatchQueryResult.DeserializeLogsBatchQueryResult(document.RootElement); + value = LogsBatchQueryResults.DeserializeLogsBatchQueryResults(document.RootElement); return Response.FromValue(value, message.Response); } default: @@ -258,7 +258,7 @@ public async Task> BatchAsync(BatchRequest body, /// The batch request body. /// The cancellation token to use. /// is null. - public Response Batch(BatchRequest body, CancellationToken cancellationToken = default) + public Response Batch(BatchRequest body, CancellationToken cancellationToken = default) { if (body == null) { @@ -271,9 +271,9 @@ public Response Batch(BatchRequest body, CancellationToken { case 200: { - LogsBatchQueryResult value = default; + LogsBatchQueryResults value = default; using var document = JsonDocument.Parse(message.Response.ContentStream); - value = LogsBatchQueryResult.DeserializeLogsBatchQueryResult(document.RootElement); + value = LogsBatchQueryResults.DeserializeLogsBatchQueryResults(document.RootElement); return Response.FromValue(value, message.Response); } default: diff --git a/sdk/monitor/Azure.Monitor.Query/src/LogsQueryClient.cs b/sdk/monitor/Azure.Monitor.Query/src/LogsQueryClient.cs index d4d79bc60435..9a9a7776d96c 100644 --- a/sdk/monitor/Azure.Monitor.Query/src/LogsQueryClient.cs +++ b/sdk/monitor/Azure.Monitor.Query/src/LogsQueryClient.cs @@ -4,12 +4,10 @@ using System; using System.Collections.Generic; using System.Globalization; -using System.Linq; using System.Text; using System.Text.Json; using System.Threading; using System.Threading.Tasks; -using System.Xml; using Azure.Core; using Azure.Core.Pipeline; using Azure.Monitor.Query.Models; @@ -26,7 +24,6 @@ public class LogsQueryClient private readonly QueryRestClient _queryClient; private readonly ClientDiagnostics _clientDiagnostics; private readonly HttpPipeline _pipeline; - private readonly RowBinder _rowBinder; /// /// Initializes a new instance of . Uses the default 'https://api.loganalytics.io' endpoint. @@ -72,7 +69,6 @@ public LogsQueryClient(Uri endpoint, TokenCredential credential, LogsQueryClient credential, options.AuthenticationScope ?? "https://api.loganalytics.io//.default")); _queryClient = new QueryRestClient(_clientDiagnostics, _pipeline, endpoint); - _rowBinder = new RowBinder(); } /// @@ -95,7 +91,7 @@ public virtual Response> Query(string workspace, string quer { Response response = Query(workspace, query, timeRange, options, cancellationToken); - return Response.FromValue(_rowBinder.BindResults(response.Value.Tables), response.GetRawResponse()); + return Response.FromValue(RowBinder.Shared.BindResults(response.Value.Tables), response.GetRawResponse()); } /// @@ -111,7 +107,7 @@ public virtual async Task>> QueryAsync(string works { Response response = await QueryAsync(workspace, query, timeRange, options, cancellationToken).ConfigureAwait(false); - return Response.FromValue(_rowBinder.BindResults(response.Value.Tables), response.GetRawResponse()); + return Response.FromValue(RowBinder.Shared.BindResults(response.Value.Tables), response.GetRawResponse()); } /// @@ -167,8 +163,8 @@ public virtual async Task> QueryAsync(string workspace /// /// The batch of queries to send. /// The to use. - /// The containing the query identifier that has to be passed into to get the result. - public virtual Response QueryBatch(LogsBatchQuery batch, CancellationToken cancellationToken = default) + /// The containing the query identifier that has to be passed into to get the result. + public virtual Response QueryBatch(LogsBatchQuery batch, CancellationToken cancellationToken = default) { Argument.AssertNotNull(batch, nameof(batch)); @@ -177,7 +173,6 @@ public virtual Response QueryBatch(LogsBatchQuery batch, C try { var response = _queryClient.Batch(batch.Batch, cancellationToken); - response.Value.RowBinder = _rowBinder; return response; } catch (Exception e) @@ -192,8 +187,8 @@ public virtual Response QueryBatch(LogsBatchQuery batch, C /// /// The batch of queries to send. /// The to use. - /// The that allows retrieving query results. - public virtual async Task> QueryBatchAsync(LogsBatchQuery batch, CancellationToken cancellationToken = default) + /// The that allows retrieving query results. + public virtual async Task> QueryBatchAsync(LogsBatchQuery batch, CancellationToken cancellationToken = default) { Argument.AssertNotNull(batch, nameof(batch)); @@ -202,7 +197,6 @@ public virtual async Task> QueryBatchAsync(LogsBa try { var response = await _queryClient.BatchAsync(batch.Batch, cancellationToken).ConfigureAwait(false); - response.Value.RowBinder = _rowBinder; return response; } catch (Exception e) diff --git a/sdk/monitor/Azure.Monitor.Query/src/Models/LogQueryResponse.cs b/sdk/monitor/Azure.Monitor.Query/src/Models/LogQueryResponse.cs index 6161db443da3..842ee238a464 100644 --- a/sdk/monitor/Azure.Monitor.Query/src/Models/LogQueryResponse.cs +++ b/sdk/monitor/Azure.Monitor.Query/src/Models/LogQueryResponse.cs @@ -1,9 +1,24 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. +using Azure.Core; + namespace Azure.Monitor.Query.Models { internal partial class LogQueryResponse { + /// Contains the tables, columns & rows resulting from the query or the error details if the query failed. + [CodeGenMember("Body")] + private LogsBatchQueryResult _body; + + public LogsBatchQueryResult Body + { + get + { + _body.HasFailed = Status >= 400; + _body.Id = Id; + return _body; + } + } } } \ No newline at end of file diff --git a/sdk/monitor/Azure.Monitor.Query/src/Models/LogsBatchQuery.cs b/sdk/monitor/Azure.Monitor.Query/src/Models/LogsBatchQuery.cs index e5e77a9f9784..92617a4a7a22 100644 --- a/sdk/monitor/Azure.Monitor.Query/src/Models/LogsBatchQuery.cs +++ b/sdk/monitor/Azure.Monitor.Query/src/Models/LogsBatchQuery.cs @@ -30,7 +30,7 @@ public LogsBatchQuery() /// The query text to execute. /// The timespan over which to query data. /// The to configure the query. - /// The query identifier that has to be passed into to get the result. + /// The query identifier that has to be passed into to get the result. public virtual string AddQuery(string workspace, string query, DateTimeRange timeRange, LogsQueryOptions options = null) { var id = _counter.ToString("G", CultureInfo.InvariantCulture); diff --git a/sdk/monitor/Azure.Monitor.Query/src/Models/LogsBatchQueryResult.cs b/sdk/monitor/Azure.Monitor.Query/src/Models/LogsBatchQueryResult.cs index ea46f0b982d6..b4753d9eba60 100644 --- a/sdk/monitor/Azure.Monitor.Query/src/Models/LogsBatchQueryResult.cs +++ b/sdk/monitor/Azure.Monitor.Query/src/Models/LogsBatchQueryResult.cs @@ -1,54 +1,81 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -using System; using System.Collections.Generic; -using System.Linq; +using System.Text.Json; using Azure.Core; namespace Azure.Monitor.Query.Models { - [CodeGenModel("BatchResponse")] - public partial class LogsBatchQueryResult + [CodeGenModel("logQueryResult")] + public partial class LogsBatchQueryResult: LogsQueryResult { - private IReadOnlyList Responses { get; } - internal RowBinder RowBinder { get; set; } + /// + /// Gets or sets the value indicating whether the batch query was successful. + /// + public bool HasFailed { get; internal set; } /// - /// Gets the result for the query that was a part of the batch. + /// Gets or sets the query id. /// - /// The query identifier returned from the . - /// The with the query results. - /// When the query with was not part of the batch. - /// When the query failed. - public LogsQueryResult GetResult(string queryId) + public string Id { get; internal set; } + + // TODO, remove after https://github.com/Azure/azure-sdk-for-net/issues/21655 is fixed + internal static LogsBatchQueryResult DeserializeLogsBatchQueryResult(JsonElement element) { - LogQueryResponse result = Responses.SingleOrDefault(r => r.Id == queryId); + Optional error = default; + IReadOnlyList tables = default; + Optional statistics = default; + Optional render = default; - if (result == null) + // This is the workaround to remove the double-encoding + if (element.ValueKind == JsonValueKind.String) { - throw new ArgumentException($"Query with ID '{queryId}' wasn't part of the batch." + - $" Please use the return value of the {nameof(LogsBatchQuery)}.{nameof(LogsBatchQuery.AddQuery)} as the '{nameof(queryId)}' argument.", nameof(queryId)); + try + { + using var document = JsonDocument.Parse(element.GetString()); + element = document.RootElement.Clone(); + } + catch + { + // ignore + } } - if (result.Body.Error != null) + foreach (var property in element.EnumerateObject()) { - throw new RequestFailedException(result.Status ?? 0, result.Body.Error.Message, result.Body.Error.Code, null); + if (property.NameEquals("error")) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + property.ThrowNonNullablePropertyIsNull(); + continue; + } + error = property.Value.Clone(); + continue; + } + if (property.NameEquals("tables")) + { + List array = new List(); + foreach (var item in property.Value.EnumerateArray()) + { + array.Add(LogsQueryResultTable.DeserializeLogsQueryResultTable(item)); + } + tables = array; + continue; + } + if (property.NameEquals("statistics")) + { + statistics = property.Value.Clone(); + continue; + } + if (property.NameEquals("render")) + { + render = property.Value.Clone(); + continue; + } } - - return result.Body; - } - - /// - /// Gets the result for the query that was a part of the batch. - /// - /// The query identifier returned from the . - /// Query results mapped to a type . - /// When the query with was not part of the batch. - /// When the query failed. - public IReadOnlyList GetResult(string queryId) - { - return RowBinder.BindResults(GetResult(queryId).Tables); + return new LogsBatchQueryResult(tables, statistics, error, render); } } -} +} \ No newline at end of file diff --git a/sdk/monitor/Azure.Monitor.Query/src/Models/LogsBatchQueryResultInternal.cs b/sdk/monitor/Azure.Monitor.Query/src/Models/LogsBatchQueryResultInternal.cs deleted file mode 100644 index 3010b18511eb..000000000000 --- a/sdk/monitor/Azure.Monitor.Query/src/Models/LogsBatchQueryResultInternal.cs +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using System; -using System.Collections.Generic; -using System.Text.Json; -using Azure.Core; - -namespace Azure.Monitor.Query.Models -{ - [CodeGenModel("logQueryResult")] - internal partial class LogsBatchQueryResultInternal: LogsQueryResult - { - internal ErrorInfo Error { get; } - - // TODO, remove after https://github.com/Azure/azure-sdk-for-net/issues/21655 is fixed - internal static LogsBatchQueryResultInternal DeserializeLogsBatchQueryResultInternal(JsonElement element) - { - Optional error = default; - IReadOnlyList tables = default; - Optional statistics = default; - Optional render = default; - - // This is the workaround to remove the double-encoding - if (element.ValueKind == JsonValueKind.String) - { - try - { - using var document = JsonDocument.Parse(element.GetString()); - element = document.RootElement.Clone(); - } - catch - { - // ignore - } - } - - foreach (var property in element.EnumerateObject()) - { - if (property.NameEquals("error")) - { - if (property.Value.ValueKind == JsonValueKind.Null) - { - property.ThrowNonNullablePropertyIsNull(); - continue; - } - error = ErrorInfo.DeserializeErrorInfo(property.Value); - continue; - } - if (property.NameEquals("tables")) - { - List array = new List(); - foreach (var item in property.Value.EnumerateArray()) - { - array.Add(LogsQueryResultTable.DeserializeLogsQueryResultTable(item)); - } - tables = array; - continue; - } - if (property.NameEquals("statistics")) - { - statistics = property.Value.Clone(); - continue; - } - if (property.NameEquals("render")) - { - render = property.Value.Clone(); - continue; - } - } - return new LogsBatchQueryResultInternal(tables, statistics, render, error.Value); - } - } -} \ No newline at end of file diff --git a/sdk/monitor/Azure.Monitor.Query/src/Models/LogsBatchQueryResults.cs b/sdk/monitor/Azure.Monitor.Query/src/Models/LogsBatchQueryResults.cs new file mode 100644 index 000000000000..62100159ba33 --- /dev/null +++ b/sdk/monitor/Azure.Monitor.Query/src/Models/LogsBatchQueryResults.cs @@ -0,0 +1,60 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.Linq; +using Azure.Core; + +namespace Azure.Monitor.Query.Models +{ + [CodeGenModel("BatchResponse")] + public partial class LogsBatchQueryResults + { + private LogsBatchQueryResult[] _results; + + private IReadOnlyList Responses { get; } + + /// + /// Gets the list of results for the batch query. + /// + public IReadOnlyList Results => _results ??= Responses.Select(r => r.Body).ToArray(); + + /// + /// Gets the result for the query that was a part of the batch. + /// + /// The query identifier returned from the . + /// The with the query results. + /// When the query with was not part of the batch. + /// When the query failed. + public LogsQueryResult GetResult(string queryId) + { + LogQueryResponse result = Responses.SingleOrDefault(r => r.Id == queryId); + + if (result == null) + { + throw new ArgumentException($"Query with ID '{queryId}' wasn't part of the batch." + + $" Please use the return value of {nameof(LogsBatchQuery)}.{nameof(LogsBatchQuery.AddQuery)} as the '{nameof(queryId)}' argument.", nameof(queryId)); + } + + if (result.Body.HasFailed) + { + throw new RequestFailedException(result.Status ?? 0, result.Body.Error.Message, result.Body.Error.Code, null); + } + + return result.Body; + } + + /// + /// Gets the result for the query that was a part of the batch. + /// + /// The query identifier returned from the . + /// Query results mapped to a type . + /// When the query with was not part of the batch. + /// When the query failed. + public IReadOnlyList GetResult(string queryId) + { + return RowBinder.Shared.BindResults(GetResult(queryId).Tables); + } + } +} diff --git a/sdk/monitor/Azure.Monitor.Query/src/Models/LogsQueryResultTable.cs b/sdk/monitor/Azure.Monitor.Query/src/Models/LogsQueryResultTable.cs index 736f2f698289..ce228865fb9d 100644 --- a/sdk/monitor/Azure.Monitor.Query/src/Models/LogsQueryResultTable.cs +++ b/sdk/monitor/Azure.Monitor.Query/src/Models/LogsQueryResultTable.cs @@ -39,5 +39,14 @@ private IReadOnlyList CreateRows() return rows; } + + /// + /// Maps table rows to a model of type . + /// + /// Query results mapped to a type . + public IReadOnlyList Deserialize() + { + return RowBinder.Shared.BindResults(new[] { this }); + } } } \ No newline at end of file diff --git a/sdk/monitor/Azure.Monitor.Query/src/Models/LogsQueryResults.cs b/sdk/monitor/Azure.Monitor.Query/src/Models/LogsQueryResults.cs index 3d1c48eb056f..fcde12061b17 100644 --- a/sdk/monitor/Azure.Monitor.Query/src/Models/LogsQueryResults.cs +++ b/sdk/monitor/Azure.Monitor.Query/src/Models/LogsQueryResults.cs @@ -11,6 +11,9 @@ namespace Azure.Monitor.Query.Models [CodeGenModel("queryResults")] public partial class LogsQueryResult { + [CodeGenMember("error")] + private readonly JsonElement _error; + [CodeGenMember("Statistics")] private readonly JsonElement _statistics; @@ -32,5 +35,10 @@ public partial class LogsQueryResult /// Returns the query visualization if the is set to true. Null otherwise. /// public BinaryData Visualization => _visualization.ValueKind == JsonValueKind.Undefined ? null : new BinaryData(_visualization.ToString()); + + /// + /// Get's the error that occured during query processing. The value would be null if the query succeeds. + /// + public ResponseError Error => _error.ValueKind == JsonValueKind.Undefined ? null : JsonSerializer.Deserialize(_error.GetRawText()); } } \ No newline at end of file diff --git a/sdk/monitor/Azure.Monitor.Query/src/RowBinder.cs b/sdk/monitor/Azure.Monitor.Query/src/RowBinder.cs index 54c8820071e1..780dfffd3457 100644 --- a/sdk/monitor/Azure.Monitor.Query/src/RowBinder.cs +++ b/sdk/monitor/Azure.Monitor.Query/src/RowBinder.cs @@ -9,6 +9,7 @@ namespace Azure.Monitor.Query { internal class RowBinder: TypeBinder { + internal static RowBinder Shared = new(); internal IReadOnlyList BindResults(IReadOnlyList tables) { List results = new List(); diff --git a/sdk/monitor/Azure.Monitor.Query/src/autorest.md b/sdk/monitor/Azure.Monitor.Query/src/autorest.md index 023478c6c34c..bda1a14456eb 100644 --- a/sdk/monitor/Azure.Monitor.Query/src/autorest.md +++ b/sdk/monitor/Azure.Monitor.Query/src/autorest.md @@ -53,6 +53,7 @@ directive: - from: swagger-document where: $.definitions.queryResults transform: > + $.properties["error"] = { "type": "object" }; $.properties["statistics"] = { "type": "object" }; $.properties["render"] = { "type": "object" }; ``` diff --git a/sdk/monitor/Azure.Monitor.Query/tests/LogsClientSamples.cs b/sdk/monitor/Azure.Monitor.Query/tests/LogsClientSamples.cs index 07f11b788fac..68e1d48d2f81 100644 --- a/sdk/monitor/Azure.Monitor.Query/tests/LogsClientSamples.cs +++ b/sdk/monitor/Azure.Monitor.Query/tests/LogsClientSamples.cs @@ -151,7 +151,7 @@ public async Task BatchQuery() 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 response = await client.QueryBatchAsync(batch); + Response response = await client.QueryBatchAsync(batch); var count = response.Value.GetResult(countQueryId).Single(); var topEntries = response.Value.GetResult(topQueryId); diff --git a/sdk/monitor/Azure.Monitor.Query/tests/LogsQueryClientClientLiveTests.cs b/sdk/monitor/Azure.Monitor.Query/tests/LogsQueryClientClientLiveTests.cs index ffaba23ee8ce..69d34e1ea6c3 100644 --- a/sdk/monitor/Azure.Monitor.Query/tests/LogsQueryClientClientLiveTests.cs +++ b/sdk/monitor/Azure.Monitor.Query/tests/LogsQueryClientClientLiveTests.cs @@ -79,6 +79,20 @@ public async Task CanQueryIntoPrimitiveString() CollectionAssert.AreEqual(new[] {"a", "b", "c"}, results.Value); } + [RecordedTest] + public async Task CanQueryPartialSuccess() + { + var client = CreateClient(); + + var results = await client.QueryAsync(TestEnvironment.WorkspaceId, + $"set truncationmaxrecords=1; datatable (s: string) ['a', 'b']", + _logsTestData.DataTimeRange); + + Assert.NotNull(results.Value.Error.Code); + Assert.NotNull(results.Value.Error.Message); + CollectionAssert.IsNotEmpty(results.Value.Error.Details); + } + [RecordedTest] public async Task CanQueryAdditionalWorkspace() { @@ -171,7 +185,7 @@ public async Task CanQueryBatch() LogsBatchQuery batch = new LogsBatchQuery(); string id1 = batch.AddQuery(TestEnvironment.WorkspaceId, "Heartbeat", _logsTestData.DataTimeRange); string id2 = batch.AddQuery(TestEnvironment.WorkspaceId, "Heartbeat", _logsTestData.DataTimeRange); - Response response = await client.QueryBatchAsync(batch); + Response response = await client.QueryBatchAsync(batch); var result1 = response.Value.GetResult(id1); var result2 = response.Value.GetResult(id2); @@ -180,6 +194,31 @@ public async Task CanQueryBatch() CollectionAssert.IsNotEmpty(result2.Tables[0].Columns); } + [RecordedTest] + public async Task CanQueryBatchMixed() + { + var client = CreateClient(); + LogsBatchQuery batch = new LogsBatchQuery(); + string id1 = batch.AddQuery(TestEnvironment.WorkspaceId, "Heartbeat", _logsTestData.DataTimeRange); + string id2 = batch.AddQuery(TestEnvironment.WorkspaceId, "Heartbeats", _logsTestData.DataTimeRange); + string id3 = batch.AddQuery(TestEnvironment.WorkspaceId, "set truncationmaxrecords=1; datatable (s: string) ['a', 'b']", _logsTestData.DataTimeRange); + + Response response = await client.QueryBatchAsync(batch); + + Assert.False(response.Value.Results.Single(r => r.Id == id1).HasFailed); + + var failedResult = response.Value.Results.Single(r => r.Id == id2); + Assert.True(failedResult.HasFailed); + Assert.NotNull(failedResult.Error.Code); + Assert.NotNull(failedResult.Error.Message); + + var partialResult = response.Value.Results.Single(r => r.Id == id3); + Assert.False(partialResult.HasFailed); + CollectionAssert.IsNotEmpty(partialResult.PrimaryTable.Rows); + Assert.NotNull(partialResult.Error.Code); + Assert.NotNull(partialResult.Error.Message); + } + [RecordedTest] public async Task CanQueryAllSupportedTypes() { @@ -414,7 +453,7 @@ public async Task CanQueryBatchWithTimespan() LogsBatchQuery batch = new LogsBatchQuery(); string id1 = batch.AddQuery(TestEnvironment.WorkspaceId, $"{_logsTestData.TableAName} | project {LogsTestData.TimeGeneratedColumnName}", _logsTestData.DataTimeRange); string id2 = batch.AddQuery(TestEnvironment.WorkspaceId, $"{_logsTestData.TableAName} | project {LogsTestData.TimeGeneratedColumnName}", timespan); - Response response = await client.QueryBatchAsync(batch); + Response response = await client.QueryBatchAsync(batch); var result1 = response.Value.GetResult(id1); var result2 = response.Value.GetResult(id2); @@ -464,7 +503,7 @@ public async Task ThrowsExceptionWhenBatchQueryNotFound() var exception = Assert.Throws(() => batchResult.Value.GetResult("12345")); Assert.AreEqual("queryId", exception.ParamName); - StringAssert.StartsWith("Query with ID '12345' wasn't part of the batch. Please use the return value of the LogsBatchQuery.AddQuery as the 'queryId' argument.", exception.Message); + StringAssert.StartsWith("Query with ID '12345' wasn't part of the batch. Please use the return value of LogsBatchQuery.AddQuery as the 'queryId' argument.", exception.Message); } [RecordedTest] diff --git a/sdk/monitor/Azure.Monitor.Query/tests/LogsQueryClientClientTests.cs b/sdk/monitor/Azure.Monitor.Query/tests/LogsQueryClientClientTests.cs index 0406485016f4..61e512459d3b 100644 --- a/sdk/monitor/Azure.Monitor.Query/tests/LogsQueryClientClientTests.cs +++ b/sdk/monitor/Azure.Monitor.Query/tests/LogsQueryClientClientTests.cs @@ -75,8 +75,8 @@ public async Task QueryBatchHandledInvalidResponse() LogsBatchQuery batch = new LogsBatchQuery(); batch.AddQuery("wid", "query", DateTimeRange.All); - LogsBatchQueryResult batchResult = await client.QueryBatchAsync(batch); - Assert.NotNull(batchResult.GetResult("0")); + LogsBatchQueryResults batchResults = await client.QueryBatchAsync(batch); + Assert.NotNull(batchResults.GetResult("0")); } [Test] diff --git a/sdk/monitor/Azure.Monitor.Query/tests/SessionRecords/LogsQueryClientClientLiveTests/CanQueryBatchMixed.json b/sdk/monitor/Azure.Monitor.Query/tests/SessionRecords/LogsQueryClientClientLiveTests/CanQueryBatchMixed.json new file mode 100644 index 000000000000..18c3f5c566ec --- /dev/null +++ b/sdk/monitor/Azure.Monitor.Query/tests/SessionRecords/LogsQueryClientClientLiveTests/CanQueryBatchMixed.json @@ -0,0 +1,279 @@ +{ + "Entries": [ + { + "RequestUri": "https://api.loganalytics.io/v1/$batch", + "RequestMethod": "POST", + "RequestHeaders": { + "Accept": "application/json", + "Authorization": "Sanitized", + "Content-Length": "593", + "Content-Type": "application/json", + "traceparent": "00-5429e4ae895b9942afeabed3e4a7f406-8a0822ba28a4af42-00", + "User-Agent": [ + "azsdk-net-Monitor.Query/1.0.0-alpha.20210623.1", + "(.NET 5.0.7; Microsoft Windows 10.0.19043)" + ], + "x-ms-client-request-id": "0da57f3f46d695fa74d87d262fc7b5d1", + "x-ms-return-client-request-id": "true" + }, + "RequestBody": { + "requests": [ + { + "id": "0", + "body": { + "query": "Heartbeat", + "timespan": "2021-06-14T00:00:00.0000000Z/P7D" + }, + "path": "/query", + "method": "POST", + "workspace": "0a1f6b9a-caa1-4e5a-ac9a-54aa9b2fb131" + }, + { + "id": "1", + "body": { + "query": "Heartbeats", + "timespan": "2021-06-14T00:00:00.0000000Z/P7D" + }, + "path": "/query", + "method": "POST", + "workspace": "0a1f6b9a-caa1-4e5a-ac9a-54aa9b2fb131" + }, + { + "id": "2", + "body": { + "query": "set truncationmaxrecords=1; datatable (s: string) [\u0027a\u0027, \u0027b\u0027]", + "timespan": "2021-06-14T00:00:00.0000000Z/P7D" + }, + "path": "/query", + "method": "POST", + "workspace": "0a1f6b9a-caa1-4e5a-ac9a-54aa9b2fb131" + } + ] + }, + "StatusCode": 200, + "ResponseHeaders": { + "Access-Control-Allow-Origin": "*", + "Access-Control-Expose-Headers": "Retry-After,Age,WWW-Authenticate,x-resource-identities,x-ms-status-location", + "Connection": "keep-alive", + "Content-Type": "application/json; charset=utf-8", + "Date": "Wed, 23 Jun 2021 19:57:28 GMT", + "Strict-Transport-Security": "max-age=15724800; includeSubDomains", + "Transfer-Encoding": "chunked", + "Vary": [ + "Accept-Encoding", + "Accept-Encoding" + ], + "Via": "1.1 draft-oms-5cd4f5c6d9-vfztg", + "X-Content-Type-Options": "nosniff" + }, + "ResponseBody": { + "responses": [ + { + "id": "1", + "status": 400, + "body": { + "error": { + "message": "The request had some invalid properties", + "code": "BadArgumentError", + "correlationId": "6a1b5b30-5c3a-40ad-9a7c-c9c15f28ebc9", + "innererror": { + "code": "SemanticError", + "message": "A semantic error occurred.", + "innererror": { + "code": "SEM0100", + "message": "\u0027\u0027 operator: Failed to resolve table or column or scalar expression named \u0027Heartbeats\u0027" + } + } + } + } + }, + { + "id": "2", + "status": 200, + "body": { + "tables": [ + { + "name": "PrimaryResult", + "columns": [ + { + "name": "s", + "type": "string" + } + ], + "rows": [ + [ + "a" + ] + ] + } + ], + "error": { + "code": "PartialError", + "message": "There were some errors when processing your query.", + "details": [ + { + "code": "EngineError", + "message": "Something went wrong processing your query on the server.", + "innererror": { + "code": "-2133196797", + "message": "Query result set has exceeded the internal record count limit 1 (E_QUERY_RESULT_SET_TOO_LARGE; see https://aka.ms/kustoquerylimits)", + "severity": 2, + "severityName": "Error" + } + } + ] + } + } + }, + { + "id": "0", + "status": 200, + "body": { + "tables": [ + { + "name": "PrimaryResult", + "columns": [ + { + "name": "TenantId", + "type": "string" + }, + { + "name": "SourceSystem", + "type": "string" + }, + { + "name": "TimeGenerated", + "type": "datetime" + }, + { + "name": "MG", + "type": "string" + }, + { + "name": "ManagementGroupName", + "type": "string" + }, + { + "name": "SourceComputerId", + "type": "string" + }, + { + "name": "ComputerIP", + "type": "string" + }, + { + "name": "Computer", + "type": "string" + }, + { + "name": "Category", + "type": "string" + }, + { + "name": "OSType", + "type": "string" + }, + { + "name": "OSName", + "type": "string" + }, + { + "name": "OSMajorVersion", + "type": "string" + }, + { + "name": "OSMinorVersion", + "type": "string" + }, + { + "name": "Version", + "type": "string" + }, + { + "name": "SCAgentChannel", + "type": "string" + }, + { + "name": "IsGatewayInstalled", + "type": "bool" + }, + { + "name": "RemoteIPLongitude", + "type": "real" + }, + { + "name": "RemoteIPLatitude", + "type": "real" + }, + { + "name": "RemoteIPCountry", + "type": "string" + }, + { + "name": "SubscriptionId", + "type": "string" + }, + { + "name": "ResourceGroup", + "type": "string" + }, + { + "name": "ResourceProvider", + "type": "string" + }, + { + "name": "Resource", + "type": "string" + }, + { + "name": "ResourceId", + "type": "string" + }, + { + "name": "ResourceType", + "type": "string" + }, + { + "name": "ComputerEnvironment", + "type": "string" + }, + { + "name": "Solutions", + "type": "string" + }, + { + "name": "VMUUID", + "type": "string" + }, + { + "name": "ComputerPrivateIPs", + "type": "dynamic" + }, + { + "name": "Type", + "type": "string" + }, + { + "name": "_ResourceId", + "type": "string" + } + ], + "rows": [] + } + ] + } + } + ] + } + } + ], + "Variables": { + "DateTimeOffsetNow": "2021-06-23T12:57:22.1739755-07:00", + "LOGS_ENDPOINT": "https://api.loganalytics.io", + "RandomSeed": "983599192", + "SECONDARY_WORKSPACE_ID": "0cf963f0-c6a5-4ced-8cd8-93a8d6e3e9d3", + "SECONDARY_WORKSPACE_KEY": "Kg==", + "WORKSPACE_ID": "0a1f6b9a-caa1-4e5a-ac9a-54aa9b2fb131", + "WORKSPACE_KEY": "Kg==" + } +} \ No newline at end of file diff --git a/sdk/monitor/Azure.Monitor.Query/tests/SessionRecords/LogsQueryClientClientLiveTests/CanQueryBatchMixedAsync.json b/sdk/monitor/Azure.Monitor.Query/tests/SessionRecords/LogsQueryClientClientLiveTests/CanQueryBatchMixedAsync.json new file mode 100644 index 000000000000..d19472ad0765 --- /dev/null +++ b/sdk/monitor/Azure.Monitor.Query/tests/SessionRecords/LogsQueryClientClientLiveTests/CanQueryBatchMixedAsync.json @@ -0,0 +1,284 @@ +{ + "Entries": [ + { + "RequestUri": "https://api.loganalytics.io/v1/$batch", + "RequestMethod": "POST", + "RequestHeaders": { + "Accept": "application/json", + "Authorization": "Sanitized", + "Content-Length": "593", + "Content-Type": "application/json", + "traceparent": "00-45db26ab6d211649b8caec4f43fc2cda-bc67c34fd235b944-00", + "User-Agent": [ + "azsdk-net-Monitor.Query/1.0.0-alpha.20210623.1", + "(.NET 5.0.7; Microsoft Windows 10.0.19043)" + ], + "x-ms-client-request-id": "cb0d2c799413dd6fa01e8f26b5c23fae", + "x-ms-return-client-request-id": "true" + }, + "RequestBody": { + "requests": [ + { + "id": "0", + "body": { + "query": "Heartbeat", + "timespan": "2021-06-14T00:00:00.0000000Z/P7D" + }, + "path": "/query", + "method": "POST", + "workspace": "0a1f6b9a-caa1-4e5a-ac9a-54aa9b2fb131" + }, + { + "id": "1", + "body": { + "query": "Heartbeats", + "timespan": "2021-06-14T00:00:00.0000000Z/P7D" + }, + "path": "/query", + "method": "POST", + "workspace": "0a1f6b9a-caa1-4e5a-ac9a-54aa9b2fb131" + }, + { + "id": "2", + "body": { + "query": "set truncationmaxrecords=1; datatable (s: string) [\u0027a\u0027, \u0027b\u0027]", + "timespan": "2021-06-14T00:00:00.0000000Z/P7D" + }, + "path": "/query", + "method": "POST", + "workspace": "0a1f6b9a-caa1-4e5a-ac9a-54aa9b2fb131" + } + ] + }, + "StatusCode": 200, + "ResponseHeaders": { + "Access-Control-Allow-Origin": "*", + "Access-Control-Expose-Headers": "Retry-After,Age,WWW-Authenticate,x-resource-identities,x-ms-status-location", + "Connection": "keep-alive", + "Content-Type": "application/json; charset=utf-8", + "Date": "Wed, 23 Jun 2021 19:57:29 GMT", + "Strict-Transport-Security": "max-age=15724800; includeSubDomains", + "Transfer-Encoding": "chunked", + "Vary": [ + "Accept-Encoding", + "Accept-Encoding" + ], + "Via": "1.1 draft-oms-5cd4f5c6d9-tkpql", + "X-Content-Type-Options": "nosniff" + }, + "ResponseBody": { + "responses": [ + { + "id": "0", + "status": 200, + "headers": { + "Age": "0", + "request-context": "appId=cid-v1:70941e4f-7e8f-40b7-b730-183893db0297" + }, + "body": { + "tables": [ + { + "name": "PrimaryResult", + "columns": [ + { + "name": "TenantId", + "type": "string" + }, + { + "name": "SourceSystem", + "type": "string" + }, + { + "name": "TimeGenerated", + "type": "datetime" + }, + { + "name": "MG", + "type": "string" + }, + { + "name": "ManagementGroupName", + "type": "string" + }, + { + "name": "SourceComputerId", + "type": "string" + }, + { + "name": "ComputerIP", + "type": "string" + }, + { + "name": "Computer", + "type": "string" + }, + { + "name": "Category", + "type": "string" + }, + { + "name": "OSType", + "type": "string" + }, + { + "name": "OSName", + "type": "string" + }, + { + "name": "OSMajorVersion", + "type": "string" + }, + { + "name": "OSMinorVersion", + "type": "string" + }, + { + "name": "Version", + "type": "string" + }, + { + "name": "SCAgentChannel", + "type": "string" + }, + { + "name": "IsGatewayInstalled", + "type": "bool" + }, + { + "name": "RemoteIPLongitude", + "type": "real" + }, + { + "name": "RemoteIPLatitude", + "type": "real" + }, + { + "name": "RemoteIPCountry", + "type": "string" + }, + { + "name": "SubscriptionId", + "type": "string" + }, + { + "name": "ResourceGroup", + "type": "string" + }, + { + "name": "ResourceProvider", + "type": "string" + }, + { + "name": "Resource", + "type": "string" + }, + { + "name": "ResourceId", + "type": "string" + }, + { + "name": "ResourceType", + "type": "string" + }, + { + "name": "ComputerEnvironment", + "type": "string" + }, + { + "name": "Solutions", + "type": "string" + }, + { + "name": "VMUUID", + "type": "string" + }, + { + "name": "ComputerPrivateIPs", + "type": "dynamic" + }, + { + "name": "Type", + "type": "string" + }, + { + "name": "_ResourceId", + "type": "string" + } + ], + "rows": [] + } + ] + } + }, + { + "id": "2", + "status": 200, + "headers": { + "Age": "0", + "request-context": "appId=cid-v1:70941e4f-7e8f-40b7-b730-183893db0297" + }, + "body": { + "tables": [ + { + "name": "PrimaryResult", + "columns": [ + { + "name": "s", + "type": "string" + } + ], + "rows": [ + [ + "a" + ] + ] + } + ], + "error": { + "code": "PartialError", + "message": "There were some errors when processing your query.", + "details": [ + { + "code": "EngineError", + "message": "Something went wrong processing your query on the server.", + "innererror": { + "code": "-2133196797", + "message": "Query result set has exceeded the internal record count limit 1 (E_QUERY_RESULT_SET_TOO_LARGE; see https://aka.ms/kustoquerylimits)", + "severity": 2, + "severityName": "Error" + } + } + ] + } + } + }, + { + "id": "1", + "status": 400, + "body": { + "error": { + "message": "The request had some invalid properties", + "code": "BadArgumentError", + "correlationId": "3dc0846a-8cc5-4425-b8a3-ec3fffa69bd0", + "innererror": { + "code": "SemanticError", + "message": "A semantic error occurred.", + "innererror": { + "code": "SEM0100", + "message": "\u0027\u0027 operator: Failed to resolve table or column or scalar expression named \u0027Heartbeats\u0027" + } + } + } + } + } + ] + } + } + ], + "Variables": { + "DateTimeOffsetNow": "2021-06-23T12:57:29.4228670-07:00", + "LOGS_ENDPOINT": "https://api.loganalytics.io", + "RandomSeed": "976811501", + "WORKSPACE_ID": "0a1f6b9a-caa1-4e5a-ac9a-54aa9b2fb131" + } +} \ No newline at end of file diff --git a/sdk/monitor/Azure.Monitor.Query/tests/SessionRecords/LogsQueryClientClientLiveTests/CanQueryPartialSuccess.json b/sdk/monitor/Azure.Monitor.Query/tests/SessionRecords/LogsQueryClientClientLiveTests/CanQueryPartialSuccess.json new file mode 100644 index 000000000000..a7d0516e95ae --- /dev/null +++ b/sdk/monitor/Azure.Monitor.Query/tests/SessionRecords/LogsQueryClientClientLiveTests/CanQueryPartialSuccess.json @@ -0,0 +1,84 @@ +{ + "Entries": [ + { + "RequestUri": "https://api.loganalytics.io/v1/workspaces/0a1f6b9a-caa1-4e5a-ac9a-54aa9b2fb131/query", + "RequestMethod": "POST", + "RequestHeaders": { + "Accept": "application/json", + "Authorization": "Sanitized", + "Content-Length": "138", + "Content-Type": "application/json", + "traceparent": "00-02a4ed5c80a71646bf563babae4cb284-b70dbfcdb7130a45-00", + "User-Agent": [ + "azsdk-net-Monitor.Query/1.0.0-alpha.20210623.1", + "(.NET 5.0.7; Microsoft Windows 10.0.19043)" + ], + "x-ms-client-request-id": "241bc8f28c0cb675e40ef70741a7dae7", + "x-ms-return-client-request-id": "true" + }, + "RequestBody": { + "query": "set truncationmaxrecords=1; datatable (s: string) [\u0027a\u0027, \u0027b\u0027]", + "timespan": "2021-06-14T00:00:00.0000000Z/P7D" + }, + "StatusCode": 200, + "ResponseHeaders": { + "Access-Control-Allow-Origin": "*", + "Access-Control-Expose-Headers": "Retry-After,Age,WWW-Authenticate,x-resource-identities,x-ms-status-location", + "Connection": "keep-alive", + "Content-Length": "509", + "Content-Type": "application/json; charset=utf-8", + "Date": "Wed, 23 Jun 2021 20:06:18 GMT", + "Strict-Transport-Security": "max-age=15724800; includeSubDomains", + "Vary": [ + "Accept-Encoding", + "Accept-Encoding" + ], + "Via": "1.1 draft-oms-5cd4f5c6d9-xhxt9", + "X-Content-Type-Options": "nosniff" + }, + "ResponseBody": { + "tables": [ + { + "name": "PrimaryResult", + "columns": [ + { + "name": "s", + "type": "string" + } + ], + "rows": [ + [ + "a" + ] + ] + } + ], + "error": { + "code": "PartialError", + "message": "There were some errors when processing your query.", + "details": [ + { + "code": "EngineError", + "message": "Something went wrong processing your query on the server.", + "innererror": { + "code": "-2133196797", + "message": "Query result set has exceeded the internal record count limit 1 (E_QUERY_RESULT_SET_TOO_LARGE; see https://aka.ms/kustoquerylimits)", + "severity": 2, + "severityName": "Error" + } + } + ] + } + } + } + ], + "Variables": { + "DateTimeOffsetNow": "2021-06-23T13:06:16.3383231-07:00", + "LOGS_ENDPOINT": "https://api.loganalytics.io", + "RandomSeed": "326254235", + "SECONDARY_WORKSPACE_ID": "0cf963f0-c6a5-4ced-8cd8-93a8d6e3e9d3", + "SECONDARY_WORKSPACE_KEY": "Kg==", + "WORKSPACE_ID": "0a1f6b9a-caa1-4e5a-ac9a-54aa9b2fb131", + "WORKSPACE_KEY": "Kg==" + } +} \ No newline at end of file diff --git a/sdk/monitor/Azure.Monitor.Query/tests/SessionRecords/LogsQueryClientClientLiveTests/CanQueryPartialSuccessAsync.json b/sdk/monitor/Azure.Monitor.Query/tests/SessionRecords/LogsQueryClientClientLiveTests/CanQueryPartialSuccessAsync.json new file mode 100644 index 000000000000..e26e9956ba46 --- /dev/null +++ b/sdk/monitor/Azure.Monitor.Query/tests/SessionRecords/LogsQueryClientClientLiveTests/CanQueryPartialSuccessAsync.json @@ -0,0 +1,82 @@ +{ + "Entries": [ + { + "RequestUri": "https://api.loganalytics.io/v1/workspaces/0a1f6b9a-caa1-4e5a-ac9a-54aa9b2fb131/query", + "RequestMethod": "POST", + "RequestHeaders": { + "Accept": "application/json", + "Authorization": "Sanitized", + "Content-Length": "138", + "Content-Type": "application/json", + "traceparent": "00-d69c54d9a290d249b743d18249bec5c3-09a2e0be2d2bfe4e-00", + "User-Agent": [ + "azsdk-net-Monitor.Query/1.0.0-alpha.20210623.1", + "(.NET 5.0.7; Microsoft Windows 10.0.19043)" + ], + "x-ms-client-request-id": "e5d20512ab57c2cd0ce82c1fcf1ea0d3", + "x-ms-return-client-request-id": "true" + }, + "RequestBody": { + "query": "set truncationmaxrecords=1; datatable (s: string) [\u0027a\u0027, \u0027b\u0027]", + "timespan": "2021-06-14T00:00:00.0000000Z/P7D" + }, + "StatusCode": 200, + "ResponseHeaders": { + "Access-Control-Allow-Origin": "*", + "Access-Control-Expose-Headers": "Retry-After,Age,WWW-Authenticate,x-resource-identities,x-ms-status-location", + "Age": "0", + "Connection": "keep-alive", + "Content-Length": "509", + "Content-Type": "application/json; charset=utf-8", + "Date": "Wed, 23 Jun 2021 20:06:18 GMT", + "Strict-Transport-Security": "max-age=15724800; includeSubDomains", + "Vary": [ + "Accept-Encoding", + "Accept-Encoding" + ], + "Via": "1.1 draft-oms-5cd4f5c6d9-8wpsh", + "X-Content-Type-Options": "nosniff" + }, + "ResponseBody": { + "tables": [ + { + "name": "PrimaryResult", + "columns": [ + { + "name": "s", + "type": "string" + } + ], + "rows": [ + [ + "a" + ] + ] + } + ], + "error": { + "code": "PartialError", + "message": "There were some errors when processing your query.", + "details": [ + { + "code": "EngineError", + "message": "Something went wrong processing your query on the server.", + "innererror": { + "code": "-2133196797", + "message": "Query result set has exceeded the internal record count limit 1 (E_QUERY_RESULT_SET_TOO_LARGE; see https://aka.ms/kustoquerylimits)", + "severity": 2, + "severityName": "Error" + } + } + ] + } + } + } + ], + "Variables": { + "DateTimeOffsetNow": "2021-06-23T13:06:18.6768873-07:00", + "LOGS_ENDPOINT": "https://api.loganalytics.io", + "RandomSeed": "2003911842", + "WORKSPACE_ID": "0a1f6b9a-caa1-4e5a-ac9a-54aa9b2fb131" + } +} \ No newline at end of file