Partage via


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

Important

La prise en charge du modèle in-process prendra fin le 10 novembre 2026. Pour continuer à bénéficier d’une prise en charge complète, nous vous recommandons vivement de migrer vos applications vers le modèle worker isolé.

Cet article est une introduction au développement d’Azure Functions à l’aide de C# dans des bibliothèques de classes .NET. Ces bibliothèques de classes sont utilisées pour exécuter in-process avec le runtime Functions. Vos fonctions .NET peuvent également exécuter des _isolated à partir du runtime Functions, ce qui offre plusieurs avantages. Pour plus d’informations, consultez le modèle worker isolé. Pour obtenir une comparaison complète des deux modèles, consultez Différences entre le modèle in-process et le modèle worker isolé.

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 de processus de travail isolé est le seul moyen d’exécuter des versions non LTS des applications .NET et .NET Framework dans les versions actuelles du runtime Functions. Pour plus d’informations, consultez Fonctions de processus Worker isolé .NET. Pour une comparaison complète entre le processus Worker isolé et les fonctions .NET in-process, consultez Différences entre les processus .NET in-process et les processus worker isolés Azure Functions.

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 prend en charge 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 également selon que vos fonctions s’exécutent in-process ou dans des processus Worker isolés.

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 ou .NET Framework pouvant être utilisé avec une version spécifique de Functions.

Version du runtime Functions Modèle de worker isolé Modèle in-process5
Functions 4.x1 .NET 9.0 (préversion)
.NET 8.0
.NET 6.02
.NET Framework 4.83
.NET 8.0
.NET 6.02
Functions 1.x4 n/a .NET Framework 4.8

1 .NET 7 a été précédemment pris en charge sur le modèle de travail isolé, mais a atteint la fin du support officiel le 14 mai 2024.

2 .NET 6 atteint la fin du support officiel le 12 novembre 2024.

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

4 La prise en charge de la version 1.x du runtime Azure Functions prend fin le 14 septembre 2026. Pour plus d’informations, lisez cette annonce relative à la prise en charge. Pour une prise en charge complète continue, vous devez migrer vos applications vers la version 4.x.

5 La prise en charge du modèle in-process prendra fin le 10 novembre 2026. Pour plus d’informations, lisez cette annonce relative à la prise en charge. Pour continuer à bénéficier d’une prise en charge complète, vous devez migrer vos applications vers le modèle worker isolé.

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.

Mise à jour pour cibler .NET 8

Les applications utilisant le modèle in-process peuvent cibler .NET 8. Pour cela, suivez les étapes décrites dans cette section. Toutefois, si vous choisissez d’exercer cette option, vous devez quand même commencer à planifier votre migration vers le modèle Worker isolé avant la fin du support du modèle in-process le 10 novembre 2026.

De nombreuses applications peuvent modifier la configuration de l’application de fonction dans Azure sans mise à jour du code ni redéploiement. Pour exécuter .NET 8 avec le modèle in-process, trois configurations sont requises :

  • Le paramètre d’application FUNCTIONS_WORKER_RUNTIME doit être défini avec la valeur « dotnet ».
  • Le paramètre d’application FUNCTIONS_EXTENSION_VERSION doit être défini avec la valeur « ~4 ».
  • Le paramètre d’application FUNCTIONS_INPROC_NET8_ENABLED doit être défini avec la valeur « 1 ».
  • Vous devez mettre à jour la configuration de la pile pour référencer .NET 8.

La prise en charge de .NET 8 utilise toujours la version 4.x du runtime Functions, et aucune modification de la version du runtime configurée n’est requise.

Pour mettre à jour votre projet local, vérifiez d’abord que vous utilisez les dernières versions des outils locaux. Vérifiez ensuite que le projet référence la version 4.4.0 ou ultérieure de Microsoft.NET.Sdk.Functions. Vous pouvez ensuite remplacer votre TargetFramework par « net8.0 ». Vous devez également mettre à jour local.settings.json pour inclure à la fois FUNCTIONS_WORKER_RUNTIME défini sur « dotnet » et FUNCTIONS_INPROC_NET8_ENABLED défini sur « 1 ».

Voici un exemple de fichier project minimal avec ces modifications :

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>net8.0</TargetFramework>
    <AzureFunctionsVersion>v4</AzureFunctionsVersion>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Include="Microsoft.NET.Sdk.Functions" Version="4.4.0" />
  </ItemGroup>
  <ItemGroup>
    <None Update="host.json">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </None>
    <None Update="local.settings.json">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
      <CopyToPublishDirectory>Never</CopyToPublishDirectory>
    </None>
  </ItemGroup>
</Project>

Voici un exemple de fichier local.settings.json minimal avec ces modifications :

{
    "IsEncrypted": false,
    "Values": {
        "AzureWebJobsStorage": "UseDevelopmentStorage=true",
        "FUNCTIONS_INPROC_NET8_ENABLED": "1",
        "FUNCTIONS_WORKER_RUNTIME": "dotnet"
    }
}

Si votre application utilise Microsoft.Azure.DurableTask.Netherite.AzureFunctions, vérifiez qu’elle cible la version 1.5.3 ou ultérieure. En raison d’un changement de comportement dans .NET 8, les applications avec des versions antérieures du package lèvent une exception de constructeur ambigu.

Vous devrez peut-être apporter d’autres modifications à votre application en fonction de la prise en charge de version de ses autres dépendances.

La version 4.x du runtime Functions fournit des fonctionnalités équivalentes pour .NET 6 et .NET 8. Le modèle in-process n’inclut pas de fonctionnalités ou de mises à jour supplémentaires qui s’intègrent à de nouvelles fonctionnalités .NET 8. Par exemple, le runtime ne prend pas en charge les services clés. Pour tirer pleinement parti des dernières fonctionnalités et améliorations de .NET 8, vous devez migrer vers le modèle de worker isolé.

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 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’exemple ci-dessus montre une méthode statique utilisée, mais les fonctions ne doivent pas obligatoirement être statiques.

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 multiple 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é configurationSource 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.

L’exemple suivant montre les parties pertinentes des .csproj fichiers qui ont différentes infrastructures cibles du même Sdk package :

<PropertyGroup>
  <TargetFramework>net8.0</TargetFramework>
  <AzureFunctionsVersion>v4</AzureFunctionsVersion>
</PropertyGroup>
<ItemGroup>
  <PackageReference Include="Microsoft.NET.Sdk.Functions" Version="4.5.0" />
</ItemGroup>

Important

À partir de la version 4.0.6517 des outils principaux, les projets de modèles in-process doivent faire référence à la version 4.5.0 ou à une version ultérieure de Microsoft.NET.Sdk.Functions. Si une version antérieure est utilisée, la commande func start génère une erreur.

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 4.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 4.x, les outils Core Tools sont inclus dans l’extension Azure Functions et Web Jobs Tools. Pour Functions 1.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 6 et versions ultérieures et requiert laversion 4.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>net8.0</TargetFramework>
  <AzureFunctionsVersion>v4</AzureFunctionsVersion>
  <PublishReadyToRun>true</PublishReadyToRun>
  <RuntimeIdentifier>win-x86</RuntimeIdentifier>
</PropertyGroup>

Important

À compter de .NET 6, la prise en charge de la compilation Composite ReadyToRun a été ajoutée. Consultez Restrictions de la plateforme et de l’architecture de ReadyToRun.

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é async 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 ServiceBusReceivedMessage, qui représente un lot de messages entrants à traiter par un appel de fonction spécifique :

using Azure.Messaging.ServiceBus;
using System.Threading;

namespace ServiceBusCancellationToken
{
    public static class servicebus
    {
        [FunctionName("servicebus")]
        public static void Run([ServiceBusTrigger("csharpguitar", Connection = "SB_CONN")]
               ServiceBusReceivedMessage[] 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é log. 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.

Avec un objet ILogger, vous appelez des méthodes d’extension Log<level> sur ILogger pour créer des journaux. 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 { "Values": { "WEBSITE_SITE_NAME": "My Site Name" } }.

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 GetEnvironmentVariable 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 ICollector<T> ou IAsyncCollector<T> 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 BindAsync<T>(). 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.x1 2.x et ultérieur2 Déclencheur Entrée Output
Stockage Blob
Azure Cosmos DB
Explorateur de données Azure
Azure SQL
Dapr4
Event Grid
Hubs d'événements
HTTP et Webhooks
IoT Hub
Kafka3
Mobile Apps
Notification Hubs
Stockage File d’attente
Redis
RabbitMQ3
SendGrid
Service Bus
SignalR
Stockage Table
Minuteur
Twilio

Remarques :

  1. La prise en charge de la version 1.x du runtime Azure Functions prendra fin le 14 septembre 2026. Nous vous recommandons fortement de migrer vos applications vers la version 4.x pour bénéficier d’une prise en charge complète.
  2. À 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.
  3. Les déclencheurs ne sont pas pris en charge dans le plan Consommation. Nécessite des déclencheurs basés sur le runtime.
  4. Pris en charge dans Kubernetes, IoT Edge et d’autres modes auto-hébergés uniquement.

Étapes suivantes