Заметка
Доступ к этой странице требует авторизации. Вы можете попробовать войти в систему или изменить каталог.
Доступ к этой странице требует авторизации. Вы можете попробовать сменить директорию.
В этой статье демонстрируется поддержка OpenTelemetry в функции Azure, которая обеспечивает распределенную трассировку между несколькими вызовами функций с помощью встроенной поддержки Application Insights и OpenTelemetry. Чтобы помочь вам начать работу, используется шаблон Azure Developer CLI azd для создания вашего проекта и развертывания Azure, в котором будет работать ваше приложение.
В этом руководстве вы будете использовать инструмент azd для:
- Инициализировать проект с поддержкой OpenTelemetry из шаблона.
- Просмотрите код, который включает интеграцию OpenTelemetry.
- Запустите и проверьте локальное приложение с поддержкой OpenTelemetry.
- Создайте приложение-функцию и связанные ресурсы в Azure.
- Разверните проект кода в приложении-функции в Azure.
- Проверьте распределенную трассировку в Application Insights.
Необходимые ресурсы Azure, созданные этим шаблоном, соответствуют текущим рекомендациям по безопасным и масштабируемым развертываниям приложений-функций в Azure. Эта же azd команда также развертывает проект кода в новом функциональном приложении в Azure.
По умолчанию, план потребления Flex следует модели выставления счетов с оплатой по факту использования, что означает, что выполнение этого краткого руководства может стоить вам всего несколько центов США или меньше в вашей учетной записи Azure.
Это важно
В настоящее время эта статья поддерживает только C#, Python и TypeScript. Чтобы завершить краткое руководство, выберите один из поддерживаемых языков в верхней части статьи.
Предпосылки
Учетная запись Azure с активной подпиской. Создайте учетную запись бесплатно .
Инициализируйте проект
Используйте команду azd init для создания кода локального проекта Azure Functions из шаблона, включающего распределенную трассировку OpenTelemetry.
В локальном терминале или командной строке выполните следующую
azd initкоманду в пустой папке:azd init --template functions-quickstart-python-azd-otel -e flexquickstart-otelЭта команда извлекает файлы проекта из репозитория шаблонов и инициализирует проект в текущей папке. Флаг
-eзадает имя текущей среды. Вazdсреде поддерживается уникальный контекст развертывания для вашего приложения, и вы можете определить более одного контекста. Имя среды также отображается в имени группы ресурсов, создаваемой в Azure.
В локальном терминале или командной строке выполните следующую
azd initкоманду в пустой папке:azd init --template functions-quickstart-typescript-azd-otel -e flexquickstart-otelЭта команда извлекает файлы проекта из репозитория шаблонов и инициализирует проект в текущей папке. Флаг
-eзадает имя текущей среды. Вazdсреде поддерживается уникальный контекст развертывания для вашего приложения, и вы можете определить более одного контекста. Имя среды также отображается в имени группы ресурсов, создаваемой в Azure.
В локальном терминале или командной строке выполните следующую
azd initкоманду в пустой папке:azd init --template functions-quickstart-dotnet-azd-otel -e flexquickstart-otelЭта команда извлекает файлы проекта из репозитория шаблонов и инициализирует проект в текущей папке. Флаг
-eзадает имя текущей среды. Вazdсреде поддерживается уникальный контекст развертывания для вашего приложения, и вы можете определить более одного контекста. Имя среды также отображается в имени группы ресурсов, создаваемой в Azure.
Просмотр кода
Шаблон создает полный сценарий распределенной трассировки с тремя функциями, которые работают вместе. Рассмотрим ключевые аспекты, связанные с OpenTelemetry:
Конфигурация OpenTelemetry
Файл src/otel-sample/host.json включает OpenTelemetry для узла функций:
{
"version": "2.0",
"telemetryMode": "OpenTelemetry",
"extensions": {
"serviceBus": {
"maxConcurrentCalls": 10
}
},
"extensionBundle": {
"id": "Microsoft.Azure.Functions.ExtensionBundle",
"version": "[4.*, 5.0.0)"
}
}
Параметр ключа "telemetryMode": "OpenTelemetry" включает распределенную трассировку между вызовами функций.
Файл src/OTelSample/host.json включает OpenTelemetry для узла функций:
{
"version": "2.0",
"telemetryMode": "OpenTelemetry",
"logging": {
"OpenTelemetry": {
"logLevel": {
"Host.General": "Warning"
}
}
}
}
Параметр ключа "telemetryMode": "OpenTelemetry" включает распределенную трассировку между вызовами функций.
Зависимости для OpenTelemetry
Файл src/otel-sample/requirements.txt содержит необходимые пакеты для интеграции OpenTelemetry:
azure-functions
azure-monitor-opentelemetry
requests
Пакет azure-monitor-opentelemetry предоставляет интеграцию OpenTelemetry с Application Insights.
Файл src/otel-sample/package.json содержит необходимые пакеты для интеграции 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"
}
}
@azure/functions-opentelemetry-instrumentation и @azure/monitor-opentelemetry-exporter пакеты обеспечивают интеграцию OpenTelemetry с Application Insights.
Файл .csproj содержит необходимые пакеты для интеграции 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" />
Эти пакеты обеспечивают интеграцию OpenTelemetry с Application Insights и инструментированием HTTP для распределенной трассировки.
Реализация функции
Функции в src/otel-sample/function_app.py демонстрируют процесс распределенного трассирования.
Первая функция 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"
)
Вторая функция 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
)
Триггер очереди сервисной шины
@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')
Конфигурация OpenTelemetry настроена в 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()],
});
Функции определяются в папке src/otel-sample/src/functions :
Первая функция 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" }),
};
}
}
Вторая функция 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,
};
}
Триггер очереди Azure 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");
}
Конфигурация OpenTelemetry настроена в 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();
Функции определяются в отдельных файлах классов:
Первая функция 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}");
}
}
Вторая функция 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; }
}
Триггер очереди Azure 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);
}
}
Распределенный поток трассировки
Эта архитектура создает полный сценарий распределенной трассировки с таким поведением:
- Первая функция HTTP получает HTTP-запрос и вызывает вторую функцию HTTP
- Вторая функция HTTP отвечает и отправляет сообщение в служебную шину
- Триггер служебной шины обрабатывает сообщение с задержкой для имитации работы обработки
Ключевые аспекты реализации OpenTelemetry:
-
Интеграция OpenTelemetry:
host.jsonфайл активирует OpenTelemetry с"telemetryMode": "OpenTelemetry" - Цепочка функций: первая функция вызывает вторую с помощью HTTP-запросов, создавая коррелированные трассировки.
- Интеграция служебной шины: вторая функция выводится в служебную шину, которая активирует третью функцию.
-
Анонимная проверка подлинности: используются
auth_level=func.AuthLevel.ANONYMOUSфункции HTTP, поэтому ключи функций не требуются
Вы можете просмотреть полный проект шаблона здесь.
-
Интеграция OpenTelemetry:
index.tsфайл настраивает OpenTelemetry с экспортерами Azure Monitor для трассировок и журналов. - Цепочка функций: первая функция вызывает вторую с помощью axios с автоматическим распространением трассировки.
- Интеграция служебной шины: вторая функция выводится в служебную шину с помощью выходных привязок, которая активирует третью функцию.
- Управляемое удостоверение: все подключения к служебной шине используют управляемое удостоверение вместо строк подключения
- Моделирование обработки: 5-секундная задержка в триггере служебной шины имитирует работу обработки сообщений
Вы можете просмотреть полный проект шаблона здесь.
-
Интеграция OpenTelemetry:
Program.csфайл настраивает OpenTelemetry с помощью экспортера Azure Monitor - Цепочка функций: первая функция вызывает вторую через HttpClient с инструментированием OpenTelemetry
- Интеграция служебной шины: вторая функция выводится в служебную шину с помощью выходных привязок, которая активирует третью функцию.
- Управляемое удостоверение: все подключения Шины Сервисов используют управляемое удостоверение вместо строк подключения
- Изолированная рабочая модель .NET 8. Использует последнюю изолированную модель рабочего процесса Azure Functions .NET для повышения производительности и гибкости.
Вы можете просмотреть полный проект шаблона здесь.
После локальной проверки функций пора опубликовать их в Azure.
Развертывание в Azure
Этот проект сконфигурирован для развертывания в новом функциональном приложении в плане Flex Consumption в Azure с поддержкой OpenTelemetry.
Подсказка
Этот проект включает набор файлов Bicep, которые azd используются для создания безопасного развертывания в плане потребления Flex, следуя передовым практикам, включая интеграцию с управляемыми удостоверениями.
Выполните следующую команду, чтобы
azdсоздать необходимые ресурсы Azure в Azure и развернуть проект кода в новом приложении-функции:azd upКорневая папка содержит файл определения, необходимый
azure.yamlazd.Если вы еще не вошли, вам будет предложено выполнить проверку подлинности с помощью учетной записи Azure.
При появлении запроса укажите следующие необходимые параметры развертывания:
Параметр Description Подписка Azure Подписка, в которой создаются ресурсы. Расположение Azure Регион Azure, в котором создается группа ресурсов, содержащая новые ресурсы Azure. Отображаются только регионы, поддерживающие план потребления Flex. Команда
azd upиспользует ответ на эти запросы с файлами конфигурации Bicep для выполнения следующих задач развертывания:Создайте и настройте эти необходимые ресурсы Azure (эквивалентно
azd provision):- Приложение функции Azure с планом Flex Consumption и поддержкой OpenTelemetry
- служба хранилища Azure (обязательно) и Application Insights (рекомендуется)
- Пространство имен и очередь Service Bus для демонстрации распределенной трассировки
- Политики и роли доступа для учетной записи
- Подключения между службами с помощью управляемых удостоверений (вместо хранимых строка подключения)
Упаковайте и разверните код в контейнере развертывания (эквивалентно
azd deploy). Затем приложение запускается и запускается в развернутом пакете.
После успешного завершения команды вы увидите ссылки на созданные ресурсы.
Тестирование распределенной трассировки
Теперь вы можете протестировать возможности распределенной трассировки OpenTelemetry, вызывая развернутые функции и наблюдая телеметрию в Application Insights.
Вызов функции в Azure
Вы можете вызвать конечные точки функций в Azure, выполнив HTTP-запросы к их URL-адресам. Так как функции HTTP в этом шаблоне настроены с анонимным доступом, ключи функций не требуются.
В локальном терминале или командной строке выполните следующую команду, чтобы получить имя приложения-функции и создать URL-адрес:
APP_NAME=$(azd env get-value AZURE_FUNCTION_NAME) echo "Function URL: https://$APP_NAME.azurewebsites.net/api/first_http_function"Команда
azd env get-valueполучает имя приложения-функции из локальной среды.Проверьте функцию в браузере, перейдя по URL-адресу:
https://your-function-app.azurewebsites.net/api/first_http_functionЗамените
your-function-appфактическим именем приложения-функции на предыдущем шаге. Этот один запрос создает распределенную трассировку, которая проходит через все три функции.
Просмотр распределенной трассировки в Application Insights
После вызова функции можно наблюдать полную распределенную трассировку в Application Insights:
Замечание
Может потребоваться несколько минут, чтобы данные телеметрии отображались в Application Insights после вызова функции. Если данные не отображаются немедленно, подождите несколько минут и обновите представление.
Перейдите к ресурсу Application Insights на портале Azure (его можно найти в той же группе ресурсов, что и приложение-функция).
Откройте карту приложения , чтобы увидеть распределенную трассировку во всех трех функциях. Вы должны увидеть поток от HTTP-запроса через ваши функции и до Service Bus.
Проверьте поиск транзакций , чтобы найти запрос и просмотреть полную временную шкалу трассировки. Выполните поиск транзакций в функциональном приложении.
Выберите определенную транзакцию, чтобы увидеть сквозную трассировку, которая показывает:
- HTTP-запрос на
first_http_function - Внутренний HTTP-вызов
second_http_function - Сообщение служебной шины, которое отправляется
- Обработка
servicebus_queue_triggerсообщения из Service Bus
- HTTP-запрос на
В сведениях о трассировке можно увидеть следующее:
- Сведения о времени: как долго каждый шаг занял
- Зависимости: соединения между функциями
- Логи: журналы приложений, связанные с трассировкой
- Метрики производительности: время отклика и пропускная способность
В этом примере демонстрируется сквозная распределенная трассировка для нескольких функций Azure с интеграцией OpenTelemetry, обеспечивающая полную видимость поведения и производительности приложения.
Повторное развертывание кода
Выполните команду azd up столько раз, сколько потребуется, чтобы развернуть обновления кода в функции-приложении и настроить ресурсы Azure.
Замечание
Последний пакет развертывания всегда перезаписывает развернутые файлы кода.
Исходные ответы на azd запросы и любые переменные среды, созданные с помощью azd , хранятся локально в именованной среде.
azd env get-values Используйте команду, чтобы просмотреть все переменные в вашей среде, которые команда использует при создании ресурсов Azure.
Очистите ресурсы
Когда вы закончите работу с приложением-функцией и связанными ресурсами, используйте эту команду, чтобы удалить приложение-функцию и связанные с ним ресурсы из Azure и избежать дополнительных затрат:
azd down --no-prompt
Замечание
Параметр --no-prompt указывает azd удалить группу ресурсов без подтверждения.
Эта команда не влияет на локальный проект кода.