Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Monitor query updates #17459

Merged
merged 58 commits into from
Sep 9, 2021
Merged
Show file tree
Hide file tree
Changes from 51 commits
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
b2c7bad
rename column to columnDescriptors and enums for error status
KarishmaGhiya Sep 3, 2021
97492a4
sample for second metric
KarishmaGhiya Sep 3, 2021
a00fe8c
update metrics query client
KarishmaGhiya Sep 3, 2021
57216a4
result status
KarishmaGhiya Sep 3, 2021
772a1ca
update samples
KarishmaGhiya Sep 3, 2021
a743827
getMetricByNames, flag for throwOnAnyFailure
KarishmaGhiya Sep 4, 2021
4f74a91
refdocs and samples
KarishmaGhiya Sep 4, 2021
206a91c
regenerate swagger with innerError rename
KarishmaGhiya Sep 4, 2021
6b5ab13
regenerate swagger with innerError rename
KarishmaGhiya Sep 4, 2021
26a3440
update api review
KarishmaGhiya Sep 4, 2021
a427687
fix lint errors
KarishmaGhiya Sep 7, 2021
ff7cdfd
update metricsQuery sample
KarishmaGhiya Sep 7, 2021
c75643f
update KQL for multiple workspaces
KarishmaGhiya Sep 7, 2021
7b9020d
update readme
KarishmaGhiya Sep 7, 2021
227bbb8
update readme
KarishmaGhiya Sep 7, 2021
60df0c5
update readme
KarishmaGhiya Sep 7, 2021
dbc6cd4
update readme
KarishmaGhiya Sep 7, 2021
0941991
Update sdk/monitor/monitor-query/README.md
KarishmaGhiya Sep 7, 2021
31987fd
Update sdk/monitor/monitor-query/README.md
KarishmaGhiya Sep 7, 2021
a929e08
Update sdk/monitor/monitor-query/README.md
KarishmaGhiya Sep 7, 2021
3a54e4d
Update sdk/monitor/monitor-query/README.md
KarishmaGhiya Sep 7, 2021
cbd309b
Update sdk/monitor/monitor-query/src/models/publicLogsModels.ts
KarishmaGhiya Sep 7, 2021
edf39ca
Update sdk/monitor/monitor-query/README.md
KarishmaGhiya Sep 7, 2021
b924d3d
Update sdk/monitor/monitor-query/README.md
KarishmaGhiya Sep 7, 2021
f64a7fc
Update sdk/monitor/monitor-query/README.md
KarishmaGhiya Sep 7, 2021
8636437
cleanup console.log statements
KarishmaGhiya Sep 7, 2021
5a21ffb
Merge branch 'monitor-query-updates' of https://github.com/KarishmaGh…
KarishmaGhiya Sep 7, 2021
5e6d08b
update optional param to be required
KarishmaGhiya Sep 7, 2021
7038eb4
rename variables
KarishmaGhiya Sep 7, 2021
fa238a8
Update sdk/monitor/monitor-query/src/models/publicLogsModels.ts
KarishmaGhiya Sep 7, 2021
41f82df
update api review file and samples
KarishmaGhiya Sep 8, 2021
2ff1efb
update sample
KarishmaGhiya Sep 8, 2021
5ac02ad
Merge branch 'monitor-query-updates' of https://github.com/KarishmaGh…
KarishmaGhiya Sep 8, 2021
a17c343
update readme
KarishmaGhiya Sep 8, 2021
6748d77
TimeInterval return type for timespan in MetricsQueryResult
KarishmaGhiya Sep 8, 2021
3bda4b4
fix tests
KarishmaGhiya Sep 8, 2021
5c930f2
update conversion
KarishmaGhiya Sep 8, 2021
fed387c
Update sdk/monitor/monitor-query/src/internal/modelConverters.ts
KarishmaGhiya Sep 8, 2021
a0cec0e
check if this works on ci
KarishmaGhiya Sep 8, 2021
9e6f633
check if this works on ci
KarishmaGhiya Sep 8, 2021
75c62d6
update conversion
KarishmaGhiya Sep 8, 2021
da9a5c1
update readme
KarishmaGhiya Sep 8, 2021
8a9ee1b
added changelog
KarishmaGhiya Sep 9, 2021
265e265
rename
KarishmaGhiya Sep 9, 2021
170dd4a
readme
KarishmaGhiya Sep 9, 2021
f89cd47
Update sdk/monitor/monitor-query/src/internal/modelConverters.ts
KarishmaGhiya Sep 9, 2021
d2ea6ce
update Error types for batch and updated samples
KarishmaGhiya Sep 9, 2021
51b3106
Merge branch 'monitor-query-updates' of https://github.com/KarishmaGh…
KarishmaGhiya Sep 9, 2021
6cdc3c0
update models
KarishmaGhiya Sep 9, 2021
aa05c8a
update models
KarishmaGhiya Sep 9, 2021
6adbbb8
update changelog
KarishmaGhiya Sep 9, 2021
d762918
update api review
KarishmaGhiya Sep 9, 2021
6554230
update reamde sample
KarishmaGhiya Sep 9, 2021
41ba681
Update sdk/monitor/monitor-query/CHANGELOG.md
KarishmaGhiya Sep 9, 2021
6479744
Update sdk/monitor/monitor-query/README.md
KarishmaGhiya Sep 9, 2021
74baa6f
Update sdk/monitor/monitor-query/README.md
KarishmaGhiya Sep 9, 2021
a5d0d52
update logic for single query status compute
KarishmaGhiya Sep 9, 2021
e78334e
Merge branch 'monitor-query-updates' of https://github.com/KarishmaGh…
KarishmaGhiya Sep 9, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 19 additions & 4 deletions sdk/monitor/monitor-query/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,29 @@
# Release History

## 1.0.0-beta.5 (Unreleased)
## 1.0.0-beta.5 (2021-09-09)

### Features Added

### Breaking Changes
- Added convenience method `getMetricByName` in `MetricsQueryResult` to allow users to fetch results of a particular metric
- Added a flag `throwOnAnyFailure` to be set by user for methods `queryLogs` and `queryLogsBatch` to enable error throwing
- Defining `AggregateBatchError` class for throwing batch errors
- Added status with potential values `("Partial" | "Success" | "Failed")` for responses of `query` and `queryBatch` APIs to indicate whether the status of results of each query.

### Bugs Fixed
### Breaking Changes

### Other Changes
- Updated methods `getMetricDefinitions` and `getMetricNamespaces` to return paginated list of items and renamed to `listMetricDefinitions` and `listMetricNames` respectively
- Renamed methods `queryLogs` and `queryLogsBatch` in `LogsQueryClient` to `query` and `queryBatch`
- Updated the constant names inside `Durations` to drop the `last` prefix
- Updated method `queryBatch` to take argument of `QueryBatch` model instead of `QueryLogsBatch` model
- Renamed `QueryLogsOptions` to `LogsQueryOptions`
- Renamed `QueryLogsBatchResult` to `LogsQueryBatchResult`
- Renamed `QueryMetricsResult` to `MetricsQueryResult`
- Renamed `QueryLogsResult` to `LogsQueryResult`, `QueryLogsBatchOptions` to `LogsQueryBatchOptions`
- Updated type for `timespan` property from `string` to `TimeInterval` type in `query` and `queryBatch`methods of`LogsQueryClient` and in `MetricsQueryResult` interface
KarishmaGhiya marked this conversation as resolved.
Show resolved Hide resolved
- Renamed `MetricColumn` to `LogsColumn` and `column` to `columnDescriptors` in `LogsTable` model
- Renamed `displayDescription` property to `description` in `Metric` and `MetricNames`
- Flattened the `metricNamespaceName` property for `MetricNamespace`
- Renamed `innererror` to `innerError` in `ErrorInfo`

## 1.0.0-beta.4 (2021-08-10)

Expand Down
144 changes: 92 additions & 52 deletions sdk/monitor/monitor-query/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -127,16 +127,6 @@ Each set of metric values is a time series with the following characteristics:

The [`MetricsQueryClient`][msdocs_metrics_client] allows you to query metrics.

#### Resource URI of a resource

The resource URI must be that of the resource for which metrics are being queried. It's normally of the format `/subscriptions/<id>/resourceGroups/<rg-name>/providers/<source>/topics/<resource-name>`.

To find the resource URI:

1. Navigate to your resource's page in the Azure portal.
2. From the **Overview** blade, select the **JSON View** link.
3. In the resulting JSON, copy the value of the `id` property.

## Examples

### Querying logs
Expand All @@ -147,7 +137,6 @@ You can use the `Durations` constants provided for some commonly used ISO8601 du
```ts
const { LogsQueryClient, Durations } = require("@azure/monitor-query");
const { DefaultAzureCredential } = require("@azure/identity");
g;

const azureLogAnalyticsWorkspaceId = "<the Workspace Id for your Azure Log Analytics resource>";
const logsQueryClient = new LogsQueryClient(new DefaultAzureCredential());
Expand All @@ -167,7 +156,7 @@ async function run() {
console.log(`Results for query '${kustoQuery}'`);

for (const table of tablesFromResult) {
const columnHeaderString = table.columns
const columnHeaderString = table.columnDescriptors
.map((column) => `${column.name}(${column.type}) `)
.join("| ");
console.log("| " + columnHeaderString);
Expand All @@ -190,12 +179,13 @@ Here is a hierarchy of the response:
```
LogsQueryResult
|---statistics
|---visalization
|---visualization
|---error
|---status ("Partial" | "Success" | "Failed")
|---tables (list of `LogsTable` objects)
|---name
|---rows
|---columns (list of `LogsColumn` objects)
|---columnDescriptors (list of `LogsColumn` objects)
|---name
|---type
```
Expand All @@ -205,7 +195,7 @@ So, to handle a response with tables,
```ts
const tablesFromResult = result.tables;
for (const table of tablesFromResult) {
const columnHeaderString = table.columns
const columnHeaderString = table.columnDescriptors
.map((column) => `${column.name}(${column.type}) `)
.join("| ");
console.log("| " + columnHeaderString);
Expand Down Expand Up @@ -250,10 +240,12 @@ export async function main() {

const tokenCredential = new DefaultAzureCredential();
const logsQueryClient = new LogsQueryClient(tokenCredential);
const queriesBatch: QueryBatch[] = [

const kqlQuery = "AppEvents | project TimeGenerated, Name, AppRoleInstance | limit 1";
KarishmaGhiya marked this conversation as resolved.
Show resolved Hide resolved
const queriesBatch = [
{
workspaceId: monitorWorkspaceId,
query: "AppEvents | project TimeGenerated, Name, AppRoleInstance | limit 1",
query: kqlQuery,
timespan: { duration: "P1D" }
},
{
Expand All @@ -276,16 +268,17 @@ export async function main() {
];

const result = await logsQueryClient.queryBatch(queriesBatch);

if (result.results == null) {
throw new Error("No response for query");
}

let i = 0;
for (const response of result.results) {
console.log(`Results for query with id: ${response.id}`);
console.log(`Results for query with query: ${queriesBatch[i]}`);

if (response.error) {
console.log(`Query had errors:`, response.error);
console.log(` Query had errors:`, response.error);
} else {
if (response.tables == null) {
console.log(`No results for query`);
Expand All @@ -295,7 +288,7 @@ export async function main() {
);

for (const table of response.tables) {
const columnHeaderString = table.columns
const columnHeaderString = table.columnDescriptors
.map((column) => `${column.name}(${column.type}) `)
.join("| ");
console.log(columnHeaderString);
Expand All @@ -322,33 +315,37 @@ Here is a hierarchy of the response:
```
LogsQueryBatchResult
|---results (list of following objects)
|---id
|---status
|---statistics
|---visalization
|---visualization
|---error
|---status ("Partial" | "Success" | "Failed")
|---tables (list of `LogsTable` objects)
|---name
|---rows
|---columns (list of `LogsColumn` objects)
|---columnDescriptors (list of `LogsColumn` objects)
|---name
|---type
```

To handle a batch response,
KarishmaGhiya marked this conversation as resolved.
Show resolved Hide resolved

```ts
let i = 0;
for (const response of result.results) {
console.log(`Results for query with id: ${response.id}`);
console.log(`Results for query with query: ${queriesBatch[i]}`);

if (response.error) {
console.log(`Query had errors:`, response.error);
console.log(` Query had errors:`, response.error);
} else {
if (response.tables == null) {
console.log(`No results for query`);
} else {
console.log(
`Printing results from query '${queriesBatch[i].query}' for '${queriesBatch[i].timespan}'`
);

for (const table of response.tables) {
const columnHeaderString = table.columns
const columnHeaderString = table.columnDescriptors
.map((column) => `${column.name}(${column.type}) `)
.join("| ");
console.log(columnHeaderString);
Expand All @@ -360,14 +357,27 @@ for (const response of result.results) {
}
}
}
// next query
i++;
}
```

A full sample can be found [here](https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/monitor/monitor-query/samples/v1/typescript/src/logsQueryBatch.ts)

**Throttling Guidance Log Queries**

Please refer the [service guidance for throttling](https://dev.loganalytics.io/documentation/Using-the-API/Limits) for API calls.
KarishmaGhiya marked this conversation as resolved.
Show resolved Hide resolved

### Query metrics

The following example gets metrics for an [Azure Metrics Advisor](https://docs.microsoft.com/azure/applied-ai-services/metrics-advisor/overview) subscription. The resource URI is that of a Metrics Advisor resource.
The following example gets metrics for an [Azure Metrics Advisor](https://docs.microsoft.com/azure/applied-ai-services/metrics-advisor/overview) subscription.
The resource URI must be that of the resource for which metrics are being queried. It's normally of the format `/subscriptions/<id>/resourceGroups/<rg-name>/providers/<source>/topics/<resource-name>`.

To find the resource URI:

1. Navigate to your resource's page in the Azure portal.
2. From the **Overview** blade, select the **JSON View** link.
3. In the resulting JSON, copy the value of the `id` property.

```ts
import { DefaultAzureCredential } from "@azure/identity";
Expand All @@ -386,31 +396,39 @@ export async function main() {
throw new Error("METRICS_RESOURCE_ID must be set in the environment for this sample");
}

const result = await metricsQueryClient.getMetricDefinitions(metricsResourceId);

for (const definition of result.definitions) {
console.log(`Definition = ${definition.name}`);
const iterator = metricsQueryClient.listMetricDefinitions(metricsResourceId);
let result = await iterator.next();
const firstMetric: MetricDefinition = result.value;
let secondMetricName: string = "TotalCalls";
for await (const result of iterator) {
console.log(` metricDefinitions - ${result.id}, ${result.name}`);
if (result.name) {
secondMetricName = result.name; // will assign the last value in the loop
}
}

const firstMetric = result.definitions[0];

console.log(`Picking an example metric to query: ${firstMetric.name}`);

const metricsResponse = await metricsQueryClient.queryMetrics(
metricsResourceId,
{ duration: Durations.FiveMinutes },
{
metricNames: [firstMetric.name!],
interval: "PT1M"
}
);
if (firstMetric.name && secondMetricName) {
console.log(`Picking an example metric to query: ${firstMetric.name} and ${secondMetricName}`);
const metricsResponse = await metricsQueryClient.query(
metricsResourceId,
[firstMetric.name, secondMetricName],
{
granularity: "PT1M",
timespan: { duration: Durations.FiveMinutes }
}
);

console.log(
`Query cost: ${metricsResponse.cost}, interval: ${metricsResponse.interval}, time span: ${metricsResponse.timespan}`
);
console.log(
`Query cost: ${metricsResponse.cost}, interval: ${metricsResponse.granularity}, time span: ${metricsResponse.timespan}`
);

const metrics: Metric[] = metricsResponse.metrics;
console.log(`Metrics:`, JSON.stringify(metrics, undefined, 2));
const metrics: Metric[] = metricsResponse.metrics;
console.log(`Metrics:`, JSON.stringify(metrics, undefined, 2));
const metric = metricsResponse.getMetricByName(firstMetric.name);
console.log(`Selected Metric: ${firstMetric.name}`, JSON.stringify(metric, undefined, 2));
} else {
console.error(`Metric names are not defined - ${firstMetric.name} and ${secondMetricName}`);
}
}

main().catch((err) => {
Expand All @@ -419,15 +437,17 @@ main().catch((err) => {
});
```

In the preceding sample, the ordering of results for the metrics in the `metricResponse` will be in the order in which the user specifies the metric names in the `metricNames` array argument for the query method. If user specifies `[firstMetric.name,secondMetricName]`, the result for `firstMetric.name` will appear before the result for `secondMetricName` in the `metricResponse`.

### Handle metrics response

The metrics query API returns a `QueryMetricsResult` object. The `QueryMetricsResult` object contains properties such as a list of `Metric`-typed objects, `interval`, `namespace`, and `timespan`. The `Metric` objects list can be accessed using the `metrics` property. Each `Metric` object in this list contains a list of `TimeSeriesElement` objects. Each `TimeSeriesElement` contains `data` and `metadataValues` properties. In visual form, the object hierarchy of the response resembles the following structure:

```
QueryMetricsResult
|---cost
|---timespan
|---interval
|---timespan (of type `TimeInterval`)
|---granularity
|---namespace
|---resourceRegion
|---metrics (list of `Metric` objects)
Expand All @@ -440,6 +460,13 @@ QueryMetricsResult
|---timeseries (list of `TimeSeriesElement` objects)
|---metadataValues
|---data (list of data points represented by `MetricValue` objects)
|---timeStamp
|---average
|---minimum
|---maximum
|---total
|---count
|---getMetricByName(metricName): Metric | undefined (convenience method)
```

#### Example of handling response
Expand Down Expand Up @@ -515,7 +542,7 @@ const queryLogsOptions: LogsQueryOptions = {
additionalWorkspaces: ["<workspace2>", "<workspace3>"]
};

const kustoQuery = "AppEvents | limit 1";
const kustoQuery = "AppEvents | limit 10";
const result = await logsQueryClient.queryLogs(
azureLogAnalyticsWorkspaceId,
kustoQuery,
Expand All @@ -524,6 +551,19 @@ const result = await logsQueryClient.queryLogs(
);
```

To view the results for each workspace, use the `TenantId` column to either order the results or filter them in the Kusto query.
**Order results by TenantId**

```
AppEvents | order by TenantId
```

**Filter results by TenantId**

```
AppEvents | filter TenantId == "<workspace2>"
```

A full sample can be found [here](https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/monitor/monitor-query/samples/v1/typescript/src/logsQueryMultipleWorkspaces.ts)

For more samples see here: [samples][samples].
Expand Down
2 changes: 1 addition & 1 deletion sdk/monitor/monitor-query/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
"build:samples": "dev-tool samples publish --force",
"build:test": "tsc -p . && rollup -c 2>&1",
"build:types": "downlevel-dts types/latest types/3.1",
"build": "npm run clean && tsc -p . && npm run lint && npm run build:nodebrowser && api-extractor run --local && npm run build:types",
"build": "npm run clean && tsc -p . && npm run build:nodebrowser && api-extractor run --local && npm run build:types",
"check-format": "prettier --list-different --config ../../../.prettierrc.json --ignore-path ../../../.prettierignore \"src/**/*.ts\" \"test/**/*.ts\" \"*.{js,json}\"",
"clean": "rimraf dist dist-* temp types *.tgz *.log coverage coverage-browser",
"docs": "typedoc --excludePrivate --excludeNotExported --excludeExternals --stripInternal --mode file --out ./dist/docs ./src",
Expand Down
Loading