Développer des fonctions de bibliothèque de classes C# à l’aide d’Azure Functions

Cet article est une introduction au développement d’Azure Functions à l’aide de C# dans des bibliothèques de classes .NET.

Important

Cet article prend en charge les fonctions de bibliothèque de classes .NET s’exécutant in-process avec le runtime. Vos fonctions C# peuvent également s’exécuter hors processus et isolées du runtime Functions. Le modèle isolé est le seul moyen d’exécuter .NET 5.x et la préversion de .NET Framework 4.8 à l’aide de versions récentes du runtime Functions. Pour plus d’informations, consultez Fonctions de processus isolé .NET.

En tant que développeur C#, vous pouvez également être intéressé par l’un des articles suivants :

Prise en main Concepts Apprentissage guidé/exemples

Azure Functions prend en charge le langage de programmation C#, mais également le langage de script C#. Pour plus d’informations sur l’utilisation de C# dans le portail Azure, consultez Informations de référence pour les développeurs de scripts C# (.csx).

Versions prises en charge

Les versions du runtime Functions fonctionnent avec des versions spécifiques de .NET. Pour en savoir plus sur les versions de Functions, consultez Vue d’ensemble des versions du runtime Azure Functions. La prise en charge des versions varie selon que vos fonctions s’exécutent in-process ou out-of-process (isolées).

Notes

Pour savoir comment modifier la version du runtime Functions utilisée par votre application de fonction, consultez Afficher et mettre à jour la version actuelle du runtime.

Le tableau suivant indique le niveau le plus élevé de .NET Core et .NET Framework pouvant être utilisé avec une version spécifique de Functions.

Version du runtime Functions In-process
(Bibliothèque de classes .NET)
Out-of-process
(Isolé .NET)
Functions 4.x .NET 6.0 .NET 6.0
.NET 7.0 (préversion)
.NET Framework 4.8 (préversion)1
Functions 3.x .NET Core 3.1 .NET 5.02
Functions 2.x .NET Core 2.13 n/a
Functions 1.x .NET Framework 4.8 n/a

1 Le processus de génération nécessite également le kit de développement logiciel (SDK) .NET 6. La prise en charge de .NET Framework 4.8 est disponible en préversion.

2 Le processus de génération nécessite également le kit de développement logiciel (SDK) .NET Core 3.1.

3 Pour plus d’informations, consultez Considérations relatives à Functions v2.x.

Pour obtenir les dernières informations sur les versions Azure Functions, notamment sur la suppression des versions mineures les plus anciennes, surveillez les annonces Azure App Service.

Considérations relatives à Functions v2.x

Les applications de fonction ciblant la version 2.x la plus récente (~2) sont automatiquement mises à niveau pour s’exécuter sur .NET Core 3.1. En raison des changements cassants entre les versions .NET Core, toutes les applications développées et compilées sur .NET Core 2.2 ne peuvent pas être mises à niveau en toute sécurité vers .NET Core 3.1. Vous pouvez désactiver cette mise à niveau en épinglant votre application de fonction à ~2.0. Functions détecte également les API non compatibles et peut épingler votre application à ~2.0 pour empêcher une exécution incorrecte sur .NET Core 3.1.

Notes

Si votre application de fonction est épinglée à ~2.0 et que vous modifiez cette version cible par ~2 , votre application de fonction peut s’arrêter. Si vous déployez à l’aide de modèles ARM, vérifiez la version de vos modèles. Si cela se produit, remplacez votre version par la cible ~2.0 et corrigez les problèmes de compatibilité.

Les applications de fonction ciblant ~2.0 continuent de s’exécuter sur .NET Core 2.2. Cette version .NET Core ne fait plus l’objet de mises à jour de sécurité et de maintenance. Pour en savoir plus, consultez cette page d’annonce.

Vous devez veiller à la compatibilité de vos fonctions avec .NET Core 3.1 dès que possible. Une fois ces problèmes résolus, remplacez votre version par ~2 ou procédez à une mise à niveau vers ~3 . Pour en savoir plus sur le ciblage des versions du runtime Functions, consultez Comment cibler des versions du runtime Azure Functions.

En cas d’exécution sur Linux dans un plan Premium ou dédié (App Service), vous épinglez votre version en ciblant plutôt une image spécifique et en définissant le paramètre de configuration de site linuxFxVersion sur DOCKER|mcr.microsoft.com/azure-functions/dotnet:2.0.14786-appservice. Pour savoir comment définir linuxFxVersion, consultez linuxFxVersion.

Projet de bibliothèque de classes Azure Functions

Dans Visual Studio, le modèle de projet Azure Functions crée un projet de bibliothèque de classes C# qui contient les fichiers suivants :

  • host.json : stocke les paramètres de configuration qui affectent toutes les fonctions dans le projet au cours d’une exécution locale ou dans Azure.
  • local.settings.json : stocke les paramètres de l’application et les chaînes de connexion utilisés au cours d’une exécution locale. Ce fichier contient des secrets et n’est pas publié dans votre application de fonction dans Azure. À la place, ajoutez des paramètres d’application à votre Function App.

Lorsque vous créez le projet, une structure de dossiers qui ressemble à l’exemple suivant est générée dans le répertoire de sortie de build :

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

Ce répertoire correspond à ce qui est déployé dans votre application de fonction dans Azure. Les extensions de liaison requises dans la version 2.x du runtime Azure Functions sont ajoutées au projet en tant que packages NuGet.

Important

Le processus de génération crée un fichier function.json pour chaque fonction. Ce fichier function.json n’est pas destiné à être directement modifié. Vous ne pouvez pas modifier la configuration des liaisons ni désactiver la fonction en modifiant ce fichier. Pour savoir comment désactiver une fonction, consultez le Guide pratique pour désactiver des fonctions.

Méthodes reconnues en tant que fonctions

Dans une bibliothèque de classes, une fonction est une méthode statique avec un attribut FunctionName et un attribut de déclencheur, comme illustré dans l’exemple suivant :

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

L’attribut FunctionName marque une méthode comme point d’entrée de la fonction. Le nom doit être unique au sein d’un projet, commencer par une lettre et ne contenir que des lettres, des chiffres, _ et -, jusqu’à 127 caractères. Les modèles de projets créent souvent une méthode nommée Run, mais le nom de la méthode peut être n’importe quel nom de méthode C# valide.

L’attribut de déclencheur spécifie le type de déclencheur et lie les données d’entrée à un paramètre de méthode. L’exemple de fonction est déclenché par un message de file d’attente, qui est lui-même transmis à la méthode dans le paramètre myQueueItem.

Paramètres de signature de méthode

La signature de méthode peut contenir des paramètres autres que ceux utilisés avec l’attribut de déclencheur. Voici quelques-uns des autres paramètres que vous pouvez inclure :

  • des liaisons d’entrée et de sortie marquées comme telles à l’aide d’attributs ;
  • un paramètre ILogger ou TraceWriter (ILogger) pour la TraceWriter.
  • un paramètre CancellationToken pour CancellationToken ;
  • des paramètres d’expressions de liaison pour obtenir des métadonnées de déclencheur.

L’ordre des paramètres dans la signature de fonction n’a pas d’importance. Par exemple, vous pouvez placer les paramètres de déclencheur avant ou après les autres liaisons, de même que vous pouvez placer le paramètre de l’enregistreur d’événements avant ou après les paramètres de liaison ou de déclencheur.

Liaisons de sortie

Une fonction peut avoir zéro ou une liaison de sortie définie à l’aide des paramètres de sortie.

L’exemple suivant modifie l’exemple précédent en ajoutant une liaison de file d’attente de sortie nommée myQueueItemCopy. La fonction écrit le contenu du message qui déclenche la fonction vers un nouveau message dans une autre file d’attente.

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

Les valeurs attribuées aux liaisons de sortie sont écrites une fois la fonction terminée. Vous pouvez utiliser plusieurs liaisons de sortie dans une fonction en attribuant tout simplement des valeurs à plusieurs paramètres de sortie.

Les articles de référence sur les liaisons (Liaisons de stockage File d’attente Azure pour Azure Functions, par exemple) décrivent les types de paramètre que vous pouvez utiliser avec les attributs de liaison de déclencheur, d’entrée ou de sortie.

Exemple d’expression de liaison

Le code suivant permet d’obtenir le nom de la file d’attente à surveiller à partir d’un paramètre d’application, et de récupérer l’heure de création du message de file d’attente dans le paramètre 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}");
    }
}

Fichier function.json généré automatiquement

Le processus de build crée un fichier function.json dans un dossier de fonction du dossier de build. Comme indiqué précédemment, ce fichier n’est pas destiné à être modifié directement. Vous ne pouvez pas modifier la configuration des liaisons ni désactiver la fonction en modifiant ce fichier.

L’objectif de ce fichier est de fournir au contrôleur de mise à l’échelle les informations à utiliser pour les décisions de mise à l’échelle affectant le plan Consommation. C’est pourquoi le fichier ne contient pas de liaisons d’entrée/de sortie, mais uniquement des informations de déclencheur.

Le fichier function.json généré inclut une propriété qui indique au runtime d’utiliser les attributs .NET pour les liaisons, au lieu de la configuration function.json. Voici un exemple :

{
  "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

La génération du fichier function.json est effectuée par le package NuGet Microsoft.NET.Sdk.Functions.

Le même package est utilisé pour les versions 1.x et 2.x du runtime Functions. Le framework cible est ce qui différencie un projet 1.x d’un projet 2.x. Voici les parties correspondantes des fichiers .csproj, qui montrent les frameworks cibles avec le même package Sdk :

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

Parmi les dépendances de package Sdk figurent les déclencheurs et les liaisons. Un projet 1.x fait référence à des déclencheurs et des liaisons 1.x parce que ceux-ci ciblent le .NET Framework, alors que les déclencheurs et liaisons 2.x ciblent .NET Core.

Le package Sdk dépend également de Sdk et indirectement de WindowsAzure.Storage. Ces dépendances garantissent que votre projet utilise des versions de package compatibles avec la version du runtime Functions qui est ciblée par le projet. Par exemple, Newtonsoft.Json a la version 11 pour .NET Framework 4.6.1, mais le runtime Functions qui cible .NET Framework 4.6.1 est compatible uniquement avec Newtonsoft.Json 9.0.1. Par conséquent, le code de fonction de votre projet doit également utiliser Newtonsoft.Json 9.0.1.

Le code source de Microsoft.NET.Sdk.Functions est disponible dans le dépôt GitHub Microsoft.NET.Sdk.Functions.

Version du runtime local

Visual Studio utilise les outils Azure Functions Core Tools pour exécuter les projets Functions sur votre ordinateur local. Ils constituent l’interface de ligne de commande du runtime Functions.

Si vous installez Core Tools à l’aide du package Windows Installer (MSI) ou à l’aide de npm, cela n’affecte pas la version de Core Tools utilisée par Visual Studio. Pour le runtime Functions version 1.x, Visual Studio stocke les versions de Core Tools dans %USERPROFILE%\AppData\Local\Azure.Functions.Cli et utilise la dernière version stockée. Pour Functions 2.x, les outils Core Tools sont inclus dans l’extension Azure Functions and Web Jobs Tools. Pour les versions 1.x et 2.x, vous pouvez voir quelle version est utilisée dans la sortie de console lorsque vous exécutez un projet 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

Vous pouvez compiler votre application de fonction en tant que binaires ReadyToRun. ReadyToRun est une forme de compilation à l’avance qui peut améliorer les performances de démarrage pour réduire l’impact de démarrage à froid lors de l’exécution dans un plan de consommation.

ReadyToRun est disponible dans .NET 3.0 et requiert laversion 3.0 d’Azure Functions Runtime.

Pour compiler votre projet en tant que ReadyToRun, mettez à jour votre fichier projet en ajoutant les éléments <PublishReadyToRun> et <RuntimeIdentifier>. Voici la configuration de la publication dans une application de fonction Windows 32 bits.

<PropertyGroup>
  <TargetFramework>netcoreapp3.1</TargetFramework>
  <AzureFunctionsVersion>v3</AzureFunctionsVersion>
  <PublishReadyToRun>true</PublishReadyToRun>
  <RuntimeIdentifier>win-x86</RuntimeIdentifier>
</PropertyGroup>

Important

ReadyToRun ne prend actuellement pas en charge la compilation croisée. Vous devez générer votre application sur la même plateforme que la cible de déploiement. Faites également attention au « nombre de bits » configuré dans votre application de fonction. Par exemple, si votre application de fonction dans Azure est Windows 64 bits, vous devez compiler votre application sur Windows avec win-x64 comme win-x64.

Vous pouvez également générer votre application avec ReadyToRun à partir de la ligne de commande. Pour plus d'informations, consultez -p:PublishReadyToRun=truel'option dans dotnet publish.

Types pris en charge pour les liaisons

Chaque liaison possède ses propres types pris en charge. Par exemple, un attribut de déclencheur d’objet blob peut être appliqué à un paramètre de chaîne, à un paramètre OCT, à un paramètre CloudBlockBlob ou à l’un des autres types pris en charge. L’article sur les références de liaison pour les liaisons d’objets blob répertorie tous les types de paramètre pris en charge. Pour plus d’informations, consultez Déclencheurs et liaisons, ainsi que les documents sur les références de liaison pour chaque type de liaison.

Conseil

Si vous envisagez d’utiliser les liaisons HTTP ou WebHook, prévoyez d’éviter l’épuisement du port qui peut résulter d’une instanciation incorrecte de HttpClient. Pour plus d’informations, consultez How to manage connections in Azure Functions (Comment gérer des connexions dans Azure Functions).

Liaison à une valeur renvoyée par la méthode

Vous pouvez utiliser une valeur de retour de méthode pour une liaison de sortie en appliquant l’attribut à la valeur de retour de méthode. Pour obtenir des exemples, consultez Déclencheurs et liaisons.

Utilisez la valeur de retour seulement si une exécution réussie de la fonction aboutit toujours à une valeur de retour à passer à la liaison de sortie. Sinon, utilisez ICollector ou IAsyncCollector, comme illustré dans la section suivante.

Écrire plusieurs valeurs de sortie

Pour écrire plusieurs valeurs dans une liaison de sortie, ou si un appel de fonction réussi n’aboutit pas nécessairement à quelque chose à passer à la liaison de sortie, utilisez les types ICollector ou IAsyncCollector. Ces types sont des collections en écriture seule, écrites dans la liaison de sortie à la fin de la méthode.

Cet exemple écrit plusieurs messages de file d’attente dans la même file d’attente à l’aide de 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

Pour rendre une fonction asynchrone, utilisez le mot clé et retournez un objet Task.

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);
    }
}

Vous ne pouvez pas utiliser de paramètres out dans des fonctions asynchrones. Pour les liaisons de sortie, utilisez la valeur de retour de fonction ou un objet collecteur à la place.

Jetons d’annulation

Une fonction peut accepter un paramètre CancellationToken qui permet au système d’exploitation de notifier votre code quand la fonction est sur le point de se terminer. Vous pouvez utiliser cette notification pour vous assurer que la fonction ne s’arrête pas de manière inattendue et laisse les données dans un état incohérent.

Considérez le cas où 0vous avez une fonction qui traite les messages par lots. La fonction suivante déclenchée par Azure Service Bus traite un tableau d’objets de Message, qui représente un lot de messages entrants à traiter par un appel de fonction spécifique :

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}");
            }
        }
    }
}

Journalisation

Dans votre code de fonction, vous pouvez écrire la sortie dans des journaux qui apparaissent sous forme de traces dans Application Insights. La méthode recommandée pour écrire dans les journaux consiste à inclure un paramètre de type ILogger, généralement nommé . La version 1. x du runtime Functions a utilisé TraceWriter, qui écrit également dans Application Insights, mais ne prend pas en charge la journalisation structurée. N’utilisez pas Console.Write pour écrire vos journaux, car ces données ne sont pas capturées par Application Insights.

ILogger

Dans votre définition de fonction, incluez un paramètre ILogger qui prend en charge la journalisation structurée.

L’objet ILogger permet d’appeler les ILogger pour créer des journaux d’activité. Le code suivant écrit des journaux d’activité Information ayant la catégorie Function.<YOUR_FUNCTION_NAME>.User. :

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

Pour en savoir plus sur la façon dont Functions implémente ILogger, consultez ILogger. Les catégories dotées du préfixe Function supposent que vous utilisez une instance ILogger. Si vous choisissez d’utiliser à la place un ILogger<T>, le nom de la catégorie peut être basé sur T.

Journalisation structurée

C’est l’ordre des espaces réservés, pas leurs noms, qui détermine les paramètres utilisés dans le message du journal. Supposons que vous disposiez du code suivant :

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

Si vous conservez la même chaîne de message et que vous inversez l’ordre des paramètres, les valeurs dans le texte du message résultant ne sont pas situées à la bonne place.

Ce mode de gestion des espaces réservés vous permet d’effectuer une journalisation structurée. Application Insights stocke les paires nom de paramètre/valeur et la chaîne de message. Ainsi, les arguments du message deviennent des champs pouvant faire l’objet de requêtes.

Si votre appel de méthode de l’enregistreur d’événements ressemble à l’exemple précédent, vous pouvez interroger le champ customDimensions.prop__rowKey. L’ajout du préfixe prop__ évite toute collision entre les champs ajoutés par le runtime et les champs ajoutés par votre fonction de code.

Vous pouvez également exécuter une requête portant sur la chaîne de message d’origine en référençant le champ customDimensions.prop__{OriginalFormat}.

Voici un exemple de représentation JSON des données customDimensions :

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

Enregistrer une télémétrie personnalisée

Il existe une version du kit de développement logiciel (SDK) Application Insights spécifique à Functions et que vous pouvez utiliser pour envoyer des données de télémétrie personnalisées de vos fonctions vers Application Insights : Microsoft.Azure.WebJobs.Logging.ApplicationInsights. Utilisez la commande suivante depuis l’invite de commandes pour installer ce package :

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

Dans cette commande, remplacez <VERSION> par une version de ce package qui prend en charge la version installée de <VERSION>.

L’exemple suivant en C# utilise l’API de télémétrie personnalisée. L’exemple concerne une bibliothèque de classes .NET, mais le code Application Insights est le même pour le script C#.

La version 2.x et les versions ultérieures du runtime utilisent les nouvelles fonctionnalités d’Application Insights pour mettre automatiquement en corrélation les données de télémétrie avec l’opération en cours. Il est inutile de définir manuellement les champs de l’opération Id, ParentId ou Name.

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());
        }
    }
}

Dans cet exemple, les données de métriques personnalisées sont agrégées par l’hôte avant d’être envoyées à la table customMetrics. Pour plus d’informations, consultez la documentation GetMetric dans Application Insights.

Lors d’une exécution locale, vous devez ajouter le paramètre APPINSIGHTS_INSTRUMENTATIONKEY avec la clé Application Insights, au fichier APPINSIGHTS_INSTRUMENTATIONKEY.

N’appelez pas TrackRequest ou StartOperation<RequestTelemetry>, afin d’éviter les doublons de requêtes pour un appel de fonction. Le runtime d’Azure Functions effectue automatiquement le suivi des demandes.

Ne définissez pas telemetryClient.Context.Operation.Id. Ce paramètre global provoque une erreur de corrélation lorsqu’un grand nombre de fonctions s’exécutent en même temps. Au lieu de cela, créez une nouvelle instance de télémétrie (DependencyTelemetry, EventTelemetry) et modifiez sa propriété Context. Passez ensuite l’instance de télémétrie à la méthode Track correspondante sur TelemetryClient (TrackDependency(), TrackEvent(), TrackMetric()). Cette méthode permet de s'assurer que les données de télémétrie comportent les bonnes informations de corrélation pour l’appel de fonction actuel.

Tester les fonctions

Les articles suivants montrent comment exécuter une fonction de bibliothèque de classes C# in-process localement à des fins de test :

Variables d'environnement

Pour obtenir une variable d’environnement ou une valeur de paramètre d’application, utilisez System.Environment.GetEnvironmentVariable, comme illustré dans l’exemple de code suivant :

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);
    }
}

Les paramètres de l’application peuvent être lus à partir de variables d’environnement lors du développement localement et de l’exécution dans Azure. Lors du développement localement, les paramètres de l’application proviennent de la collection Values dans le fichier Values. Dans les deux environnements, local et Azure, GetEnvironmentVariable("<app setting name>") récupère la valeur du paramètre d’application nommé. Par exemple, lorsque vous exécutez localement, « My Site Name » est retourné si votre fichier local.settings.json contient .

La propriété System.Configuration.ConfigurationManager.AppSettings est une autre API permettant d’obtenir des valeurs de paramètre d’application, mais nous vous recommandons d’utiliser comme indiqué ici.

Liaison au runtime

Avec C# et d’autres langages .NET, vous pouvez utiliser un schéma de liaison impératif, par opposition aux liaisons déclaratives dans les attributs. La liaison impérative est utile lorsque les paramètres de liaison doivent être calculés au moment du runtime plutôt que lors de la conception. Avec ce modèle, vous pouvez effectuer une liaison à la volée avec une liaison d’entrée et de sortie prise en charge dans le code de votre fonction.

Définissez une liaison impérative comme suit :

  • N’incluez pas d’attribut dans la signature de fonction pour les liaisons impératives souhaitées.

  • Transmettez un paramètre d’entrée Binder binder ou IBinder binder.

  • Utilisez le modèle en C# suivant pour effectuer la liaison de données.

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

    BindingTypeAttribute est l’attribut .NET qui définit votre liaison et T est le type d’entrée ou de sortie pris en charge par ce type de liaison. T ne peut pas être un type de paramètre out (comme out JObject). Par exemple, la liaison de sortie de la table Mobile Apps prend en charge six types de sortie, mais vous pouvez utiliser uniquement ICollectorT ou IAsyncCollectorT> avec des liaisons impératives.

Exemple d’attribut unique

L’exemple de code suivant crée une liaison de sortie d’objet blob de stockage avec un chemin d’objet blob défini au moment de l’exécution, puis écrit une chaîne vers l’objet 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!");
        };
    }
}

BlobAttribute définit la liaison d’entrée ou de sortie de l’objet blob de stockage, et TextWriter est un type de liaison de sortie pris en charge.

Exemple d’attributs multiples

L’exemple précédent obtient le paramètre d’application pour la chaîne de connexion du compte de stockage principal de l’application de fonction (à savoir AzureWebJobsStorage). Vous pouvez spécifier un paramètre d’application personnalisé à utiliser pour le compte de stockage en ajoutant l’attribut StorageAccountAttribute et en transmettant le tableau d’attributs dans . Utilisez un paramètre Binder, et non IBinder. Par exemple :

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!!");
        }
    }
}

Déclencheurs et liaisons

Ce tableau présente les liaisons qui sont prises en charge dans les versions majeures du runtime Azure Functions :

Type 1.x 2.x et ultérieures1 Déclencheur Entrée Output
Stockage Blob
Azure Cosmos DB
Azure SQL (préversion)
Dapr3
Event Grid
Hubs d'événements
HTTP webhooks
IoT Hub
Kafka2
Mobile Apps
Notification Hubs
Stockage File d’attente
RabbitMQ2
SendGrid
Service Bus
SignalR
Stockage Table
Minuteur
Twilio

1 À compter du runtime de la version 2.x, toutes les liaisons à l’exception de HTTP et du minuteur doivent être inscrites. Consultez Inscrire des extensions de liaison.

2 Les déclencheurs ne sont pas pris en charge dans le plan Consommation. Nécessite des déclencheurs basés sur le runtime.

3 Pris en charge uniquement dans Kubernetes, IoT Edge et d’autres modes autohébergés uniquement.

Étapes suivantes