diff --git a/sdk/monitor/monitor-query/README.md b/sdk/monitor/monitor-query/README.md index 2c83482a4a4f..731ca7788944 100644 --- a/sdk/monitor/monitor-query/README.md +++ b/sdk/monitor/monitor-query/README.md @@ -101,6 +101,8 @@ Each set of metric values is a time series with the following characteristics: ## Examples - [Logs query](#logs-query) + - [Workspace-centric logs query](#workspace-centric-logs-query) + - [Resource-centric logs query](#resource-centric-logs-query) - [Handle logs query response](#handle-logs-query-response) - [Batch logs query](#batch-logs-query) - [Handle logs batch query response](#handle-logs-batch-query-response) @@ -115,6 +117,12 @@ Each set of metric values is a time series with the following characteristics: The `LogsQueryClient` can be used to query a Log Analytics workspace using the [Kusto Query Language][kusto_query_language]. The `timespan.duration` can be specified as a string in an ISO 8601 duration format. You can use the `Durations` constants provided for some commonly used ISO 8601 durations. +You can query logs by workspace ID or resource ID. The result is returned as a table with a collection of rows. + +#### Workspace-centric logs query + +To query by workspace ID, use the `LogsQueryClient.queryWorkspace` method: + ```ts import { DefaultAzureCredential } from "@azure/identity"; import { Durations, LogsQueryClient, LogsQueryResultStatus, LogsTable } from "@azure/monitor-query"; @@ -163,6 +171,106 @@ async function processTables(tablesFromResult: LogsTable[]) { run().catch((err) => console.log("ERROR:", err)); ``` +#### Resource-centric logs query + +The following example demonstrates how to query logs directly from an Azure resource. Here, the `queryResource` method is used and an Azure resource ID is passed in (e.g. /subscriptions/{subscription-id}/resourceGroups/{resource-group-name}/providers/{resource-provider}/{resource-type}/{resource-name}). + +To find the resource ID: + +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 +/** + * @summary Demonstrates how to run a query against a Log Analytics workspace, using an Azure resource ID. + */ + +import { DefaultAzureCredential } from "@azure/identity"; +import { + Durations, + LogsQueryClient, + LogsTable, + LogsQueryOptions, + LogsQueryResultStatus, +} from "@azure/monitor-query"; +import * as dotenv from "dotenv"; +dotenv.config(); + +const logsResourceId = process.env.LOGS_RESOURCE_ID; + +export async function main() { + const tokenCredential = new DefaultAzureCredential(); + const logsQueryClient = new LogsQueryClient(tokenCredential); + + if (!logsResourceId) { + throw new Error("LOGS_RESOURCE_ID must be set in the environment for this sample"); + } + + const kustoQuery = `MyTable_CL | summarize count()` + + console.log(`Running '${kustoQuery}' over the last One Hour`); + const queryLogsOptions: LogsQueryOptions = { + // explicitly control the amount of time the server can spend processing the query. + serverTimeoutInSeconds: 600, // sets the timeout to 10 minutes + // optionally enable returning additional statistics about the query's execution. + // (by default, this is off) + includeQueryStatistics: true, + }; + + const result = await logsQueryClient.queryResource( + logsResourceId, + kustoQuery, + { duration: Durations.sevenDays }, + queryLogsOptions); + + const executionTime = + result.statistics && result.statistics.query && (result.statistics.query as any).executionTime; + + console.log( + `Results for query '${kustoQuery}', execution time: ${ + executionTime == null ? "unknown" : executionTime + }` + ); + + if (result.status === LogsQueryResultStatus.Success) { + const tablesFromResult: LogsTable[] = result.tables; + + if (tablesFromResult.length === 0) { + console.log(`No results for query '${kustoQuery}'`); + return; + } + console.log(`This query has returned table(s) - `); + processTables(tablesFromResult); + } else { + console.log(`Error processing the query '${kustoQuery}' - ${result.partialError}`); + if (result.partialTables.length > 0) { + console.log(`This query has also returned partial data in the following table(s) - `); + processTables(result.partialTables); + } + } +} + +async function processTables(tablesFromResult: LogsTable[]) { + for (const table of tablesFromResult) { + const columnHeaderString = table.columnDescriptors + .map((column) => `${column.name}(${column.type}) `) + .join("| "); + console.log("| " + columnHeaderString); + + for (const row of table.rows) { + const columnValuesString = row.map((columnValue) => `'${columnValue}' `).join("| "); + console.log("| " + columnValuesString); + } + } +} + +main().catch((err) => { + console.error("The sample encountered an error:", err); + process.exit(1); +}); +``` + #### Handle logs query response The `queryWorkspace` function of `LogsQueryClient` returns a `LogsQueryResult` object. The object type can be `LogsQuerySuccessfulResult` or `LogsQueryPartialResult`. Here's a hierarchy of the response: @@ -312,7 +420,6 @@ The `queryBatch` function of `LogsQueryClient` returns a `LogsQueryBatchResult` Here's a hierarchy of the response: ``` - LogsQuerySuccessfulResult |---statistics |---visualization diff --git a/sdk/monitor/monitor-query/samples-dev/logsResourceCentricQuery.ts b/sdk/monitor/monitor-query/samples-dev/logsResourceCentricQuery.ts new file mode 100644 index 000000000000..b18a5423318b --- /dev/null +++ b/sdk/monitor/monitor-query/samples-dev/logsResourceCentricQuery.ts @@ -0,0 +1,90 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +/** + * @summary Demonstrates how to run a query against a Log Analytics workspace, using an Azure resource ID. + */ + +import { DefaultAzureCredential } from "@azure/identity"; +import { + Durations, + LogsQueryClient, + LogsTable, + LogsQueryOptions, + LogsQueryResultStatus, +} from "@azure/monitor-query"; +import * as dotenv from "dotenv"; +dotenv.config(); + +const logsResourceId = process.env.LOGS_RESOURCE_ID; + +export async function main() { + const tokenCredential = new DefaultAzureCredential(); + const logsQueryClient = new LogsQueryClient(tokenCredential); + + if (!logsResourceId) { + throw new Error("LOGS_RESOURCE_ID must be set in the environment for this sample"); + } + + const kustoQuery = `MyTable_CL | summarize count()`; + + console.log(`Running '${kustoQuery}' over the last One Hour`); + const queryLogsOptions: LogsQueryOptions = { + // explicitly control the amount of time the server can spend processing the query. + serverTimeoutInSeconds: 600, // sets the timeout to 10 minutes + // optionally enable returning additional statistics about the query's execution. + // (by default, this is off) + includeQueryStatistics: true, + }; + + const result = await logsQueryClient.queryResource( + logsResourceId, + kustoQuery, + { duration: Durations.sevenDays }, + queryLogsOptions); + + const executionTime = + result.statistics && result.statistics.query && (result.statistics.query as any).executionTime; + + console.log( + `Results for query '${kustoQuery}', execution time: ${ + executionTime == null ? "unknown" : executionTime + }` + ); + + if (result.status === LogsQueryResultStatus.Success) { + const tablesFromResult: LogsTable[] = result.tables; + + if (tablesFromResult.length === 0) { + console.log(`No results for query '${kustoQuery}'`); + return; + } + console.log(`This query has returned table(s) - `); + processTables(tablesFromResult); + } else { + console.log(`Error processing the query '${kustoQuery}' - ${result.partialError}`); + if (result.partialTables.length > 0) { + console.log(`This query has also returned partial data in the following table(s) - `); + processTables(result.partialTables); + } + } +} + +async function processTables(tablesFromResult: LogsTable[]) { + for (const table of tablesFromResult) { + const columnHeaderString = table.columnDescriptors + .map((column) => `${column.name}(${column.type}) `) + .join("| "); + console.log("| " + columnHeaderString); + + for (const row of table.rows) { + const columnValuesString = row.map((columnValue) => `'${columnValue}' `).join("| "); + console.log("| " + columnValuesString); + } + } +} + +main().catch((err) => { + console.error("The sample encountered an error:", err); + process.exit(1); +}); diff --git a/sdk/monitor/monitor-query/samples/v1/javascript/README.md b/sdk/monitor/monitor-query/samples/v1/javascript/README.md index 67f753a45f0d..eee2ede761ba 100644 --- a/sdk/monitor/monitor-query/samples/v1/javascript/README.md +++ b/sdk/monitor/monitor-query/samples/v1/javascript/README.md @@ -4,9 +4,10 @@ These sample programs show how to use the JavaScript client libraries for Monito | **File Name** | **Description** | | ------------------------------------------------------------- | ----------------------------------------------------------------------- | -| [logsQuery.js][logsquery] | Demonstrates how to run a query against a Log Analytics workspace | +| [logsQuery.js][logsquery] | Demonstrates how to run a query against a Log Analytics workspace, using a workspace ID | | [logsQueryBatch.js][logsquerybatch] | Demonstrates how to run a batch query against a Log Analytics workspace | | [logsQueryMultipleWorkspaces.js][logsquerymultipleworkspaces] | Demonstrates how to run a query against a Log Analytics workspace | +| [logsResourceCentricQuery.js][logsresourcecentricquery] | Demonstrates how to run a query against a Log Analytics workspace, using an Azure resource ID | | [metricsQuery.js][metricsquery] | Demonstrates how to query metrics using the MetricsClient. | ## Prerequisites @@ -52,6 +53,7 @@ Take a look at our [API Documentation][apiref] for more information about the AP [logsquery]: https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/monitor/monitor-query/samples/v1/javascript/logsQuery.js [logsquerybatch]: https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/monitor/monitor-query/samples/v1/javascript/logsQueryBatch.js [logsquerymultipleworkspaces]: https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/monitor/monitor-query/samples/v1/javascript/logsQueryMultipleWorkspaces.js +[logsresourcecentricquery]: https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/monitor/monitor-query/samples/v1/javascript/logsResourceCentricQuery.js [metricsquery]: https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/monitor/monitor-query/samples/v1/javascript/metricsQuery.js [apiref]: https://docs.microsoft.com/javascript/api/ [freesub]: https://azure.microsoft.com/free/ diff --git a/sdk/monitor/monitor-query/samples/v1/javascript/logsResourceCentricQuery.js b/sdk/monitor/monitor-query/samples/v1/javascript/logsResourceCentricQuery.js new file mode 100644 index 000000000000..8ce38c45df39 --- /dev/null +++ b/sdk/monitor/monitor-query/samples/v1/javascript/logsResourceCentricQuery.js @@ -0,0 +1,86 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +/** + * @summary Demonstrates how to run a query against a Log Analytics workspace, using an Azure resource ID. + */ + +const { DefaultAzureCredential } = require("@azure/identity"); +const { Durations, LogsQueryClient, LogsQueryResultStatus } = require("@azure/monitor-query"); +require("dotenv").config(); + +const logsResourceId = process.env.LOGS_RESOURCE_ID; + +async function main() { + const tokenCredential = new DefaultAzureCredential(); + const logsQueryClient = new LogsQueryClient(tokenCredential); + + if (!logsResourceId) { + throw new Error("LOGS_RESOURCE_ID must be set in the environment for this sample"); + } + + const kustoQuery = `MyTable_CL | summarize count()`; + + console.log(`Running '${kustoQuery}' over the last One Hour`); + const queryLogsOptions = { + // explicitly control the amount of time the server can spend processing the query. + serverTimeoutInSeconds: 600, + // optionally enable returning additional statistics about the query's execution. + // (by default, this is off) + includeQueryStatistics: true, + }; + + const result = await logsQueryClient.queryResource( + logsResourceId, + kustoQuery, + { duration: Durations.sevenDays }, + queryLogsOptions + ); + + const executionTime = + result.statistics && result.statistics.query && result.statistics.query.executionTime; + + console.log( + `Results for query '${kustoQuery}', execution time: ${ + executionTime == null ? "unknown" : executionTime + }` + ); + + if (result.status === LogsQueryResultStatus.Success) { + const tablesFromResult = result.tables; + + if (tablesFromResult.length === 0) { + console.log(`No results for query '${kustoQuery}'`); + return; + } + console.log(`This query has returned table(s) - `); + processTables(tablesFromResult); + } else { + console.log(`Error processing the query '${kustoQuery}' - ${result.partialError}`); + if (result.partialTables.length > 0) { + console.log(`This query has also returned partial data in the following table(s) - `); + processTables(result.partialTables); + } + } +} + +async function processTables(tablesFromResult) { + for (const table of tablesFromResult) { + const columnHeaderString = table.columnDescriptors + .map((column) => `${column.name}(${column.type}) `) + .join("| "); + console.log("| " + columnHeaderString); + + for (const row of table.rows) { + const columnValuesString = row.map((columnValue) => `'${columnValue}' `).join("| "); + console.log("| " + columnValuesString); + } + } +} + +main().catch((err) => { + console.error("The sample encountered an error:", err); + process.exit(1); +}); + +module.exports = { main }; diff --git a/sdk/monitor/monitor-query/samples/v1/typescript/README.md b/sdk/monitor/monitor-query/samples/v1/typescript/README.md index 8461b1b3651e..2c97bc3e56e0 100644 --- a/sdk/monitor/monitor-query/samples/v1/typescript/README.md +++ b/sdk/monitor/monitor-query/samples/v1/typescript/README.md @@ -4,9 +4,10 @@ These sample programs show how to use the TypeScript client libraries for Monito | **File Name** | **Description** | | ------------------------------------------------------------- | ----------------------------------------------------------------------- | -| [logsQuery.ts][logsquery] | Demonstrates how to run a query against a Log Analytics workspace | +| [logsQuery.ts][logsquery] | Demonstrates how to run a query against a Log Analytics workspace, using a workspace ID | | [logsQueryBatch.ts][logsquerybatch] | Demonstrates how to run a batch query against a Log Analytics workspace | | [logsQueryMultipleWorkspaces.ts][logsquerymultipleworkspaces] | Demonstrates how to run a query against a Log Analytics workspace | +| [logsResourceCentricQuery.ts][logsresourcecentricquery] | Demonstrates how to run a query against a Log Analytics workspace, using an Azure resource ID | | [metricsQuery.ts][metricsquery] | Demonstrates how to query metrics using the MetricsClient. | ## Prerequisites @@ -64,9 +65,10 @@ Take a look at our [API Documentation][apiref] for more information about the AP [logsquery]: https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/monitor/monitor-query/samples/v1/typescript/src/logsQuery.ts [logsquerybatch]: https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/monitor/monitor-query/samples/v1/typescript/src/logsQueryBatch.ts [logsquerymultipleworkspaces]: https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/monitor/monitor-query/samples/v1/typescript/src/logsQueryMultipleWorkspaces.ts +[logsresourcecentricquery]: https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/monitor/monitor-query/samples/v1/typescript/src/logsResourceCentricQuery.ts [metricsquery]: https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/monitor/monitor-query/samples/v1/typescript/src/metricsQuery.ts -[apiref]: https://docs.microsoft.com/javascript/api/ +[apiref]: https://learn.microsoft.com/javascript/api/ [freesub]: https://azure.microsoft.com/free/ -[createinstance_azuremonitor]: https://docs.microsoft.com/azure/azure-monitor/ +[createinstance_azuremonitor]: https://learn.microsoft.com/azure/azure-monitor/ [package]: https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/monitor/monitor-query/README.md [typescript]: https://www.typescriptlang.org/docs/home.html diff --git a/sdk/monitor/monitor-query/samples/v1/typescript/src/logsResourceCentricQuery.ts b/sdk/monitor/monitor-query/samples/v1/typescript/src/logsResourceCentricQuery.ts new file mode 100644 index 000000000000..b18a5423318b --- /dev/null +++ b/sdk/monitor/monitor-query/samples/v1/typescript/src/logsResourceCentricQuery.ts @@ -0,0 +1,90 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +/** + * @summary Demonstrates how to run a query against a Log Analytics workspace, using an Azure resource ID. + */ + +import { DefaultAzureCredential } from "@azure/identity"; +import { + Durations, + LogsQueryClient, + LogsTable, + LogsQueryOptions, + LogsQueryResultStatus, +} from "@azure/monitor-query"; +import * as dotenv from "dotenv"; +dotenv.config(); + +const logsResourceId = process.env.LOGS_RESOURCE_ID; + +export async function main() { + const tokenCredential = new DefaultAzureCredential(); + const logsQueryClient = new LogsQueryClient(tokenCredential); + + if (!logsResourceId) { + throw new Error("LOGS_RESOURCE_ID must be set in the environment for this sample"); + } + + const kustoQuery = `MyTable_CL | summarize count()`; + + console.log(`Running '${kustoQuery}' over the last One Hour`); + const queryLogsOptions: LogsQueryOptions = { + // explicitly control the amount of time the server can spend processing the query. + serverTimeoutInSeconds: 600, // sets the timeout to 10 minutes + // optionally enable returning additional statistics about the query's execution. + // (by default, this is off) + includeQueryStatistics: true, + }; + + const result = await logsQueryClient.queryResource( + logsResourceId, + kustoQuery, + { duration: Durations.sevenDays }, + queryLogsOptions); + + const executionTime = + result.statistics && result.statistics.query && (result.statistics.query as any).executionTime; + + console.log( + `Results for query '${kustoQuery}', execution time: ${ + executionTime == null ? "unknown" : executionTime + }` + ); + + if (result.status === LogsQueryResultStatus.Success) { + const tablesFromResult: LogsTable[] = result.tables; + + if (tablesFromResult.length === 0) { + console.log(`No results for query '${kustoQuery}'`); + return; + } + console.log(`This query has returned table(s) - `); + processTables(tablesFromResult); + } else { + console.log(`Error processing the query '${kustoQuery}' - ${result.partialError}`); + if (result.partialTables.length > 0) { + console.log(`This query has also returned partial data in the following table(s) - `); + processTables(result.partialTables); + } + } +} + +async function processTables(tablesFromResult: LogsTable[]) { + for (const table of tablesFromResult) { + const columnHeaderString = table.columnDescriptors + .map((column) => `${column.name}(${column.type}) `) + .join("| "); + console.log("| " + columnHeaderString); + + for (const row of table.rows) { + const columnValuesString = row.map((columnValue) => `'${columnValue}' `).join("| "); + console.log("| " + columnValuesString); + } + } +} + +main().catch((err) => { + console.error("The sample encountered an error:", err); + process.exit(1); +}); diff --git a/sdk/monitor/monitor-query/samples/v1/typescript/tsconfig.json b/sdk/monitor/monitor-query/samples/v1/typescript/tsconfig.json index 416c2dd82e00..e26ce2a6d8f7 100644 --- a/sdk/monitor/monitor-query/samples/v1/typescript/tsconfig.json +++ b/sdk/monitor/monitor-query/samples/v1/typescript/tsconfig.json @@ -1,6 +1,6 @@ { "compilerOptions": { - "target": "ES2018", + "target": "ES2020", "module": "commonjs", "moduleResolution": "node", "resolveJsonModule": true,