Note
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier les répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de changer de répertoire.
Cet article illustre la prise en charge d’OpenTelemetry dans Azure Function, qui permet le suivi distribué sur plusieurs appels de fonction à l’aide de la prise en charge intégrée d’Application Insights et d’OpenTelemetry. Pour vous aider à commencer, un modèle Azure Developer CLI (azd) est utilisé pour créer votre projet de code ainsi que le déploiement Azure dans lequel exécuter votre application.
Dans ce tutoriel, vous utilisez l’outil azd pour :
- Initialisez un projet OpenTelemetry à l'aide d'un modèle.
- Passez en revue le code qui active l’intégration d’OpenTelemetry.
- Exécutez et vérifiez votre application OpenTelemetry localement.
- Créez une application de fonction et des ressources associées dans Azure.
- Déployez votre projet de code sur l’application de fonction dans Azure.
- Vérifiez le suivi distribué dans Application Insights.
Les ressources Azure requises créées par ce modèle suivent les meilleures pratiques actuelles pour les déploiements d’applications de fonction sécurisées et évolutives dans Azure. La même azd commande déploie également votre projet de code sur votre nouvelle application de fonction dans Azure.
Par défaut, le plan Flex Consumption suit un modèle de facturation avec paiement à l’utilisation , ce qui signifie que l’exécution de ce guide de démarrage rapide entraîne un petit coût de quelques cents USD ou moins dans votre compte Azure.
Important
Cet article prend actuellement en charge uniquement C#, Python et TypeScript. Pour suivre le guide de démarrage rapide, sélectionnez l’une de ces langues prises en charge en haut de l’article.
Prerequisites
Un compte Azure avec un abonnement actif. Créez un compte gratuitement.
Initialiser le projet
Utilisez la azd init commande pour créer un projet de code Azure Functions local à partir d’un modèle qui inclut le suivi distribué OpenTelemetry.
Dans votre terminal local ou à l’invite de commandes, exécutez cette commande
azd initdans un dossier vide :azd init --template functions-quickstart-python-azd-otel -e flexquickstart-otelCette commande extrait les fichiers projet du référentiel de modèles et initialise le projet dans le dossier actif. L’indicateur
-edéfinit un nom pour l’environnement actuel. Dansazd, l’environnement gère un contexte de déploiement unique pour votre application et vous pouvez en définir plusieurs. Le nom de l’environnement apparaît également dans le nom du groupe de ressources que vous créez dans Azure.
Dans votre terminal local ou à l’invite de commandes, exécutez cette commande
azd initdans un dossier vide :azd init --template functions-quickstart-typescript-azd-otel -e flexquickstart-otelCette commande extrait les fichiers projet du référentiel de modèles et initialise le projet dans le dossier actif. L’indicateur
-edéfinit un nom pour l’environnement actuel. Dansazd, l’environnement gère un contexte de déploiement unique pour votre application et vous pouvez en définir plusieurs. Le nom de l’environnement apparaît également dans le nom du groupe de ressources que vous créez dans Azure.
Dans votre terminal local ou à l’invite de commandes, exécutez cette commande
azd initdans un dossier vide :azd init --template functions-quickstart-dotnet-azd-otel -e flexquickstart-otelCette commande extrait les fichiers projet du référentiel de modèles et initialise le projet dans le dossier actif. L’indicateur
-edéfinit un nom pour l’environnement actuel. Dansazd, l’environnement gère un contexte de déploiement unique pour votre application et vous pouvez en définir plusieurs. Le nom de l’environnement apparaît également dans le nom du groupe de ressources que vous créez dans Azure.
Vérifier le code
Le modèle crée un scénario de suivi distribué complet avec trois fonctions qui fonctionnent ensemble. Examinons les aspects clés liés à OpenTelemetry :
Configuration d’OpenTelemetry
Le src/otel-sample/host.json fichier active OpenTelemetry pour l’hôte Functions :
{
"version": "2.0",
"telemetryMode": "OpenTelemetry",
"extensions": {
"serviceBus": {
"maxConcurrentCalls": 10
}
},
"extensionBundle": {
"id": "Microsoft.Azure.Functions.ExtensionBundle",
"version": "[4.*, 5.0.0)"
}
}
Le paramètre "telemetryMode": "OpenTelemetry" de clé active le suivi distribué entre les appels de fonction.
Le src/OTelSample/host.json fichier active OpenTelemetry pour l’hôte Functions :
{
"version": "2.0",
"telemetryMode": "OpenTelemetry",
"logging": {
"OpenTelemetry": {
"logLevel": {
"Host.General": "Warning"
}
}
}
}
Le paramètre "telemetryMode": "OpenTelemetry" de clé active le suivi distribué entre les appels de fonction.
Dépendances pour OpenTelemetry
Le src/otel-sample/requirements.txt fichier inclut les packages nécessaires pour l’intégration d’OpenTelemetry :
azure-functions
azure-monitor-opentelemetry
requests
Le azure-monitor-opentelemetry package fournit l’intégration d’OpenTelemetry à Application Insights.
Le src/otel-sample/package.json fichier inclut les packages nécessaires pour l’intégration d’OpenTelemetry :
{
"dependencies": {
"@azure/functions": "^4.0.0",
"@azure/functions-opentelemetry-instrumentation": "^0.1.0",
"@azure/monitor-opentelemetry-exporter": "^1.0.0",
"axios": "^1.6.0"
}
}
Les packages @azure/functions-opentelemetry-instrumentation et @azure/monitor-opentelemetry-exporter fournissent l'intégration d'OpenTelemetry avec Application Insights.
Le .csproj fichier inclut les packages nécessaires pour l’intégration d’OpenTelemetry :
<PackageReference Include="Azure.Monitor.OpenTelemetry.Exporter" Version="1.4.0" />
<PackageReference Include="Microsoft.Azure.Functions.Worker.OpenTelemetry" Version="1.4.0" />
<PackageReference Include="OpenTelemetry.Instrumentation.Http" Version="1.10.0" />
Ces packages fournissent l’intégration d’OpenTelemetry à Application Insights et à l’instrumentation HTTP pour le suivi distribué.
Implémentation de fonction
Les fonctions dans src/otel-sample/function_app.py démontrent un flux de traçage distribué :
Première fonction HTTP
@app.function_name("first_http_function")
@app.route(route="first_http_function", auth_level=func.AuthLevel.ANONYMOUS)
def first_http_function(req: func.HttpRequest) -> func.HttpResponse:
logging.info('Python HTTP trigger function (first) processed a request.')
# Call the second function
base_url = f"{req.url.split('/api/')[0]}/api"
second_function_url = f"{base_url}/second_http_function"
response = requests.get(second_function_url)
second_function_result = response.text
result = {
"message": "Hello from the first function!",
"second_function_response": second_function_result
}
return func.HttpResponse(
json.dumps(result),
status_code=200,
mimetype="application/json"
)
Deuxième fonction HTTP
@app.function_name("second_http_function")
@app.route(route="second_http_function", auth_level=func.AuthLevel.ANONYMOUS)
@app.service_bus_queue_output(arg_name="outputsbmsg", queue_name="%ServiceBusQueueName%",
connection="ServiceBusConnection")
def second_http_function(req: func.HttpRequest, outputsbmsg: func.Out[str]) -> func.HttpResponse:
logging.info('Python HTTP trigger function (second) processed a request.')
message = "This is the second function responding."
# Send a message to the Service Bus queue
queue_message = "Message from second HTTP function to trigger ServiceBus queue processing"
outputsbmsg.set(queue_message)
logging.info('Sent message to ServiceBus queue: %s', queue_message)
return func.HttpResponse(
message,
status_code=200
)
Déclencheur de file d'attente du Service Bus
@app.service_bus_queue_trigger(arg_name="azservicebus", queue_name="%ServiceBusQueueName%",
connection="ServiceBusConnection")
def servicebus_queue_trigger(azservicebus: func.ServiceBusMessage):
logging.info('Python ServiceBus Queue trigger start processing a message: %s',
azservicebus.get_body().decode('utf-8'))
time.sleep(5) # Simulate processing work
logging.info('Python ServiceBus Queue trigger end processing a message')
La configuration OpenTelemetry est configurée dans src/otel-sample/index.ts:
import { AzureFunctionsInstrumentation } from '@azure/functions-opentelemetry-instrumentation';
import { AzureMonitorTraceExporter, AzureMonitorLogExporter } from '@azure/monitor-opentelemetry-exporter';
import { getNodeAutoInstrumentations, getResourceDetectors } from '@opentelemetry/auto-instrumentations-node';
import { registerInstrumentations } from '@opentelemetry/instrumentation';
import { detectResources } from '@opentelemetry/resources';
import { LoggerProvider, SimpleLogRecordProcessor } from '@opentelemetry/sdk-logs';
import { NodeTracerProvider, SimpleSpanProcessor } from '@opentelemetry/sdk-trace-node';
const resource = detectResources({ detectors: getResourceDetectors() });
const tracerProvider = new NodeTracerProvider({
resource,
spanProcessors: [new SimpleSpanProcessor(new AzureMonitorTraceExporter())]
});
tracerProvider.register();
const loggerProvider = new LoggerProvider({
resource,
processors: [new SimpleLogRecordProcessor(new AzureMonitorLogExporter())],
});
registerInstrumentations({
tracerProvider,
loggerProvider,
instrumentations: [getNodeAutoInstrumentations(), new AzureFunctionsInstrumentation()],
});
Les fonctions sont définies dans le src/otel-sample/src/functions dossier :
Première fonction HTTP
export async function firstHttpFunction(
request: HttpRequest,
context: InvocationContext
): Promise<HttpResponseInit> {
context.log("TypeScript HTTP trigger function (first) processed a request.");
try {
// Call the second function
const baseUrl = request.url.split("/api/")[0];
const secondFunctionUrl = `${baseUrl}/api/second_http_function`;
const response = await axios.get(secondFunctionUrl);
const secondFunctionResult = response.data;
const result = {
message: "Hello from the first function!",
second_function_response: secondFunctionResult,
};
return {
status: 200,
body: JSON.stringify(result),
headers: { "Content-Type": "application/json" },
};
} catch (error) {
return {
status: 500,
body: JSON.stringify({ error: "Failed to process request" }),
};
}
}
Deuxième fonction HTTP
export async function secondHttpFunction(
request: HttpRequest,
context: InvocationContext
): Promise<HttpResponseInit> {
context.log("TypeScript HTTP trigger function (second) processed a request.");
const message = "This is the second function responding.";
// Send a message to the Service Bus queue
const queueMessage =
"Message from second HTTP function to trigger ServiceBus queue processing";
context.extraOutputs.set(serviceBusOutput, queueMessage);
context.log("Sent message to ServiceBus queue:", queueMessage);
return {
status: 200,
body: message,
};
}
Déclencheur de file d'attente du Service Bus
export async function serviceBusQueueTrigger(
message: unknown,
context: InvocationContext
): Promise<void> {
context.log("TypeScript ServiceBus Queue trigger start processing a message:", message);
// Simulate processing time
await new Promise((resolve) => setTimeout(resolve, 5000));
context.log("TypeScript ServiceBus Queue trigger end processing a message");
}
La configuration OpenTelemetry est configurée dans src/OTelSample/Program.cs:
using Azure.Monitor.OpenTelemetry.Exporter;
using Microsoft.Azure.Functions.Worker;
using Microsoft.Azure.Functions.Worker.OpenTelemetry;
using OpenTelemetry.Trace;
var builder = FunctionsApplication.CreateBuilder(args);
builder.ConfigureFunctionsWebApplication();
builder.Logging.AddOpenTelemetry(logging =>
{
logging.IncludeFormattedMessage = true;
logging.IncludeScopes = true;
});
builder.Services.AddOpenTelemetry()
.WithTracing(tracing =>
{
tracing.AddHttpClientInstrumentation();
});
builder.Services.AddOpenTelemetry().UseAzureMonitorExporter();
builder.Services.AddOpenTelemetry().UseFunctionsWorkerDefaults();
builder.Services.AddHttpClient();
builder.Build().Run();
Les fonctions sont définies dans des fichiers de classe distincts :
Première fonction HTTP
public class FirstHttpTrigger
{
private readonly ILogger<FirstHttpTrigger> _logger;
private readonly IHttpClientFactory _httpClientFactory;
public FirstHttpTrigger(ILogger<FirstHttpTrigger> logger, IHttpClientFactory httpClientFactory)
{
_logger = logger;
_httpClientFactory = httpClientFactory;
}
[Function("first_http_function")]
public async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", "post")] HttpRequestData req)
{
_logger.LogInformation("first_http_function function processed a request.");
var baseUrl = $"{req.Url.AbsoluteUri.Split("/api/")[0]}/api";
var targetUri = $"{baseUrl}/second_http_function";
var client = _httpClientFactory.CreateClient();
var response = await client.GetAsync(targetUri);
var content = await response.Content.ReadAsStringAsync();
return new OkObjectResult($"Called second_http_function, status: {response.StatusCode}, content: {content}");
}
}
Deuxième fonction HTTP
public class SecondHttpTrigger
{
private readonly ILogger<SecondHttpTrigger> _logger;
public SecondHttpTrigger(ILogger<SecondHttpTrigger> logger)
{
_logger = logger;
}
[Function("second_http_function")]
public MultiResponse Run([HttpTrigger(AuthorizationLevel.Anonymous, "get", "post")] HttpRequestData req)
{
_logger.LogInformation("second_http_function function processed a request.");
return new MultiResponse
{
Messages = new string[] { "Hello" },
HttpResponse = req.CreateResponse(System.Net.HttpStatusCode.OK)
};
}
}
public class MultiResponse
{
[ServiceBusOutput("%ServiceBusQueueName%", Connection = "ServiceBusConnection")]
public string[]? Messages { get; set; }
[HttpResult]
public HttpResponseData? HttpResponse { get; set; }
}
Déclencheur de file d'attente du Service Bus
public class ServiceBusQueueTrigger
{
private readonly ILogger<ServiceBusQueueTrigger> _logger;
public ServiceBusQueueTrigger(ILogger<ServiceBusQueueTrigger> logger)
{
_logger = logger;
}
[Function("servicebus_queue_trigger")]
public async Task Run(
[ServiceBusTrigger("%ServiceBusQueueName%", Connection = "ServiceBusConnection")]
ServiceBusReceivedMessage message,
ServiceBusMessageActions messageActions)
{
_logger.LogInformation("Message ID: {id}", message.MessageId);
_logger.LogInformation("Message Body: {body}", message.Body);
// Complete the message
await messageActions.CompleteMessageAsync(message);
}
}
Flux de suivi distribué
Cette architecture crée un scénario de suivi distribué complet, avec ce comportement :
- La première fonction HTTP reçoit une requête HTTP et appelle la deuxième fonction HTTP
- La deuxième fonction HTTP répond et envoie un message à Service Bus
- Le déclencheur Service Bus traite le message avec un délai pour simuler le travail de traitement
Aspects clés de l’implémentation d’OpenTelemetry :
-
Intégration d’OpenTelemetry : le
host.jsonfichier active OpenTelemetry avec"telemetryMode": "OpenTelemetry" - Chaînage de fonctions : la première fonction appelle la seconde à l’aide de requêtes HTTP, créant des traces corrélées
- Intégration de Service Bus : la deuxième fonction est sortie vers Service Bus, ce qui déclenche la troisième fonction
-
Authentification anonyme : les fonctions HTTP utilisent
auth_level=func.AuthLevel.ANONYMOUS, donc aucune clé de fonction n’est requise
Vous pouvez consulter le projet de modèle complet ici.
-
Intégration d'OpenTelemetry : Ce fichier
index.tsconfigure OpenTelemetry avec les exportateurs Azure Monitor pour les traces et les journaux. - Chaînage de fonctions : la première fonction appelle la seconde à l’aide d’axios avec propagation de trace automatique
- Intégration de Service Bus : la deuxième fonction génère des sorties vers Service Bus à l’aide de liaisons de sortie, ce qui déclenche la troisième fonction
- Identité managée : toutes les connexions Service Bus utilisent une identité managée au lieu de chaînes de connexion
- Simulation de traitement : le délai de 5 secondes dans le déclencheur Service Bus simule le travail de traitement des messages
Vous pouvez consulter le projet de modèle complet ici.
-
Intégration d’OpenTelemetry : le
Program.csfichier configure OpenTelemetry avec l’exportateur Azure Monitor - Chaînage de fonctions : la première fonction appelle la seconde à l’aide de HttpClient avec l’instrumentation OpenTelemetry
- Intégration de Service Bus : la deuxième fonction génère des sorties vers Service Bus à l’aide de liaisons de sortie, ce qui déclenche la troisième fonction
- Identité managée : toutes les connexions Service Bus utilisent une identité managée au lieu de chaînes de connexion
- .NET 8 Worker isolé : Utilise le modèle de worker isolé .NET le plus récent d'Azure Functions pour des performances et une flexibilité accrues.
Vous pouvez consulter le projet de modèle complet ici.
Après avoir vérifié vos fonctions en local, il est temps de les publier sur Azure.
Déployer sur Azure
Ce projet est configuré pour utiliser la commande azd up afin de déployer ce projet sur une nouvelle application de fonctions dans un plan de consommation Flex sur Azure avec le support d’OpenTelemetry.
Conseil / Astuce
Ce projet comprend un ensemble de fichiers Bicep que azd utilisés pour créer un déploiement sécurisé vers un plan de consommation Flex qui suit les meilleures pratiques, notamment les connexions d'identité gérées.
Exécutez cette commande pour qu’
azdcrée les ressources Azure requises dans Azure et déployer votre projet de code dans la nouvelle application de fonction :azd upLe dossier racine contient le fichier de définition
azure.yamlexigé parazd.Si vous n’êtes pas déjà connecté, vous êtes invité à vous authentifier auprès de votre compte Azure.
Lorsque vous y êtes invité, fournissez ces paramètres de déploiement requis :
Paramètre Descriptif Abonnement Azure Abonnement dans lequel vos ressources sont créées. Emplacement Azure Région Azure dans laquelle créer le groupe de ressources qui contient les nouvelles ressources Azure. Seules sont montrées les régions qui prennent actuellement en charge le plan Consommation flexible. La commande
azd uputilise votre réponse à ces invites avec les fichiers de configuration Bicep pour effectuer ces tâches de déploiement :Créez et configurez ces ressources Azure requises (équivalentes à
azd provision) :- Plan de Consommation Flex d'Azure Functions et application fonctionnelle avec OpenTelemetry activé
- Stockage Azure (obligatoire) et Application Insights (recommandé)
- Espace de noms et file d’attente Service Bus pour la démonstration de suivi distribué
- Stratégies d’accès et rôles pour votre compte
- Connexions de service à service avec des identités managées (au lieu de chaînes de connexion stockées)
Empaquetez et déployez votre code sur le conteneur de déploiement (équivalent à
azd deploy). L’application est ensuite démarrée et s’exécute dans le package déployé.
Une fois la commande terminée, vous voyez des liens vers les ressources que vous avez créées.
Effectuer des tests de suivi distribué
Vous pouvez maintenant tester la fonctionnalité de suivi distribué OpenTelemetry en appelant vos fonctions déployées et en observant les données de télémétrie dans Application Insights.
Appeler la fonction sur Azure
Vous pouvez appeler vos points de terminaison de fonction dans Azure en effectuant des requêtes HTTP à leurs URL. Étant donné que les fonctions HTTP de ce modèle sont configurées avec un accès anonyme, aucune clé de fonction n’est requise.
Dans votre terminal local ou invite de commandes, exécutez cette commande pour obtenir le nom de l’application de fonction et construire l’URL :
APP_NAME=$(azd env get-value AZURE_FUNCTION_NAME) echo "Function URL: https://$APP_NAME.azurewebsites.net/api/first_http_function"La commande
azd env get-valueobtient le nom de votre application de fonction à partir de l’environnement local.Testez la fonction dans votre navigateur en accédant à l’URL :
https://your-function-app.azurewebsites.net/api/first_http_functionRemplacez
your-function-apppar le nom de votre application de fonction réelle à l’étape précédente. Cette requête unique crée une trace distribuée qui transite par les trois fonctions.
Afficher le suivi distribué dans Application Insights
Après avoir appelant la fonction, vous pouvez observer la trace distribuée complète dans Application Insights :
Note
Il peut s'écouler quelques minutes avant que les données de télémétrie apparaissent dans Application Insights après l'invocation de votre fonction. Si vous ne voyez pas les données immédiatement, attendez quelques minutes et actualisez la vue.
Accédez à votre ressource Application Insights dans le portail Azure (vous pouvez la trouver dans le même groupe de ressources que votre application de fonction).
Ouvrez la carte d’application pour afficher la trace distribuée sur les trois fonctions. Vous devez voir le flux de la requête HTTP via vos fonctions et vers Service Bus.
Vérifiez la recherche de transactions pour rechercher votre demande et consultez la chronologie complète des traces. Recherchez des transactions à partir de votre application de fonction.
Sélectionnez une transaction spécifique pour afficher la trace de bout en bout qui montre :
- Requête HTTP vers
first_http_function - Appel HTTP interne à
second_http_function - Message de Service Bus en cours d'envoi
- Le traitement du message
servicebus_queue_triggerprovenant d’Azure Service Bus
- Requête HTTP vers
Dans les détails de la trace, vous pouvez voir :
- Informations sur le temps : durée de chaque étape
- Dépendances : connexions entre les fonctions
- Journaux de l'application corrélés avec la trace
- Métriques de performances : temps de réponse et débit
Cet exemple illustre le suivi distribué de bout en bout sur plusieurs fonctions Azure avec l’intégration d’OpenTelemetry, ce qui offre une visibilité complète sur le comportement et les performances de votre application.
Redéployer votre code
Exécutez la azd up commande autant de fois que vous devez provisionner vos ressources Azure et déployer des mises à jour de code sur votre application de fonction.
Note
Le dernier package de déploiement remplace toujours les fichiers de code déployés.
Vos réponses initiales aux invites d’azd et toutes les variables d’environnement générées par azd sont stockées localement dans votre environnement nommé. Utilisez la azd env get-values commande pour passer en revue toutes les variables de votre environnement que la commande utilise lors de la création de ressources Azure.
Nettoyer les ressources
Lorsque vous avez terminé d’utiliser votre application de fonction et vos ressources associées, utilisez cette commande pour supprimer l’application de fonction et ses ressources associées d’Azure et éviter d’entraîner d’autres coûts :
azd down --no-prompt
Note
L’option --no-prompt indique à azd de supprimer votre groupe de ressources sans confirmation de votre part.
Cette commande n’affecte pas votre projet de code local.