Skip to content

Commit

Permalink
Add preview Log Analytics query extension (#250)
Browse files Browse the repository at this point in the history
* Initial extension commit

* Add initial readme, history

* vendor sdk, change imports, update text, and update index

* Fix CI, update version from regen with wheel==0.30.0

* add codeowner

* fix versions, ci, wheel issues

* rename loganalytics -> log-analytics

* switch command -> custom command

* unused imports

* fix after python environment mess

* naming

* fix homepage and bump minor version

* fix src tests

* loganalytics -> log-analytics

* rename directory

* params

* accidental deletion

* codeowners

* fix CI test namespacing issue(?)

* Delete lastfailed

* Delete nodeids

* update parameter name

* change --kql to --analytics-query, bump version/index/history
  • Loading branch information
alexeldeib authored and williexu committed Jul 27, 2018
1 parent 0ef3e90 commit 89518d0
Show file tree
Hide file tree
Showing 36 changed files with 1,155 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .github/CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,6 @@

/src/express-route-cross-connection/ @tjprescott

/src/log-analytics/ @alexeldeib

/src/mesh/ @linggengmsft
33 changes: 33 additions & 0 deletions src/index.json
Original file line number Diff line number Diff line change
Expand Up @@ -951,6 +951,39 @@
"version": "0.9.1"
}
}
],
"log-analytics": [
{
"filename": "log_analytics-0.1.2-py2.py3-none-any.whl",
"sha256Digest": "b958800232b5340871999f1e90aa3b198e1be645d5d7553e2f023759912f87a8",
"downloadUrl": "https://files.pythonhosted.org/packages/0c/06/78ddfe634d2af7b35a4931b7a17aea9f026c202316b18f861f462857a2fc/log_analytics-0.1.2-py2.py3-none-any.whl",
"metadata": {
"azext.isPreview": true,
"extensions": {
"python.details": {
"contacts": [
{
"email": "aleldeib@microsoft.com",
"name": "Ace Eldeib",
"role": "author"
}
],
"document_names": {
"description": "DESCRIPTION.rst"
},
"project_urls": {
"Home": "https://github.com/Azure/azure-cli-extensions/tree/master/src/log-analytics"
}
}
},
"generator": "bdist_wheel (0.30.0)",
"license": "MIT",
"metadata_version": "2.0",
"name": "log-analytics",
"summary": "Support for Azure Log Analytics query capabilities.",
"version": "0.1.2"
}
}
]
}
}
14 changes: 14 additions & 0 deletions src/log-analytics/HISTORY.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
0.1.2
++++++++++++++++++

* Change --kql to --analytics-query

0.1.1
++++++++++++++++++

* Fix homepage

0.1.0
++++++++++++++++++

* Initial release.
2 changes: 2 additions & 0 deletions src/log-analytics/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Commands for working with Azure Log Analytics
==============================================
36 changes: 36 additions & 0 deletions src/log-analytics/azext_loganalytics/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# --------------------------------------------------------------------------------------------
# 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_loganalytics._help import helps # pylint: disable=unused-import


class LogAnalyticsCommandsLoader(AzCommandsLoader):

def __init__(self, cli_ctx=None):
from azure.cli.core.commands import CliCommandType
from azext_loganalytics._client_factory import loganalytics_data_plane_client
loganalytics_custom = CliCommandType(
operations_tmpl='azext_loganalytics.custom#{}',
client_factory=loganalytics_data_plane_client
)

super(LogAnalyticsCommandsLoader, self).__init__(
cli_ctx=cli_ctx,
custom_command_type=loganalytics_custom
)

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

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


COMMAND_LOADER_CLS = LogAnalyticsCommandsLoader
14 changes: 14 additions & 0 deletions src/log-analytics/azext_loganalytics/_client_factory.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# --------------------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for license information.
# --------------------------------------------------------------------------------------------


def loganalytics_data_plane_client(cli_ctx, _):
"""Initialize Log Analytics data client for use with CLI."""
from .vendored_sdks.loganalytics import LogAnalyticsDataClient
from azure.cli.core._profile import Profile
profile = Profile(cli_ctx=cli_ctx)
cred, _, _ = profile.get_login_credentials(
resource="https://api.loganalytics.io")
return LogAnalyticsDataClient(cred)
28 changes: 28 additions & 0 deletions src/log-analytics/azext_loganalytics/_help.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# --------------------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for license information.
# --------------------------------------------------------------------------------------------

from knack.help_files import helps

# pylint: disable=line-too-long

helps['monitor log-analytics query'] = """
type: command
short-summary: Query a Log Analytics workspace.
parameters:
- workspace: --workspace -w
type: string
short-summary: GUID of the Log Analytics workspace.
- analytics-query: --analytics-query
type: string
short-summary: Query to execute over the Log Analytics data.
- timespan: --timespan -t
type: string
short-summary: Timespan over which to query data. Defaults to all data.
- workspaces: --workspaces
type: array
short-summary: Additional workspaces to union data for querying. Specify additional workspace IDs separated by commas.
examples:
- name:
"""
14 changes: 14 additions & 0 deletions src/log-analytics/azext_loganalytics/_params.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# --------------------------------------------------------------------------------------------
# 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 log-analytics query') as c:
c.argument('workspace', options_list=['--workspace', '-w'], help='GUID of the Log Analytics Workspace')
c.argument('analytics-query', help='Query to execute over Log Analytics data.')
c.argument('timespan', options_list=['--timespan', '-t'], help='Timespan over which to query. Defaults to querying all available data.')
c.argument('workspaces', nargs='+', help='Optional additional workspaces over which to join data for the query.')
3 changes: 3 additions & 0 deletions src/log-analytics/azext_loganalytics/azext_metadata.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"azext.isPreview": true
}
12 changes: 12 additions & 0 deletions src/log-analytics/azext_loganalytics/commands.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# --------------------------------------------------------------------------------------------
# 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_command_table(self, _):

with self.command_group('monitor log-analytics') as g:
g.custom_command('query', 'execute_query')
14 changes: 14 additions & 0 deletions src/log-analytics/azext_loganalytics/custom.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# --------------------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for license information.
# --------------------------------------------------------------------------------------------

from knack.log import get_logger

logger = get_logger(__name__)


def execute_query(client, workspace, analytics_query, timespan=None, workspaces=None):
"""Executes a query against the provided Log Analytics workspace."""
from .vendored_sdks.loganalytics.models import QueryBody
return client.query(workspace, QueryBody(query=analytics_query, timespan=timespan, workspaces=workspaces))
4 changes: 4 additions & 0 deletions src/log-analytics/azext_loganalytics/tests/__init__.py
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.
# --------------------------------------------------------------------------------------------
4 changes: 4 additions & 0 deletions src/log-analytics/azext_loganalytics/tests/latest/__init__.py
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,63 @@
interactions:
- request:
body: '{"query": "Heartbeat | getschema"}'
headers:
Accept: [application/json]
Accept-Encoding: ['gzip, deflate']
Connection: [keep-alive]
Content-Length: ['34']
Content-Type: [application/json; charset=utf-8]
User-Agent: [python/3.6.6 (Windows-10-10.0.17134-SP0) requests/2.19.1 msrest/0.5.4
azure-loganalytics/0.1.0]
method: POST
uri: https://api.loganalytics.io/v1/workspaces/cab864ad-d0c1-496b-bc5e-4418315621bf/query
response:
body: {string: '{"tables":[{"name":"getschema","columns":[{"name":"ColumnName","type":"string"},{"name":"ColumnOrdinal","type":"int"},{"name":"DataType","type":"string"},{"name":"ColumnType","type":"string"}],"rows":[["TenantId",0,"System.String","string"],["SourceSystem",1,"System.String","string"],["TimeGenerated",2,"System.DateTime","datetime"],["MG",3,"System.String","string"],["ManagementGroupName",4,"System.String","string"],["SourceComputerId",5,"System.String","string"],["ComputerIP",6,"System.String","string"],["Computer",7,"System.String","string"],["Category",8,"System.String","string"],["OSType",9,"System.String","string"],["OSName",10,"System.String","string"],["OSMajorVersion",11,"System.String","string"],["OSMinorVersion",12,"System.String","string"],["Version",13,"System.String","string"],["SCAgentChannel",14,"System.String","string"],["IsGatewayInstalled",15,"System.SByte","bool"],["RemoteIPLongitude",16,"System.Double","real"],["RemoteIPLatitude",17,"System.Double","real"],["RemoteIPCountry",18,"System.String","string"],["SubscriptionId",19,"System.String","string"],["ResourceGroup",20,"System.String","string"],["ResourceProvider",21,"System.String","string"],["Resource",22,"System.String","string"],["ResourceId",23,"System.String","string"],["ResourceType",24,"System.String","string"],["ComputerEnvironment",25,"System.String","string"],["Solutions",26,"System.String","string"],["VMUUID",27,"System.String","string"],["Type",28,"System.String","string"]]}]}'}
headers:
access-control-allow-origin: ['*']
access-control-expose-headers: ['Retry-After,Age,WWW-Authenticate,x-resource-identities,x-ms-status-location']
connection: [keep-alive]
content-length: ['1482']
content-location: ['https://eastus.api.loganalytics.io/v1/workspaces/cab864ad-d0c1-496b-bc5e-4418315621bf/query']
content-type: [application/json; charset=utf-8]
date: ['Fri, 27 Jul 2018 23:07:57 GMT']
server: [nginx]
strict-transport-security: [max-age=31536000000; includeSubDomains, max-age=31536000;
includeSubDomains]
transfer-encoding: [chunked]
vary: [Accept-Encoding]
via: [1.1 draft-oms-blue.aa4dbcee-9107-11e8-9ab8-70b3d5800008]
x-content-type-options: [nosniff]
status: {code: 200, message: OK}
- request:
body: '{"query": "Heartbeat | getschema"}'
headers:
Accept: [application/json]
Accept-Encoding: ['gzip, deflate']
Connection: [keep-alive]
Content-Length: ['34']
Content-Type: [application/json; charset=utf-8]
User-Agent: [python/3.6.6 (Windows-10-10.0.17134-SP0) requests/2.19.1 msrest/0.5.4
azure-loganalytics/0.1.0]
method: POST
uri: https://api.loganalytics.io/v1/workspaces/cab864ad-d0c1-496b-bc5e-4418315621bf/query
response:
body: {string: '{"tables":[{"name":"getschema","columns":[{"name":"ColumnName","type":"string"},{"name":"ColumnOrdinal","type":"int"},{"name":"DataType","type":"string"},{"name":"ColumnType","type":"string"}],"rows":[["TenantId",0,"System.String","string"],["SourceSystem",1,"System.String","string"],["TimeGenerated",2,"System.DateTime","datetime"],["MG",3,"System.String","string"],["ManagementGroupName",4,"System.String","string"],["SourceComputerId",5,"System.String","string"],["ComputerIP",6,"System.String","string"],["Computer",7,"System.String","string"],["Category",8,"System.String","string"],["OSType",9,"System.String","string"],["OSName",10,"System.String","string"],["OSMajorVersion",11,"System.String","string"],["OSMinorVersion",12,"System.String","string"],["Version",13,"System.String","string"],["SCAgentChannel",14,"System.String","string"],["IsGatewayInstalled",15,"System.SByte","bool"],["RemoteIPLongitude",16,"System.Double","real"],["RemoteIPLatitude",17,"System.Double","real"],["RemoteIPCountry",18,"System.String","string"],["SubscriptionId",19,"System.String","string"],["ResourceGroup",20,"System.String","string"],["ResourceProvider",21,"System.String","string"],["Resource",22,"System.String","string"],["ResourceId",23,"System.String","string"],["ResourceType",24,"System.String","string"],["ComputerEnvironment",25,"System.String","string"],["Solutions",26,"System.String","string"],["VMUUID",27,"System.String","string"],["Type",28,"System.String","string"]]}]}'}
headers:
access-control-allow-origin: ['*']
access-control-expose-headers: ['Retry-After,Age,WWW-Authenticate,x-resource-identities,x-ms-status-location']
age: ['0']
connection: [keep-alive]
content-length: ['1482']
content-location: ['https://eastus.api.loganalytics.io/v1/workspaces/cab864ad-d0c1-496b-bc5e-4418315621bf/query']
content-type: [application/json; charset=utf-8]
date: ['Fri, 27 Jul 2018 23:07:58 GMT']
server: [nginx]
strict-transport-security: [max-age=31536000000; includeSubDomains, max-age=31536000;
includeSubDomains]
transfer-encoding: [chunked]
vary: [Accept-Encoding]
via: [1.1 draft-oms-blue.cbd591df-9107-11e8-9ab8-70b3d5800008]
x-content-type-options: [nosniff]
status: {code: 200, message: OK}
version: 1
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# --------------------------------------------------------------------------------------------
# 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
from azure.cli.testsdk import ScenarioTest


class LogAnalyticsDataClientTests(ScenarioTest):
"""Test class for Log Analytics data client."""
def test_query(self):
"""Tests data plane query capabilities for Log Analytics."""
self.cmd('az monitor log-analytics query --workspace cab864ad-d0c1-496b-bc5e-4418315621bf --analytics-query "Heartbeat | getschema"', checks=[
self.check('tables[0].rows[0][0]', 'TenantId')
])
query_result = self.cmd('az monitor log-analytics query -w cab864ad-d0c1-496b-bc5e-4418315621bf --analytics-query "Heartbeat | getschema"').get_output_in_json()
assert len(query_result['tables'][0]['rows']) == 29
assert isinstance(query_result['tables'][0]['rows'][0][1], (int, float, complex))
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# --------------------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for license information.
# --------------------------------------------------------------------------------------------

__import__('pkg_resources').declare_namespace(__name__)
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# coding=utf-8
# --------------------------------------------------------------------------
# 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.
# Changes may cause incorrect behavior and will be lost if the code is
# regenerated.
# --------------------------------------------------------------------------

from .log_analytics_data_client import LogAnalyticsDataClient
from .version import VERSION

__all__ = ['LogAnalyticsDataClient']

__version__ = VERSION

Loading

0 comments on commit 89518d0

Please sign in to comment.