# Set up Azure Data Explorer in the AppHost

<Image
  src={kustoIcon}
  alt="Azure Data Explorer logo"
  width={100}
  height={100}
  class:list={'float-inline-left icon'}
  data-zoom-off
/>

This article is the reference for the Aspire Azure Data Explorer (Kusto) hosting integration. It enumerates the AppHost APIs — with examples for both `AppHost.cs` and `apphost.mts` — that you use to model Azure Data Explorer clusters and databases in your [`AppHost`](/get-started/app-host/) project.

[Azure Data Explorer](https://azure.microsoft.com/services/data-explorer/) (also known as Kusto) is a fast and highly scalable data exploration service for log and telemetry data. The hosting integration models the following types:

- `AzureKustoClusterResource`: A top-level cluster resource that holds databases and carries connection information.
- `AzureKustoReadWriteDatabaseResource`: A read-write database within a cluster.
- `AzureKustoEmulatorResource`: The local Kustainer emulator running as a container.

## Installation

To start building an Aspire app that uses Azure Data Explorer, install the [📦 Aspire.Hosting.Azure.Kusto](https://www.nuget.org/packages/Aspire.Hosting.Azure.Kusto) NuGet package:

```bash title="Terminal"
aspire add azure-kusto
```

<LearnMore>
  Learn more about [`aspire add`](/reference/cli/commands/aspire-add/) in the command reference.
</LearnMore>

Or, choose a manual installation approach:

```csharp title="C# — AppHost.cs"
#:package Aspire.Hosting.Azure.Kusto@*
```

```xml title="XML — AppHost.csproj"
<PackageReference Include="Aspire.Hosting.Azure.Kusto" Version="*" />
```

```bash title="Terminal"
aspire add azure-kusto
```

<LearnMore>
  Learn more about [`aspire add`](/reference/cli/commands/aspire-add/) in the command reference.
</LearnMore>

This updates your `aspire.config.json` with the Azure Data Explorer hosting integration package:

```json title="aspire.config.json" ins={3}
{
  "packages": {
    "Aspire.Hosting.Azure.Kusto": "13.3.0-preview.1.26256.5"
  }
}
```

## Add an Azure Data Explorer cluster resource

Once you've installed the hosting integration, call `AddAzureKustoCluster` (or `addAzureKustoCluster`) to declare a cluster, then call `AddReadWriteDatabase` (or `addReadWriteDatabase`) to declare one or more databases inside it:

```csharp title="C# — AppHost.cs"
var builder = DistributedApplication.CreateBuilder(args);

var kusto = builder.AddAzureKustoCluster("kusto");
var database = kusto.AddReadWriteDatabase("analytics");

builder.AddProject<Projects.ExampleProject>()
    .WithReference(database)
    .WaitFor(database);

// After adding all resources, run the app...
```
```typescript title="TypeScript — apphost.mts"
import { createBuilder } from './.aspire/modules/aspire.mjs';

const builder = await createBuilder();

const kusto = await builder.addAzureKustoCluster("kusto");
const database = await kusto.addReadWriteDatabase("analytics");

await builder.addNodeApp("api", "./api", "index.js")
    .withReference(database)
    .waitFor(database);

// After adding all resources, run the app...
```
The preceding code adds an Azure Data Explorer cluster named `kusto` with a read-write database named `analytics`. The `WithReference` (or `withReference`) method injects the connection information into the consuming project.
**Caution:** When you call `AddAzureKustoCluster`, it implicitly calls `AddAzureProvisioning` —
  which adds support for generating Azure resources dynamically during app startup.
  The app must configure the appropriate subscription and location. For more
  information, see [Local provisioning: Configuration](/integrations/cloud/azure/local-provisioning/#configuration).

## Run as emulator

The hosting integration supports running Azure Data Explorer locally using the Kustainer container image. This lets you develop and test without an Azure subscription or an existing cluster.

```csharp title="C# — AppHost.cs"
var builder = DistributedApplication.CreateBuilder(args);

var kusto = builder.AddAzureKustoCluster("kusto")
    .RunAsEmulator();

var database = kusto.AddReadWriteDatabase("analytics");

builder.AddProject<Projects.ExampleProject>()
    .WithReference(database)
    .WaitFor(database);

// After adding all resources, run the app...
```
```typescript title="TypeScript — apphost.mts"
import { createBuilder } from './.aspire/modules/aspire.mjs';

const builder = await createBuilder();

const kusto = await builder.addAzureKustoCluster("kusto")
    .runAsEmulator();

const database = await kusto.addReadWriteDatabase("analytics");

await builder.addNodeApp("api", "./api", "index.js")
    .withReference(database)
    .waitFor(database);

// After adding all resources, run the app...
```
When running as an emulator, databases are automatically created when the container starts and the connection string is configured automatically for local development.

### Configure the emulator host port

By default, the emulator uses a dynamic host port. To fix the host port, pass a `configureContainer` callback and call `WithHostPort` (or `withHostPort`):

```csharp title="C# — AppHost.cs"
var builder = DistributedApplication.CreateBuilder(args);

var kusto = builder.AddAzureKustoCluster("kusto")
    .RunAsEmulator(emulator =>
    {
        emulator.WithHostPort(8080);
    });

// After adding all resources, run the app...
```
```typescript title="TypeScript — apphost.mts"
import { createBuilder } from './.aspire/modules/aspire.mjs';

const builder = await createBuilder();

const kusto = await builder.addAzureKustoCluster("kusto")
    .runAsEmulator({
        configureContainer: async (emulator) => {
            await emulator.withHostPort({ port: 8080 });
        },
    });

// After adding all resources, run the app...
```
### Add a database creation script

When running as an emulator, you can provide a KQL script to initialize the database with tables and data:

```csharp title="C# — AppHost.cs"
var builder = DistributedApplication.CreateBuilder(args);

var kusto = builder.AddAzureKustoCluster("kusto")
    .RunAsEmulator();

var database = kusto.AddReadWriteDatabase("analytics")
    .WithCreationScript("""
        .create table Events (
            Timestamp: datetime,
            EventType: string,
            Message: string
        )
        """);

builder.AddProject<Projects.ExampleProject>()
    .WithReference(database)
    .WaitFor(database);

// After adding all resources, run the app...
```
```typescript title="apphost.mts"
import { createBuilder } from './.aspire/modules/aspire.mjs';

const builder = await createBuilder();

const kusto = await builder.addAzureKustoCluster("kusto")
    .runAsEmulator();

const database = await kusto.addReadWriteDatabase("analytics")
    .withCreationScript(`
        .create table Events (
            Timestamp: datetime,
            EventType: string,
            Message: string
        )
        `);

const exampleProject = await builder.addProject("example", "../ExampleProject/ExampleProject.csproj");
await exampleProject
    .withReference(database)
    .waitFor(database);

// After adding all resources, run the app...
```
**Note:** The creation script is only executed when running as an emulator. In production scenarios, database schema should be managed through your deployment and provisioning process.

## Provisioning-generated Bicep

If you're new to [Bicep](https://learn.microsoft.com/azure/azure-resource-manager/bicep/overview), it's a domain-specific language for defining Azure resources. With Aspire, you don't need to write Bicep by hand — the provisioning APIs generate it for you. When you publish your app, the generated Bicep is written alongside the manifest file. When you add an Azure Data Explorer resource, the following Bicep is generated:

```bicep title="Generated Bicep — kusto.bicep"
@description('The location for the resource(s) to be deployed.')
param location string = resourceGroup().location

param principalId string

param principalName string

resource kusto 'Microsoft.Kusto/clusters@2024-04-13' = {
  name: take('kusto${uniqueString(resourceGroup().id)}', 22)
  location: location
  sku: {
    name: 'Dev(No SLA)_Standard_E2a_v4'
    tier: 'Basic'
    capacity: 1
  }
  properties: {
    enableAutoStop: true
  }
  tags: {
    'aspire-resource-name': 'kusto'
  }
}

resource analytics 'Microsoft.Kusto/clusters/databases@2024-04-13' = {
  name: 'analytics'
  location: location
  kind: 'ReadWrite'
  parent: kusto
}

resource kusto_principalAssignment 'Microsoft.Kusto/clusters/principalAssignments@2024-04-13' = {
  name: guid(kusto.id, principalId, 'AllDatabasesAdmin')
  properties: {
    principalId: principalId
    principalType: 'App'
    role: 'AllDatabasesAdmin'
  }
  parent: kusto
}

output kustoClusterUri string = kusto.properties.uri
```

The preceding Bicep provisions an Azure Data Explorer cluster with a dev/test SKU and a read-write database.

The generated Bicep is a starting point — customise it through the C# provisioning APIs, not by editing the file directly, as direct edits are overwritten on the next publish.

### Customize provisioning infrastructure

All Aspire Azure resources subclass `AzureProvisioningResource`. The `ConfigureInfrastructure` (or `configureInfrastructure`) API lets you customise the generated Bicep with a fluent callback:

```csharp title="C# — AppHost.cs"
var builder = DistributedApplication.CreateBuilder(args);

var kusto = builder.AddAzureKustoCluster("kusto")
    .ConfigureInfrastructure(infra =>
    {
        var cluster = infra.GetProvisionableResources()
            .OfType<KustoCluster>()
            .Single();

        cluster.Sku = new KustoSku
        {
            Name = KustoSkuName.StandardE8aV4,
            Tier = KustoSkuTier.Standard,
            Capacity = 2
        };
        cluster.IsAutoStopEnabled = false;
        cluster.Tags.Add("environment", "production");
    });

kusto.AddReadWriteDatabase("analytics");
```
```typescript title="TypeScript — apphost.mts"
import { createBuilder } from './.aspire/modules/aspire.mjs';

const builder = await createBuilder();

const kusto = await builder.addAzureKustoCluster("kusto");
await kusto.configureInfrastructure(async (infra) => {
    // Modify infra resources here using the AzureResourceInfrastructure API
});

await kusto.addReadWriteDatabase("analytics");

// After adding all resources, run the app...
```
The preceding C# code:

- Retrieves the `KustoCluster` from the provisionable resources.
- Sets the SKU to `StandardE8aV4` with a capacity of `2`.
- Disables auto-stop.
- Adds a tag with key `environment` and value `production`.

For more configuration options, see [Azure.Provisioning customization](/integrations/cloud/azure/customize-resources/#azureprovisioning-customization). For the full list of configurable properties, see the [Azure.Provisioning.Kusto](https://learn.microsoft.com/dotnet/api/azure.provisioning.kusto) API documentation.

## Connection properties

When you add an Azure Data Explorer resource to your application, the connection properties are made available to consuming resources:

### Cluster resource

| Property | Description |
|----------|-------------|
| `Uri` | The URI of the Azure Data Explorer cluster endpoint. |

### Database resource

| Property | Description |
|----------|-------------|
| `Uri` | The URI of the parent cluster endpoint (inherited from cluster). |
| `DatabaseName` | The name of the database. |

The connection string format is: `Data Source=https://{cluster-uri};Initial Catalog={database-name}`
**Note:** The Azure Data Explorer hosting integration does not include a corresponding client integration package. Use the [Kusto .NET SDK](https://learn.microsoft.com/azure/data-explorer/kusto/api/netfx/about-the-sdk) directly in your application to query data.

## Hosting integration health checks

The Azure Data Explorer hosting integration automatically adds health checks for both cluster and database resources. The health check verifies that the cluster is reachable and responding to queries, and that any referenced database exists and is accessible.

Health check status is displayed in the Aspire dashboard resource list.

## See also

- [Azure Data Explorer documentation](https://learn.microsoft.com/azure/data-explorer/)
- [Kusto Query Language (KQL) overview](https://learn.microsoft.com/azure/data-explorer/kusto/query/)
- [Kusto .NET SDK](https://learn.microsoft.com/azure/data-explorer/kusto/api/netfx/about-the-sdk)
- [Customize Azure resources](/integrations/cloud/azure/customize-resources/)
- [Azure integration overview](/integrations/cloud/azure/overview/)