Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
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
1 change: 1 addition & 0 deletions sdk/monitor/azure-monitor-query/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
- `workspaces`, `workspace_ids`, `qualified_names` and `azure_resource_ids` are now merged into a single `additional_workspaces` list in the query API.
- The `LogQueryRequest` object now takes in a `workspace_id` and `additional_workspaces` instead of `workspace`.
- `aggregation` param is now a list instead of a string in the `query` method.
- `duration` must now be provided as a timedelta instead of a string.

### Key Bugs Fixed

Expand Down
8 changes: 5 additions & 3 deletions sdk/monitor/azure-monitor-query/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ This sample shows sending multiple queries at the same time using batch query AP

```Python
import os
from datetime import timedelta
import pandas as pd
from azure.monitor.query import LogsQueryClient, LogsQueryRequest
from azure.identity import ClientSecretCredential
Expand All @@ -169,13 +170,13 @@ client = LogsQueryClient(credential)
requests = [
LogsQueryRequest(
query="AzureActivity | summarize count()",
duration="PT1H",
duration=timedelta(hours=1),
workspace= os.environ['LOG_WORKSPACE_ID']
),
LogsQueryRequest(
query= """AppRequests | take 10 |
summarize avgRequestDuration=avg(DurationMs) by bin(TimeGenerated, 10m), _ResourceId""",
duration="PT1H",
duration=timedelta(hours=1),
start_time=datetime(2021, 6, 2),
workspace= os.environ['LOG_WORKSPACE_ID']
),
Expand Down Expand Up @@ -228,6 +229,7 @@ This example shows getting the metrics for an EventGrid subscription. The resour

```Python
import os
from datetime import timedelta
from azure.monitor.query import MetricsQueryClient
from azure.identity import ClientSecretCredential

Expand All @@ -245,7 +247,7 @@ response = client.query(
metrics_uri,
metric_names=["PublishSuccessCount"],
start_time=datetime(2021, 5, 25),
duration='P1D'
duration=timedelta(days=1),

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

indent?

)

for metric in response.metrics:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ def order_results(request_order, responses):
return ordered

def construct_iso8601(start=None, end=None, duration=None):
if duration is not None:
duration = _duration_to_iso8601(duration)
Comment thread
rakshith91 marked this conversation as resolved.
Outdated
iso_str = None
if start is not None:
start = Serializer.serialize_iso(start)
Expand All @@ -64,5 +66,8 @@ def construct_iso8601(start=None, end=None, duration=None):
end = Serializer.serialize_iso(end)
iso_str = duration + '/' + end
else:
iso_str = duration
iso_str = duration
Comment thread
rakshith91 marked this conversation as resolved.
Outdated
return iso_str

def _duration_to_iso8601(duration):
return 'PT{}S'.format(duration.total_seconds())
Comment thread
rakshith91 marked this conversation as resolved.
Outdated
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

if TYPE_CHECKING:
from azure.core.credentials import TokenCredential
from datetime import timedelta


class LogsQueryClient(object):
Expand Down Expand Up @@ -49,7 +50,7 @@ def __init__(self, credential, **kwargs):
self._query_op = self._client.query

def query(self, workspace_id, query, duration=None, **kwargs):
# type: (str, str, str, Any) -> LogsQueryResults
# type: (str, str, timedelta, Any) -> LogsQueryResults

@xiangyan99 xiangyan99 Jun 24, 2021

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
# type: (str, str, timedelta, Any) -> LogsQueryResults
# type: (str, str, Optional[timedelta], Any) -> LogsQueryResults

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i'll update all these :)

"""Execute an Analytics query.

Executes an Analytics query for data.
Expand All @@ -63,9 +64,9 @@ def query(self, workspace_id, query, duration=None, **kwargs):
:param query: The Analytics query. Learn more about the `Analytics query syntax
<https://azure.microsoft.com/documentation/articles/app-insights-analytics-reference/>`_.
:type query: str
:param str duration: The duration for which to query the data. This can also be accompanied
:param ~datetime.timedelta duration: The duration for which to query the data. This can also be accompanied
with either start_time or end_time. If start_time or end_time is not provided, the current time is
taken as the end time. This should be provided in a ISO8601 string format like 'PT1H', 'P1Y2M10DT2H30M'.
taken as the end time.
:keyword datetime start_time: The start time from which to query the data. This should be accompanied
with either end_time or duration.
:keyword datetime end_time: The end time till which to query the data. This should be accompanied
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
from ._helpers import get_metrics_authentication_policy, construct_iso8601

if TYPE_CHECKING:
from datetime import timedelta
from azure.core.credentials import TokenCredential
from azure.core.paging import ItemPaged

Expand Down Expand Up @@ -53,7 +54,7 @@ def __init__(self, credential, **kwargs):
self._definitions_op = self._client.metric_definitions

def query(self, resource_uri, metric_names, duration=None, **kwargs):
# type: (str, list, str, Any) -> MetricsResult
# type: (str, list, timedelta, Any) -> MetricsResult
"""Lists the metric values for a resource.

**Note**: Although the start_time, end_time, duration are optional parameters, it is highly
Expand All @@ -63,9 +64,9 @@ def query(self, resource_uri, metric_names, duration=None, **kwargs):
:type resource_uri: str
:param metric_names: The names of the metrics to retrieve.
:type metric_names: list[str]
:param str duration: The duration for which to query the data. This can also be accompanied
:param ~datetime.timedelta duration: The duration for which to query the data. This can also be accompanied
with either start_time or end_time. If start_time or end_time is not provided, the current time is
taken as the end time. This should be provided in a ISO8601 string format like 'PT1H', 'P1Y2M10DT2H30M'.
taken as the end time.
:keyword datetime start_time: The start time from which to query the data. This should be accompanied
with either end_time or duration.
:keyword datetime end_time: The end time till which to query the data. This should be accompanied
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -151,9 +151,9 @@ class LogsQueryRequest(InternalLogQueryRequest):
:param query: The Analytics query. Learn more about the `Analytics query syntax
<https://azure.microsoft.com/documentation/articles/app-insights-analytics-reference/>`_.
:type query: str
:param str duration: The duration for which to query the data. This can also be accompanied
:param ~datetime.timedelta duration: The duration for which to query the data. This can also be accompanied
with either start_time or end_time. If start_time or end_time is not provided, the current time is
taken as the end time. This should be provided in a ISO8601 string format like 'PT1H', 'P1Y2M10DT2H30M'.
taken as the end time.
:keyword datetime start_time: The start time from which to query the data. This should be accompanied
with either end_time or duration.
:keyword datetime end_time: The end time till which to query the data. This should be accompanied
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
# license information.
# --------------------------------------------------------------------------

from datetime import timedelta
from typing import Any, Union, Sequence, Dict, TYPE_CHECKING
from azure.core.exceptions import HttpResponseError
from .._generated.aio._monitor_query_client import MonitorQueryClient
Expand Down Expand Up @@ -41,7 +42,7 @@ async def query(
self,
workspace_id: str,
query: str,
duration: str = None,
duration: timedelta = None,
**kwargs: Any) -> LogsQueryResults:
"""Execute an Analytics query.

Expand All @@ -56,9 +57,9 @@ async def query(
:param query: The Analytics query. Learn more about the `Analytics query syntax
<https://azure.microsoft.com/documentation/articles/app-insights-analytics-reference/>`_.
:type query: str
:param str duration: The duration for which to query the data. This can also be accompanied
:param ~datetime.timedelta duration: The duration for which to query the data. This can also be accompanied
with either start_time or end_time. If start_time or end_time is not provided, the current time is
taken as the end time. This should be provided in a ISO8601 string format like 'PT1H', 'P1Y2M10DT2H30M'.
taken as the end time.
:keyword datetime start_time: The start time from which to query the data. This should be accompanied
with either end_time or duration.
:keyword datetime end_time: The end time till which to query the data. This should be accompanied
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

# pylint: disable=anomalous-backslash-in-string

from datetime import timedelta
from typing import TYPE_CHECKING, Any, List

from azure.core.async_paging import AsyncItemPaged
Expand Down Expand Up @@ -42,7 +43,13 @@ def __init__(self, credential: "AsyncTokenCredential", **kwargs: Any) -> None:
self._namespace_op = self._client.metric_namespaces
self._definitions_op = self._client.metric_definitions

async def query(self, resource_uri: str, metric_names: List, duration: str = None, **kwargs: Any) -> MetricsResult:
async def query(
self,
resource_uri: str,
metric_names: List,
duration: timedelta = None,
**kwargs: Any
) -> MetricsResult:
"""Lists the metric values for a resource.

**Note**: Although the start_time, end_time, duration are optional parameters, it is highly
Expand All @@ -52,9 +59,9 @@ async def query(self, resource_uri: str, metric_names: List, duration: str = Non
:type resource_uri: str
:param metric_names: The names of the metrics to retrieve.
:type metric_names: list
:param str duration: The duration for which to query the data. This can also be accompanied
:param ~datetime.timedelta duration: The duration for which to query the data. This can also be accompanied
with either start_time or end_time. If start_time or end_time is not provided, the current time is
taken as the end time. This should be provided in a ISO8601 string format like 'PT1H', 'P1Y2M10DT2H30M'.
taken as the end time.
:keyword datetime start_time: The start time from which to query the data. This should be accompanied
with either end_time or duration.
:keyword datetime end_time: The end time till which to query the data. This should be accompanied
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

import os
import asyncio
from datetime import datetime
from datetime import datetime, timedelta
import urllib3
from azure.monitor.query.aio import MetricsQueryClient
from azure.identity.aio import ClientSecretCredential
Expand All @@ -25,7 +25,7 @@ async def query_metrics():
metrics_uri,
metric_names=["PublishSuccessCount"],
start_time=datetime(2021, 5, 25),
duration='P1D'
duration=timedelta(days=1)
)

for metric in response.metrics:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.

from datetime import datetime
from datetime import datetime, timedelta
import os
import pandas as pd
from azure.monitor.query import LogsQueryClient, LogsQueryRequest
Expand All @@ -20,13 +20,13 @@
requests = [
LogsQueryRequest(
query="AzureActivity | summarize count()",
duration="PT1H",
duration=timedelta(hours=1),
workspace_id= os.environ['LOG_WORKSPACE_ID']
),
LogsQueryRequest(
query= """AppRequests | take 10 |
summarize avgRequestDuration=avg(DurationMs) by bin(TimeGenerated, 10m), _ResourceId""",
duration="PT1H",
duration=timedelta(hours=1),
start_time=datetime(2021, 6, 2),
workspace_id= os.environ['LOG_WORKSPACE_ID']
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

import os
import pandas as pd
from datetime import datetime
from datetime import datetime, timedelta
from msrest.serialization import UTC
from azure.monitor.query import LogsQueryClient
from azure.identity import ClientSecretCredential
Expand All @@ -27,7 +27,7 @@
end_time = datetime.now(UTC())

# returns LogsQueryResults
response = client.query(os.environ['LOG_WORKSPACE_ID'], query, duration='PT1H', end_time=end_time)
response = client.query(os.environ['LOG_WORKSPACE_ID'], query, duration=timedelta(days=1), end_time=end_time)

if not response.tables:
print("No results for the query")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# Licensed under the MIT License.

import os
from datetime import datetime
from datetime import datetime, timedelta
from msrest.serialization import UTC
from azure.monitor.query import LogsQueryClient
from azure.identity import ClientSecretCredential
Expand All @@ -23,7 +23,7 @@
end_time = datetime.now(UTC())

# returns LogsQueryResults
response = client.query(os.environ['LOG_WORKSPACE_ID'], query, duration='PT1H', end_time=end_time)
response = client.query(os.environ['LOG_WORKSPACE_ID'], query, duration=timedelta(hours=1), end_time=end_time)

if not response.tables:
print("No results for the query")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
metrics_uri,
metric_names=["MatchedEventCount"],
start_time=datetime(2021, 6, 21),
duration='P1D',
duration=timedelta(days=1),
aggregation=['Count']
)

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from datetime import datetime
from datetime import datetime, time, timedelta
import pytest
import os
from azure.identity.aio import ClientSecretCredential
Expand All @@ -20,7 +20,7 @@ async def test_metrics_auth():
os.environ['METRICS_RESOURCE_URI'],
metric_names=["MatchedEventCount"],
start_time=datetime(2021, 6, 21),
duration='P1D',
duration=timedelta(days=1),
aggregation=['Count']
)
assert response
Expand Down
33 changes: 26 additions & 7 deletions sdk/monitor/azure-monitor-query/tests/test_logs_timespans.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from datetime import datetime, time, timedelta
from datetime import datetime, timedelta
import pytest
import json
import os
Expand All @@ -8,6 +8,8 @@
from azure.core.exceptions import HttpResponseError
from azure.monitor.query import LogsQueryClient, LogsQueryRequest

from azure.monitor.query._helpers import _duration_to_iso8601

def _credential():
credential = ClientSecretCredential(
client_id = os.environ['AZURE_CLIENT_ID'],
Expand Down Expand Up @@ -52,11 +54,11 @@ def test_query_duration_and_end_time():
query = "AppRequests | take 5"

end_time = datetime.now(UTC())
duration = 'P3D'
duration = timedelta(days=3)

def callback(request):
dic = json.loads(request.http_request.body)
assert 'P3D/' in dic.get('timespan')
assert 'PT259200.0S/' in dic.get('timespan')

client.query(os.environ['LOG_WORKSPACE_ID'], query, duration=duration, end_time=end_time, raw_request_hook=callback)

Expand All @@ -68,11 +70,11 @@ def test_query_duration_and_start_time():

end_time = datetime.now(UTC())
start_time = end_time - timedelta(days=3)
duration = 'P3D'
duration = timedelta(days=3)

def callback(request):
dic = json.loads(request.http_request.body)
assert '/P3D' in dic.get('timespan')
assert '/PT259200.0S' in dic.get('timespan')

client.query(os.environ['LOG_WORKSPACE_ID'], query, duration=duration, start_time=start_time, raw_request_hook=callback)

Expand All @@ -83,10 +85,27 @@ def test_query_duration_only():
client = LogsQueryClient(credential)
query = "AppRequests | take 5"

duration = 'P3D'
duration = timedelta(days=3)

def callback(request):
dic = json.loads(request.http_request.body)
assert 'P3D' in dic.get('timespan')
assert 'PT259200.0S' in dic.get('timespan')

client.query(os.environ['LOG_WORKSPACE_ID'], query, duration=duration, raw_request_hook=callback)

def test_duration_to_iso8601():
d1 = timedelta(days=1)
d2 = timedelta(weeks=1)
d3 = timedelta(weeks=3, days=4)
d4 = timedelta(seconds=10)
d5 = timedelta(microseconds=1000)
d6 = timedelta(milliseconds=100000)
d7 = timedelta(hours=24, days=1)

assert _duration_to_iso8601(d1) == 'PT86400.0S'
assert _duration_to_iso8601(d2) == 'PT604800.0S'
assert _duration_to_iso8601(d3) == 'PT2160000.0S'
assert _duration_to_iso8601(d4) == 'PT10.0S'
assert _duration_to_iso8601(d5) == 'PT0.001S'
assert _duration_to_iso8601(d5) == 'PT0.001S'
assert _duration_to_iso8601(d7) == 'PT172800.0S'
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import pytest
import os
from datetime import datetime
from datetime import datetime, timedelta
from azure.identity import ClientSecretCredential
from azure.monitor.query import MetricsQueryClient

Expand All @@ -20,7 +20,7 @@ def test_metrics_auth():
os.environ['METRICS_RESOURCE_URI'],
metric_names=["MatchedEventCount"],
start_time=datetime(2021, 6, 21),
duration='P1D',
duration=timedelta(days=1),
aggregation=['Count']
)
assert response
Expand Down