Skip to content

Commit

Permalink
App Insights control plane (#600)
Browse files Browse the repository at this point in the history
  • Loading branch information
alexeldeib authored and yugangw-msft committed Apr 16, 2019
1 parent 3b5ad3e commit 1148304
Show file tree
Hide file tree
Showing 11 changed files with 1,318 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -49,3 +49,7 @@ def cf_events(cli_ctx, _, subscription=None):

def cf_components(cli_ctx, _, subscription=None):
return applicationinsights_mgmt_plane_client(cli_ctx, _, subscription=subscription).components


def cf_api_key(cli_ctx, _, subscription=None):
return applicationinsights_mgmt_plane_client(cli_ctx, _, subscription=subscription).api_keys
146 changes: 146 additions & 0 deletions src/application-insights/azext_applicationinsights/_help.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,126 @@
provided, then --offset will be ignored.
"""

helps['monitor app-insights component'] = """
type: group
short-summary: Manage an Application Insights component or its subcomponents.
"""

helps['monitor app-insights component create'] = """
type: command
short-summary: Create a new Application Insights resource.
parameters:
- name: --application-type
type: string
short-summary: Type of application being monitored. Possible values include 'web', 'other'. Default value is'web' .
- name: --kind -k
type: string
short-summary: The kind of application that this component refers to, used to customize UI. This value is a freeform string, values should typically be one of web, ios, other, store, java, phone.
examples:
- name: Create a component with kind web and location.
text: |
az monitor app-insights component create --app demoApp --location westus2 --kind web -g demoRg --application-type web
"""

helps['monitor app-insights component update'] = """
type: command
short-summary: Update properties on an existing Application Insights resource. The primary value which can be updated is kind, which customizes the UI experience.
parameters:
- name: --kind -k
type: string
short-summary: The kind of application that this component refers to, used to customize UI. This value is a freeform string, values should typically be one of web, ios, other, store, java, phone.
examples:
- name: Update a component with kind web.
text: |
az monitor app-insights component update --app demoApp -k web -g demoRg
"""

helps['monitor app-insights component update-tags'] = """
type: command
short-summary: Update tags on an existing Application Insights resource.
examples:
- name: Update the tag 'name' to equal 'value'.
text: |
az monitor app-insights component update-tags --app demoApp --tags name=value -g demoRg
"""

helps['monitor app-insights component show'] = """
type: command
short-summary: Get an Application Insights resource.
examples:
- name: Get a component by name.
text: |
az monitor app-insights component show --app demoApp -g demoRg
- name: List components in a resource group.
text: |
az monitor app-insights component show -g demoRg
- name: List components in the currently selected subscription.
text: |
az monitor app-insights component show
"""

helps['monitor app-insights component delete'] = """
type: command
short-summary: Create a new Application Insights resource.
examples:
- name: Create a component with kind web and location.
text: |
az monitor app-insights component delete --app demoApp -g demoRg
"""

helps['monitor app-insights api-key'] = """
type: group
short-summary: Operations on API keys associated with an Application Insights component.
"""

helps['monitor app-insights api-key show'] = """
type: command
short-summary: Get all keys or a specific API key associated with an Application Insights resource.
parameters:
- name: --api-key
type: string
short-summary: name of the API key to fetch. Can be found using `api-keys show`.
examples:
- name: Fetch API Key.
text: |
az monitor app-insights api-key show --app demoApp -g demoRg --api-key demo-key
- name: Fetch API Keys.
text: |
az monitor app-insights api-key show --app demoApp -g demoRg
"""

helps['monitor app-insights api-key delete'] = """
type: command
short-summary: Delete an API key from an Application Insights resource.
parameters:
- name: --api-key
type: string
short-summary: Name of the API key to delete. Can be found using `api-keys show`.
examples:
- name: Delete API Key.
text: |
az monitor app-insights api-key delete --app demoApp -g demoRg --api-key demo-key
"""

helps['monitor app-insights api-key create'] = """
type: command
short-summary: Create a new API key for use with an Application Insights resource.
parameters:
- name: --api-key
type: string
short-summary: Name of the API key to create.
- name: --read-properties
type: list
short-summary: A space seperated list of names of read Roles for this API key to inherit. Possible values include ReadTelemetry and AuthenticateSDKControlChannel.
- name: --write-properties
type: list
short-summary: A space seperated list of names of write Roles for this API key to inherit. Possible values include WriteAnnotations.
examples:
- name: Create a component with kind web and location.
text: |
az monitor app-insights api-key create --api-key cli-demo --read-properties ReadTelemetry -g demoRg --app testApp
"""

helps['monitor app-insights metrics'] = """
type: group
short-summary: Retrieve metrics from an application.
Expand All @@ -34,6 +154,15 @@
helps['monitor app-insights query'] = """
type: command
short-summary: Execute a query over data in your application.
parameters:
- name: --offset
short-summary: >
Time offset of the query range, in ##d##h format.
long-summary: >
Can be used with either --start-time or --end-time. If used with --start-time, then
the end time will be calculated by adding the offset. If used with --end-time (default), then
the start time will be calculated by subtracting the offset. If --start-time and --end-time are
provided, then --offset will be ignored.
examples:
- name: Execute a simple query over past 3.5 days.
text: |
Expand All @@ -47,6 +176,14 @@
- name: --interval
short-summary: >
The interval over which to aggregate metrics, in ##h##m format.
- name: --offset
short-summary: >
Time offset of the query range, in ##d##h format.
long-summary: >
Can be used with either --start-time or --end-time. If used with --start-time, then
the end time will be calculated by adding the offset. If used with --end-time (default), then
the start time will be calculated by subtracting the offset. If --start-time and --end-time are
provided, then --offset will be ignored.
examples:
- name: View the count of availabilityResults events.
text: |
Expand All @@ -65,6 +202,15 @@
helps['monitor app-insights events show'] = """
type: command
short-summary: List events by type or view a single event from an application, specified by type and ID.
parameters:
- name: --offset
short-summary: >
Time offset of the query range, in ##d##h format.
long-summary: >
Can be used with either --start-time or --end-time. If used with --start-time, then
the end time will be calculated by adding the offset. If used with --end-time (default), then
the start time will be calculated by subtracting the offset. If --start-time and --end-time are
provided, then --offset will be ignored.
examples:
- name: Get an availability result by ID.
text: |
Expand Down
36 changes: 32 additions & 4 deletions src/application-insights/azext_applicationinsights/_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,36 @@
# --------------------------------------------------------------------------------------------

# pylint: disable=line-too-long
from azure.cli.core.commands.parameters import get_datetime_type
from azure.cli.core.commands.parameters import get_datetime_type, get_location_type, tags_type
from azure.cli.command_modules.monitor.actions import get_period_type
from ._validators import validate_applications


def load_arguments(self, _):
with self.argument_context('monitor app-insights') as c:
c.argument('application', options_list=['--app', '-a'], id_part='name', help='GUID, app name, or fully-qualified Azure resource name of Application Insights component. The application GUID may be acquired from the API Access menu item on any Application Insights resource in the Azure portal. If using an application name, please specify resource group.')
c.argument('start_time', arg_type=get_datetime_type(help='Start-time of time range for which to retrieve data.'))
c.argument('end_time', arg_type=get_datetime_type(help='End of time range for current operation. Defaults to the current time.'))
c.argument('offset', help='Filter results based on UTC hour offset.', type=get_period_type(as_timedelta=True))

with self.argument_context('monitor app-insights component create') as c:
c.argument('location', arg_type=get_location_type(self.cli_ctx))
c.argument('application-type', options_list=['application-type', '--type', '-t'], help="Type of application being monitored. Possible values include: 'web', 'other'. Default value: 'web' .")
c.argument('kind', options_list=['--kind', '-k'], help='The kind of application that this component refers to, used to customize UI. This value is a freeform string, values should typically be one of the following: web, ios, other, store, java, phone.')
c.argument('tags', tags_type)

with self.argument_context('monitor app-insights component update') as c:
c.argument('location', arg_type=get_location_type(self.cli_ctx))
c.argument('application-type', options_list=['application-type', '--type', '-t'], help="Type of application being monitored. Possible values include: 'web', 'other'. Default value: 'web' .")
c.argument('kind', options_list=['--kind', '-k'], help='The kind of application that this component refers to, used to customize UI. This value is a freeform string, values should typically be one of the following: web, ios, other, store, java, phone.')

with self.argument_context('monitor app-insights component update-tags') as c:
c.argument('tags', tags_type)

with self.argument_context('monitor app-insights api-key create') as c:
c.argument('api_key', help='The name of the API key to create.')
c.argument('read_properties', nargs='+', options_list=['--read-properties'])
c.argument('write_properties', nargs='+')

with self.argument_context('monitor app-insights api-key show') as c:
c.argument('api_key', help='The name of the API key to fetch.')

with self.argument_context('monitor app-insights metrics show') as c:
c.argument('metric', options_list=['--metrics', '-m'], help='The metric to retrieve. May be either a standard AI metric or an application-specific custom metric.')
Expand All @@ -24,11 +43,20 @@ def load_arguments(self, _):
c.argument('segment', help='The name of the dimension to segment the metric values by. This dimension must be applicable to the metric you are retrieving. To segment by more than one dimension at a time, separate them with a comma (,). In this case, the metric data will be segmented in the order the dimensions are listed in the parameter.')
c.argument('top', help='The number of segments to return. This value is only valid when segment is specified.')
c.argument('filter_arg', options_list=['--filter'], help=' An expression used to filter the results. This value should be a valid OData filter expression where the keys of each clause should be applicable dimensions for the metric you are retrieving.')
c.argument('start_time', arg_type=get_datetime_type(help='Start-time of time range for which to retrieve data.'))
c.argument('end_time', arg_type=get_datetime_type(help='End of time range for current operation. Defaults to the current time.'))
c.argument('offset', help='Filter results based on UTC hour offset.', type=get_period_type(as_timedelta=True))

with self.argument_context('monitor app-insights events show') as c:
c.argument('event_type', options_list=['--type'], help='The type of events to retrieve.')
c.argument('event', options_list=['--event'], help='GUID of the event to retrieve. This could be obtained by first listing and filtering events, then selecting an event of interest.')
c.argument('start_time', arg_type=get_datetime_type(help='Start-time of time range for which to retrieve data.'))
c.argument('end_time', arg_type=get_datetime_type(help='End of time range for current operation. Defaults to the current time.'))
c.argument('offset', help='Filter results based on UTC hour offset.', type=get_period_type(as_timedelta=True))

with self.argument_context('monitor app-insights query') as c:
c.argument('application', validator=validate_applications, options_list=['--apps', '-a'], nargs='+', id_part='name', help='GUID, app name, or fully-qualified Azure resource name of Application Insights component. The application GUID may be acquired from the API Access menu item on any Application Insights resource in the Azure portal. If using an application name, please specify resource group.')
c.argument('analytics_query', help='Query to execute over Application Insights data.')
c.argument('start_time', arg_type=get_datetime_type(help='Start-time of time range for which to retrieve data.'))
c.argument('end_time', arg_type=get_datetime_type(help='End of time range for current operation. Defaults to the current time.'))
c.argument('offset', help='Filter results based on UTC hour offset.', type=get_period_type(as_timedelta=True))
36 changes: 35 additions & 1 deletion src/application-insights/azext_applicationinsights/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@
from azext_applicationinsights._client_factory import (
cf_events,
cf_metrics,
cf_query
cf_query,
cf_components,
cf_api_key
)

from azure.cli.core.commands import CliCommandType
Expand All @@ -31,6 +33,38 @@ def load_command_table(self, _):
client_factory=cf_query
)

components_sdk = CliCommandType(
operations_tmpl='azext_applicationinsights.vendored_sdks.mgmt_applicationinsights.operations.components_operations#ComponentsOperations.{}',
client_factory=cf_components
)

components_custom_sdk = CliCommandType(
operations_tmpl='azext_applicationinsights.custom#{}',
client_factory=cf_components
)

api_key_sdk = CliCommandType(
operations_tmpl='azext_applicationinsights.vendored_sdks.mgmt_applicationinsights.operations.api_keys_operations#APIKeysOperations.{}',
client_factory=cf_api_key
)

api_key_custom_sdk = CliCommandType(
operations_tmpl='azext_applicationinsights.custom#{}',
client_factory=cf_api_key
)

with self.command_group('monitor app-insights component', command_type=components_sdk, custom_command_type=components_custom_sdk) as g:
g.custom_command('create', 'create_or_update_component')
g.custom_command('update', 'update_component')
g.custom_command('show', 'show_components')
g.custom_command('delete', 'delete_component')
g.custom_command('update-tags', 'update_component_tags')

with self.command_group('monitor app-insights api-key', command_type=api_key_sdk, custom_command_type=api_key_custom_sdk) as g:
g.custom_command('create', 'create_api_key')
g.custom_command('show', 'show_api_key')
g.custom_command('delete', 'delete_api_key')

with self.command_group('monitor app-insights metrics', metrics_sdk) as g:
g.custom_command('show', 'get_metric')
g.custom_command('get-metadata', 'get_metrics_metadata')
Expand Down
67 changes: 66 additions & 1 deletion src/application-insights/azext_applicationinsights/custom.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@

# pylint: disable=line-too-long

from knack.util import CLIError
from knack.log import get_logger
from .util import get_id_from_azure_resource, get_query_targets, get_timespan
from .util import get_id_from_azure_resource, get_query_targets, get_timespan, get_linked_properties

logger = get_logger(__name__)

Expand All @@ -31,3 +32,67 @@ def get_metric(cmd, client, application, metric, start_time=None, end_time=None,

def get_metrics_metadata(cmd, client, application, resource_group_name=None):
return client.metrics.get_metadata(get_id_from_azure_resource(cmd.cli_ctx, application, resource_group=resource_group_name))


def create_or_update_component(client, application, resource_group_name, location, tags=None, kind="web", application_type='web'):
from .vendored_sdks.mgmt_applicationinsights.models import ApplicationInsightsComponent
component = ApplicationInsightsComponent(location, kind, application_type=application_type, tags=tags)
return client.create_or_update(resource_group_name, application, component)


def update_component(client, application, resource_group_name, kind=None):
existing_component = client.get(resource_group_name, application)
if kind:
existing_component.kind = kind
return client.create_or_update(resource_group_name, application, existing_component)


def update_component_tags(client, application, resource_group_name, tags):
return client.update_tags(resource_group_name, application, tags)


def get_component(client, application, resource_group_name):
return client.get(resource_group_name, application)


def show_components(client, application=None, resource_group_name=None):
if application:
if resource_group_name:
return client.get(resource_group_name, application)
raise CLIError("Application provided without resource group. Either specify app with resource group, or remove app.")
if resource_group_name:
return client.list_by_resource_group(resource_group_name)
return client.list()


def delete_component(client, application, resource_group_name):
return client.delete(resource_group_name, application)


def create_api_key(cmd, client, application, resource_group_name, api_key, read_properties=None, write_properties=None):
from .vendored_sdks.mgmt_applicationinsights.models import APIKeyRequest
if read_properties is None:
read_properties = ['ReadTelemetry', 'AuthenticateSDKControlChannel']
if write_properties is None:
write_properties = ['WriteAnnotations']
linked_read_properties, linked_write_properties = get_linked_properties(cmd.cli_ctx, application, resource_group_name, read_properties, write_properties)
api_key_request = APIKeyRequest(api_key, linked_read_properties, linked_write_properties)
return client.create(resource_group_name, application, api_key_request)


def show_api_key(client, application, resource_group_name, api_key=None):
if api_key is None:
return client.list(resource_group_name, application)
result = list(filter(lambda result: result.name == api_key, client.list(resource_group_name, application)))
if len(result) == 1:
return result[0]
elif len(result) > 1:
return result
return None


def delete_api_key(client, application, resource_group_name, api_key):
existing_key = list(filter(lambda result: result.name == api_key, client.list(resource_group_name, application)))
if existing_key != []:
return client.delete(resource_group_name, application, existing_key[0].id.split('/')[-1])
raise CLIError('--api-key provided but key not found for deletion.')
Loading

0 comments on commit 1148304

Please sign in to comment.