Skip to content
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

Add preview Log Analytics query extension #250

Merged
merged 23 commits into from
Jul 27, 2018
Merged
Show file tree
Hide file tree
Changes from 19 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
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.1-py2.py3-none-any.whl",
"sha256Digest": "98b88daa6eb978354bbcdc177fba48921186193da0b3f2906fb61845024f352b",
"downloadUrl": "https://files.pythonhosted.org/packages/87/ff/6aff19ead74388299b176b907ec2f0abbd39dbfedf46349ab37476b5f57b/log_analytics-0.1.1-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.1"
}
}
]
}
}
1 change: 1 addition & 0 deletions src/log-analytics/.pytest_cache/v/cache/lastfailed
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{}
Copy link
Contributor

Choose a reason for hiding this comment

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

remove this

3 changes: 3 additions & 0 deletions src/log-analytics/.pytest_cache/v/cache/nodeids
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[
"azext_loganalytics/tests/latest/test_loganalytics_commands.py::LogAnalyticsDataClientTests::test_query"
]
Copy link
Contributor

Choose a reason for hiding this comment

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

remove this

9 changes: 9 additions & 0 deletions src/log-analytics/HISTORY.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
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.
- kql: --kql -k
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('kql', 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, kql, 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=kql, 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 21:37:12 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.91272c6c-91e2-11e8-b1c7-4a76e6685f8c]
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 21:37:12 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.4f639d62-91d5-11e8-b1c7-4a76e6685f8c]
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 --kql "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 --kql "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