Skip to content

Latest commit

 

History

History
712 lines (546 loc) · 22.9 KB

app-management-commands.md

File metadata and controls

712 lines (546 loc) · 22.9 KB
title description ms.reviewer ms.topic ms.date
Create an app to run management commands
Learn how to create an app to run management commands using Kusto client libraries.
yogilad
how-to
11/07/2023

Create an app to run management commands

In this article, you learn how to:

[!div class="checklist"]

Prerequisites

Set up your development environment to use the Kusto client library.

Run a management command and process the results

In your preferred IDE or text editor, create a project or file named management commands using the convention appropriate for your preferred language. Then add the following code:

  1. Create a client app that connects your cluster. Replace the <your_cluster_uri> placeholder with your cluster name.

    [!NOTE] For management commands, you'll use the CreateCslAdminProvider client factory method.

    using Kusto.Data;
    using Kusto.Data.Net.Client;
    
    namespace ManagementCommands {
      class ManagementCommands {
        static void Main(string[] args) {
          var clusterUri = "<your_cluster_uri>";
          var kcsb = new KustoConnectionStringBuilder(clusterUri)
              .WithAadUserPromptAuthentication();
    
          using (var kustoClient = KustoClientFactory.CreateCslAdminProvider(kcsb)) {
          }
        }
      }
    }
    from azure.kusto.data import KustoClient, KustoConnectionStringBuilder
    
    def main():
      cluster_uri = "<your_cluster_uri>"
      kcsb = KustoConnectionStringBuilder.with_interactive_login(cluster_uri)
    
      with KustoClient(kcsb) as kusto_client:
    
    if __name__ == "__main__":
      main()
    import { Client as KustoClient, KustoConnectionStringBuilder } from "azure-kusto-data/";
    import { InteractiveBrowserCredentialInBrowserOptions } from "@azure/identity";
    
    async function main() {
      const clusterUri = "<your_cluster_uri>";
      const authOptions = {
        clientId: "5e39af3b-ba50-4255-b547-81abfb507c58",
        redirectUri: "http://localhost:5173",
      } as InteractiveBrowserCredentialInBrowserOptions;
      const kcsb = KustoConnectionStringBuilder.withUserPrompt(clusterUri, authOptions);
      const kustoClient = new KustoClient(kcsb);
    }
    
    main();

    [!INCLUDE node-vs-browser-auth]

    import com.microsoft.azure.kusto.data.Client;
    import com.microsoft.azure.kusto.data.ClientFactory;
    import com.microsoft.azure.kusto.data.KustoOperationResult;
    import com.microsoft.azure.kusto.data.KustoResultSetTable;
    import com.microsoft.azure.kusto.data.KustoResultColumn;
    import com.microsoft.azure.kusto.data.auth.ConnectionStringBuilder;
    
    public class ManagementCommands {
      public static void main(String[] args) throws Exception {
        try {
          String clusterUri = "<your_cluster_uri>";
          ConnectionStringBuilder kcsb = ConnectionStringBuilder.createWithUserPrompt(clusterUri);
    
          try (Client kustoClient = ClientFactory.createClient(kcsb)) {
          }
        }
      }
    }

  2. Define a function that prints the command being run and its resultant tables. This function unpacks the column names in the result tables and prints each name-value pair on a new line.

    static void PrintResultsAsValueList(string command, IDataReader response) {
      while (response.Read()) {
        Console.WriteLine("\n{0}\n", new String('-', 20));
        Console.WriteLine("Command: {0}", command);
        Console.WriteLine("Result:");
        for (int i = 0; i < response.FieldCount; i++) {
          Console.WriteLine("\t{0} - {1}", response.GetName(i), response.IsDBNull(i) ? "None" : response.GetString(i));
        }
      }
    }
    def print_result_as_value_list(command, response):
      # create a list of columns
      cols = (col.column_name for col in response.primary_results[0].columns)
    
      print("\n" + "-" * 20 + "\n")
      print("Command: " + command)
      # print the values for each row
      for row in response.primary_results[0]:
        print("Result:")
        for col in cols:
          print("\t", col, "-", row[col])
    function printResultsAsValueList(command: string, response: KustoResponseDataSet) {
      // create a list of columns
      const cols = response.primaryResults[0].columns;
    
      console.log("\n" + "-".repeat(20) + "\n")
      console.log("Command: " + command)
      // print the values for each row
      for (const row of response.primaryResults[0].rows()) {
        console.log("Result:")
        for (col of cols)
        console.log("\t", col.name, "-", row.getValueAt(col.ordinal) ? row.getValueAt(col.ordinal).toString() : "None")
      }
    }
    public static void printResultsAsValueList(String command, KustoResultSetTable results) {
      while (results.next()) {
        System.out.println("\n" + "-".repeat(20) + "\n");
        System.out.println("Command: " + command);
        System.out.println("Result:");
        KustoResultColumn[] columns = results.getColumns();
        for (int i = 0; i < columns.length; i++) {
          System.out.println("\t" + columns[i].getColumnName() + " - " + (results.getObject(i) == null ? "None" : results.getString(i)));
        }
      }
    }

  3. Define the command to run. The command creates a table called MyStormEvents and defines the table schema as a list of column names and types. Replace the <your_database> placeholder with your database name.

    string database = "<your_database>";
    string table = "MyStormEvents";
    
    // Create a table named MyStormEvents
    // The brackets contain a list of column Name:Type pairs that defines the table schema
    string command = @$".create table {table}
                      (StartTime:datetime,
                       EndTime:datetime,
                       State:string,
                       DamageProperty:int,
                       DamageCrops:int,
                       Source:string,
                       StormSummary:dynamic)";
    database = "<your_database>"
    table = "MyStormEvents"
    
    # Create a table named MyStormEvents
    # The brackets contain a list of column Name:Type pairs that defines the table schema
    command = ".create table " + table + " " \
              "(StartTime:datetime," \
              " EndTime:datetime," \
              " State:string," \
              " DamageProperty:int," \
              " DamageCrops:int," \
              " Source:string," \
              " StormSummary:dynamic)"
    const database = "<your_database>";
    const table = "MyStormEvents";
    
    // Create a table named MyStormEvents
    // The brackets contain a list of column Name:Type pairs that defines the table schema
    const command = `.create table ${table}
                  (StartTime:datetime,
                   EndTime:datetime,
                   State:string,
                   DamageProperty:int,
                   Source:string,
                   StormSummary:dynamic)`;
    String database = "<your_database>";
    String table = "MyStormEvents";
    
    // Create a table named MyStormEvents
    // The brackets contain a list of column Name:Type pairs that defines the table schema
    String command = ".create table " + table + " " +
                     "(StartTime:datetime," +
                     " EndTime:datetime," +
                     " State:string," +
                     " DamageProperty:int," +
                     " DamageCrops:int," +
                     " Source:string," +
                     " StormSummary:dynamic)";

  4. Run the command and print the result using the previously defined function.

    [!NOTE] You'll use the ExecuteControlCommand method to run the command.

    using (var response = kustoClient.ExecuteControlCommand(database, command, null)) {
      PrintResultsAsValueList(command, response);
    }

    [!NOTE] You'll use the execute_mgmt method to run the command.

    response = kusto_client.execute_mgmt(database, command)
    print_result_as_value_list(command, response)

    [!NOTE] You'll use the executeMgmt method to run the command.

    const response = await kustoClient.executeMgmt(database, command);
    printResultsAsValueList(command, response)
    KustoOperationResult response = kusto_client.execute(database, command);
    printResultsAsValueList(command, response.getPrimaryResults());

The complete code should look like this:

using Kusto.Data;
using Kusto.Data.Net.Client;

namespace ManagementCommands {
  class ManagementCommands {
    static void Main(string[] args) {
      string clusterUri = "https://<your_cluster_uri>";
      var kcsb = new KustoConnectionStringBuilder(clusterUri)
          .WithAadUserPromptAuthentication();

      using (var kustoClient = KustoClientFactory.CreateCslAdminProvider(kcsb)) {
        string database = "<your_database>";
        string table = "MyStormEvents";

        // Create a table named MyStormEvents
        // The brackets contain a list of column Name:Type pairs that defines the table schema
        string command = @$".create table {table} 
                          (StartTime:datetime,
                           EndTime:datetime,
                           State:string,
                           DamageProperty:int,
                           DamageCrops:int,
                           Source:string,
                           StormSummary:dynamic)";

        using (var response = kustoClient.ExecuteControlCommand(database, command, null)) {
          PrintResultsAsValueList(command, response);
        }
      }
    }

    static void PrintResultsAsValueList(string command, IDataReader response) {
      while (response.Read()) {
        Console.WriteLine("\n{0}\n", new String('-', 20));
        Console.WriteLine("Command: {0}", command);
        Console.WriteLine("Result:");
        for (int i = 0; i < response.FieldCount; i++) {
          Console.WriteLine("\t{0} - {1}", response.GetName(i), response.IsDBNull(i) ? "None" : response.GetString(i));
        }
      }
    }
  }
}
from azure.kusto.data import KustoClient, KustoConnectionStringBuilder

def main():
  cluster_uri = "https://<your_cluster_uri>"
  kcsb = KustoConnectionStringBuilder.with_interactive_login(cluster_uri)

  with KustoClient(kcsb) as kusto_client:

    database = "<your_database>"
    table = "MyStormEvents"

    # Create a table named MyStormEvents
    # The brackets contain a list of column Name:Type pairs that defines the table schema
    command = ".create table " + table + " " \
              "(StartTime:datetime," \
              " EndTime:datetime," \
              " State:string," \
              " DamageProperty:int," \
              " DamageCrops:int," \
              " Source:string," \
              " StormSummary:dynamic)"

    response = kusto_client.execute_mgmt(database, command)
    print_result_as_value_list(command, response)

def print_result_as_value_list(command, response):
  # create a list of columns
  cols = (col.column_name for col in response.primary_results[0].columns)

  print("\n" + "-" * 20 + "\n")
  print("Command: " + command)
  # print the values for each row
  for row in response.primary_results[0]:
    print("Result:")
    for col in cols:
      print("\t", col, "-", row[col])

if __name__ == "__main__":
  main()
import { Client as KustoClient, KustoConnectionStringBuilder, KustoResponseDataSet } from "azure-kusto-data/";
import { InteractiveBrowserCredentialInBrowserOptions } from "@azure/identity";

async function main() {
  const clusterUri = "<your_cluster_uri>";
  const authOptions = {
    clientId: "5e39af3b-ba50-4255-b547-81abfb507c58",
    redirectUri: "http://localhost:5173",
  } as InteractiveBrowserCredentialInBrowserOptions;
  const kcsb = KustoConnectionStringBuilder.withUserPrompt(clusterUri, authOptions);
  const kustoClient = new KustoClient(kcsb);

  const database = "<your_database>";
  const table = "MyStormEvents";

  // Create a table named MyStormEvents
  // The brackets contain a list of column Name:Type pairs that defines the table schema
  const command = `.create table ${table}
                 (StartTime:datetime,
                  EndTime:datetime,
                  State:string,
                  DamageProperty:int,
                  Source:string,
                  StormSummary:dynamic)`;

  const response = await kustoClient.executeMgmt(database, command);
  printResultsAsValueList(command, response)
}

function printResultsAsValueList(command: string, response: KustoResponseDataSet) {
  // create a list of columns
  const cols = response.primaryResults[0].columns;

  console.log("\n" + "-".repeat(20) + "\n")
  console.log("Command: " + command)
  // print the values for each row
  for (const row of response.primaryResults[0].rows()) {
    console.log("Result:")
    for (const col of cols) {
        console.log("\t", col.name, "-", row.getValueAt(col.ordinal) ? row.getValueAt(col.ordinal).toString() : "None")
    }
  }
}

main();

[!INCLUDE node-vs-browser-auth]

import com.microsoft.azure.kusto.data.Client;
import com.microsoft.azure.kusto.data.ClientFactory;
import com.microsoft.azure.kusto.data.KustoOperationResult;
import com.microsoft.azure.kusto.data.KustoResultSetTable;
import com.microsoft.azure.kusto.data.KustoResultColumn;
import com.microsoft.azure.kusto.data.auth.ConnectionStringBuilder;

public class ManagementCommands {
  public static void main(String[] args) throws Exception {
    try {
      String clusterUri = "https://<your_cluster_uri>";
      ConnectionStringBuilder kcsb = ConnectionStringBuilder.createWithUserPrompt(clusterUri);
      try (Client kustoClient = ClientFactory.createClient(kcsb)) {
        String database = "<your_database>";
        String table = "MyStormEvents";

        // Create a table named MyStormEvents
        // The brackets contain a list of column Name:Type pairs that defines the table schema
        String command = ".create table " + table + " " +
                         "(StartTime:datetime," +
                         " EndTime:datetime," +
                         " State:string," +
                         " DamageProperty:int," +
                         " DamageCrops:int," +
                         " Source:string," +
                         " StormSummary:dynamic)";

        KustoOperationResult response = kustoClient.execute(database, command);
        printResultsAsValueList(command, response.getPrimaryResults());
      }
    }
  }
  public static void printResultsAsValueList(String command, KustoResultSetTable results) {
    while (results.next()) {
      System.out.println("\n" + "-".repeat(20) + "\n");
      System.out.println("Command: " + command);
      System.out.println("Result:");
      KustoResultColumn[] columns = results.getColumns();
      for (int i = 0; i < columns.length; i++) {
        System.out.println("\t" + columns[i].getColumnName() + " - " + (results.getObject(i) == null ? "None" : results.getString(i)));
      }
    }
  }
}

Run your app

In a command shell, use the following command to run your app:

# Change directory to the folder that contains the management commands project
dotnet run .
python management_commands.py

In a Node.js environment:

node management-commands.js

In a browser environment, use the appropriate command to run your app. For example, for Vite-React:

npm run dev

Note

In a browser environment, open the developer tools console to see the output.

mvn install exec:java -Dexec.mainClass="<groupId>.ManagementCommands"

You should see a result similar to the following:

--------------------

Command: .create table MyStormEvents 
                 (StartTime:datetime,
                  EndTime:datetime,
                  State:string,
                  DamageProperty:int,
                  Source:string,
                  StormSummary:dynamic)
Result:
   TableName - MyStormEvents
   Schema - {"Name":"MyStormEvents","OrderedColumns":[{"Name":"StartTime","Type":"System.DateTime","CslType":"datetime"},{"Name":"EndTime","Type":"System.DateTime","CslType":"datetime"},{"Name":"State","Type":"System.String","CslType":"string"},{"Name":"DamageProperty","Type":"System.Int32","CslType":"int"},{"Name":"Source","Type":"System.String","CslType":"string"},{"Name":"StormSummary","Type":"System.Object","CslType":"dynamic"}]}
   DatabaseName - MyDatabaseName
   Folder - None
   DocString - None

Change the table level ingestion batching policy

You can customize the ingestion batching behavior for tables by changing the corresponding table policy. For more information, see IngestionBatching policy.

Note

If you don't specify all parameters of a PolicyObject, the unspecified parameters will be set to default values. For example, specifying only "MaximumBatchingTimeSpan" will result in "MaximumNumberOfItems" and "MaximumRawDataSizeMB" being set to default.

For example, you can modify the app to change the ingestion batching policy timeout value to 30 seconds by altering the ingestionBatching policy for the MyStormEvents table using the following command:

// Reduce the default batching timeout to 30 seconds
command = @$".alter-merge table {table} policy ingestionbatching '{{ ""MaximumBatchingTimeSpan"":""00:00:30"" }}'";

using (var response = kustoClient.ExecuteControlCommand(database, command, null))
{
  PrintResultsAsValueList(command, response);
}
# Reduce the default batching timeout to 30 seconds
command = ".alter-merge table " + table + " policy ingestionbatching '{ \"MaximumBatchingTimeSpan\":\"00:00:30\" }'"

response = kusto_client.execute_mgmt(database, command)
print_result_as_value_list(command, response)
// Reduce the default batching timeout to 30 seconds
command = ".alter-merge table " + table + " policy ingestionbatching '{ \"MaximumBatchingTimeSpan\":\"00:00:30\" }'"

response = await kustoClient.executeMgmt(database, command)
printResultsAsValueList(command, response)
// Reduce the default batching timeout to 30 seconds
command = ".alter-merge table " + table + " policy ingestionbatching '{ \"MaximumBatchingTimeSpan\":\"00:00:30\" }'";

response = kusto_client.execute(database, command);
printResultsAsValueList(command, response.getPrimaryResults());

When you add the code to your app and run it, you should see a result similar to the following:

--------------------

Command: .alter-merge table MyStormEvents policy ingestionbatching '{ "MaximumBatchingTimeSpan":"00:00:30" }'
Result:
   PolicyName - IngestionBatchingPolicy
   EntityName - [YourDatabase].[MyStormEvents]
   Policy - {
  "MaximumBatchingTimeSpan": "00:00:30",
  "MaximumNumberOfItems": 500,
  "MaximumRawDataSizeMB": 1024
}
   ChildEntities - None
   EntityType - Table

Show the database level retention policy

You can use management commands to display a database's retention policy.

For example, you can modify the app to display your database's retention policy using the following code. The result is curated to project away two columns from the result:

// Show the database retention policy (drop some columns from the result)
command = @$".show database {database} policy retention | project-away ChildEntities, EntityType";

using (var response = kustoClient.ExecuteControlCommand(database, command, null)) {
  PrintResultsAsValueList(command, response);
}
# Show the database retention policy (drop some columns from the result)
command = ".show database " + database + " policy retention | project-away ChildEntities, EntityType"

response = kusto_client.execute_mgmt(database, command)
print_result_as_value_list(command, response)
// Show the database retention policy (drop some columns from the result)
command = ".show database " + database + " policy retention | project-away ChildEntities, EntityType"

response = await kustoClient.executeMgmt(database, command)
printResultsAsValueList(command, response)
// Show the database retention policy (drop some columns from the result)
command = ".show database " + database + " policy retention | project-away ChildEntities, EntityType";

response = kusto_client.execute(database, command);
printResultsAsValueList(command, response.getPrimaryResults());

When you add the code to your app and run it, you should see a result similar to the following:

--------------------

Command: .show database YourDatabase policy retention | project-away ChildEntities, EntityType
Result:
   PolicyName - RetentionPolicy
   EntityName - [YourDatabase]
   Policy - {
  "SoftDeletePeriod": "365.00:00:00",
  "Recoverability": "Enabled"
}

Next step

[!div class="nextstepaction"] Create an app to get data using queued ingestion