Create the client
An authenticated client is required to query Logs or Metrics. To authenticate, the following example uses DefaultAzureCredential from the @azure/identity package.
import { DefaultAzureCredential } from "@azure/identity";
import { LogsQueryClient, MetricsQueryClient, MetricsBatchQueryClient } from "@azure/monitor-query";
const credential = new DefaultAzureCredential();
const logsQueryClient: LogsQueryClient = new LogsQueryClient(credential);
// or
const metricsQueryClient: MetricsQueryClient = new MetricsQueryClient(credential);
// or
const endPoint: string = "<YOUR_METRICS_ENDPOINT>"; //for example, https://eastus.metrics.monitor.azure.com/
const metricsQueryClient: MetricsQueryClient = new MetricsQueryClient(endPoint, credential);
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. For example, /subscriptions/{subscription-id}/resourceGroups/{resource-group-name}/providers/{resource-provider}/{resource-type}/{resource-name}.
To find the resource ID:
- Navigate to your resource's page in the Azure portal.
- From the Overview blade, select the JSON View link.
- In the resulting JSON, copy the value of the
id property.
/**
- @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);
> });
>
Does it look like I am on the right track in completing this setup?
Do I need any credentials? Tenet ID or something else to connect?
python
from azure.identity import ClientSecretCredential, DefaultAzureCredential
from azure.monitor.query import LogsQueryClient, LogsQueryStatus, MetricsQueryClient
CLIENT_ID = os.getenv("CLIENT_ID")
CLIENT_SECRET = os.getenv("CLIENT_SECRET")
TENANT_ID= os.getenv("TENANT_ID")
WORKSPACE_ID = os.getenv("WORKSPACE_ID")
LOGS_RESOURCE_ID = os.getenv("LOGS_RESOURCE_ID")
logs_resource_id = os.getenv("LOGS_RESOURCE_ID")
credential = DefaultAzureCredential()
logs_query_client = LogsQueryClient(credential)
@app.route('/logicapp-logs', methods=['GET'])
def get_logicapp_logs():
# Create a credential object
credential = DefaultAzureCredential()
# Create a LogsQueryClient
logs_query_client = LogsQueryClient(credential)
# Create a MetricsQueryClient
metrics_query_client = MetricsQueryClient(credential)
# If you need to specify an endpoint for the MetricsQueryClient
endpoint = os.getenv("METRICS_ENDPOINT") # for example, "https://eastus.metrics.monitor.azure.com/"
metrics_query_client_with_endpoint = MetricsQueryClient(endpoint=endpoint, credential=credential)
@app.route('/logicapp-logs', methods=['GET'])
def get_logicapp_logs():
try:
print(f"WORKSPACE_ID: {WORKSPACE_ID}")
print(f"CLIENT_ID: {CLIENT_ID}")
print(f"TENANT_ID: {TENANT_ID}")
print(f"LOGS_RESOURCE_ID: {LOGS_RESOURCE_ID}")
kusto_query = """
AzureDiagnostics
| where ResourceProvider == "MICROSOFT.LOGIC"
| where Category == "WorkflowRuntime"
| project runId=RunId, status=Status, timestamp=TimeGenerated, error=Error
| order by timestamp desc
| limit 100
"""
# Query the Logic App resource directly using its resource ID
response = logs_query_client.query_resource(
LOGS_RESOURCE_ID,
kusto_query,
duration=timedelta(days=7) # Adjust as needed
)
if response.status == LogsQueryStatus.SUCCESS:
logs = response.tables[0].rows if response.tables else []
formatted_logs = [
{
"runId": row[0],
"status": row[1],
"timestamp": row[2].isoformat(),
"error": row[3] or "N/A"
}
for row in logs
]
return jsonify(formatted_logs)
else:
return jsonify({"message": "Error fetching logs."}), 500
except Exception as error:
print(f"An error occurred: {str(error)}")
return jsonify({"error": str(error)}), 500
logs_resource_id = os.getenv("LOGS_RESOURCE_ID")
credential = DefaultAzureCredential()
logs_query_client = LogsQueryClient(credential)
@app.route('/logicapp-logs', methods=['GET'])
def get_logicapp_logs():
JS FILE:
import React, { useState, useEffect } from 'react';
function Azure() {
const [logs, setLogs] = useState([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
fetch('http://localhost:5000/logicapp-logs')
.then(response => response.json())
.then(data => {
setLogs(data);
setLoading(false);
console.log("Logs:", data);
})
.catch(error => {
setError(error.message);
setLoading(false);
});
}, []);
if (loading) return <p>Loading...</p>;
if (error) return <p>Error fetching logs: {error}</p>;
if (logs.length === 0) return <p>No logs available.</p>;
return (
<div>
<h1>Azure Logic App Logs</h1>
<ul>
{logs.map((log, index) => (
<li key={index}>
<p><strong>Run ID:</strong> {log.runId}</p>
<p><strong>Status:</strong> {log.status}</p>
<p><strong>Timestamp:</strong> {new Date(log.timestamp).toLocaleString()}</p>
<p><strong>Error:</strong> {log.error}</p>
<hr />
</li>
))}
</ul>
</div>
);
}
export default Azure;
import React, { useState, useEffect } from 'react';
function Azure() {
const [logs, setLogs] = useState([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
getLogs();
}, []);
const getLogs = () => {
fetch('/logicapp-logs')
.then(response => {
if (!response.ok) {