Skip to content

[Monitor] Update query package to use TypeSpec #42205

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

Merged
merged 3 commits into from
Jul 29, 2025
Merged
Show file tree
Hide file tree
Changes from all 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
12 changes: 11 additions & 1 deletion sdk/monitor/azure-monitor-query/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,17 +1,27 @@
# Release History

## 1.4.2 (Unreleased)
## 2.0.0 (Unreleased)

### Features Added

### Breaking Changes

- `MetricsClient` and `MetricsQueryClient` have been removed from the `azure-monitor-query` package. This is part of the migration to split logs and metrics functionality into separate packages. ([#42205](https://github.com/Azure/azure-sdk-for-python/pull/42205))
- The `MetricsClient` has been moved to the new `azure-monitor-querymetrics` package.
- Functionality provided by `MetricsQueryClient` can be access through the `azure-mgmt-monitor` package.
- For more details, see the [migration guide](https://aka.ms/azsdk/python/monitor/query/migration).

### Bugs Fixed

- Fixed an issue where the package version in operation user agent strings was always set to "unknown" instead of the actual package version. ([#39866](https://github.com/Azure/azure-sdk-for-python/pull/39866))

### Other Changes

- Bump minimum dependencies:
- `azure-core` to `>=1.30.0`
- `isodate` to `>=0.6.1`
- `typing-extensions` to `>=4.6.0`

## 1.4.1 (2025-01-14)

### Other Changes
Expand Down
6 changes: 3 additions & 3 deletions sdk/monitor/azure-monitor-query/MANIFEST.in
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
recursive-include tests *.py *.yaml
recursive-include samples *.py
include *.md
include LICENSE
include azure/monitor/query/py.typed
recursive-include tests *.py
recursive-include samples *.py *.md
include azure/__init__.py
include azure/monitor/__init__.py
include azure/monitor/query/py.typed
194 changes: 12 additions & 182 deletions sdk/monitor/azure-monitor-query/README.md

Large diffs are not rendered by default.

44 changes: 2 additions & 42 deletions sdk/monitor/azure-monitor-query/TROUBLESHOOTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,14 @@ This troubleshooting guide contains instructions to diagnose frequently encounte

* [General Troubleshooting](#general-troubleshooting)
* [Enable client logging](#enable-client-logging)
* [Troubleshooting authentication issues with logs and metrics query requests](#authentication-errors)
* [Troubleshooting authentication issues with query requests](#authentication-errors)
* [Troubleshooting running async APIs](#errors-with-running-async-apis)
* [Troubleshooting Logs Query](#troubleshooting-logs-query)
* [Troubleshooting insufficient access error](#troubleshooting-insufficient-access-error-for-logs-query)
* [Troubleshooting invalid Kusto query](#troubleshooting-invalid-kusto-query)
* [Troubleshooting empty log query results](#troubleshooting-empty-log-query-results)
* [Troubleshooting server timeouts when executing logs query request](#troubleshooting-server-timeouts-when-executing-logs-query-request)
* [Troubleshooting partially successful logs query requests](#troubleshooting-partially-successful-logs-query-requests)
* [Troubleshooting Metrics Query](#troubleshooting-metrics-query)
* [Troubleshooting insufficient access error](#troubleshooting-insufficient-access-error-for-metrics-query)
* [Troubleshooting unsupported granularity for metrics query](#troubleshooting-unsupported-granularity-for-metrics-query)
* [Additional azure-core configurations](#additional-azure-core-configurations)

## General Troubleshooting
Expand Down Expand Up @@ -53,11 +50,7 @@ client.query_workspace(logging_enable=True)

### Authentication errors

Azure Monitor Query supports Azure Active Directory authentication. Both LogsQueryClient and
MetricsQueryClient have methods to set the `credential`. To provide a valid credential, you can use
`azure-identity` dependency. For more details on getting started, refer to
the [README](https://github.com/Azure/azure-sdk-for-python/tree/main/sdk/monitor/azure-monitor-query#create-the-client)
of Azure Monitor Query library. You can also refer to
Azure Monitor Query supports Microsoft Entra ID authentication. LogsQueryClient has methods to set the `credential`. To provide a valid credential, you can use the `azure-identity` package. For more details on getting started, refer to the [README](https://github.com/Azure/azure-sdk-for-python/tree/main/sdk/monitor/azure-monitor-query#create-the-client) of the Azure Monitor Query library. You can also refer to
the [Azure Identity documentation](https://learn.microsoft.com/python/api/overview/azure/identity-readme)
for more details on the various types of credential supported in `azure-identity`.

Expand Down Expand Up @@ -174,39 +167,6 @@ data = response.partial_data
error = response.partial_error
```

## Troubleshooting Metrics Query

### Troubleshooting insufficient access error for metrics query

If you get an HTTP error with status code 403 (Forbidden), it means that the provided credentials does not have
sufficient permissions to query the workspace.
```text
"{"error":{"message":"The provided credentials have insufficient access to perform the requested operation","code":"InsufficientAccessError","correlationId":""}}"
```

1. Check that the application or user that is making the request has sufficient permissions:
* You can refer to this document to [manage access to workspaces](https://learn.microsoft.com/azure/azure-monitor/logs/manage-access#manage-access-using-workspace-permissions)
2. If the user or application is granted sufficient privileges to query the workspace, make sure you are
authenticating as that user/application. If you are authenticating using the
[DefaultAzureCredential](https://github.com/Azure/azure-sdk-for-python/tree/main/sdk/identity/azure-identity#defaultazurecredential)
then check the logs to verify that the credential used is the one you expected. To enable logging, see [enable
client logging](#enable-client-logging) section above.

For more help on troubleshooting authentication errors please see the Azure Identity client library [troubleshooting guide](https://github.com/Azure/azure-sdk-for-python/blob/main/sdk/identity/azure-identity/TROUBLESHOOTING.md).

### Troubleshooting unsupported granularity for metrics query

If you notice the following exception, this is due to an invalid time granularity in the metrics query request. Your
query might have set the `granularity` keyword argument to an unsupported duration.

```text
"{"code":"BadRequest","message":"Invalid time grain duration: PT10M, supported ones are: 00:01:00,00:05:00,00:15:00,00:30:00,01:00:00,06:00:00,12:00:00,1.00:00:00"}"
```

As documented in the error message, the supported granularity for metrics queries are 1 minute, 5 minutes, 15 minutes,
30 minutes, 1 hour, 6 hours, 12 hours and 1 day.


## Additional azure-core configurations

When calling the methods, some properties including `retry_mode`, `timeout`, `connection_verify` can be configured by passing in as keyword arguments. See
Expand Down
3 changes: 3 additions & 0 deletions sdk/monitor/azure-monitor-query/_metadata.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"apiVersion": "v1"
}
6 changes: 6 additions & 0 deletions sdk/monitor/azure-monitor-query/apiview-properties.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"CrossLanguagePackageId": "MonitorQueryLogs",
"CrossLanguageDefinitionId": {
"azure.monitor.query.models._ColumnType": "MonitorQueryLogs.ColumnDataType"
}
}
2 changes: 1 addition & 1 deletion sdk/monitor/azure-monitor-query/assets.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@
"AssetsRepo": "Azure/azure-sdk-assets",
"AssetsRepoPrefixPath": "python",
"TagPrefix": "python/monitor/azure-monitor-query",
"Tag": "python/monitor/azure-monitor-query_79499b2a8c"
"Tag": "python/monitor/azure-monitor-query_5e44a95839"
}
2 changes: 1 addition & 1 deletion sdk/monitor/azure-monitor-query/azure/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__path__ = __import__("pkgutil").extend_path(__path__, __name__)
__path__ = __import__("pkgutil").extend_path(__path__, __name__) # type: ignore
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__path__ = __import__("pkgutil").extend_path(__path__, __name__)
__path__ = __import__("pkgutil").extend_path(__path__, __name__) # type: ignore
66 changes: 18 additions & 48 deletions sdk/monitor/azure-monitor-query/azure/monitor/query/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,61 +2,31 @@
# --------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for license information.
# Code generated by Microsoft (R) Python Code Generator.
# Changes may cause incorrect behavior and will be lost if the code is regenerated.
# --------------------------------------------------------------------------
# pylint: disable=wrong-import-position

from ._logs_query_client import LogsQueryClient
from ._metrics_query_client import MetricsQueryClient
from ._metrics_client import MetricsClient
from typing import TYPE_CHECKING

from ._enums import (
LogsQueryStatus,
MetricAggregationType,
MetricClass,
MetricNamespaceClassification,
MetricUnit,
)
if TYPE_CHECKING:
from ._patch import * # pylint: disable=unused-wildcard-import

from ._exceptions import LogsQueryError
from ._client import MonitorQueryLogsClient # type: ignore
from ._version import VERSION

from ._models import (
LogsQueryResult,
LogsTable,
LogsQueryPartialResult,
LogsTableRow,
MetricsQueryResult,
LogsBatchQuery,
MetricNamespace,
MetricDefinition,
TimeSeriesElement,
Metric,
MetricValue,
MetricAvailability,
)
__version__ = VERSION

from ._version import VERSION
try:
from ._patch import __all__ as _patch_all
from ._patch import *
except ImportError:
_patch_all = []
from ._patch import patch_sdk as _patch_sdk

__all__ = [
"MetricAggregationType",
"LogsQueryClient",
"LogsQueryResult",
"LogsQueryPartialResult",
"LogsQueryStatus",
"LogsQueryError",
"LogsTable",
"LogsTableRow",
"LogsBatchQuery",
"MetricsQueryClient",
"MetricsClient",
"MetricNamespace",
"MetricNamespaceClassification",
"MetricDefinition",
"MetricUnit",
"MetricsQueryResult",
"TimeSeriesElement",
"Metric",
"MetricValue",
"MetricClass",
"MetricAvailability",
"MonitorQueryLogsClient",
]
__all__.extend([p for p in _patch_all if p not in __all__]) # pyright: ignore

__version__ = VERSION
_patch_sdk()
Original file line number Diff line number Diff line change
Expand Up @@ -2,42 +2,45 @@
# --------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for license information.
# Code generated by Microsoft (R) AutoRest Code Generator.
# Code generated by Microsoft (R) Python Code Generator.
# Changes may cause incorrect behavior and will be lost if the code is regenerated.
# --------------------------------------------------------------------------

from copy import deepcopy
from typing import Any
from typing import Any, TYPE_CHECKING
from typing_extensions import Self

from azure.core import PipelineClient
from azure.core.pipeline import policies
from azure.core.rest import HttpRequest, HttpResponse

from ._configuration import MonitorBatchMetricsClientConfiguration
from ._serialization import Deserializer, Serializer
from .operations import MetricsBatchOperations
from ._configuration import MonitorQueryLogsClientConfiguration
from ._operations._operations import _MonitorQueryLogsClientOperationsMixin
from ._utils.serialization import Deserializer, Serializer

if TYPE_CHECKING:
from azure.core.credentials import TokenCredential

class MonitorBatchMetricsClient:
"""Azure Monitor Batch Metrics Python Client.

:ivar metrics_batch: MetricsBatchOperations operations
:vartype metrics_batch: monitor_batch_metrics_client.operations.MetricsBatchOperations
:param endpoint: The regional endpoint to use, for example
https://eastus.metrics.monitor.azure.com. The region should match the region of the requested
resources. For global resources, the region should be 'global'. Required.
:type endpoint: str
:keyword api_version: Api Version. Default value is "2024-02-01". Note that overriding this
default value may result in unsupported behavior.
:paramtype api_version: str
class MonitorQueryLogsClient(_MonitorQueryLogsClientOperationsMixin):
"""MonitorQueryLogsClient.

:param credential: Credential used to authenticate requests to the service. Required.
:type credential: ~azure.core.credentials.TokenCredential
:keyword endpoint: The Log Analytics service endpoint. Default value is
"https://api.loganalytics.io".
:paramtype endpoint: str
:keyword api_version: The service API version. Known values are "v1" and None. Default value is
"v1". Note that overriding this default value may result in unsupported behavior.
:paramtype api_version: str or ~azure.monitor.query.models.Versions
"""

def __init__( # pylint: disable=missing-client-constructor-parameter-credential
self, endpoint: str, **kwargs: Any
def __init__(
self, credential: "TokenCredential", *, endpoint: str = "https://api.loganalytics.io", **kwargs: Any
) -> None:
_endpoint = "{endpoint}"
self._config = MonitorBatchMetricsClientConfiguration(endpoint=endpoint, **kwargs)
_endpoint = "{endpoint}/{apiVersion}"
self._config = MonitorQueryLogsClientConfiguration(credential=credential, endpoint=endpoint, **kwargs)

_policies = kwargs.pop("policies", None)
if _policies is None:
_policies = [
Expand All @@ -60,7 +63,6 @@ def __init__( # pylint: disable=missing-client-constructor-parameter-credential
self._serialize = Serializer()
self._deserialize = Deserializer()
self._serialize.client_side_validation = False
self.metrics_batch = MetricsBatchOperations(self._client, self._config, self._serialize, self._deserialize)

def send_request(self, request: HttpRequest, *, stream: bool = False, **kwargs: Any) -> HttpResponse:
"""Runs the network request through the client's chained policies.
Expand All @@ -83,6 +85,7 @@ def send_request(self, request: HttpRequest, *, stream: bool = False, **kwargs:
request_copy = deepcopy(request)
path_format_arguments = {
"endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, "str", skip_quote=True),
"apiVersion": self._serialize.url("self._config.api_version", self._config.api_version, "str"),
}

request_copy.url = self._client.format_url(request_copy.url, **path_format_arguments)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,40 +2,48 @@
# --------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for license information.
# Code generated by Microsoft (R) AutoRest Code Generator.
# Code generated by Microsoft (R) Python Code Generator.
# Changes may cause incorrect behavior and will be lost if the code is regenerated.
# --------------------------------------------------------------------------

from typing import Any
from typing import Any, TYPE_CHECKING

from azure.core.pipeline import policies

VERSION = "unknown"
from ._version import VERSION

if TYPE_CHECKING:
from azure.core.credentials import TokenCredential

class MonitorBatchMetricsClientConfiguration: # pylint: disable=too-many-instance-attributes
"""Configuration for MonitorBatchMetricsClient.

class MonitorQueryLogsClientConfiguration: # pylint: disable=too-many-instance-attributes
"""Configuration for MonitorQueryLogsClient.

Note that all parameters used to create this instance are saved as instance
attributes.

:param endpoint: The regional endpoint to use, for example
https://eastus.metrics.monitor.azure.com. The region should match the region of the requested
resources. For global resources, the region should be 'global'. Required.
:param credential: Credential used to authenticate requests to the service. Required.
:type credential: ~azure.core.credentials.TokenCredential
:param endpoint: The Log Analytics service endpoint. Default value is
"https://api.loganalytics.io".
:type endpoint: str
:keyword api_version: Api Version. Default value is "2024-02-01". Note that overriding this
default value may result in unsupported behavior.
:paramtype api_version: str
:keyword api_version: The service API version. Known values are "v1" and None. Default value is
"v1". Note that overriding this default value may result in unsupported behavior.
:paramtype api_version: str or ~azure.monitor.query.models.Versions
"""

def __init__(self, endpoint: str, **kwargs: Any) -> None:
api_version: str = kwargs.pop("api_version", "2024-02-01")
def __init__(
self, credential: "TokenCredential", endpoint: str = "https://api.loganalytics.io", **kwargs: Any
) -> None:
api_version: str = kwargs.pop("api_version", "v1")

if endpoint is None:
raise ValueError("Parameter 'endpoint' must not be None.")
if credential is None:
raise ValueError("Parameter 'credential' must not be None.")

self.credential = credential
self.endpoint = endpoint
self.api_version = api_version
self.credential_scopes = kwargs.pop("credential_scopes", ["https://api.loganalytics.io/.default"])
kwargs.setdefault("sdk_moniker", "monitor-query/{}".format(VERSION))
self.polling_interval = kwargs.get("polling_interval", 30)
self._configure(**kwargs)
Expand All @@ -50,3 +58,7 @@ def _configure(self, **kwargs: Any) -> None:
self.redirect_policy = kwargs.get("redirect_policy") or policies.RedirectPolicy(**kwargs)
self.retry_policy = kwargs.get("retry_policy") or policies.RetryPolicy(**kwargs)
self.authentication_policy = kwargs.get("authentication_policy")
if self.credential and not self.authentication_policy:
self.authentication_policy = policies.BearerTokenCredentialPolicy(
self.credential, *self.credential_scopes, **kwargs
)
Loading
Loading