Skip to content
Draft
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
9 changes: 9 additions & 0 deletions src/monitor-trace-association/HISTORY.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
.. :changelog:

Release History
===============

1.0.0b1
++++++
* Initial preview release. Adds ``az monitor trace-association`` commands for
``Microsoft.Monitor/traceAssociations`` (API version 2026-01-01-preview).
48 changes: 48 additions & 0 deletions src/monitor-trace-association/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# Azure CLI monitor-trace-association Extension #

This is an extension to Azure CLI to manage Azure Monitor **Trace Associations**
(`Microsoft.Monitor/traceAssociations`) resources.

A trace association is an ARM **extension resource** that maps a scope (an Application
Insights component, a resource group, or a subscription) to an Azure Monitor Workspace
for trace routing. Each scope has at most one direct association (singleton `default`);
multi-homing is achieved through inheritance from parent scopes.

> **Preview / DRAFT.** This extension targets API version `2026-01-01-preview`, whose
> spec currently lives in the private `azure-rest-api-specs-pr` repo
> (PR [#27737](https://github.com/Azure/azure-rest-api-specs-pr/pull/27737)). The command
> bodies here are a functional prototype that call ARM directly; they will be **replaced
> by aaz-dev-generated code** once the spec is published to the public
> `Azure/azure-rest-api-specs` repo. Do not merge until then.

## How to use ##
Install this extension using the below CLI command
```
az extension add --name monitor-trace-association
```

### Included Features
#### trace-association
##### Create / update
```
az monitor trace-association create \
--resource-uri "subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myRg/providers/Microsoft.Insights/components/myAppInsights" \
--azure-monitor-workspace-resource-id "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/obs-rg/providers/Microsoft.Monitor/accounts/app-amw"
```
##### Show
```
az monitor trace-association show \
--resource-uri "subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myRg/providers/Microsoft.Insights/components/myAppInsights"
```
##### List (by scope)
```
az monitor trace-association list \
--resource-uri "subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myRg/providers/Microsoft.Insights/components/myAppInsights"
```
##### Delete
```
az monitor trace-association delete \
--resource-uri "subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myRg/providers/Microsoft.Insights/components/myAppInsights"
```

The singleton name defaults to `default`; pass `--name/-n default` to be explicit.
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# --------------------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for license information.
# --------------------------------------------------------------------------------------------

from azure.cli.core import AzCommandsLoader
from azext_monitor_trace_association._help import helps # pylint: disable=unused-import


class MonitorTraceAssociationCommandsLoader(AzCommandsLoader):

def __init__(self, cli_ctx=None):
from azure.cli.core.commands import CliCommandType
custom_command_type = CliCommandType(
operations_tmpl='azext_monitor_trace_association.custom#{}')
super().__init__(cli_ctx=cli_ctx,
custom_command_type=custom_command_type)

def load_command_table(self, args):
from azext_monitor_trace_association.commands import load_command_table
load_command_table(self, args)
return self.command_table

def load_arguments(self, command):
from azext_monitor_trace_association._params import load_arguments
load_arguments(self, command)


COMMAND_LOADER_CLS = MonitorTraceAssociationCommandsLoader
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# --------------------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for license information.
# --------------------------------------------------------------------------------------------

# pylint: disable=line-too-long
# pylint: disable=too-many-lines

from knack.help_files import helps # pylint: disable=unused-import


helps['monitor trace-association'] = """
type: group
short-summary: Manage trace associations that route a scope's traces to an Azure Monitor Workspace.
long-summary: >
A trace association (Microsoft.Monitor/traceAssociations) is an ARM extension resource
mapping a scope (Application Insights component, resource group, or subscription) to an
Azure Monitor Workspace. Each scope has at most one direct association (singleton 'default').
"""

helps['monitor trace-association create'] = """
type: command
short-summary: Create or update the trace association for a scope.
examples:
- name: Route an Application Insights component's traces to an Azure Monitor Workspace.
text: |
az monitor trace-association create \\
--resource-uri "subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myRg/providers/Microsoft.Insights/components/myAppInsights" \\
--azure-monitor-workspace-resource-id "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/obs-rg/providers/Microsoft.Monitor/accounts/app-amw"
"""

helps['monitor trace-association update'] = """
type: command
short-summary: Update the trace association for a scope.
"""

helps['monitor trace-association show'] = """
type: command
short-summary: Show the trace association for a scope.
"""

helps['monitor trace-association delete'] = """
type: command
short-summary: Delete the trace association for a scope.
"""

helps['monitor trace-association list'] = """
type: command
short-summary: List trace associations for a scope.
"""
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# --------------------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for license information.
# --------------------------------------------------------------------------------------------

# pylint: disable=line-too-long


def load_arguments(self, _):
with self.argument_context('monitor trace-association') as c:
c.argument('resource_uri',
options_list=['--resource-uri', '--scope'],
help="The fully qualified Azure Resource Manager identifier of the resource "
"(scope) the trace association applies to, e.g. an Application Insights "
"component, a resource group, or a subscription.")
c.argument('name',
options_list=['--name', '-n'],
default='default',
help="The trace association singleton name. Only 'default' is valid.")

with self.argument_context('monitor trace-association create') as c:
c.argument('azure_monitor_workspace_resource_id',
options_list=['--azure-monitor-workspace-resource-id', '--amw-id'],
help="Resource ID of the target Azure Monitor Workspace "
"(Microsoft.Monitor/accounts). Must exist at creation time.")

with self.argument_context('monitor trace-association update') as c:
c.argument('azure_monitor_workspace_resource_id',
options_list=['--azure-monitor-workspace-resource-id', '--amw-id'],
help="Resource ID of the target Azure Monitor Workspace "
"(Microsoft.Monitor/accounts).")
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"azext.isPreview": true,
"azext.minCliCoreVersion": "2.61.0"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# --------------------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for license information.
# --------------------------------------------------------------------------------------------

from azure.cli.core.commands import CliCommandType


def load_command_table(self, _):
trace_association_custom = CliCommandType(
operations_tmpl='azext_monitor_trace_association.custom#{}')

with self.command_group('monitor trace-association',
custom_command_type=trace_association_custom,
is_preview=True) as g:
g.custom_command('create', 'create_trace_association')
g.custom_command('update', 'update_trace_association')
g.custom_show_command('show', 'show_trace_association')
g.custom_command('delete', 'delete_trace_association', confirmation=True)
g.custom_command('list', 'list_trace_association')
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# --------------------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for license information.
# --------------------------------------------------------------------------------------------

# NOTE (DRAFT): These command bodies call ARM directly via send_raw_request as a functional
# prototype for the 2026-01-01-preview API. They will be replaced by aaz-dev-generated code
# once the spec is published to the public Azure/azure-rest-api-specs repo.

import json

from knack.log import get_logger

from azure.cli.core.util import send_raw_request

logger = get_logger(__name__)

API_VERSION = '2026-01-01-preview'
RESOURCE_TYPE = 'Microsoft.Monitor/traceAssociations'


def _build_url(cli_ctx, resource_uri, name=None):
arm_endpoint = cli_ctx.cloud.endpoints.resource_manager.rstrip('/')
scope = resource_uri.strip('/')
url = '{}/{}/providers/{}'.format(arm_endpoint, scope, RESOURCE_TYPE)
if name:
url = '{}/{}'.format(url, name)
return '{}?api-version={}'.format(url, API_VERSION)


def create_trace_association(cmd, resource_uri, azure_monitor_workspace_resource_id, name='default'):
url = _build_url(cmd.cli_ctx, resource_uri, name)
body = json.dumps({
'properties': {
'azureMonitorWorkspaceResourceId': azure_monitor_workspace_resource_id
}
})
response = send_raw_request(cmd.cli_ctx, 'PUT', url,
headers=['Content-Type=application/json'], body=body)
return response.json()


def update_trace_association(cmd, resource_uri, azure_monitor_workspace_resource_id=None, name='default'):
url = _build_url(cmd.cli_ctx, resource_uri, name)
existing = send_raw_request(cmd.cli_ctx, 'GET', url).json()
properties = existing.get('properties') or {}
if azure_monitor_workspace_resource_id:
properties['azureMonitorWorkspaceResourceId'] = azure_monitor_workspace_resource_id
body = json.dumps({'properties': properties})
response = send_raw_request(cmd.cli_ctx, 'PUT', url,
headers=['Content-Type=application/json'], body=body)
return response.json()


def show_trace_association(cmd, resource_uri, name='default'):
url = _build_url(cmd.cli_ctx, resource_uri, name)
return send_raw_request(cmd.cli_ctx, 'GET', url).json()


def delete_trace_association(cmd, resource_uri, name='default'):
url = _build_url(cmd.cli_ctx, resource_uri, name)
send_raw_request(cmd.cli_ctx, 'DELETE', url)


def list_trace_association(cmd, resource_uri):
url = _build_url(cmd.cli_ctx, resource_uri)
data = send_raw_request(cmd.cli_ctx, 'GET', url).json()
return data.get('value', data)
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# --------------------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for license information.
# --------------------------------------------------------------------------------------------
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# --------------------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for license information.
# --------------------------------------------------------------------------------------------
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# --------------------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for license information.
# --------------------------------------------------------------------------------------------

from azure.cli.testsdk import ScenarioTest


class MonitorTraceAssociationScenario(ScenarioTest):

def test_monitor_trace_association(self):
# Placeholder preview test. An end-to-end scenario needs a scope resource (e.g. an
# Application Insights component) and an Azure Monitor Workspace; the recorded test is
# wired up once the public spec and a recordable test environment are available.
self.assertTrue(True)
1 change: 1 addition & 0 deletions src/monitor-trace-association/setup.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#setup.cfg
44 changes: 44 additions & 0 deletions src/monitor-trace-association/setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# --------------------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for license information.
# --------------------------------------------------------------------------------------------

from codecs import open
from setuptools import setup, find_packages

# HISTORY.rst entry.
VERSION = '1.0.0b1'

CLASSIFIERS = [
'Development Status :: 4 - Beta',
'Intended Audience :: Developers',
'Intended Audience :: System Administrators',
'Programming Language :: Python',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.9',
'Programming Language :: Python :: 3.10',
'Programming Language :: Python :: 3.11',
'License :: OSI Approved :: MIT License',
]

DEPENDENCIES = []

with open('README.md', 'r', encoding='utf-8') as f:
README = f.read()
with open('HISTORY.rst', 'r', encoding='utf-8') as f:
HISTORY = f.read()

setup(
name='monitor-trace-association',
version=VERSION,
description='Microsoft Azure Command-Line Tools MonitorTraceAssociation Extension.',
long_description=README + '\n\n' + HISTORY,
license='MIT',
author='Microsoft Corporation',
author_email='azpycli@microsoft.com',
url='https://github.com/Azure/azure-cli-extensions/tree/main/src/monitor-trace-association',
classifiers=CLASSIFIERS,
packages=find_packages(exclude=["tests"]),
package_data={'azext_monitor_trace_association': ['azext_metadata.json']},
install_requires=DEPENDENCIES
)
Loading