Associações de saída do Azure Data Explorer para Azure Functions (versão prévia)

Quando uma função é executada, a associação de saída do Azure Data Explorer ingere dados no Azure Data Explorer.

Para obter informações sobre a instalação e detalhes de configuração, confira a visão geral.

Exemplos

A função C# pode ser criada por meio de um dos seguintes modos C#:

  • Modelo de trabalho isolado: função C# compilada executada em um processo de trabalho que está isolado do runtime. É necessário um processo de trabalho isolado para dar suporte às funções C# executadas nas versões LTS e não LTS do .NET e do .NET Framework.
  • Modelo em processo: função C# compilada no mesmo processo que o runtime do Functions.
  • Script C#: usado principalmente ao criar funções C# no portal do Azure.

Mais exemplos da associação de saída do Azure Data Explorer estão disponíveis no Repositório do GitHub.

Esta seção contém os seguintes exemplos:

Os exemplos se referem a uma classe Product e a uma tabela de banco de dados correspondente:

public class Product
{
    [JsonProperty(nameof(ProductID))]
    public long ProductID { get; set; }

    [JsonProperty(nameof(Name))]
    public string Name { get; set; }

    [JsonProperty(nameof(Cost))]
    public double Cost { get; set; }
}
.create-merge table Products (ProductID:long, Name:string, Cost:double)

Gatilho HTTP, gravar um registro

O exemplo a seguir mostra uma função C# que adiciona um único registro a um banco de dados. A função usa dados fornecidos em uma solicitação HTTP POST como um corpo JSON.

using Microsoft.Azure.Functions.Worker;
using Microsoft.Azure.Functions.Worker.Extensions.Kusto;
using Microsoft.Azure.Functions.Worker.Http;
using Microsoft.Azure.WebJobs.Extensions.Kusto.SamplesOutOfProc.OutputBindingSamples.Common;

namespace Microsoft.Azure.WebJobs.Extensions.Kusto.SamplesOutOfProc.OutputBindingSamples
{
    public static class AddProduct
    {
        [Function("AddProduct")]
        [KustoOutput(Database: "productsdb", Connection = "KustoConnectionString", TableName = "Products")]
        public static async Task<Product> Run(
            [HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "addproductuni")]
            HttpRequestData req)
        {
            Product? prod = await req.ReadFromJsonAsync<Product>();
            return prod ?? new Product { };
        }
    }
}

Gatilho HTTP, gravar registros com mapeamento

O exemplo a seguir mostra uma função C# que adiciona uma única coleção de registros a um banco de dados. A função usa o mapeamento que transforma um Product em Item.

Para transformar dados de Product em Item, a função usa uma referência de mapeamento:

.create-merge table Item (ItemID:long, ItemName:string, ItemCost:float)


-- Create a mapping that transforms an Item to a Product

.create-or-alter table Product ingestion json mapping "item_to_product_json" '[{"column":"ProductID","path":"$.ItemID"},{"column":"Name","path":"$.ItemName"},{"column":"Cost","path":"$.ItemCost"}]'
namespace Microsoft.Azure.WebJobs.Extensions.Kusto.SamplesOutOfProc.OutputBindingSamples.Common
{
    public class Item
    {
        public long ItemID { get; set; }

        public string? ItemName { get; set; }

        public double ItemCost { get; set; }
    }
}
using Microsoft.Azure.Functions.Worker;
using Microsoft.Azure.Functions.Worker.Extensions.Kusto;
using Microsoft.Azure.Functions.Worker.Http;
using Microsoft.Azure.WebJobs.Extensions.Kusto.SamplesOutOfProc.OutputBindingSamples.Common;

namespace Microsoft.Azure.WebJobs.Extensions.Kusto.SamplesOutOfProc.OutputBindingSamples
{
    public static class AddProductsWithMapping
    {
        [Function("AddProductsWithMapping")]
        [KustoOutput(Database: "productsdb", Connection = "KustoConnectionString", TableName = "Products", MappingRef = "item_to_product_json")]
        public static async Task<Item> Run(
            [HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "addproductswithmapping")]
            HttpRequestData req)
        {
            Item? item = await req.ReadFromJsonAsync<Item>();
            return item ?? new Item { };
        }
    }
}

Mais exemplos da associação de entrada do Azure Data Explorer java estão disponíveis no Repositório do GitHub.

Esta seção contém os seguintes exemplos:

Os exemplos se referem a uma classe Products (em um arquivo Product.java separado) e a uma tabela de banco de dados correspondente Products (definida anteriormente):

package com.microsoft.azure.kusto.common;

import com.fasterxml.jackson.annotation.JsonProperty;

public class Product {
    @JsonProperty("ProductID")
    public long ProductID;
    @JsonProperty("Name")
    public String Name;
    @JsonProperty("Cost")
    public double Cost;

    public Product() {
    }

    public Product(long ProductID, String name, double Cost) {
        this.ProductID = ProductID;
        this.Name = name;
        this.Cost = Cost;
    }
}

Gatilho HTTP, gravar um registro em uma tabela

O exemplo a seguir mostra uma associação de saída do Azure Data Explorer em uma função Java que adiciona um registro de produto a uma tabela. A função usa dados fornecidos em uma solicitação HTTP POST como um corpo JSON. A função usa outra dependência da biblioteca com.fasterxml.jackson.core para analisar o corpo JSON.

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.13.4.1</version>
</dependency>
package com.microsoft.azure.kusto.outputbindings;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.microsoft.azure.functions.HttpMethod;
import com.microsoft.azure.functions.HttpRequestMessage;
import com.microsoft.azure.functions.HttpResponseMessage;
import com.microsoft.azure.functions.HttpStatus;
import com.microsoft.azure.functions.OutputBinding;
import com.microsoft.azure.functions.annotation.AuthorizationLevel;
import com.microsoft.azure.functions.annotation.FunctionName;
import com.microsoft.azure.functions.annotation.HttpTrigger;
import com.microsoft.azure.functions.kusto.annotation.KustoOutput;
import com.microsoft.azure.kusto.common.Product;

import java.io.IOException;
import java.util.Optional;

import static com.microsoft.azure.kusto.common.Constants.*;

public class AddProduct {
    @FunctionName("AddProduct")
    public HttpResponseMessage run(@HttpTrigger(name = "req", methods = {
            HttpMethod.POST}, authLevel = AuthorizationLevel.ANONYMOUS, route = "addproductuni") HttpRequestMessage<Optional<String>> request,
            @KustoOutput(name = "product", database = "productsdb", tableName = "Products", connection = KUSTOCONNSTR) OutputBinding<Product> product)
            throws IOException {

        if (request.getBody().isPresent()) {
            String json = request.getBody().get();
            ObjectMapper mapper = new ObjectMapper();
            Product p = mapper.readValue(json, Product.class);
            product.setValue(p);
            return request.createResponseBuilder(HttpStatus.OK).header("Content-Type", "application/json").body(product)
                    .build();
        } else {
            return request.createResponseBuilder(HttpStatus.NO_CONTENT).header("Content-Type", "application/json")
                    .build();
        }
    }
}

Gatilho HTTP, gravação em duas tabelas

O exemplo a seguir mostra uma associação de saída do Azure Data Explorer em uma função Java que adiciona um registro a um banco de dados em duas tabelas diferentes (Product e ProductChangeLog). A função usa dados fornecidos em uma solicitação HTTP POST como um corpo JSON e várias ligações de saída. A função usa outra dependência da biblioteca com.fasterxml.jackson.core para analisar o corpo JSON.

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.13.4.1</version>
</dependency>

A segunda tabela, ProductsChangeLog, corresponde à seguinte definição:

.create-merge table ProductsChangeLog (ProductID:long, CreatedAt:datetime)

e a classe Java em ProductsChangeLog.java:

package com.microsoft.azure.kusto.common;

import com.fasterxml.jackson.annotation.JsonProperty;

public class ProductsChangeLog {
    @JsonProperty("ProductID")
    public long ProductID;
    @JsonProperty("CreatedAt")
    public String CreatedAt;

    public ProductsChangeLog() {
    }

    public ProductsChangeLog(long ProductID, String CreatedAt) {
        this.ProductID = ProductID;
        this.CreatedAt = CreatedAt;
    }
}
package com.microsoft.azure.kusto.outputbindings;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.microsoft.azure.functions.HttpMethod;
import com.microsoft.azure.functions.HttpRequestMessage;
import com.microsoft.azure.functions.HttpResponseMessage;
import com.microsoft.azure.functions.HttpStatus;
import com.microsoft.azure.functions.OutputBinding;
import com.microsoft.azure.functions.annotation.AuthorizationLevel;
import com.microsoft.azure.functions.annotation.FunctionName;
import com.microsoft.azure.functions.annotation.HttpTrigger;
import com.microsoft.azure.functions.kusto.annotation.KustoOutput;
import com.microsoft.azure.kusto.common.Product;
import com.microsoft.azure.kusto.common.ProductsChangeLog;

import static com.microsoft.azure.kusto.common.Constants.*;

import java.io.IOException;
import java.time.Clock;
import java.time.Instant;
import java.util.Optional;

public class AddMultiTable {
    @FunctionName("AddMultiTable")
    public HttpResponseMessage run(@HttpTrigger(name = "req", methods = {
            HttpMethod.POST}, authLevel = AuthorizationLevel.ANONYMOUS, route = "addmultitable") HttpRequestMessage<Optional<String>> request,
            @KustoOutput(name = "product", database = "productsdb", tableName = "Products", connection = KUSTOCONNSTR) OutputBinding<Product> product,
            @KustoOutput(name = "productChangeLog", database = "productsdb", tableName = "ProductsChangeLog",
                    connection = KUSTOCONNSTR) OutputBinding<ProductsChangeLog> productChangeLog)
            throws IOException {

        if (request.getBody().isPresent()) {
            String json = request.getBody().get();
            ObjectMapper mapper = new ObjectMapper();
            Product p = mapper.readValue(json, Product.class);
            product.setValue(p);
            productChangeLog.setValue(new ProductsChangeLog(p.ProductID, Instant.now(Clock.systemUTC()).toString()));
            return request.createResponseBuilder(HttpStatus.OK).header("Content-Type", "application/json").body(product)
                    .build();
        } else {
            return request.createResponseBuilder(HttpStatus.NO_CONTENT).header("Content-Type", "application/json")
                    .build();
        }
    }
}

Mais exemplos da associação de saída do Azure Data Explorer estão disponíveis no Repositório do GitHub.

Esta seção contém os seguintes exemplos:

Os exemplos se referem a uma tabela de banco de dados.

Os exemplos referem-se às tabelas Products e ProductsChangeLog (definidas anteriormente).

Gatilho HTTP, gravar registros em uma tabela

O exemplo a seguir mostra uma associação de saída do Azure Data Explorer em um arquivo function.json e uma função de script C# que adiciona registros a uma tabela. A função usa dados fornecidos em uma solicitação HTTP POST como um corpo JSON.

Veja a seguir o exemplo da associação de dados no arquivo function.json:

{
  "bindings": [
    {
      "authLevel": "function",
      "name": "req",
      "direction": "in",
      "type": "httpTrigger",
      "methods": [
        "post"
      ],
      "route": "addproduct"
    },
    {
      "name": "$return",
      "type": "http",
      "direction": "out"
    },
    {
      "name": "product",
      "type": "kusto",
      "database": "productsdb",
      "direction": "out",
      "tableName": "Products",
      "connection": "KustoConnectionString"
    }
  ],
  "disabled": false
}

A seção configuração explica essas propriedades.

O snippet a seguir é um exemplo de código JavaScript:

// Insert the product, which will insert it into the Products table.
module.exports = async function (context, req) {
    // Note that this expects the body to be a JSON object or array of objects which have a property
    // matching each of the columns in the table to insert to.
    context.bindings.product = req.body;
    return {
        status: 201,
        body: req.body
    };
}

Gatilho HTTP, gravação em duas tabelas

O exemplo a seguir mostra uma associação de saída do Azure Data Explorer em um arquivo function.json e uma função de script C# que adiciona registros a um banco de dados em duas tabelas diferentes (Products e ProductsChangeLog). A função usa dados fornecidos em uma solicitação HTTP POST como um corpo JSON e várias ligações de saída.

A segunda tabela, ProductsChangeLog, corresponde à seguinte definição:

.create-merge table ProductsChangeLog (ProductID:long, CreatedAt:datetime)

Veja a seguir o snippet da associação de dados no arquivo function.json:

{
  "bindings": [
    {
      "authLevel": "function",
      "name": "req",
      "direction": "in",
      "type": "httpTrigger",
      "methods": [
        "post"
      ],
      "route": "addmultitable"
    },
    {
      "name": "res",
      "type": "http",
      "direction": "out"
    },
    {
      "name": "product",
      "type": "kusto",
      "database": "productsdb",
      "direction": "out",
      "tableName": "Products",
      "connection": "KustoConnectionString"
    },
    {
      "name": "productchangelog",
      "type": "kusto",
      "database": "productsdb",
      "direction": "out",
      "tableName": "ProductsChangeLog",
      "connection": "KustoConnectionString"
    }
  ],
  "disabled": false
}

A seção configuração explica essas propriedades.

O snippet a seguir é um exemplo de código JavaScript:

module.exports = async function (context, req) {
    context.log('JavaScript HTTP trigger and Kusto output binding function processed a request.');
    context.log(req.body);

    if (req.body) {
        var changeLog = {ProductID:req.body.ProductID, CreatedAt: new Date().toISOString()};
        context.bindings.product = req.body;
        context.bindings.productchangelog = changeLog;
        context.res = {
            body: req.body,
            mimetype: "application/json",
            status: 201
        }
    } else {
        context.res = {
            status: 400,
            body: "Error reading request body"
        }
    }
}

Mais exemplos da associação de saída do Azure Data Explorer estão disponíveis no Repositório do GitHub.

Esta seção contém os seguintes exemplos:

Os exemplos referem-se às tabelas Products e ProductsChangeLog (definidas anteriormente).

Gatilho HTTP, gravar registros em uma tabela

O exemplo a seguir mostra uma associação de saída do Azure Data Explorer em um arquivo function.json e uma função Python que adiciona registros a uma tabela. A função usa dados fornecidos em uma solicitação HTTP POST como um corpo JSON.

Veja a seguir o snippet da associação de dados no arquivo function.json:

{
  "scriptFile": "__init__.py",
  "bindings": [
    {
      "authLevel": "Anonymous",
      "type": "httpTrigger",
      "direction": "in",
      "name": "req",
      "methods": [
        "post"
      ],
      "route": "addproductuni"
    },
    {
      "type": "http",
      "direction": "out",
      "name": "$return"
    },
    {
      "name": "product",
      "type": "kusto",
      "database": "sdktestsdb",
      "direction": "out",
      "tableName": "Products",
      "connection": "KustoConnectionString"
    }
  ]
}

A seção configuração explica essas propriedades.

O snippet a seguir é um exemplo de código Python:

import azure.functions as func
from Common.product import Product


def main(req: func.HttpRequest, product: func.Out[str]) -> func.HttpResponse:
    body = str(req.get_body(),'UTF-8')
    product.set(body)
    return func.HttpResponse(
        body=body,
        status_code=201,
        mimetype="application/json"
    )

Gatilho HTTP, gravação em duas tabelas

O exemplo a seguir mostra uma associação de saída do Azure Data Explorer em um arquivo function.json e uma função de script C# que adiciona registros a um banco de dados em duas tabelas diferentes (Products e ProductsChangeLog). A função usa dados fornecidos em uma solicitação HTTP POST como um corpo JSON e várias ligações de saída. A segunda tabela, ProductsChangeLog, corresponde à seguinte definição:

.create-merge table ProductsChangeLog (ProductID:long, CreatedAt:datetime)

Veja a seguir o snippet da associação de dados no arquivo function.json:

{
  "scriptFile": "__init__.py",
  "bindings": [
    {
      "authLevel": "Anonymous",
      "type": "httpTrigger",
      "direction": "in",
      "name": "req",
      "methods": [
        "post"
      ],
      "route": "addmultitable"
    },
    {
      "type": "http",
      "direction": "out",
      "name": "$return"
    },
    {
      "name": "product",
      "type": "kusto",
      "database": "sdktestsdb",
      "direction": "out",
      "tableName": "Products",
      "connection": "KustoConnectionString"
    },
    {
      "name": "productchangelog",
      "type": "kusto",
      "database": "sdktestsdb",
      "direction": "out",
      "tableName": "ProductsChangeLog",
      "connection": "KustoConnectionString"
    }
  ]
}

A seção configuração explica essas propriedades.

O snippet a seguir é um exemplo de código Python:

import json
from datetime import datetime

import azure.functions as func
from Common.product import Product


def main(req: func.HttpRequest, product: func.Out[str],productchangelog: func.Out[str]) -> func.HttpResponse:
    body = str(req.get_body(),'UTF-8')
    # parse x:
    product.set(body)
    id = json.loads(body)["ProductID"]

    changelog = {
        "ProductID": id,
        "CreatedAt": datetime.now().isoformat(),
    }
    productchangelog.set(json.dumps(changelog))
    return func.HttpResponse(
        body=body,
        status_code=201,
        mimetype="application/json"
    )

Atributos

A biblioteca C# usa o atributo KustoAttribute para declarar as associações do Azure Data Explorer na função, que tem as seguintes propriedades.

Propriedade de atributo Descrição
Banco de dados Obrigatórios. O banco de dados no qual a consulta deve ser executada.
Conexão Obrigatórios. O nome da variável que contém a cadeia de conexão, resolvida por meio de variáveis de ambiente ou por meio de configurações do aplicativo de funções. O padrão é pesquisar na variável KustoConnectionString. No runtime, essa variável é pesquisada no ambiente. A cadeia de conexão está documentada nas cadeias de conexão do Kusto. Por exemplo: "KustoConnectionString": "Data Source=https://your_cluster.kusto.windows.net;Database=your_Database;Fed=True;AppClientId=your_AppId;AppKey=your_AppKey;Authority Id=your_TenantId.
TableName Obrigatórios. A tabela na qual ingerir os dados.
MappingRef Opcional. Atributo para passar uma referência de mapeamento que já está definida no cluster.
ManagedServiceIdentity Opcional. Uma identidade gerenciada pode ser usada para se conectar ao Azure Data Explorer. Para usar uma identidade gerenciada pelo sistema, use "system". Todos os outros nomes de identidade são interpretados como identidade gerenciada pelo usuário.
DataFormat Opcional. O formato de dados padrão é multijson/json. Isso ser definido como formatos de texto com suporte no formato de datasource enumeração. Os exemplos são validados e fornecidos para formatos CSV e JSON.

Anotações

A biblioteca de runtime de funções Java usa a anotação @KustoInput (com.microsoft.azure.functions.kusto.annotation.KustoOutput):

Elemento Descrição
name Obrigatórios. O nome da variável que representa os resultados da consulta no código da função.
Banco de Dados Obrigatórios. O banco de dados no qual a consulta deve ser executada.
connection Obrigatórios. O nome da variável que contém a cadeia de conexão, resolvida por meio de variáveis de ambiente ou por meio de configurações do aplicativo de funções. O padrão é pesquisar na variável KustoConnectionString. No runtime, essa variável é pesquisada no ambiente. A cadeia de conexão está documentada nas cadeias de conexão do Kusto. Por exemplo: "KustoConnectionString": "Data Source=https://your_cluster.kusto.windows.net;Database=your_Database;Fed=True;AppClientId=your_AppId;AppKey=your_AppKey;Authority Id=your_TenantId.
tableName Obrigatórios. A tabela na qual ingerir os dados.
mappingRef Opcional. Atributo para passar uma referência de mapeamento que já está definida no cluster.
dataFormat Opcional. O formato de dados padrão é multijson/json. Isso ser definido como formatos de texto com suporte no formato de datasource enumeração. Os exemplos são validados e fornecidos para formatos CSV e JSON.
managedServiceIdentity Uma identidade gerenciada pode ser usada para se conectar ao Azure Data Explorer. Para usar uma identidade gerenciada pelo sistema, use "system". Todos os outros nomes de identidade são interpretados como identidade gerenciada pelo usuário.

Configuração

A tabela a seguir explica as propriedades de configuração de associação que você define no arquivo function.json.

Propriedade function.json Descrição
type Obrigatórios. Deve ser definido como kusto.
direction Obrigatórios. Deve ser definido como out.
name Obrigatórios. O nome da variável que representa os resultados da consulta no código da função.
Banco de Dados Obrigatórios. O banco de dados no qual a consulta deve ser executada.
connection Obrigatórios. O nome da variável que contém a cadeia de conexão, resolvida por meio de variáveis de ambiente ou por meio de configurações do aplicativo de funções. O padrão é pesquisar na variável KustoConnectionString. No runtime, essa variável é pesquisada no ambiente. A cadeia de conexão está documentada nas cadeias de conexão do Kusto. Por exemplo: "KustoConnectionString": "Data Source=https://your_cluster.kusto.windows.net;Database=your_Database;Fed=True;AppClientId=your_AppId;AppKey=your_AppKey;Authority Id=your_TenantId.
tableName Obrigatórios. A tabela na qual ingerir os dados.
mappingRef Opcional. Atributo para passar uma referência de mapeamento que já está definida no cluster.
dataFormat Opcional. O formato de dados padrão é multijson/json. Isso ser definido como formatos de texto com suporte no formato de datasource enumeração. Os exemplos são validados e fornecidos para formatos CSV e JSON.
managedServiceIdentity Uma identidade gerenciada pode ser usada para se conectar ao Azure Data Explorer. Para usar uma identidade gerenciada pelo sistema, use "system". Todos os outros nomes de identidade são interpretados como identidade gerenciada pelo usuário.

Quando você estiver desenvolvendo localmente, adicione as configurações do aplicativo no arquivo local.settings.json na coleção Values.

Uso

O construtor do atributo usa o banco de dados e os atributos TableName, MappingRef e DataFormat e o nome da configuração de conexão. O comando KQL pode ser uma instrução KQL ou uma função KQL. O nome da configuração da cadeia de conexão corresponde à configuração do aplicativo (em local.settings.json para desenvolvimento local) que contém as cadeias de conexão Kusto. Por exemplo: "KustoConnectionString": "Data Source=https://your_cluster.kusto.windows.net;Database=your_Database;Fed=True;AppClientId=your_AppId;AppKey=your_AppKey;Authority Id=your_TenantId. As consultas executadas pela associação de entrada são parametrizadas. Os valores fornecidos nos parâmetros KQL são usados em runtime.

Próximas etapas

Leitura de dados de uma tabela (associação de entrada)