diff --git a/sdk/monitor/azure-monitor-query/samples/sample_log_query_client.py b/sdk/monitor/azure-monitor-query/samples/sample_log_query_client.py index 8836bc71d8b7..10a160f71bed 100644 --- a/sdk/monitor/azure-monitor-query/samples/sample_log_query_client.py +++ b/sdk/monitor/azure-monitor-query/samples/sample_log_query_client.py @@ -4,6 +4,7 @@ import os import pandas as pd from datetime import datetime +from msrest.serialization import UTC from azure.monitor.query import LogsQueryClient from azure.identity import ClientSecretCredential @@ -20,12 +21,13 @@ # Response time trend # request duration over the last 12 hours. # [START send_logs_query] -query = """AppRequests | -where TimeGenerated > ago(12h) | +query = """AppRequests | summarize avgRequestDuration=avg(DurationMs) by bin(TimeGenerated, 10m), _ResourceId""" +end_time = datetime.now(UTC()) + # returns LogsQueryResults -response = client.query(os.environ['LOG_WORKSPACE_ID'], query, start_time=datetime(2021, 6, 2), end_time=datetime.now()) +response = client.query(os.environ['LOG_WORKSPACE_ID'], query, duration='PT1H', end_time=end_time) if not response.tables: print("No results for the query") @@ -40,28 +42,3 @@ 1 2021-05-27T08:50:00Z /subscriptions/faa080af-c1d8-40ad-9cce-e1a450c... 18.11655 2 2021-05-27T09:00:00Z /subscriptions/faa080af-c1d8-40ad-9cce-e1a450c... 24.5271 """ - -# if you dont want to use pandas - here's how you can process it. - -#response.tables is a LogsQueryResultTable -for table in response.tables: - for col in table.columns: #LogsQueryResultColumn - print(col.name + "/"+ col.type + " | ", end="") - print("\n") - for row in table.rows: - for item in row: - print(item + " | ", end="") - print("\n") - - -""" -TimeGenerated/datetime | _ResourceId/string | avgRequestDuration/real | - -2021-05-11T08:20:00Z | /subscriptions//resourcegroups/cobey-azuresdkshinydashboardgrp/providers/microsoft.insights/components/cobey-willthisbestatic | 10.8915 | - -2021-05-11T08:30:00Z | /subscriptions//resourcegroups/cobey-azuresdkshinydashboardgrp/providers/microsoft.insights/components/cobey-willthisbestatic | 33.23276666666667 | - -2021-05-11T08:40:00Z | /subscriptions//resourcegroups/cobey-azuresdkshinydashboardgrp/providers/microsoft.insights/components/cobey-willthisbestatic | 21.83535 | - -2021-05-11T08:50:00Z | /subscriptions//resourcegroups/cobey-azuresdkshinydashboardgrp/providers/microsoft.insights/components/cobey-willthisbestatic | 11.028649999999999 | -""" \ No newline at end of file diff --git a/sdk/monitor/azure-monitor-query/samples/sample_log_query_client_without_pandas.py b/sdk/monitor/azure-monitor-query/samples/sample_log_query_client_without_pandas.py new file mode 100644 index 000000000000..69538566582e --- /dev/null +++ b/sdk/monitor/azure-monitor-query/samples/sample_log_query_client_without_pandas.py @@ -0,0 +1,55 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. + +import os +from datetime import datetime +from msrest.serialization import UTC +from azure.monitor.query import LogsQueryClient +from azure.identity import ClientSecretCredential + +# [START client_auth_with_token_cred] +credential = ClientSecretCredential( + client_id = os.environ['AZURE_CLIENT_ID'], + client_secret = os.environ['AZURE_CLIENT_SECRET'], + tenant_id = os.environ['AZURE_TENANT_ID'] + ) + +client = LogsQueryClient(credential) +# [END client_auth_with_token_cred] + +# Response time trend +# request duration over the last 12 hours. +# [START send_logs_query] +query = """AppRequests | +summarize avgRequestDuration=avg(DurationMs) by bin(TimeGenerated, 10m), _ResourceId""" + +end_time = datetime.now(UTC()) + +# returns LogsQueryResults +response = client.query(os.environ['LOG_WORKSPACE_ID'], query, duration='PT1H', end_time=end_time) + +if not response.tables: + print("No results for the query") + +#response.tables is a LogsQueryResultTable +for table in response.tables: + for col in table.columns: #LogsQueryResultColumn + print(col.name + "/"+ col.type + " | ", end="") + print("\n") + for row in table.rows: + for item in row: + print(item + " | ", end="") + print("\n") + + +""" +TimeGenerated/datetime | _ResourceId/string | avgRequestDuration/real | + +2021-05-11T08:20:00Z | /subscriptions//resourcegroups/cobey-azuresdkshinydashboardgrp/providers/microsoft.insights/components/cobey-willthisbestatic | 10.8915 | + +2021-05-11T08:30:00Z | /subscriptions//resourcegroups/cobey-azuresdkshinydashboardgrp/providers/microsoft.insights/components/cobey-willthisbestatic | 33.23276666666667 | + +2021-05-11T08:40:00Z | /subscriptions//resourcegroups/cobey-azuresdkshinydashboardgrp/providers/microsoft.insights/components/cobey-willthisbestatic | 21.83535 | + +2021-05-11T08:50:00Z | /subscriptions//resourcegroups/cobey-azuresdkshinydashboardgrp/providers/microsoft.insights/components/cobey-willthisbestatic | 11.028649999999999 | +""" \ No newline at end of file diff --git a/sdk/monitor/azure-monitor-query/tests/test_logs_client.py b/sdk/monitor/azure-monitor-query/tests/test_logs_client.py index 750ef9cefee6..97d225e7c853 100644 --- a/sdk/monitor/azure-monitor-query/tests/test_logs_client.py +++ b/sdk/monitor/azure-monitor-query/tests/test_logs_client.py @@ -13,7 +13,7 @@ def _credential(): return credential @pytest.mark.live_test_only -def test_logs_auth(): +def test_logs_single_query(): credential = _credential() client = LogsQueryClient(credential) query = """AppRequests | @@ -26,6 +26,28 @@ def test_logs_auth(): assert response is not None assert response.tables is not None +@pytest.mark.live_test_only +def test_logs_single_query_with_non_200(): + credential = _credential() + client = LogsQueryClient(credential) + query = """AppInsights | + where TimeGenerated > ago(12h)""" + + with pytest.raises(HttpResponseError) as e: + client.query(os.environ['LOG_WORKSPACE_ID'], query) + + assert "SemanticError" in e.value.message + +@pytest.mark.live_test_only +def test_logs_single_query_with_partial_success(): + credential = _credential() + client = LogsQueryClient(credential) + query = "set truncationmaxrecords=1; union * | project TimeGenerated | take 10" + + response = client.query(os.environ['LOG_WORKSPACE_ID'], query) + + assert response is not None + @pytest.mark.live_test_only def test_logs_server_timeout(): client = LogsQueryClient(_credential()) diff --git a/sdk/monitor/azure-monitor-query/tests/test_logs_timespans.py b/sdk/monitor/azure-monitor-query/tests/test_logs_timespans.py new file mode 100644 index 000000000000..85af60795414 --- /dev/null +++ b/sdk/monitor/azure-monitor-query/tests/test_logs_timespans.py @@ -0,0 +1,92 @@ +from datetime import datetime, time, timedelta +import pytest +import json +import os +from msrest.serialization import UTC + +from azure.identity import ClientSecretCredential +from azure.core.exceptions import HttpResponseError +from azure.monitor.query import LogsQueryClient, LogsQueryRequest + +def _credential(): + credential = ClientSecretCredential( + client_id = os.environ['AZURE_CLIENT_ID'], + client_secret = os.environ['AZURE_CLIENT_SECRET'], + tenant_id = os.environ['AZURE_TENANT_ID'] + ) + return credential + +@pytest.mark.live_test_only +def test_query_no_duration(): + credential = _credential() + client = LogsQueryClient(credential) + query = """AppRequests | + where TimeGenerated > ago(12h) | + summarize avgRequestDuration=avg(DurationMs) by bin(TimeGenerated, 10m), _ResourceId""" + + def callback(request): + dic = json.loads(request.http_request.body) + assert dic.get('timespan') is None + # returns LogsQueryResults + client.query(os.environ['LOG_WORKSPACE_ID'], query) + +@pytest.mark.live_test_only +def test_query_start_and_end_time(): + credential = _credential() + client = LogsQueryClient(credential) + query = "AppRequests | take 5" + + end_time = datetime.now(UTC()) + start_time = end_time - timedelta(days=3) + + def callback(request): + dic = json.loads(request.http_request.body) + assert dic.get('timespan') is not None + + client.query(os.environ['LOG_WORKSPACE_ID'], query, start_time=start_time, end_time=end_time, raw_request_hook=callback) + +@pytest.mark.live_test_only +def test_query_duration_and_end_time(): + credential = _credential() + client = LogsQueryClient(credential) + query = "AppRequests | take 5" + + end_time = datetime.now(UTC()) + duration = 'P3D' + + def callback(request): + dic = json.loads(request.http_request.body) + assert 'P3D/' in dic.get('timespan') + + client.query(os.environ['LOG_WORKSPACE_ID'], query, duration=duration, end_time=end_time, raw_request_hook=callback) + +@pytest.mark.live_test_only +def test_query_duration_and_start_time(): + credential = _credential() + client = LogsQueryClient(credential) + query = "AppRequests | take 5" + + end_time = datetime.now(UTC()) + start_time = end_time - timedelta(days=3) + duration = 'P3D' + + def callback(request): + dic = json.loads(request.http_request.body) + assert '/P3D' in dic.get('timespan') + + client.query(os.environ['LOG_WORKSPACE_ID'], query, duration=duration, start_time=start_time, raw_request_hook=callback) + + +@pytest.mark.live_test_only +def test_query_duration_only(): + credential = _credential() + client = LogsQueryClient(credential) + query = "AppRequests | take 5" + + duration = 'P3D' + + def callback(request): + dic = json.loads(request.http_request.body) + assert 'P3D' in dic.get('timespan') + + client.query(os.environ['LOG_WORKSPACE_ID'], query, duration=duration, raw_request_hook=callback)