Skip to content

Commit 17180e2

Browse files
pakrymchristothes
andauthored
Add ThrowOnPartialError to Azure.Monitor.Query (Azure#23988)
Co-authored-by: Christopher Scott <chriscott@hotmail.com>
1 parent 9ffdb2d commit 17180e2

23 files changed

+568
-78
lines changed

sdk/monitor/Azure.Monitor.Query/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@ string topQueryId = batch.AddQuery(
212212
"AzureActivity | summarize Count = count() by ResourceGroup | top 10 by Count",
213213
new DateTimeRange(TimeSpan.FromDays(1)));
214214

215-
Response<LogsBatchQueryResults> response = await client.QueryBatchAsync(batch);
215+
Response<LogsBatchQueryResultCollection> response = await client.QueryBatchAsync(batch);
216216

217217
var count = response.Value.GetResult<int>(countQueryId).Single();
218218
var topEntries = response.Value.GetResult<MyLogEntryModel>(topQueryId);

sdk/monitor/Azure.Monitor.Query/api/Azure.Monitor.Query.netstandard2.0.cs

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ public LogsQueryClient(System.Uri endpoint, Azure.Core.TokenCredential credentia
1717
public virtual Azure.Response<Azure.Monitor.Query.Models.LogsQueryResult> Query(string workspaceId, string query, Azure.Core.DateTimeRange timeRange, Azure.Monitor.Query.LogsQueryOptions options = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; }
1818
public virtual System.Threading.Tasks.Task<Azure.Response<Azure.Monitor.Query.Models.LogsQueryResult>> QueryAsync(string workspaceId, string query, Azure.Core.DateTimeRange timeRange, Azure.Monitor.Query.LogsQueryOptions options = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; }
1919
public virtual System.Threading.Tasks.Task<Azure.Response<System.Collections.Generic.IReadOnlyList<T>>> QueryAsync<T>(string workspaceId, string query, Azure.Core.DateTimeRange timeRange, Azure.Monitor.Query.LogsQueryOptions options = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; }
20-
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; }
21-
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; }
20+
public virtual Azure.Response<Azure.Monitor.Query.Models.LogsBatchQueryResultCollection> QueryBatch(Azure.Monitor.Query.LogsBatchQuery batch, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; }
21+
public virtual System.Threading.Tasks.Task<Azure.Response<Azure.Monitor.Query.Models.LogsBatchQueryResultCollection>> QueryBatchAsync(Azure.Monitor.Query.LogsBatchQuery batch, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; }
2222
public virtual Azure.Response<System.Collections.Generic.IReadOnlyList<T>> Query<T>(string workspaceId, string query, Azure.Core.DateTimeRange timeRange, Azure.Monitor.Query.LogsQueryOptions options = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; }
2323
}
2424
public partial class LogsQueryClientOptions : Azure.Core.ClientOptions
@@ -37,6 +37,7 @@ public LogsQueryOptions() { }
3737
public bool IncludeStatistics { get { throw null; } set { } }
3838
public bool IncludeVisualization { get { throw null; } set { } }
3939
public System.TimeSpan? ServerTimeout { get { throw null; } set { } }
40+
public bool ThrowOnPartialErrors { get { throw null; } set { } }
4041
}
4142
public partial class MetricsQueryClient
4243
{
@@ -76,16 +77,21 @@ namespace Azure.Monitor.Query.Models
7677
public partial class LogsBatchQueryResult : Azure.Monitor.Query.Models.LogsQueryResult
7778
{
7879
internal LogsBatchQueryResult() { }
79-
public bool HasFailed { get { throw null; } }
8080
public string Id { get { throw null; } }
81+
public Azure.Monitor.Query.Models.LogsBatchQueryResultStatus Status { get { throw null; } }
8182
}
82-
public partial class LogsBatchQueryResults
83+
public partial class LogsBatchQueryResultCollection : System.Collections.ObjectModel.ReadOnlyCollection<Azure.Monitor.Query.Models.LogsBatchQueryResult>
8384
{
84-
internal LogsBatchQueryResults() { }
85-
public System.Collections.Generic.IReadOnlyList<Azure.Monitor.Query.Models.LogsBatchQueryResult> Results { get { throw null; } }
85+
internal LogsBatchQueryResultCollection() : base (default(System.Collections.Generic.IList<Azure.Monitor.Query.Models.LogsBatchQueryResult>)) { }
8686
public Azure.Monitor.Query.Models.LogsBatchQueryResult GetResult(string queryId) { throw null; }
8787
public System.Collections.Generic.IReadOnlyList<T> GetResult<T>(string queryId) { throw null; }
8888
}
89+
public enum LogsBatchQueryResultStatus
90+
{
91+
Success = 0,
92+
PartialFailure = 1,
93+
Failure = 2,
94+
}
8995
[System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
9096
public readonly partial struct LogsColumnType : System.IEquatable<Azure.Monitor.Query.Models.LogsColumnType>
9197
{

sdk/monitor/Azure.Monitor.Query/src/Generated/Models/BatchQueryResponse.cs

Lines changed: 3 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

sdk/monitor/Azure.Monitor.Query/src/Generated/Models/LogsBatchQueryResults.Serialization.cs renamed to sdk/monitor/Azure.Monitor.Query/src/Generated/Models/BatchResponse.Serialization.cs

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

sdk/monitor/Azure.Monitor.Query/src/Generated/Models/LogsBatchQueryResults.cs renamed to sdk/monitor/Azure.Monitor.Query/src/Generated/Models/BatchResponse.cs

Lines changed: 8 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

sdk/monitor/Azure.Monitor.Query/src/Generated/QueryRestClient.cs

Lines changed: 6 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

sdk/monitor/Azure.Monitor.Query/src/LogsQueryClient.cs

Lines changed: 35 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using System;
55
using System.Collections.Generic;
66
using System.Globalization;
7+
using System.Linq;
78
using System.Text;
89
using System.Text.Json;
910
using System.Threading;
@@ -219,7 +220,7 @@ public virtual async Task<Response<LogsQueryResult>> QueryAsync(string workspace
219220
/// &quot;AzureActivity | summarize Count = count() by ResourceGroup | top 10 by Count&quot;,
220221
/// new DateTimeRange(TimeSpan.FromDays(1)));
221222
///
222-
/// Response&lt;LogsBatchQueryResults&gt; response = await client.QueryBatchAsync(batch);
223+
/// Response&lt;LogsBatchQueryResultCollection&gt; response = await client.QueryBatchAsync(batch);
223224
///
224225
/// var count = response.Value.GetResult&lt;int&gt;(countQueryId).Single();
225226
/// var topEntries = response.Value.GetResult&lt;MyLogEntryModel&gt;(topQueryId);
@@ -233,8 +234,8 @@ public virtual async Task<Response<LogsQueryResult>> QueryAsync(string workspace
233234
/// </summary>
234235
/// <param name="batch">The batch of queries to send.</param>
235236
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to use.</param>
236-
/// <returns>The <see cref="LogsBatchQueryResults"/> containing the query identifier that has to be passed into <see cref="LogsBatchQueryResults.GetResult"/> to get the result.</returns>
237-
public virtual Response<LogsBatchQueryResults> QueryBatch(LogsBatchQuery batch, CancellationToken cancellationToken = default)
237+
/// <returns>The <see cref="LogsBatchQueryResultCollection"/> containing the query identifier that has to be passed into <see cref="LogsBatchQueryResultCollection.GetResult"/> to get the result.</returns>
238+
public virtual Response<LogsBatchQueryResultCollection> QueryBatch(LogsBatchQuery batch, CancellationToken cancellationToken = default)
238239
{
239240
Argument.AssertNotNull(batch, nameof(batch));
240241

@@ -243,7 +244,7 @@ public virtual Response<LogsBatchQueryResults> QueryBatch(LogsBatchQuery batch,
243244
try
244245
{
245246
var response = _queryClient.Batch(new BatchRequest(batch.Requests), cancellationToken);
246-
return response;
247+
return ConvertBatchResponse(batch, response);
247248
}
248249
catch (Exception e)
249250
{
@@ -272,7 +273,7 @@ public virtual Response<LogsBatchQueryResults> QueryBatch(LogsBatchQuery batch,
272273
/// &quot;AzureActivity | summarize Count = count() by ResourceGroup | top 10 by Count&quot;,
273274
/// new DateTimeRange(TimeSpan.FromDays(1)));
274275
///
275-
/// Response&lt;LogsBatchQueryResults&gt; response = await client.QueryBatchAsync(batch);
276+
/// Response&lt;LogsBatchQueryResultCollection&gt; response = await client.QueryBatchAsync(batch);
276277
///
277278
/// var count = response.Value.GetResult&lt;int&gt;(countQueryId).Single();
278279
/// var topEntries = response.Value.GetResult&lt;MyLogEntryModel&gt;(topQueryId);
@@ -286,8 +287,8 @@ public virtual Response<LogsBatchQueryResults> QueryBatch(LogsBatchQuery batch,
286287
/// </summary>
287288
/// <param name="batch">The batch of Kusto queries to send.</param>
288289
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to use.</param>
289-
/// <returns>The <see cref="LogsBatchQueryResults"/> that allows retrieving query results.</returns>
290-
public virtual async Task<Response<LogsBatchQueryResults>> QueryBatchAsync(LogsBatchQuery batch, CancellationToken cancellationToken = default)
290+
/// <returns>The <see cref="LogsBatchQueryResultCollection"/> that allows retrieving query results.</returns>
291+
public virtual async Task<Response<LogsBatchQueryResultCollection>> QueryBatchAsync(LogsBatchQuery batch, CancellationToken cancellationToken = default)
291292
{
292293
Argument.AssertNotNull(batch, nameof(batch));
293294

@@ -296,7 +297,7 @@ public virtual async Task<Response<LogsBatchQueryResults>> QueryBatchAsync(LogsB
296297
try
297298
{
298299
var response = await _queryClient.BatchAsync(new BatchRequest(batch.Requests), cancellationToken).ConfigureAwait(false);
299-
return response;
300+
return ConvertBatchResponse(batch, response);
300301
}
301302
catch (Exception e)
302303
{
@@ -305,6 +306,27 @@ public virtual async Task<Response<LogsBatchQueryResults>> QueryBatchAsync(LogsB
305306
}
306307
}
307308

309+
private static Response<LogsBatchQueryResultCollection> ConvertBatchResponse(LogsBatchQuery batch, Response<BatchResponse> response)
310+
{
311+
List<LogsBatchQueryResult> batchResponses = new List<LogsBatchQueryResult>();
312+
foreach (var innerResponse in response.Value.Responses)
313+
{
314+
var body = innerResponse.Body;
315+
body.Status = innerResponse.Status switch
316+
{
317+
>= 400 => LogsBatchQueryResultStatus.Failure,
318+
_ when body.Error != null => LogsBatchQueryResultStatus.PartialFailure,
319+
_ => LogsBatchQueryResultStatus.Success
320+
};
321+
body.Id = innerResponse.Id;
322+
batchResponses.Add(body);
323+
}
324+
325+
return Response.FromValue(
326+
new LogsBatchQueryResultCollection(batchResponses, batch),
327+
response.GetRawResponse());
328+
}
329+
308330
/// <summary>
309331
/// Create a Kusto query from an interpolated string. The interpolated values will be quoted and escaped as necessary.
310332
/// </summary>
@@ -499,6 +521,11 @@ await JsonDocument.ParseAsync(message.Response.ContentStream, default, cancellat
499521
JsonDocument.Parse(message.Response.ContentStream, default);
500522

501523
LogsQueryResult value = LogsQueryResult.DeserializeLogsQueryResult(document.RootElement);
524+
var responseError = value.Error;
525+
if (responseError != null && options?.ThrowOnPartialErrors != false)
526+
{
527+
throw value.CreateExceptionForErrorResponse(message.Response.Status);
528+
}
502529
return Response.FromValue(value, message.Response);
503530
}
504531
default:

sdk/monitor/Azure.Monitor.Query/src/LogsQueryOptions.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,5 +36,10 @@ public class LogsQueryOptions
3636
/// Gets a list of additional workspaces names to include in the query.
3737
/// </summary>
3838
public IList<string> AdditionalWorkspaces { get; } = new ChangeTrackingList<string>();
39+
40+
/// <summary>
41+
/// Gets or sets the value indicating whether to throw when a partial error is returned with the logs response.
42+
/// </summary>
43+
public bool ThrowOnPartialErrors { get; set; } = true;
3944
}
4045
}

sdk/monitor/Azure.Monitor.Query/src/Models/BatchQueryRequest.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,6 @@ namespace Azure.Monitor.Query.Models
55
{
66
internal partial class BatchQueryRequest
77
{
8+
internal LogsQueryOptions Options { get; set; }
89
}
910
}
Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,9 @@
11
// Copyright (c) Microsoft Corporation. All rights reserved.
22
// Licensed under the MIT License.
33

4-
using Azure.Core;
5-
64
namespace Azure.Monitor.Query.Models
75
{
86
internal partial class BatchQueryResponse
97
{
10-
/// <summary> Contains the tables, columns &amp; rows resulting from the query or the error details if the query failed. </summary>
11-
[CodeGenMember("Body")]
12-
private LogsBatchQueryResult _body;
13-
14-
public LogsBatchQueryResult Body
15-
{
16-
get
17-
{
18-
_body.HasFailed = Status >= 400;
19-
_body.Id = Id;
20-
return _body;
21-
}
22-
}
238
}
249
}

0 commit comments

Comments
 (0)