Enlaces de salida de Azure Data Explorer para Azure Functions (versión preliminar)

Cuando se ejecuta una función, el enlace de salida de Azure Data Explorer ingiere datos en Azure Data Explorer.

Para obtener información sobre los detalles de instalación y configuración, vea la información general.

Ejemplos

Se puede crear una función C# mediante uno de los siguientes modos de C#:

  • Modelo de trabajo aislado: función compilada en C# que se ejecuta en un proceso trabajador aislado del tiempo de ejecución. Se requiere un proceso de trabajo aislado para admitir funciones de C# ejecutándose en versiones de .NET que son y no son LTS y .NET Framework.
  • Modelo en curso: función C# compilada que se ejecuta en el mismo proceso que el tiempo de ejecución de Functions.
  • Script de C#: se usa principalmente al crear funciones de C# en Azure Portal.

Hay disponibles más ejemplos para el enlace de salida de Azure Data Explorer en el repositorio de GitHub.

En esta sección se incluyen los ejemplos siguientes:

Los ejemplos hacen referencia a una clase Product y una tabla de base de datos correspondiente:

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)

Desencadenador HTTP, escribir un registro

En el ejemplo siguiente se muestra una función de C# que agrega un registro a una base de datos. La función utiliza los datos proporcionados en una solicitud HTTP POST como un cuerpo 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 { };
        }
    }
}

Desencadenador HTTP, escritura de registros con asignación

En el ejemplo siguiente se muestra una función de C# que agrega una colección de registros a una base de datos. La función usa la asignación que transforma un objeto Product en Item.

Para transformar datos de Product a Item, la función usa una referencia de asignación:

.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 { };
        }
    }
}

Hay disponibles más ejemplos para el enlace de entrada de Azure Data Explorer en el repositorio de GitHub.

En esta sección se incluyen los ejemplos siguientes:

En este ejemplo se hace referencia a una clase Products (en un archivo Product.java independiente) y una tabla de base de datos correspondiente 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;
    }
}

Desencadenador HTTP, escritura de registros en una tabla

En el siguiente ejemplo se muestra un enlace de salida de Azure Data Explorer en una función de Java que agrega un registro de producto a una tabla. La función utiliza los datos proporcionados en una solicitud HTTP POST como un cuerpo JSON. La función toma otra dependencia de la biblioteca com.fasterxml.jackson.core para analizar el cuerpo 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();
        }
    }
}

Desencadenador HTTP, escritura en dos tablas

En el siguiente ejemplo se muestra un enlace de salida de Azure Data Explorer en una función de Java que agrega registros a una base de datos en dos tablas diferentes (Product y ProductChangeLog). La función utiliza los datos proporcionados en una solicitud HTTP POST como un cuerpo JSON y varios enlaces de salida. La función toma otra dependencia de la biblioteca com.fasterxml.jackson.core para analizar el cuerpo JSON.

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

La segunda tabla, ProductsChangeLog, corresponde a la siguiente definición:

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

y la clase de Java en 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();
        }
    }
}

Hay disponibles más ejemplos para el enlace de salida de Azure Data Explorer en el repositorio de GitHub.

En esta sección se incluyen los ejemplos siguientes:

Los ejemplos hacen referencia a una tabla de base de datos.

Los ejemplos hacen referencia a las tablas Products y ProductsChangeLog (definidas anteriormente).

Desencadenador HTTP, escritura de registros en una tabla

En el ejemplo siguiente se muestra un enlace de salida de Azure Data Explorer en un archivo function.json y una función de JavaScript que agrega registros a una tabla. La función utiliza los datos proporcionados en una solicitud HTTP POST como un cuerpo JSON.

En el siguiente ejemplo se muestran los datos de enlace del archivo 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
}

En la sección de configuración se explican estas propiedades.

El siguiente fragmento de código es un ejemplo de código de 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
    };
}

Desencadenador HTTP, escritura en dos tablas

En el ejemplo siguiente se muestra un enlace de salida de Azure Data Explorer en un archivo function.json y una función de JavaScript que agrega registros a una base de datos en dos tablas diferentes (Products y ProductsChangeLog). La función utiliza los datos proporcionados en una solicitud HTTP POST como un cuerpo JSON y varios enlaces de salida.

La segunda tabla, ProductsChangeLog, corresponde a la siguiente definición:

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

El siguiente fragmento de código enlaza datos en el archivo 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
}

En la sección de configuración se explican estas propiedades.

El siguiente fragmento de código es un ejemplo de código de 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"
        }
    }
}

Hay disponibles más ejemplos para el enlace de salida de Azure Data Explorer en el repositorio de GitHub.

En esta sección se incluyen los ejemplos siguientes:

Los ejemplos hacen referencia a las tablas Products y ProductsChangeLog (definidas anteriormente).

Desencadenador HTTP, escritura de registros en una tabla

En el ejemplo siguiente se muestra un enlace de salida de Azure Data Explorer en un archivo function.json y una función de Python que agrega registros a una tabla. La función utiliza los datos proporcionados en una solicitud HTTP POST como un cuerpo JSON.

El siguiente fragmento de código enlaza datos en el archivo 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"
    }
  ]
}

En la sección de configuración se explican estas propiedades.

El siguiente fragmento de código es un ejemplo 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"
    )

Desencadenador HTTP, escritura en dos tablas

En el ejemplo siguiente se muestra un enlace de salida de Azure Data Explorer en un archivo function.json y una función de JavaScript que agrega registros a una base de datos en dos tablas diferentes (Products y ProductsChangeLog). La función utiliza los datos proporcionados en una solicitud HTTP POST como un cuerpo JSON y varios enlaces de salida. La segunda tabla, ProductsChangeLog, corresponde a la siguiente definición:

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

El siguiente fragmento de código enlaza datos en el archivo 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"
    }
  ]
}

En la sección de configuración se explican estas propiedades.

El siguiente fragmento de código es un ejemplo 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

La biblioteca de C# usa el atributo KustoAttribute para declarar los enlaces de Azure Data Explorer en la función, que tiene las siguientes propiedades.

Propiedad de atributo Descripción
Base de datos Necesario. La base de datos en la que se debe ejecutar la consulta.
Conexión Necesario. El nombre de la variable que contiene la cadena de conexión, resuelta a través de variables de entorno o a través de la configuración de la aplicación de funciones. El valor predeterminado que se busca en la variable KustoConnectionString. En el runtime, esta variable se compara con el entorno. La documentación sobre la cadena de conexión está en las cadenas de conexión de Kusto. Por ejemplo: "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 Necesario. Tabla en la que se van a ingerir los datos.
MappingRef Opcional. Atributo para pasar una referencia de asignación que ya está definida en el clúster.
ManagedServiceIdentity Opcional. Se puede usar una identidad administrada para conectarse a Azure Data Explorer. Para usar una identidad administrada por el sistema, use "system"; cualquier otro nombre de identidad se interpreta como identidad administrada por el usuario.
DataFormat Opcional. El formato predeterminado de datos es multijson/json. Esto se puede establecer en formatos de texto admitidos en la enumeración del formato datasource de origen de datos. Los ejemplos se validan y proporcionan para formatos CSV y JSON.

anotaciones

La biblioteca del runtime de funciones de Java usa la anotación @KustoInput (com.microsoft.azure.functions.kusto.annotation.KustoOutput).

Elemento Descripción
name Necesario. Nombre de la variable que representa los resultados de la consulta en el código de la función.
database Necesario. La base de datos en la que se debe ejecutar la consulta.
conexión Necesario. El nombre de la variable que contiene la cadena de conexión, resuelta a través de variables de entorno o a través de la configuración de la aplicación de funciones. El valor predeterminado que se busca en la variable KustoConnectionString. En el runtime, esta variable se compara con el entorno. La documentación sobre la cadena de conexión está en las cadenas de conexión de Kusto. Por ejemplo: "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 Necesario. Tabla en la que se van a ingerir los datos.
mappingRef Opcional. Atributo para pasar una referencia de asignación que ya está definida en el clúster.
dataFormat Opcional. El formato predeterminado de datos es multijson/json. Esto se puede establecer en formatos de texto admitidos en la enumeración del formato datasource de origen de datos. Los ejemplos se validan y proporcionan para formatos CSV y JSON.
managedServiceIdentity Se puede usar una identidad administrada para conectarse a Azure Data Explorer. Para usar una identidad administrada por el sistema, use "system"; cualquier otro nombre de identidad se interpreta como identidad administrada por el usuario.

Configuración

En la siguiente tabla se explican las propiedades de configuración de enlace que se establecen en el archivo function.json.

Propiedad de function.json Descripción
type Necesario. Se debe establecer en kusto.
direction Necesario. Se debe establecer en out.
name Necesario. Nombre de la variable que representa los resultados de la consulta en el código de la función.
database Necesario. La base de datos en la que se debe ejecutar la consulta.
conexión Necesario. El nombre de la variable que contiene la cadena de conexión, resuelta a través de variables de entorno o a través de la configuración de la aplicación de funciones. El valor predeterminado que se busca en la variable KustoConnectionString. En el runtime, esta variable se compara con el entorno. La documentación sobre la cadena de conexión está en las cadenas de conexión de Kusto. Por ejemplo: "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 Necesario. Tabla en la que se van a ingerir los datos.
mappingRef Opcional. Atributo para pasar una referencia de asignación que ya está definida en el clúster.
dataFormat Opcional. El formato predeterminado de datos es multijson/json. Esto se puede establecer en formatos de texto admitidos en la enumeración del formato datasource de origen de datos. Los ejemplos se validan y proporcionan para formatos CSV y JSON.
managedServiceIdentity Se puede usar una identidad administrada para conectarse a Azure Data Explorer. Para usar una identidad administrada por el sistema, use "system"; cualquier otro nombre de identidad se interpreta como identidad administrada por el usuario.

Cuando esté desarrollando localmente, agregue la configuración de la aplicación en el archivo local.settings.json de la colección Values.

Uso

El constructor del atributo toma la base de datos y los atributos TableName, MappingRef y DataFormat y el nombre de la configuración de conexión. El comando de KQL puede ser una instrucción KQL o una función KQL. El nombre de la configuración de la cadena de conexión se corresponde con la configuración de la aplicación (en local.settings.json para el desarrollo local) que contiene las cadenas de conexiones Kusto. Por ejemplo: "KustoConnectionString": "Data Source=https://your_cluster.kusto.windows.net;Database=your_Database;Fed=True;AppClientId=your_AppId;AppKey=your_AppKey;Authority Id=your_TenantId. Las consultas ejecutadas por el enlace de entrada se parametrizan. Los valores proporcionados en los parámetros KQL se usan en el runtime.

Pasos siguientes

Leer datos de una tabla (enlace de entrada)