0
# Monitoring and Operations
1
2
Monitoring capabilities including operation results tracking, SKU information retrieval, and management of attached database configurations for database sharing scenarios. This enables operational oversight and resource planning for Kusto deployments.
3
4
## Capabilities
5
6
### Operations Discovery
7
8
Operations to discover available management operations and their capabilities.
9
10
```python { .api }
11
def list(**kwargs) -> Iterable[Operation]:
12
"""
13
List available operations for the Kusto resource provider.
14
15
Returns:
16
Iterable of Operation objects describing available operations
17
"""
18
```
19
20
### Operation Results Tracking
21
22
Operations to track the status and results of long-running operations.
23
24
```python { .api }
25
def get(
26
location: str,
27
operation_id: str,
28
**kwargs
29
) -> OperationResult:
30
"""
31
Get the result of a long-running operation.
32
33
Parameters:
34
- location: Azure region where the operation was initiated
35
- operation_id: Unique identifier of the operation
36
37
Returns:
38
OperationResult with operation status and details
39
"""
40
```
41
42
### Location-Based Operation Results
43
44
Operations to retrieve operation results based on location for geographically distributed operations.
45
46
```python { .api }
47
def get(
48
location: str,
49
operation_id: str,
50
**kwargs
51
) -> OperationResult:
52
"""
53
Get the result of a location-based long-running operation.
54
55
Parameters:
56
- location: Azure region where the operation was initiated
57
- operation_id: Unique identifier of the operation
58
59
Returns:
60
OperationResult with operation status and details
61
"""
62
```
63
64
### SKU Information Retrieval
65
66
Operations to discover available SKUs and their capabilities for capacity planning.
67
68
```python { .api }
69
def list(**kwargs) -> Iterable[SkuDescription]:
70
"""
71
List available SKUs for Kusto clusters.
72
73
Returns:
74
Iterable of SkuDescription objects with SKU details and availability
75
"""
76
```
77
78
### Attached Database Configurations
79
80
Management of attached database configurations that enable database sharing between clusters.
81
82
```python { .api }
83
def get(
84
resource_group_name: str,
85
cluster_name: str,
86
attached_database_configuration_name: str,
87
**kwargs
88
) -> AttachedDatabaseConfiguration:
89
"""
90
Get an attached database configuration.
91
92
Parameters:
93
- resource_group_name: Name of the resource group
94
- cluster_name: Name of the Kusto cluster
95
- attached_database_configuration_name: Name of the configuration
96
97
Returns:
98
AttachedDatabaseConfiguration object
99
"""
100
101
def begin_create_or_update(
102
resource_group_name: str,
103
cluster_name: str,
104
attached_database_configuration_name: str,
105
parameters: AttachedDatabaseConfiguration,
106
**kwargs
107
) -> LROPoller[AttachedDatabaseConfiguration]:
108
"""
109
Create or update an attached database configuration.
110
111
Parameters:
112
- resource_group_name: Name of the resource group
113
- cluster_name: Name of the Kusto cluster
114
- attached_database_configuration_name: Name of the configuration
115
- parameters: AttachedDatabaseConfiguration with settings
116
117
Returns:
118
LROPoller for the long-running operation returning AttachedDatabaseConfiguration
119
"""
120
121
def begin_delete(
122
resource_group_name: str,
123
cluster_name: str,
124
attached_database_configuration_name: str,
125
**kwargs
126
) -> LROPoller[None]:
127
"""
128
Delete an attached database configuration.
129
130
Parameters:
131
- resource_group_name: Name of the resource group
132
- cluster_name: Name of the Kusto cluster
133
- attached_database_configuration_name: Name of the configuration
134
135
Returns:
136
LROPoller for the long-running delete operation
137
"""
138
139
def list_by_cluster(
140
resource_group_name: str,
141
cluster_name: str,
142
**kwargs
143
) -> Iterable[AttachedDatabaseConfiguration]:
144
"""
145
List attached database configurations for a cluster.
146
147
Parameters:
148
- resource_group_name: Name of the resource group
149
- cluster_name: Name of the Kusto cluster
150
151
Returns:
152
Iterable of AttachedDatabaseConfiguration objects
153
"""
154
155
def check_name_availability(
156
resource_group_name: str,
157
cluster_name: str,
158
resource_name: AttachedDatabaseConfigurationsCheckNameRequest,
159
**kwargs
160
) -> CheckNameResult:
161
"""
162
Check if an attached database configuration name is available.
163
164
Parameters:
165
- resource_group_name: Name of the resource group
166
- cluster_name: Name of the Kusto cluster
167
- resource_name: CheckNameRequest with name to validate
168
169
Returns:
170
CheckNameResult indicating availability
171
"""
172
```
173
174
## Usage Examples
175
176
### Monitoring Long-Running Operations
177
178
```python
179
# Start a long-running operation (e.g., cluster creation)
180
poller = client.clusters.begin_create_or_update(
181
resource_group_name="my-resource-group",
182
cluster_name="my-cluster",
183
parameters=cluster_params
184
)
185
186
# Get operation details
187
operation_id = poller._operation.resource().name
188
location = "East US"
189
190
# Check operation status
191
operation_result = client.operations_results.get(
192
location=location,
193
operation_id=operation_id
194
)
195
196
print(f"Operation Status: {operation_result.status}")
197
print(f"Operation Name: {operation_result.name}")
198
199
if operation_result.error:
200
print(f"Operation Error: {operation_result.error.message}")
201
```
202
203
### Listing Available SKUs
204
205
```python
206
# Get all available SKUs
207
available_skus = list(client.skus.list())
208
209
print("Available Kusto Cluster SKUs:")
210
for sku in available_skus:
211
print(f"- {sku.name}: {sku.tier}")
212
print(f" Locations: {', '.join(sku.locations)}")
213
print(f" Capabilities: {len(sku.capabilities)} features")
214
215
for capability in sku.capabilities:
216
print(f" {capability.name}: {capability.value}")
217
print()
218
```
219
220
### Creating an Attached Database Configuration
221
222
```python
223
from azure.mgmt.kusto.models import (
224
AttachedDatabaseConfiguration,
225
DefaultPrincipalsModificationKind,
226
TableLevelSharingProperties
227
)
228
229
# Configure table-level sharing
230
table_sharing = TableLevelSharingProperties(
231
tables_to_include=["Table1", "Table2", "Table3"],
232
tables_to_exclude=[],
233
external_tables_to_include=["ExternalTable1"],
234
external_tables_to_exclude=[],
235
materialized_views_to_include=["MaterializedView1"],
236
materialized_views_to_exclude=[],
237
functions_to_include=["Function1", "Function2"],
238
functions_to_exclude=[]
239
)
240
241
# Create attached database configuration
242
attached_config = AttachedDatabaseConfiguration(
243
location="East US",
244
database_name="SharedDatabase",
245
cluster_resource_id="/subscriptions/sub-id/resourceGroups/source-rg/providers/Microsoft.Kusto/clusters/source-cluster",
246
default_principals_modification_kind=DefaultPrincipalsModificationKind.UNION,
247
table_level_sharing_properties=table_sharing,
248
database_name_prefix="Shared_"
249
)
250
251
# Create the configuration
252
poller = client.attached_database_configurations.begin_create_or_update(
253
resource_group_name="my-resource-group",
254
cluster_name="my-follower-cluster",
255
attached_database_configuration_name="shared-database-config",
256
parameters=attached_config
257
)
258
259
config = poller.result()
260
print(f"Attached database configuration created: {config.name}")
261
print(f"Attached databases: {', '.join(config.attached_database_names)}")
262
```
263
264
### Discovering Available Operations
265
266
```python
267
# List all available operations
268
operations = list(client.operations.list())
269
270
print("Available Kusto Management Operations:")
271
for operation in operations:
272
print(f"- {operation.name}")
273
print(f" Display Name: {operation.display.operation}")
274
print(f" Description: {operation.display.description}")
275
print(f" Provider: {operation.display.provider}")
276
print(f" Resource: {operation.display.resource}")
277
print()
278
```
279
280
### Monitoring Cluster Health
281
282
```python
283
# Get cluster details for health monitoring
284
cluster = client.clusters.get(
285
resource_group_name="my-resource-group",
286
cluster_name="my-cluster"
287
)
288
289
print(f"Cluster Health Status:")
290
print(f"- Name: {cluster.name}")
291
print(f"- State: {cluster.state}")
292
print(f"- Provisioning State: {cluster.provisioning_state}")
293
print(f"- URI: {cluster.uri}")
294
print(f"- Data Ingestion URI: {cluster.data_ingestion_uri}")
295
print(f"- SKU: {cluster.sku.name} ({cluster.sku.capacity} instances)")
296
297
# List follower databases
298
followers = list(client.clusters.list_follower_databases(
299
resource_group_name="my-resource-group",
300
cluster_name="my-cluster"
301
))
302
303
print(f"- Follower Databases: {len(followers)}")
304
for follower in followers:
305
print(f" - {follower.cluster_resource_id} -> {follower.database_name}")
306
```
307
308
## Key Types
309
310
```python { .api }
311
class Operation:
312
"""Represents an available management operation."""
313
name: str # Operation name
314
is_data_action: bool # Whether operation is a data action
315
display: OperationDisplay # Display information
316
origin: str # Operation origin
317
properties: dict # Additional properties
318
319
class OperationDisplay:
320
"""Display information for an operation."""
321
provider: str # Resource provider name
322
resource: str # Resource type
323
operation: str # Operation name
324
description: str # Operation description
325
326
class OperationResult:
327
"""Result of a long-running operation."""
328
# Read-only properties
329
id: str # Operation ID
330
name: str # Operation name
331
status: str # Operation status
332
start_time: datetime # Operation start time
333
end_time: datetime # Operation end time
334
percent_complete: float # Completion percentage
335
properties: dict # Operation-specific properties
336
error: ErrorDetail # Error details if operation failed
337
338
class SkuDescription:
339
"""Description of an available SKU."""
340
resource_type: str # Resource type
341
name: str # SKU name
342
tier: str # SKU tier
343
locations: List[str] # Available locations
344
location_info: List[SkuLocationInfoItem] # Location-specific information
345
capabilities: List[ResourceSkuCapabilities] # SKU capabilities
346
restrictions: List[dict] # SKU restrictions
347
348
class ResourceSkuCapabilities:
349
"""Capabilities of a resource SKU."""
350
name: str # Capability name
351
value: str # Capability value
352
353
class SkuLocationInfoItem:
354
"""Location-specific SKU information."""
355
location: str # Azure region
356
zones: List[str] # Available zones
357
zone_details: List[ResourceSkuZoneDetails] # Zone-specific details
358
359
class AttachedDatabaseConfiguration:
360
"""Configuration for sharing databases between clusters."""
361
# Read-only properties
362
id: str # Resource ID
363
name: str # Configuration name
364
type: str # Resource type
365
provisioning_state: ProvisioningState # Provisioning state
366
attached_database_names: List[str] # Names of attached databases
367
368
# Configuration properties
369
location: str # Azure region
370
database_name: str # Database name pattern (* for all)
371
cluster_resource_id: str # Source cluster resource ID
372
default_principals_modification_kind: DefaultPrincipalsModificationKind # Principal handling
373
table_level_sharing_properties: TableLevelSharingProperties # Table sharing config
374
database_name_override: str # Override database name
375
database_name_prefix: str # Prefix for database names
376
377
class TableLevelSharingProperties:
378
"""Table-level sharing configuration."""
379
tables_to_include: List[str] # Tables to include
380
tables_to_exclude: List[str] # Tables to exclude
381
external_tables_to_include: List[str] # External tables to include
382
external_tables_to_exclude: List[str] # External tables to exclude
383
materialized_views_to_include: List[str] # Materialized views to include
384
materialized_views_to_exclude: List[str] # Materialized views to exclude
385
functions_to_include: List[str] # Functions to include
386
functions_to_exclude: List[str] # Functions to exclude
387
388
class AttachedDatabaseConfigurationsCheckNameRequest:
389
"""Request to check attached database configuration name availability."""
390
name: str # Name to check
391
type: str # Resource type
392
393
from enum import Enum
394
395
class DefaultPrincipalsModificationKind(str, Enum):
396
"""Default principals modification behavior."""
397
UNION = "Union" # Combine source and target principals
398
REPLACE = "Replace" # Replace target principals with source
399
NONE = "None" # No principal modification
400
```
401
402
## Error Handling and Monitoring Patterns
403
404
### Monitoring Operation Progress
405
406
```python
407
from azure.core.exceptions import HttpResponseError
408
import time
409
410
def monitor_long_running_operation(poller, operation_name):
411
"""Monitor a long-running operation with progress reporting."""
412
print(f"Starting {operation_name}...")
413
414
try:
415
while not poller.done():
416
print(f"Operation in progress... Status: {poller.status()}")
417
time.sleep(30) # Wait 30 seconds between checks
418
419
result = poller.result()
420
print(f"{operation_name} completed successfully")
421
return result
422
423
except HttpResponseError as e:
424
print(f"{operation_name} failed: {e.message}")
425
426
# Get detailed error information
427
if hasattr(e, 'error') and e.error:
428
print(f"Error Code: {e.error.code}")
429
print(f"Error Details: {e.error.message}")
430
431
if hasattr(e.error, 'details') and e.error.details:
432
for detail in e.error.details:
433
print(f"Additional Info: {detail.code} - {detail.message}")
434
435
raise
436
437
# Usage example
438
poller = client.clusters.begin_create_or_update(
439
resource_group_name="my-resource-group",
440
cluster_name="my-cluster",
441
parameters=cluster_params
442
)
443
444
cluster = monitor_long_running_operation(poller, "Cluster Creation")
445
```
446
447
### Health Check Implementation
448
449
```python
450
def perform_cluster_health_check(client, resource_group_name, cluster_name):
451
"""Perform comprehensive health check on a Kusto cluster."""
452
health_status = {
453
"cluster_accessible": False,
454
"provisioning_state": None,
455
"cluster_state": None,
456
"databases": [],
457
"data_connections": [],
458
"issues": []
459
}
460
461
try:
462
# Check cluster status
463
cluster = client.clusters.get(
464
resource_group_name=resource_group_name,
465
cluster_name=cluster_name
466
)
467
468
health_status["cluster_accessible"] = True
469
health_status["provisioning_state"] = cluster.provisioning_state
470
health_status["cluster_state"] = cluster.state
471
472
# Check if cluster is in a healthy state
473
if cluster.state != "Running":
474
health_status["issues"].append(f"Cluster state is {cluster.state}, expected Running")
475
476
if cluster.provisioning_state != "Succeeded":
477
health_status["issues"].append(f"Provisioning state is {cluster.provisioning_state}, expected Succeeded")
478
479
# Check databases
480
databases = list(client.databases.list_by_cluster(
481
resource_group_name=resource_group_name,
482
cluster_name=cluster_name
483
))
484
485
for db in databases:
486
db_status = {
487
"name": db.name,
488
"provisioning_state": db.provisioning_state,
489
"healthy": db.provisioning_state == "Succeeded"
490
}
491
health_status["databases"].append(db_status)
492
493
if not db_status["healthy"]:
494
health_status["issues"].append(f"Database {db.name} provisioning state is {db.provisioning_state}")
495
496
# Check data connections for each database
497
try:
498
connections = list(client.data_connections.list_by_database(
499
resource_group_name=resource_group_name,
500
cluster_name=cluster_name,
501
database_name=db.name
502
))
503
504
for conn in connections:
505
conn_status = {
506
"database": db.name,
507
"name": conn.name,
508
"kind": conn.kind,
509
"provisioning_state": conn.provisioning_state,
510
"healthy": conn.provisioning_state == "Succeeded"
511
}
512
health_status["data_connections"].append(conn_status)
513
514
if not conn_status["healthy"]:
515
health_status["issues"].append(f"Data connection {conn.name} in {db.name} provisioning state is {conn.provisioning_state}")
516
517
except HttpResponseError as e:
518
health_status["issues"].append(f"Failed to check data connections for {db.name}: {e.message}")
519
520
except HttpResponseError as e:
521
health_status["issues"].append(f"Failed to access cluster: {e.message}")
522
523
return health_status
524
525
# Usage example
526
health = perform_cluster_health_check(client, "my-resource-group", "my-cluster")
527
print(f"Cluster Health: {'HEALTHY' if not health['issues'] else 'ISSUES FOUND'}")
528
529
if health["issues"]:
530
print("Issues found:")
531
for issue in health["issues"]:
532
print(f"- {issue}")
533
```