Skip to content

Commit

Permalink
Add LogTable and LogTableRow to MonitorQueryModelFactory (#25592)
Browse files Browse the repository at this point in the history
  • Loading branch information
nisha-bhatia authored Dec 18, 2021
1 parent 5dcc7ec commit 72510aa
Show file tree
Hide file tree
Showing 9 changed files with 165 additions and 29 deletions.
9 changes: 2 additions & 7 deletions sdk/monitor/Azure.Monitor.Query/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,9 @@
# Release History

## 1.1.0-beta.1 (Unreleased)

## 1.1.0 (2021-12-07)
### Features Added
- Added `LogsTable` and `LogsTableRow` to `MonitorQueryModelFactory`

### Breaking Changes

### Bugs Fixed

### Other Changes

## 1.0.1 (2021-11-09)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -343,7 +343,9 @@ internal MetricValue() { }
public static partial class MonitorQueryModelFactory
{
public static Azure.Monitor.Query.Models.LogsQueryResult LogsQueryResult(System.Collections.Generic.IReadOnlyList<Azure.Monitor.Query.Models.LogsTable> allTables, System.BinaryData statistics, System.BinaryData visualization, System.BinaryData error) { throw null; }
public static Azure.Monitor.Query.Models.LogsTable LogsTable(string name, System.Collections.Generic.IEnumerable<Azure.Monitor.Query.Models.LogsTableColumn> columns, System.Collections.Generic.IEnumerable<Azure.Monitor.Query.Models.LogsTableRow> rows) { throw null; }
public static Azure.Monitor.Query.Models.LogsTableColumn LogsTableColumn(string name = null, Azure.Monitor.Query.Models.LogsColumnType type = default(Azure.Monitor.Query.Models.LogsColumnType)) { throw null; }
public static Azure.Monitor.Query.Models.LogsTableRow LogsTableRow(System.Collections.Generic.IEnumerable<Azure.Monitor.Query.Models.LogsTableColumn> columns, System.Collections.Generic.IEnumerable<object> values) { throw null; }
public static Azure.Monitor.Query.Models.MetricAvailability MetricAvailability(System.TimeSpan? granularity = default(System.TimeSpan?), System.TimeSpan? retention = default(System.TimeSpan?)) { throw null; }
public static Azure.Monitor.Query.Models.MetricsQueryResult MetricsQueryResult(int? cost, string timespan, System.TimeSpan? granularity, string @namespace, string resourceRegion, System.Collections.Generic.IReadOnlyList<Azure.Monitor.Query.Models.MetricResult> metrics) { throw null; }
public static Azure.Monitor.Query.Models.MetricValue MetricValue(System.DateTimeOffset timeStamp = default(System.DateTimeOffset), double? average = default(double?), double? minimum = default(double?), double? maximum = default(double?), double? total = default(double?), double? count = default(double?)) { throw null; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<PropertyGroup>
<Description>A library for querying Azure Monitor's Logs and Metrics data sources.</Description>
<AssemblyTitle>Azure Monitor Query client library</AssemblyTitle>
<Version>1.1.0-beta.1</Version>
<Version>1.1.0</Version>
<!--The ApiCompatVersion is managed automatically and should not generally be modified manually.-->
<ApiCompatVersion>1.0.1</ApiCompatVersion>
<PackageTags>Azure Monitor Query</PackageTags>
Expand Down
30 changes: 30 additions & 0 deletions sdk/monitor/Azure.Monitor.Query/src/Models/LogsTableColumn.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using System.Collections.Generic;
using System.Linq;
using Azure.Core;

namespace Azure.Monitor.Query.Models
{
[CodeGenModel("Column")]
public partial class LogsTableColumn
{
/// <inheritdoc />
public override string ToString()
{
return $"{Name} ({Type})";
}

internal static Dictionary<string, int> GetColumnMapFromColumns(IEnumerable<LogsTableColumn> columns)
{
Dictionary<string, int> columnMap = new();
var columnsList = columns.ToArray();
for (var index = 0; index < columnsList.Length; index++)
{
columnMap[columnsList[index].Name] = index;
}
return columnMap;
}
}
}
2 changes: 1 addition & 1 deletion sdk/monitor/Azure.Monitor.Query/src/Models/LogsTableRow.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public class LogsTableRow: IReadOnlyList<object>
{
private readonly Dictionary<string, int> _columnMap;
private readonly IReadOnlyList<LogsTableColumn> _columns;
private readonly JsonElement _row;
internal JsonElement _row;

internal LogsTableRow(Dictionary<string, int> columnMap, IReadOnlyList<LogsTableColumn> columns, JsonElement row)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,11 @@

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.Json;
using Azure.Monitor.Query.Models;

namespace Azure.Monitor.Query.Models
{
Expand All @@ -12,7 +16,7 @@ namespace Azure.Monitor.Query.Models
/// </summary>
public static partial class MonitorQueryModelFactory
{
/// <summary> Initializes a new instance of MetricsQueryResult. </summary>
/// <summary> Enables the user to create an instance of a <see cref="MetricsQueryResult"/>. </summary>
/// <param name="cost"> The integer value representing the relative cost of the query. </param>
/// <param name="timespan"> The timespan for which the data was retrieved. Its value consists of two datetimes concatenated, separated by &apos;/&apos;. This may be adjusted in the future and returned back from what was originally requested. </param>
/// <param name="granularity"> The interval (window size) for which the metric data was returned in. This may be adjusted in the future and returned back from what was originally requested. This is not present if a metadata request was made. </param>
Expand All @@ -24,7 +28,7 @@ public static MetricsQueryResult MetricsQueryResult(int? cost, string timespan,
return new MetricsQueryResult(cost, timespan, granularity, @namespace, resourceRegion, metrics);
}

/// <summary> Initializes a new instance of LogsQueryResult. </summary>
/// <summary> Enables the user to create an instance of a <see cref="LogsQueryResult"/>. </summary>
/// <param name="allTables"> The list of tables, columns and rows. </param>
/// <param name="statistics"> Any object. </param>
/// <param name="visualization"> Any object. </param>
Expand All @@ -36,5 +40,45 @@ public static LogsQueryResult LogsQueryResult(IReadOnlyList<LogsTable> allTables
JsonElement errorJson = error.ToObjectFromJson<JsonElement>();
return new LogsQueryResult(allTables, statisticsJson, visualizationJson, errorJson);
}

/// <summary> Enables the user to create an instance of a <see cref="LogsTableRow"/>. </summary>
/// <param name="columns"> The list of columns. </param>
/// <param name="values"> An object array representing the rows of the table. </param>
/// <returns> A new <see cref="Models.LogsTableRow"/> instance for mocking. </returns>
public static LogsTableRow LogsTableRow(IEnumerable<LogsTableColumn> columns, IEnumerable<object> values)
{
var columnsList = columns.ToArray();
var columnMap = Models.LogsTableColumn.GetColumnMapFromColumns(columns);
JsonElement row = JsonElementFromObject(values);
return new LogsTableRow(columnMap, columnsList, row);
}

/// <summary> Enables the user to create an instance of a <see cref="LogsTable"/>. </summary>
/// <param name="name"> The name of the table. </param>
/// <param name="columns"> The list of columns. </param>
/// <param name="rows"> The list of rows. </param>
/// <exception cref="ArgumentNullException"> <paramref name="name"/> or <paramref name="rows"/> is <c>null</c>. </exception>
public static LogsTable LogsTable(string name, IEnumerable<LogsTableColumn> columns, IEnumerable<LogsTableRow> rows)
{
using MemoryStream stream = new MemoryStream();
using Utf8JsonWriter writer = new Utf8JsonWriter(stream);
writer.WriteStartArray();
foreach (var row in rows)
{
row._row.WriteTo(writer);
}
writer.WriteEndArray();
writer.Flush();
var doc = JsonDocument.Parse(stream.ToArray());
var logsTableRow = doc.RootElement.Clone();
return new LogsTable(name, columns, logsTableRow);
}

private static JsonElement JsonElementFromObject<TValue>(TValue value, JsonSerializerOptions options = default)
{
var bytes = JsonSerializer.SerializeToUtf8Bytes(value, options);
var doc = JsonDocument.Parse(bytes);
return doc.RootElement.Clone();
}
}
}
17 changes: 0 additions & 17 deletions sdk/monitor/Azure.Monitor.Query/src/Models/QueryResultColumn.cs

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -754,7 +754,7 @@ private record TestModelForTypesNullable
public BinaryData Dynamic { get; set; }
}

[Test]
[RecordedTest]
public async Task ValidateNanAndInfResultsDoubleAsync()
{
var client = CreateClient();
Expand Down
82 changes: 82 additions & 0 deletions sdk/monitor/Azure.Monitor.Query/tests/LogsQueryClientTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Azure.Core;
Expand Down Expand Up @@ -192,5 +193,86 @@ public void MonitorQueryModelFactory_LogsQueryResult_ConvertBinaryDataToJsonElem
Assert.AreEqual("PartialError", result.Error.Code);
Assert.AreEqual("There were some errors when processing your query.", result.Error.Message);
}

[Test]
public void ValidateMonitorModelFactoryTableCreation()
{
LogsTableColumn logsTableColumn0 = MonitorQueryModelFactory.LogsTableColumn("column0", LogsColumnType.Datetime);
LogsTableColumn logsTableColumn1 = MonitorQueryModelFactory.LogsTableColumn("column1", LogsColumnType.Guid);
LogsTableColumn logsTableColumn2 = MonitorQueryModelFactory.LogsTableColumn("column2", LogsColumnType.Int);
LogsTableColumn logsTableColumn3 = MonitorQueryModelFactory.LogsTableColumn("column3", LogsColumnType.Long);
LogsTableColumn logsTableColumn4 = MonitorQueryModelFactory.LogsTableColumn("column4", LogsColumnType.Real);
LogsTableColumn logsTableColumn5 = MonitorQueryModelFactory.LogsTableColumn("column5", LogsColumnType.String);
LogsTableColumn logsTableColumn6 = MonitorQueryModelFactory.LogsTableColumn("column6", LogsColumnType.Timespan);
LogsTableColumn logsTableColumn7 = MonitorQueryModelFactory.LogsTableColumn("column7", LogsColumnType.Decimal);
LogsTableColumn logsTableColumn8 = MonitorQueryModelFactory.LogsTableColumn("column8", LogsColumnType.Bool);
LogsTableColumn logsTableColumn9 = MonitorQueryModelFactory.LogsTableColumn("column9", LogsColumnType.Dynamic);
LogsTableColumn[] logsTableColumns = new LogsTableColumn[] { logsTableColumn0, logsTableColumn1, logsTableColumn2, logsTableColumn3, logsTableColumn4, logsTableColumn5, logsTableColumn6, logsTableColumn7, logsTableColumn8, logsTableColumn9};
Object[] rowValues = new Object[] { "2015-12-31T23:59:59.9Z", "74be27de-1e4e-49d9-b579-fe0b331d3642", 12345, 1234567890123, 12345.6789, "string value", "00:00:10", "0.10101", false, "{\u0022a\u0022:123,\u0022b\u0022:\u0022hello\u0022,\u0022c\u0022:[1,2,3],\u0022d\u0022:{}}" };

LogsTableRow logsTableRow = MonitorQueryModelFactory.LogsTableRow(logsTableColumns, rowValues);
LogsTableRow[] rowArray = new LogsTableRow[] { logsTableRow };
LogsTable logsTable = MonitorQueryModelFactory.LogsTable("tester", logsTableColumns.AsEnumerable(), rowArray.AsEnumerable());

Assert.AreEqual("tester", logsTable.Name);
Assert.AreEqual(1, logsTable.Rows.Count);
Assert.AreEqual(10, logsTable.Columns.Count);

Assert.AreEqual("column0", logsTable.Columns[0].Name);
Assert.AreEqual("datetime", logsTable.Columns[0].Type.ToString());
Assert.AreEqual("column1", logsTable.Columns[1].Name);
Assert.AreEqual("guid", logsTable.Columns[1].Type.ToString());
Assert.AreEqual("column2", logsTable.Columns[2].Name);
Assert.AreEqual("int", logsTable.Columns[2].Type.ToString());
Assert.AreEqual("column3", logsTable.Columns[3].Name);
Assert.AreEqual("long", logsTable.Columns[3].Type.ToString());
Assert.AreEqual("column4", logsTable.Columns[4].Name);
Assert.AreEqual("real", logsTable.Columns[4].Type.ToString());
Assert.AreEqual("column5", logsTable.Columns[5].Name);
Assert.AreEqual("string", logsTable.Columns[5].Type.ToString());
Assert.AreEqual("column6", logsTable.Columns[6].Name);
Assert.AreEqual("timespan", logsTable.Columns[6].Type.ToString());
Assert.AreEqual("column7", logsTable.Columns[7].Name);
Assert.AreEqual("decimal", logsTable.Columns[7].Type.ToString());
Assert.AreEqual("column8", logsTable.Columns[8].Name);
Assert.AreEqual("bool", logsTable.Columns[8].Type.ToString());
Assert.AreEqual("column9", logsTable.Columns[9].Name);
Assert.AreEqual("dynamic", logsTable.Columns[9].Type.ToString());

var expectedDate = DateTimeOffset.Parse("2015-12-31 23:59:59.9+00:00");

Assert.AreEqual(expectedDate, logsTable.Rows[0].GetDateTimeOffset(0));
Assert.AreEqual(expectedDate, logsTable.Rows[0].GetObject("column0"));
Assert.AreEqual(false, logsTable.Rows[0].GetBoolean("column8"));
Assert.AreEqual(false, logsTable.Rows[0].GetBoolean(8));
Assert.AreEqual(false, logsTable.Rows[0].GetObject("column8"));
Assert.AreEqual(Guid.Parse("74be27de-1e4e-49d9-b579-fe0b331d3642"), logsTable.Rows[0].GetGuid("column1"));
Assert.AreEqual(Guid.Parse("74be27de-1e4e-49d9-b579-fe0b331d3642"), logsTable.Rows[0].GetGuid(1));
Assert.AreEqual(Guid.Parse("74be27de-1e4e-49d9-b579-fe0b331d3642"), logsTable.Rows[0].GetObject("column1"));
Assert.AreEqual(12345, logsTable.Rows[0].GetInt32("column2"));
Assert.AreEqual(12345, logsTable.Rows[0].GetInt32(2));
Assert.AreEqual(12345, logsTable.Rows[0].GetObject("column2"));
Assert.AreEqual(1234567890123, logsTable.Rows[0].GetInt64("column3"));
Assert.AreEqual(1234567890123, logsTable.Rows[0].GetInt64(3));
Assert.AreEqual(1234567890123, logsTable.Rows[0].GetObject("column3"));
Assert.AreEqual(12345.6789d, logsTable.Rows[0].GetDouble("column4"));
Assert.AreEqual(12345.6789d, logsTable.Rows[0].GetDouble(4));
Assert.AreEqual(12345.6789d, logsTable.Rows[0].GetObject("column4"));
Assert.AreEqual("string value", logsTable.Rows[0].GetString("column5"));
Assert.AreEqual("string value", logsTable.Rows[0].GetString(5));
Assert.AreEqual("string value", logsTable.Rows[0].GetObject("column5"));
Assert.AreEqual(TimeSpan.FromSeconds(10), logsTable.Rows[0].GetTimeSpan("column6"));
Assert.AreEqual(TimeSpan.FromSeconds(10), logsTable.Rows[0].GetTimeSpan(6));
Assert.AreEqual(TimeSpan.FromSeconds(10), logsTable.Rows[0].GetObject("column6"));
Assert.AreEqual(0.10101m, logsTable.Rows[0].GetDecimal("column7"));
Assert.AreEqual(0.10101m, logsTable.Rows[0].GetDecimal(7));
Assert.AreEqual(0.10101m, logsTable.Rows[0].GetObject("column7"));
Assert.IsFalse(logsTable.Rows[0].GetBoolean("column8"));
Assert.IsFalse(logsTable.Rows[0].GetBoolean(8));
Assert.AreEqual(false, logsTable.Rows[0].GetObject("column8"));
Assert.AreEqual("{\"a\":123,\"b\":\"hello\",\"c\":[1,2,3],\"d\":{}}", logsTable.Rows[0].GetDynamic(9).ToString());
Assert.AreEqual("{\"a\":123,\"b\":\"hello\",\"c\":[1,2,3],\"d\":{}}", logsTable.Rows[0].GetDynamic("column9").ToString());
Assert.AreEqual("{\"a\":123,\"b\":\"hello\",\"c\":[1,2,3],\"d\":{}}", logsTable.Rows[0].GetObject("column9").ToString());
}
}
}

0 comments on commit 72510aa

Please sign in to comment.