From ab33d3baa0d7a96ec6a6750c9a5b749f3e609308 Mon Sep 17 00:00:00 2001 From: Michael Date: Mon, 3 Feb 2025 13:45:14 +0200 Subject: [PATCH 1/5] added functions for kqldashboard apis --- src/sempy_labs/_kql_dashboards.py | 199 ++++++++++++++++++++++++++++++ 1 file changed, 199 insertions(+) create mode 100644 src/sempy_labs/_kql_dashboards.py diff --git a/src/sempy_labs/_kql_dashboards.py b/src/sempy_labs/_kql_dashboards.py new file mode 100644 index 00000000..dd9244cb --- /dev/null +++ b/src/sempy_labs/_kql_dashboards.py @@ -0,0 +1,199 @@ +import sempy.fabric as fabric +import pandas as pd +import sempy_labs._icons as icons +from typing import Optional +from sempy_labs._helper_functions import ( + resolve_workspace_name_and_id, + _base_api, + _create_dataframe, +) +from uuid import UUID +import requests +import json + + +def list_kql_dashboards(workspace: Optional[str | UUID] = None) -> pd.DataFrame: + """ + Shows the KQL dashboards within a workspace. + + This is a wrapper function for the following API: `Items - List KQL Dashboards `_. + + Parameters + ---------- + workspace : str | uuid.UUID, default=None + The Fabric workspace name or ID. + Defaults to None which resolves to the workspace of the attached lakehouse + or if no lakehouse attached, resolves to the workspace of the notebook. + + Returns + ------- + pandas.DataFrame + A pandas dataframe showing the KQL dashboards within a workspace. + """ + + columns = { + "KQL Dashboard Name": "string", + "KQL Dashboard Id": "string", + "Description": "string", + } + df = _create_dataframe(columns=columns) + + (workspace_name, workspace_id) = resolve_workspace_name_and_id(workspace) + + responses = _base_api( + request=f"v1/workspaces/{workspace_id}/kqlDashboards", uses_pagination=True + ) + + for r in responses: + for v in r.get("value", []): + new_data = { + "KQL Dashboard Name": v.get("displayName"), + "KQL Dashboard Id": v.get("id"), + "Description": v.get("description"), + } + df = pd.concat([df, pd.DataFrame(new_data, index=[0])], ignore_index=True) + + return df + + +def create_kql_dashboard( + name: str, + content: Optional[str] = None, + description: Optional[str] = None, + workspace: Optional[str | UUID] = None, +): + """ + Creates a KQL dashboard. + + This is a wrapper function for the following API: `Items - Create KQL Dashboard `_. + + Parameters + ---------- + name: str + Name of the KQL dashboard. + content: Optional[dict], default=None + The RealTimeDashboard.json content. + description : str, default=None + A description of the environment. + workspace : str | uuid.UUID, default=None + The Fabric workspace name or ID. + Defaults to None which resolves to the workspace of the attached lakehouse + or if no lakehouse attached, resolves to the workspace of the notebook. + """ + + (workspace_name, workspace_id) = resolve_workspace_name_and_id(workspace) + + payload = {"displayName": name} + + if description: + payload["description"] = description + + if content: + # platform_payload = '' + payload["definition"] = { + "format": None, + "parts": [ + { + "path": "RealTimeDashboard.json", + "payload": content, + "payloadType": "InlineBase64", + }, + # { + # "path": ".platform", + # "payload": platform_payload, + # "payloadType": "InlineBase64" + # } + ], + } + + _base_api( + request=f"v1/workspaces/{workspace_id}/kqlDashboards", + method="post", + payload=payload, + status_codes=201, + ) + + print( + f"{icons.green_dot} The '{name}' KQL dashboard has been created within the '{workspace_name}' workspace." + ) + + +def create_workspace_montiring_dashboard( + name: str = "Fabric Workspace Monitoring Dashboard", + workspace: Optional[str | UUID] = None, +): + """ + Creates a workspace monitoring dashboard. + + This is a wrapper function for the following API: `Items - Create Workspace Monitoring Dashboard `_. + + Parameters + ---------- + name : str, default="Fabric Workspace Monitoring Dashboard" + The name of the workspace monitoring dashboard. + workspace : str | uuid.UUID, default=None + The Fabric workspace name or ID. + Defaults to None which resolves to the workspace of the attached lakehouse + or if no lakehouse attached, resolves to the workspace of the notebook. + """ + from sempy_labs._kql_databases import list_kql_databases + + (workspace_name, workspace_id) = resolve_workspace_name_and_id(workspace) + db_name = "Monitoring KQL database" + + url = "https://raw.githubusercontent.com/microsoft/fabric-toolbox/refs/heads/main/monitoring/workspace-monitoring-dashboards/Fabric%20Workspace%20Monitoring%20Dashboard.json" + response = requests.get(url) + content = json.loads(response.content) + + # Resolve the cluster URI and database ID + dfK = list_kql_databases(workspace=workspace) + dfK_filt = dfK[dfK["KQL Database Name"] == db_name] + if dfK_filt.empty: + raise ValueError( + f"{icons.red_dot} Workspace monitoring is not set up for the '{workspace_name}' workspace." + ) + cluster_uri = dfK_filt["Query Service URI"].iloc[0] + database_id = dfK_filt["KQL Database Id"].iloc[0] + + content["dataSources"] = [ + { + "kind": "kusto-trident", + "scopeId": "kusto-trident", + "clusterUri": cluster_uri, + "database": database_id, + "name": db_name, + "id": "b7d7ce56-c612-4d4f-ab1a-1a6f6212efd0", + "workspace": workspace_id, + } + ] + + create_kql_dashboard(name=name, content=content, workspace=workspace) + + +def delete_kql_dashboard( + kql_dashboard: str | UUID, workspace: Optional[str | UUID] = None +): + """ + Deletes a KQL database. + + This is a wrapper function for the following API: `Items - Delete KQL Dashboard `_. + + Parameters + ---------- + kql_dashboard: str | uuid.UUID + Name or ID of the KQL dashboard. + workspace : str | uuid.UUID, default=None + The Fabric workspace name or ID. + Defaults to None which resolves to the workspace of the attached lakehouse + or if no lakehouse attached, resolves to the workspace of the notebook. + """ + + (workspace_name, workspace_id) = resolve_workspace_name_and_id(workspace) + item_id = fabric.resolve_item_id( + item_name=kql_dashboard, type="KQLDashboard", workspace=workspace_id + ) + + fabric.delete_item(item_id=item_id, workspace=workspace) + print( + f"{icons.green_dot} The '{kql_dashboard}' KQL database within the '{workspace_name}' workspace has been deleted." + ) From 5f3225fe93e660b4546a77339ea0033b08601ccc Mon Sep 17 00:00:00 2001 From: Michael Date: Mon, 3 Feb 2025 13:58:58 +0200 Subject: [PATCH 2/5] updated help --- src/sempy_labs/_kql_dashboards.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sempy_labs/_kql_dashboards.py b/src/sempy_labs/_kql_dashboards.py index dd9244cb..f3258815 100644 --- a/src/sempy_labs/_kql_dashboards.py +++ b/src/sempy_labs/_kql_dashboards.py @@ -123,9 +123,9 @@ def create_workspace_montiring_dashboard( workspace: Optional[str | UUID] = None, ): """ - Creates a workspace monitoring dashboard. + Creates a workspace monitoring dashboard based on `this `_ template. - This is a wrapper function for the following API: `Items - Create Workspace Monitoring Dashboard `_. + This function requires the workspace to have workspace monitoring enabled. Parameters ---------- From 2575f031c38a06f775a4edcc1682e6b3601a36e1 Mon Sep 17 00:00:00 2001 From: Michael Date: Mon, 3 Feb 2025 15:45:19 +0200 Subject: [PATCH 3/5] conv to b64 --- src/sempy_labs/_kql_dashboards.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/sempy_labs/_kql_dashboards.py b/src/sempy_labs/_kql_dashboards.py index f3258815..e71f7924 100644 --- a/src/sempy_labs/_kql_dashboards.py +++ b/src/sempy_labs/_kql_dashboards.py @@ -6,6 +6,7 @@ resolve_workspace_name_and_id, _base_api, _create_dataframe, + _conv_b64, ) from uuid import UUID import requests @@ -106,6 +107,8 @@ def create_kql_dashboard( ], } + payload = _conv_b64(payload) + _base_api( request=f"v1/workspaces/{workspace_id}/kqlDashboards", method="post", From 9fdd41ce3baa88f95277b638e49c5c84c3c72512 Mon Sep 17 00:00:00 2001 From: Michael Date: Tue, 4 Feb 2025 09:47:28 +0200 Subject: [PATCH 4/5] fixed kql dash functions --- src/sempy_labs/__init__.py | 10 ++++++++++ src/sempy_labs/_kql_dashboards.py | 13 +++---------- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/src/sempy_labs/__init__.py b/src/sempy_labs/__init__.py index c1144d5f..fdf78dac 100644 --- a/src/sempy_labs/__init__.py +++ b/src/sempy_labs/__init__.py @@ -1,3 +1,9 @@ +from sempy_labs._kql_dashboards import ( + list_kql_dashboards, + create_kql_dashboard, + delete_kql_dashboard, + create_workspace_montiring_dashboard, +) from sempy_labs._graphQL import ( list_graphql_apis, create_graphql_api, @@ -511,4 +517,8 @@ "delta_analyzer", # "dax_perf_test", # "dax_perf_test_bulk", + "list_kql_dashboards", + "create_kql_dashboard", + "delete_kql_dashboard", + "create_workspace_montiring_dashboard", ] diff --git a/src/sempy_labs/_kql_dashboards.py b/src/sempy_labs/_kql_dashboards.py index e71f7924..e264a998 100644 --- a/src/sempy_labs/_kql_dashboards.py +++ b/src/sempy_labs/_kql_dashboards.py @@ -7,6 +7,7 @@ _base_api, _create_dataframe, _conv_b64, + generate_guid, ) from uuid import UUID import requests @@ -90,25 +91,17 @@ def create_kql_dashboard( payload["description"] = description if content: - # platform_payload = '' payload["definition"] = { "format": None, "parts": [ { "path": "RealTimeDashboard.json", - "payload": content, + "payload": _conv_b64(content), "payloadType": "InlineBase64", }, - # { - # "path": ".platform", - # "payload": platform_payload, - # "payloadType": "InlineBase64" - # } ], } - payload = _conv_b64(payload) - _base_api( request=f"v1/workspaces/{workspace_id}/kqlDashboards", method="post", @@ -165,7 +158,7 @@ def create_workspace_montiring_dashboard( "clusterUri": cluster_uri, "database": database_id, "name": db_name, - "id": "b7d7ce56-c612-4d4f-ab1a-1a6f6212efd0", + "id": generate_guid(), "workspace": workspace_id, } ] From 4210f7ead13b2e6afeec9679bcc94e39ae9952cd Mon Sep 17 00:00:00 2001 From: Michael Date: Tue, 4 Feb 2025 10:47:30 +0200 Subject: [PATCH 5/5] update naming --- src/sempy_labs/__init__.py | 4 ++-- src/sempy_labs/_kql_dashboards.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/sempy_labs/__init__.py b/src/sempy_labs/__init__.py index fdf78dac..d12a94d3 100644 --- a/src/sempy_labs/__init__.py +++ b/src/sempy_labs/__init__.py @@ -2,7 +2,7 @@ list_kql_dashboards, create_kql_dashboard, delete_kql_dashboard, - create_workspace_montiring_dashboard, + create_workspace_monitoring_dashboard, ) from sempy_labs._graphQL import ( list_graphql_apis, @@ -520,5 +520,5 @@ "list_kql_dashboards", "create_kql_dashboard", "delete_kql_dashboard", - "create_workspace_montiring_dashboard", + "create_workspace_monitoring_dashboard", ] diff --git a/src/sempy_labs/_kql_dashboards.py b/src/sempy_labs/_kql_dashboards.py index e264a998..2c8f7106 100644 --- a/src/sempy_labs/_kql_dashboards.py +++ b/src/sempy_labs/_kql_dashboards.py @@ -114,7 +114,7 @@ def create_kql_dashboard( ) -def create_workspace_montiring_dashboard( +def create_workspace_monitoring_dashboard( name: str = "Fabric Workspace Monitoring Dashboard", workspace: Optional[str | UUID] = None, ):