Tworzenie funkcji biblioteki klas języka C# przy użyciu Azure Functions

Ten artykuł stanowi wprowadzenie do tworzenia Azure Functions przy użyciu języka C# w bibliotekach klas platformy .NET.

Ważne

W tym artykule obsługiwane są funkcje biblioteki klas platformy .NET, które są uruchamiane w procesie w środowisku uruchomieniowym. Funkcje języka C# mogą również zabrakło możliwości przetwarzania i odizolować od środowiska uruchomieniowego usługi Functions. Model izolowanego procesu roboczego to jedyny sposób uruchamiania wersji innych niż LTS platformy .NET i .NET Framework aplikacji w bieżących wersjach środowiska uruchomieniowego usługi Functions. Aby dowiedzieć się więcej, zobacz Funkcje procesów procesów procesów izolowanych na platformie .NET. Aby uzyskać kompleksowe porównanie izolowanego procesu roboczego i przetwarzania funkcji .NET, zobacz Różnice między procesem w procesie i izolowanym procesem roboczym .NET Azure Functions.

Jako deweloper języka C# możesz również zainteresować się jednym z następujących artykułów:

Wprowadzenie Pojęcia Nauka/przykłady z przewodnikiem

Azure Functions obsługuje języki programowania skryptów języka C# i C#. Jeśli szukasz wskazówek dotyczących korzystania z języka C# w Azure Portal, zobacz dokumentację dla deweloperów skryptu języka C# (csx).

Obsługiwane wersje

Wersje środowiska uruchomieniowego usługi Functions współpracują z określonymi wersjami platformy .NET. Aby dowiedzieć się więcej na temat wersji usługi Functions, zobacz omówienie wersji środowiska uruchomieniowego Azure Functions. Obsługa wersji zależy od tego, czy funkcje działają w procesie przetwarzania, czy izolowanego procesu roboczego.

Uwaga

Aby dowiedzieć się, jak zmienić wersję środowiska uruchomieniowego usługi Functions używaną przez aplikację funkcji, zobacz wyświetlanie i aktualizowanie bieżącej wersji środowiska uruchomieniowego.

W poniższej tabeli przedstawiono najwyższy poziom platformy .NET Core lub .NET Framework, który może być używany z określoną wersją usługi Functions.

Wersja środowiska uruchomieniowego usługi Functions Wewnątrz procesu
(Biblioteka klas platformy .NET)
Proces izolowanego procesu roboczego
(Izolowana platforma.NET)
Functions 4.x .NET 6.0 .NET 6.0
.NET 7.0 (GA)1
.NET Framework 4.8 (GA)1
Functions 3.x .NET Core 3.1
Functions w wersji 2.x .NET Core 2.12 n/d
Functions w wersji 1.x .NET Framework 4.8 n/d

1 Proces kompilacji wymaga również zestawu .NET 6 SDK. Obsługa .NET Framework 4.8 jest ogólnie dostępna.

2 Aby uzyskać szczegółowe informacje, zobacz Zagadnienia dotyczące funkcji w wersji 2.x.

Najnowsze informacje o Azure Functions wydaniach, w tym o usunięciu określonych starszych wersji pomocniczych, monitoruj Azure App Service ogłoszeń.

Zagadnienia dotyczące funkcji w wersji 2.x

Aplikacje funkcji przeznaczone dla najnowszej wersji 2.x (~2) są automatycznie uaktualniane do uruchamiania na platformie .NET Core 3.1. Ze względu na zmiany powodujące niezgodność między wersjami platformy .NET Core nie wszystkie aplikacje opracowane i skompilowane na platformie .NET Core 2.2 można bezpiecznie uaktualnić do platformy .NET Core 3.1. Możesz zrezygnować z tego uaktualnienia, przypinając aplikację funkcji do ~2.0. Funkcje wykrywa również niezgodne interfejsy API i mogą przypiąć aplikację, aby ~2.0 zapobiec nieprawidłowemu wykonywaniu na platformie .NET Core 3.1.

Uwaga

Jeśli aplikacja funkcji jest przypięta do ~2.0 elementu docelowego i zmienisz tę wersję na ~2, aplikacja funkcji może ulec awarii. Jeśli wdrażasz przy użyciu szablonów usługi ARM, sprawdź wersję w szablonach. W takim przypadku zmień wersję z powrotem na docelową ~2.0 i rozwiąż problemy ze zgodnością.

Aplikacje funkcji przeznaczone ~2.0 do kontynuowania działania na platformie .NET Core 2.2. Ta wersja platformy .NET Core nie odbiera już aktualizacji zabezpieczeń i innych aktualizacji konserwacji. Aby dowiedzieć się więcej, zobacz tę stronę ogłoszenia.

Należy pracować nad tym, aby funkcje były zgodne z platformą .NET Core 3.1 tak szybko, jak to możliwe. Po rozwiązaniu tych problemów zmień wersję z powrotem na ~2 lub uaktualnij ją do ~3. Aby dowiedzieć się więcej na temat określania docelowych wersji środowiska uruchomieniowego usługi Functions, zobacz How to target Azure Functions runtime versions (Jak kierować się wersjami środowiska uruchomieniowego Azure Functions).

W przypadku uruchamiania w systemie Linux w planie Premium lub dedykowanym (App Service) należy przypiąć wersję, zamiast tego ustawiając określony obraz, ustawiając linuxFxVersion ustawienie konfiguracji witryny na wartość DOCKER|mcr.microsoft.com/azure-functions/dotnet:2.0.14786-appservice Aby dowiedzieć się, jak ustawić linuxFxVersion, zobacz Ręczne aktualizacje wersji w systemie Linux.

Projekt biblioteki klas usługi Functions

W programie Visual Studio szablon projektu Azure Functions tworzy projekt biblioteki klas języka C#zawierający następujące pliki:

  • host.json — przechowuje ustawienia konfiguracji, które mają wpływ na wszystkie funkcje w projekcie podczas uruchamiania lokalnie lub na platformie Azure.
  • local.settings.json — przechowuje ustawienia aplikacji i parametry połączenia używane podczas uruchamiania lokalnego. Ten plik zawiera wpisy tajne i nie jest publikowany w aplikacji funkcji na platformie Azure. Zamiast tego dodaj ustawienia aplikacji do aplikacji funkcji.

Podczas kompilowania projektu struktura folderów, która wygląda podobnie do poniższego przykładu, jest generowana w katalogu wyjściowym kompilacji:

<framework.version>
 | - bin
 | - MyFirstFunction
 | | - function.json
 | - MySecondFunction
 | | - function.json
 | - host.json

Ten katalog jest tym, co jest wdrażane w aplikacji funkcji na platformie Azure. Rozszerzenia powiązań wymagane w wersji 2.x środowiska uruchomieniowego usługi Functions są dodawane do projektu jako pakiety NuGet.

Ważne

Proces kompilacji tworzy plik function.json dla każdej funkcji. Ten plik function.json nie ma być edytowany bezpośrednio. Nie można zmienić konfiguracji powiązania ani wyłączyć funkcji, edytując ten plik. Aby dowiedzieć się, jak wyłączyć funkcję, zobacz Jak wyłączyć funkcje.

Metody rozpoznawane jako funkcje

W bibliotece klas funkcja jest metodą z atrybutem FunctionName wyzwalacza i, jak pokazano w poniższym przykładzie:

public static class SimpleExample
{
    [FunctionName("QueueTrigger")]
    public static void Run(
        [QueueTrigger("myqueue-items")] string myQueueItem, 
        ILogger log)
    {
        log.LogInformation($"C# function processed: {myQueueItem}");
    }
} 

Atrybut FunctionName oznacza metodę jako punkt wejścia funkcji. Nazwa musi być unikatowa w projekcie, zaczynać się literą i zawierać tylko litery, cyfry, _i -, maksymalnie 127 znaków. Szablony projektów często tworzą metodę o nazwie Run, ale nazwa metody może być dowolną prawidłową nazwą metody języka C#. W powyższym przykładzie pokazano używaną metodę statyczną, ale funkcje nie muszą być statyczne.

Atrybut wyzwalacza określa typ wyzwalacza i wiąże dane wejściowe z parametrem metody. Przykładowa funkcja jest wyzwalana przez komunikat kolejki, a komunikat kolejki jest przekazywany do metody w parametrze myQueueItem .

Parametry podpisu metody

Sygnatura metody może zawierać parametry inne niż używane z atrybutem wyzwalacza. Oto kilka innych parametrów, które można uwzględnić:

Kolejność parametrów w podpisie funkcji nie ma znaczenia. Można na przykład umieścić parametry wyzwalacza przed lub po innych powiązaniach i można umieścić parametr rejestratora przed lub po wyzwalaczu lub po parametrach powiązania.

Powiązania wyjściowe

Funkcja może mieć zero lub jedno powiązanie wyjściowe zdefiniowane przy użyciu parametrów wyjściowych.

Poniższy przykład modyfikuje poprzedni, dodając powiązanie kolejki wyjściowej o nazwie myQueueItemCopy. Funkcja zapisuje zawartość komunikatu, który wyzwala funkcję do nowego komunikatu w innej kolejce.

public static class SimpleExampleWithOutput
{
    [FunctionName("CopyQueueMessage")]
    public static void Run(
        [QueueTrigger("myqueue-items-source")] string myQueueItem, 
        [Queue("myqueue-items-destination")] out string myQueueItemCopy,
        ILogger log)
    {
        log.LogInformation($"CopyQueueMessage function processed: {myQueueItem}");
        myQueueItemCopy = myQueueItem;
    }
}

Wartości przypisane do powiązań wyjściowych są zapisywane po zakończeniu działania funkcji. W funkcji można użyć więcej niż jednego powiązania wyjściowego, przypisując wartości do wielu parametrów wyjściowych.

Artykuły referencyjne dotyczące powiązań (na przykład kolejki usługi Storage) wyjaśniają typy parametrów, których można używać z atrybutami wyzwalacza, danych wejściowych lub wyjściowych.

Przykład wyrażeń powiązań

Poniższy kod pobiera nazwę kolejki do monitorowania z ustawienia aplikacji i pobiera czas tworzenia komunikatów w kolejce w parametrze insertionTime .

public static class BindingExpressionsExample
{
    [FunctionName("LogQueueMessage")]
    public static void Run(
        [QueueTrigger("%queueappsetting%")] string myQueueItem,
        DateTimeOffset insertionTime,
        ILogger log)
    {
        log.LogInformation($"Message content: {myQueueItem}");
        log.LogInformation($"Created at: {insertionTime}");
    }
}

Automatycznie wygenerowany plik function.json

Proces kompilacji tworzy plik function.json w folderze funkcji w folderze kompilacji. Jak wspomniano wcześniej, ten plik nie jest przeznaczony do bezpośredniej edycji. Nie można zmienić konfiguracji powiązania ani wyłączyć funkcji, edytując ten plik.

Celem tego pliku jest dostarczenie informacji kontrolerowi skalowania, które mają być używane do podejmowania decyzji dotyczących skalowania w planie Zużycie. Z tego powodu plik zawiera tylko informacje o wyzwalaczu, a nie powiązania wejściowe/wyjściowe.

Wygenerowany plik function.json zawiera configurationSource właściwość, która nakazuje środowisku uruchomieniowemu używanie atrybutów platformy .NET dla powiązań, a nie konfiguracji function.json . Oto przykład:

{
  "generatedBy": "Microsoft.NET.Sdk.Functions-1.0.0.0",
  "configurationSource": "attributes",
  "bindings": [
    {
      "type": "queueTrigger",
      "queueName": "%input-queue-name%",
      "name": "myQueueItem"
    }
  ],
  "disabled": false,
  "scriptFile": "..\\bin\\FunctionApp1.dll",
  "entryPoint": "FunctionApp1.QueueTrigger.Run"
}

Microsoft.NET. Sdk.Functions

Generowanie pliku function.json jest wykonywane przez pakiet NuGet Microsoft.NET. Sdk.Functions.

Ten sam pakiet jest używany zarówno w wersji 1.x, jak i 2.x środowiska uruchomieniowego usługi Functions. Platforma docelowa odróżnia projekt 1.x od projektu w wersji 2.x. Poniżej przedstawiono odpowiednie części .csproj plików z różnymi platformami docelowymi z tym samym Sdk pakietem:

<PropertyGroup>
  <TargetFramework>netcoreapp2.1</TargetFramework>
  <AzureFunctionsVersion>v2</AzureFunctionsVersion>
</PropertyGroup>
<ItemGroup>
  <PackageReference Include="Microsoft.NET.Sdk.Functions" Version="1.0.8" />
</ItemGroup>

Sdk Wśród zależności pakietów są wyzwalacze i powiązania. Projekt w wersji 1.x odwołuje się do wyzwalaczy i powiązań 1.x, ponieważ te wyzwalacze i powiązania są przeznaczone dla .NET Framework, a 2.x wyzwalacze i powiązania są przeznaczone dla platformy .NET Core.

Pakiet Sdk zależy również od pliku Newtonsoft.Json i pośrednio w systemie WindowsAzure.Storage. Te zależności zapewniają, że projekt korzysta z wersji tych pakietów, które współpracują z wersją środowiska uruchomieniowego usługi Functions przeznaczoną dla projektu. Na przykład Newtonsoft.Json ma wersję 11 dla .NET Framework 4.6.1, ale środowisko uruchomieniowe usługi Functions przeznaczone dla .NET Framework 4.6.1 jest zgodne tylko z wersją Newtonsoft.Json 9.0.1. Dlatego kod funkcji w tym projekcie musi również używać Newtonsoft.Json wersji 9.0.1.

Kod źródłowy dla Microsoft.NET.Sdk.Functions elementu jest dostępny w repozytorium GitHub azure-functions-vs-build-sdk.

Lokalna wersja środowiska uruchomieniowego

Program Visual Studio używa narzędzi Azure Functions Core Tools do uruchamiania projektów usługi Functions na komputerze lokalnym. Core Tools to interfejs wiersza polecenia dla środowiska uruchomieniowego usługi Functions.

Jeśli zainstalujesz narzędzia Core Tools przy użyciu pakietu Instalatora Windows (MSI) lub narzędzia npm, nie ma to wpływu na wersję narzędzi Core Tools używaną przez program Visual Studio. W przypadku środowiska uruchomieniowego usługi Functions w wersji 1.x program Visual Studio przechowuje wersje narzędzi Core Tools w folderze %USERPROFILE%\AppData\Local\Azure.Functions.Cli i używa najnowszej przechowywanej tam wersji. W przypadku usługi Functions 2.x narzędzia Core Tools są dołączone do rozszerzenia narzędzi Azure Functions i Web Jobs. W przypadku wersji 1.x i 2.x można zobaczyć, jaka wersja jest używana w danych wyjściowych konsoli podczas uruchamiania projektu usługi Functions:

[3/1/2018 9:59:53 AM] Starting Host (HostId=contoso2-1518597420, Version=2.0.11353.0, ProcessId=22020, Debug=False, Attempt=0, FunctionsExtensionVersion=)

ReadyToRun

Aplikację funkcji można skompilować jako pliki binarne ReadyToRun. ReadyToRun to forma kompilacji przed czasem, która może poprawić wydajność uruchamiania, aby zmniejszyć wpływ zimnego startu podczas uruchamiania w planie Zużycie.

Funkcja ReadyToRun jest dostępna na platformie .NET 3.1 i .NET 6 (w proc i izolowanym) oraz na platformie .NET 7 i wymaga wersji 3.0 lub 4.0 środowiska uruchomieniowego Azure Functions.

Aby skompilować projekt jako ReadyToRun, zaktualizuj plik projektu, dodając <PublishReadyToRun> elementy i <RuntimeIdentifier> . Poniżej przedstawiono konfigurację publikowania w aplikacji funkcji systemu Windows 32-bitowej.

<PropertyGroup>
  <TargetFramework>net6.0</TargetFramework>
  <AzureFunctionsVersion>v4</AzureFunctionsVersion>
  <PublishReadyToRun>true</PublishReadyToRun>
  <RuntimeIdentifier>win-x86</RuntimeIdentifier>
</PropertyGroup>

Ważne

Począwszy od platformy .NET 6, dodano obsługę kompilacji Composite ReadyToRun. Zapoznaj się z ograniczeniami dotyczącymi architektury i platformy ReadyToRun.

Możesz również skompilować aplikację za pomocą funkcji ReadyToRun z poziomu wiersza polecenia. Aby uzyskać więcej informacji, zobacz opcję w dotnet publishpliku -p:PublishReadyToRun=true .

Obsługiwane typy powiązań

Każde powiązanie ma własne obsługiwane typy; na przykład atrybut wyzwalacza obiektu blob można zastosować do parametru ciągu, parametru POCO, parametru CloudBlockBlob lub dowolnego z kilku innych obsługiwanych typów. Artykuł referencyjny dotyczący powiązań obiektów blob zawiera listę wszystkich obsługiwanych typów parametrów . Aby uzyskać więcej informacji, zobacz Wyzwalacze i powiązania oraz dokumentację referencyjną powiązań dla każdego typu powiązania.

Porada

Jeśli planujesz używać powiązań HTTP lub webhook, zaplanuj uniknięcie wyczerpania portów, które mogą być spowodowane przez niewłaściwe utworzenie wystąpienia elementu HttpClient. Aby uzyskać więcej informacji, zobacz Jak zarządzać połączeniami w Azure Functions.

Powiązanie z wartością zwracaną przez metodę

Możesz użyć wartości zwracanej metody dla powiązania wyjściowego, stosując atrybut do wartości zwracanej metody. Aby zapoznać się z przykładami, zobacz Wyzwalacze i powiązania.

Użyj wartości zwracanej tylko wtedy, gdy pomyślne wykonanie funkcji zawsze powoduje zwrócenie wartości do przekazania do powiązania wyjściowego. W przeciwnym razie użyj polecenia ICollector lub IAsyncCollector, jak pokazano w poniższej sekcji.

Pisanie wielu wartości wyjściowych

Aby zapisać wiele wartości do powiązania wyjściowego lub jeśli pomyślne wywołanie funkcji może nie spowodować przekazania niczego do powiązania wyjściowego, użyj ICollector typów lub IAsyncCollector . Te typy to kolekcje tylko do zapisu, które są zapisywane w powiązaniu wyjściowym po zakończeniu działania metody.

W tym przykładzie wiele komunikatów w kolejce jest zapisywanych w tej samej kolejce przy użyciu polecenia ICollector:

public static class ICollectorExample
{
    [FunctionName("CopyQueueMessageICollector")]
    public static void Run(
        [QueueTrigger("myqueue-items-source-3")] string myQueueItem,
        [Queue("myqueue-items-destination")] ICollector<string> myDestinationQueue,
        ILogger log)
    {
        log.LogInformation($"C# function processed: {myQueueItem}");
        myDestinationQueue.Add($"Copy 1: {myQueueItem}");
        myDestinationQueue.Add($"Copy 2: {myQueueItem}");
    }
}

Async

Aby utworzyć funkcję asynchroniczną, użyj słowa kluczowego async i zwróć Task obiekt.

public static class AsyncExample
{
    [FunctionName("BlobCopy")]
    public static async Task RunAsync(
        [BlobTrigger("sample-images/{blobName}")] Stream blobInput,
        [Blob("sample-images-copies/{blobName}", FileAccess.Write)] Stream blobOutput,
        CancellationToken token,
        ILogger log)
    {
        log.LogInformation($"BlobCopy function processed.");
        await blobInput.CopyToAsync(blobOutput, 4096, token);
    }
}

Nie można używać out parametrów w funkcjach asynchronicznych. W przypadku powiązań wyjściowych należy zamiast tego użyć wartości zwracanej przez funkcję lub obiektu modułu zbierającego .

Tokeny anulowania

Funkcja może akceptować parametr CancellationToken , który umożliwia systemowi operacyjnemu powiadamianie kodu o zakończeniu działania funkcji. Możesz użyć tego powiadomienia, aby upewnić się, że funkcja nie zostanie nieoczekiwanie zakończona w sposób, który pozostawia dane w stanie niespójnym.

Rozważ przypadek, gdy masz funkcję, która przetwarza komunikaty w partiach. Następująca funkcja wyzwalana Azure Service Bus przetwarza tablicę obiektów Message, która reprezentuje partię przychodzących komunikatów, które mają być przetwarzane przez wywołanie określonej funkcji:

using Microsoft.Azure.ServiceBus;
using System.Threading;

namespace ServiceBusCancellationToken
{
    public static class servicebus
    {
        [FunctionName("servicebus")]
        public static void Run([ServiceBusTrigger("csharpguitar", Connection = "SB_CONN")]
               Message[] messages, CancellationToken cancellationToken, ILogger log)
        {
            try
            { 
                foreach (var message in messages)
                {
                    if (cancellationToken.IsCancellationRequested)
                    {
                        log.LogInformation("A cancellation token was received. Taking precautionary actions.");
                        //Take precautions like noting how far along you are with processing the batch
                        log.LogInformation("Precautionary activities --complete--.");
                        break;
                    }
                    else
                    {
                        //business logic as usual
                        log.LogInformation($"Message: {message} was processed.");
                    }
                }
            }
            catch (Exception ex)
            {
                log.LogInformation($"Something unexpected happened: {ex.Message}");
            }
        }
    }
}

Rejestrowanie

W kodzie funkcji można zapisywać dane wyjściowe w dziennikach, które są wyświetlane jako ślady w usłudze Application Insights. Zalecanym sposobem zapisywania w dziennikach jest dołączenie parametru typu ILogger, który zazwyczaj nosi nazwę log. W wersji 1.x środowiska uruchomieniowego usługi Functions użyto TraceWriterpolecenia , który również zapisuje dane w usłudze Application Insights, ale nie obsługuje rejestrowania strukturalnego. Nie używaj Console.Write funkcji do zapisywania dzienników, ponieważ te dane nie są przechwytywane przez usługę Application Insights.

ILogger

W definicji funkcji uwzględnij parametr ILogger , który obsługuje rejestrowanie strukturalne.

ILogger Obiekt wywołuje Log<level>metody rozszerzenia w aplikacji ILogger w celu utworzenia dzienników. Poniższy kod zapisuje dzienniki Information z kategorią Function.<YOUR_FUNCTION_NAME>.User.:

public static async Task<HttpResponseMessage> Run(HttpRequestMessage req, ILogger logger)
{
    logger.LogInformation("Request for item with key={itemKey}.", id);

Aby dowiedzieć się więcej na temat implementowania ILoggerfunkcji, zobacz Zbieranie danych telemetrycznych. Kategorie poprzedzone Function założeniem ILogger , że używasz wystąpienia. Jeśli zdecydujesz się zamiast tego użyć ILogger<T>, nazwa kategorii może zamiast tego być oparta na .T

Rejestrowanie strukturalne

Kolejność symboli zastępczych, a nie ich nazwy, określa, które parametry są używane w komunikacie dziennika. Załóżmy, że masz następujący kod:

string partitionKey = "partitionKey";
string rowKey = "rowKey";
logger.LogInformation("partitionKey={partitionKey}, rowKey={rowKey}", partitionKey, rowKey);

Jeśli zachowasz ten sam ciąg komunikatu i odwrócisz kolejność parametrów, wynikowy tekst komunikatu będzie miał wartości w nieprawidłowych miejscach.

Symbole zastępcze są obsługiwane w ten sposób, aby można było rejestrować ze strukturą. Usługa Application Insights przechowuje pary nazwa-wartość parametru i ciąg komunikatu. Wynikiem jest to, że argumenty komunikatu stają się polami, dla których można wykonywać zapytania.

Jeśli wywołanie metody rejestratora wygląda jak w poprzednim przykładzie, możesz wykonać zapytanie względem pola customDimensions.prop__rowKey. Prefiks jest dodawany w celu upewnienia prop__ się, że nie ma kolizji między polami dodawanymi przez środowisko uruchomieniowe i polami dodanymi przez kod funkcji.

Możesz również wykonać zapytanie dotyczące oryginalnego ciągu komunikatu, odwołując się do pola customDimensions.prop__{OriginalFormat}.

Oto przykładowa reprezentacja customDimensions danych w formacie JSON:

{
  "customDimensions": {
    "prop__{OriginalFormat}":"C# Queue trigger function processed: {message}",
    "Category":"Function",
    "LogLevel":"Information",
    "prop__message":"c9519cbf-b1e6-4b9b-bf24-cb7d10b1bb89"
  }
}

Rejestrowanie telemetrii niestandardowej

Istnieje specyficzna dla usługi Functions wersja zestawu SDK usługi Application Insights, której można użyć do wysyłania niestandardowych danych telemetrycznych z funkcji do usługi Application Insights: Microsoft. Azure.WebJobs.Logging.ApplicationInsights. Użyj następującego polecenia w wierszu polecenia, aby zainstalować ten pakiet:

dotnet add package Microsoft.Azure.WebJobs.Logging.ApplicationInsights --version <VERSION>

W tym poleceniu zastąp <VERSION> element wersją tego pakietu, która obsługuje zainstalowaną wersję Microsoft. Azure.WebJobs.

W poniższych przykładach w języku C# użyto niestandardowego interfejsu API telemetrii. Przykład dotyczy biblioteki klas platformy .NET, ale kod usługi Application Insights jest taki sam dla skryptu języka C#.

Wersje 2.x i nowsze środowiska uruchomieniowego używają nowszych funkcji w usłudze Application Insights, aby automatycznie korelować dane telemetryczne z bieżącą operacją. Nie ma potrzeby ręcznego ustawiania operacji Id, ParentIdlub Name pól.

using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;

using Microsoft.ApplicationInsights;
using Microsoft.ApplicationInsights.DataContracts;
using Microsoft.ApplicationInsights.Extensibility;
using System.Linq;

namespace functionapp0915
{
    public class HttpTrigger2
    {
        private readonly TelemetryClient telemetryClient;

        /// Using dependency injection will guarantee that you use the same configuration for telemetry collected automatically and manually.
        public HttpTrigger2(TelemetryConfiguration telemetryConfiguration)
        {
            this.telemetryClient = new TelemetryClient(telemetryConfiguration);
        }

        [FunctionName("HttpTrigger2")]
        public Task<IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = null)]
            HttpRequest req, ExecutionContext context, ILogger log)
        {
            log.LogInformation("C# HTTP trigger function processed a request.");
            DateTime start = DateTime.UtcNow;

            // Parse query parameter
            string name = req.Query
                .FirstOrDefault(q => string.Compare(q.Key, "name", true) == 0)
                .Value;

            // Write an event to the customEvents table.
            var evt = new EventTelemetry("Function called");
            evt.Context.User.Id = name;
            this.telemetryClient.TrackEvent(evt);

            // Generate a custom metric, in this case let's use ContentLength.
            this.telemetryClient.GetMetric("contentLength").TrackValue(req.ContentLength);

            // Log a custom dependency in the dependencies table.
            var dependency = new DependencyTelemetry
            {
                Name = "GET api/planets/1/",
                Target = "swapi.co",
                Data = "https://swapi.co/api/planets/1/",
                Timestamp = start,
                Duration = DateTime.UtcNow - start,
                Success = true
            };
            dependency.Context.User.Id = name;
            this.telemetryClient.TrackDependency(dependency);

            return Task.FromResult<IActionResult>(new OkResult());
        }
    }
}

W tym przykładzie dane metryk niestandardowych są agregowane przez hosta przed wysłaniem ich do tabeli customMetrics. Aby dowiedzieć się więcej, zobacz dokumentację getmetric w usłudze Application Insights.

W przypadku uruchamiania lokalnego APPINSIGHTS_INSTRUMENTATIONKEY należy dodać ustawienie z kluczem usługi Application Insights do pliku local.settings.json .

Nie wywołujej wywołań TrackRequest ani StartOperation<RequestTelemetry> dlatego, że zobaczysz zduplikowane żądania wywołania funkcji. Środowisko uruchomieniowe usługi Functions automatycznie śledzi żądania.

Nie ustawiaj wartości telemetryClient.Context.Operation.Id. To ustawienie globalne powoduje nieprawidłową korelację, gdy wiele funkcji jest uruchomionych jednocześnie. Zamiast tego utwórz nowe wystąpienie telemetrii (DependencyTelemetry, EventTelemetry) i zmodyfikuj jego Context właściwość. Następnie przekaż wystąpienie telemetrii do odpowiedniej Track metody w dniu TelemetryClient (TrackDependency(), TrackEvent(), TrackMetric()). Ta metoda zapewnia, że dane telemetryczne mają poprawne szczegóły korelacji dla wywołania bieżącej funkcji.

Testowanie funkcji

W poniższych artykułach pokazano, jak uruchomić lokalnie funkcję biblioteki klas języka C# w procesie na potrzeby testowania:

Zmienne środowiskowe

Aby uzyskać zmienną środowiskową lub wartość ustawienia aplikacji, użyj polecenia System.Environment.GetEnvironmentVariable, jak pokazano w poniższym przykładzie kodu:

public static class EnvironmentVariablesExample
{
    [FunctionName("GetEnvironmentVariables")]
    public static void Run([TimerTrigger("0 */5 * * * *")]TimerInfo myTimer, ILogger log)
    {
        log.LogInformation($"C# Timer trigger function executed at: {DateTime.Now}");
        log.LogInformation(GetEnvironmentVariable("AzureWebJobsStorage"));
        log.LogInformation(GetEnvironmentVariable("WEBSITE_SITE_NAME"));
    }

    private static string GetEnvironmentVariable(string name)
    {
        return name + ": " +
            System.Environment.GetEnvironmentVariable(name, EnvironmentVariableTarget.Process);
    }
}

Ustawienia aplikacji można odczytywać ze zmiennych środowiskowych zarówno podczas programowania lokalnego, jak i podczas uruchamiania na platformie Azure. Podczas tworzenia aplikacji lokalnie ustawienia aplikacji pochodzą z Values kolekcji w pliku local.settings.json . W obu środowiskach, lokalnie i na platformie Azure, GetEnvironmentVariable("<app setting name>") pobiera wartość nazwanego ustawienia aplikacji. Na przykład w przypadku uruchamiania lokalnego plik "Moja nazwa witryny" zostanie zwrócony, jeśli plik local.settings.json zawiera wartość { "Values": { "WEBSITE_SITE_NAME": "My Site Name" } }.

Właściwość System.Configuration.ConfigurationManager.AppSettings jest alternatywnym interfejsem API służącym do pobierania wartości ustawień aplikacji, ale zalecamy użycie metody GetEnvironmentVariable , jak pokazano tutaj.

Wiązanie w czasie wykonywania

W języku C# i innych językach platformy .NET można użyć wzorca powiązania imperatywnego , w przeciwieństwie do powiązań deklaratywnych w atrybutach. Powiązanie imperatywne jest przydatne, gdy parametry powiązania muszą być obliczane w czasie wykonywania, a nie w czasie projektowania. Za pomocą tego wzorca można powiązać z obsługiwanymi powiązaniami wejściowymi i wyjściowymi na bieżąco w kodzie funkcji.

Zdefiniuj powiązanie imperatywne w następujący sposób:

  • Nie dołączaj atrybutu do podpisu funkcji dla żądanych powiązań imperatywnych.

  • Przekaż parametr Binder binder wejściowy lub IBinder binder.

  • Użyj następującego wzorca języka C#, aby wykonać powiązanie danych.

    using (var output = await binder.BindAsync<T>(new BindingTypeAttribute(...)))
    {
        ...
    }
    

    BindingTypeAttribute to atrybut .NET, który definiuje powiązanie i T jest typem wejściowym lub wyjściowym obsługiwanym przez ten typ powiązania. T nie może być typem parametru out (takim jak out JObject). Na przykład powiązanie wyjściowe tabeli Mobile Apps obsługuje sześć typów danych wyjściowych, ale można użyć tylko elementu ICollector<T lub IAsyncCollector T> z powiązaniem imperatywnego.><

Przykład pojedynczego atrybutu

Poniższy przykładowy kod tworzy powiązanie wyjściowe obiektu blob usługi Storage ze ścieżką obiektu blob zdefiniowaną w czasie wykonywania, a następnie zapisuje ciąg w obiekcie blob.

public static class IBinderExample
{
    [FunctionName("CreateBlobUsingBinder")]
    public static void Run(
        [QueueTrigger("myqueue-items-source-4")] string myQueueItem,
        IBinder binder,
        ILogger log)
    {
        log.LogInformation($"CreateBlobUsingBinder function processed: {myQueueItem}");
        using (var writer = binder.Bind<TextWriter>(new BlobAttribute(
                    $"samples-output/{myQueueItem}", FileAccess.Write)))
        {
            writer.Write("Hello World!");
        };
    }
}

Obiekt BlobAttribute definiuje powiązanie wejściowe lub wyjściowe obiektu blob usługi Storage , a TextWriter jest obsługiwanym typem powiązania wyjściowego.

Przykład wielu atrybutów

Powyższy przykład pobiera ustawienie aplikacji dla głównych parametrów połączenia konta magazynu aplikacji funkcji (czyli AzureWebJobsStorage). Możesz określić niestandardowe ustawienie aplikacji, które ma być używane dla konta magazynu, dodając atrybut StorageAccountAttribute i przekazując tablicę atrybutów do elementu BindAsync<T>(). Użyj parametru Binder , a nie IBinder. Przykład:

public static class IBinderExampleMultipleAttributes
{
    [FunctionName("CreateBlobInDifferentStorageAccount")]
    public async static Task RunAsync(
            [QueueTrigger("myqueue-items-source-binder2")] string myQueueItem,
            Binder binder,
            ILogger log)
    {
        log.LogInformation($"CreateBlobInDifferentStorageAccount function processed: {myQueueItem}");
        var attributes = new Attribute[]
        {
        new BlobAttribute($"samples-output/{myQueueItem}", FileAccess.Write),
        new StorageAccountAttribute("MyStorageAccount")
        };
        using (var writer = await binder.BindAsync<TextWriter>(attributes))
        {
            await writer.WriteAsync("Hello World!!");
        }
    }
}

Wyzwalacze i powiązania

W tej tabeli przedstawiono powiązania obsługiwane w głównych wersjach środowiska uruchomieniowego Azure Functions:

Typ 1.x 2.x i nowsze1 Wyzwalacz Dane wejściowe Dane wyjściowe
Blob Storage
Azure Cosmos DB
Azure SQL (wersja zapoznawcza)
Dapr3
Event Grid
Event Hubs
Elementy webhook PROTOKOŁU HTTP &
IoT Hub
Kafka2
Aplikacje mobilne
Notification Hubs
Queue Storage
RabbitMQ2
SendGrid
Service Bus
SignalR
Table Storage
Czasomierz
Twilio

1 Począwszy od środowiska uruchomieniowego w wersji 2.x, wszystkie powiązania z wyjątkiem protokołu HTTP i czasomierza muszą być zarejestrowane. Zobacz Rejestrowanie rozszerzeń powiązań.

2 Wyzwalacze nie są obsługiwane w planie Zużycie. Wymaga wyzwalaczy opartych na środowisku uruchomieniowym.

3 Obsługiwane tylko w przypadku platformy Kubernetes, IoT Edge i innych trybów hostowanych samodzielnie.

Następne kroki