Диагностика в Устойчивых функциях в Azure

Существует несколько способов диагностики неполадок в устойчивых функциях. Некоторые из этих вариантов такие же, как и для обычных функций, а некоторые уникальны для устойчивых функций.

Application Insights

Application Insights является рекомендуемым средством для выполнения диагностики и мониторинга в Функциях Azure. То же относится и к устойчивым функциям. Общие сведения об использовании Application Insights в приложении-функции см. в статье Мониторинг Функций Azure.

Расширение устойчивых функций в службе "Функции Azure" также генерирует события отслеживания для выполнения трассировки на протяжении всего процесса оркестрации. Эти события отслеживания можно найти и запросить на портале Azure с помощью средства Аналитика Application Insights.

Данные отслеживания

Каждое событие жизненного цикла экземпляра оркестрации инициирует запись события отслеживания в коллекцию трассировки в Application Insights. Это событие содержит полезные данные customDimensions с несколькими полями. Все имена полей указаны с префиксом prop__.

  • hubName. Имя центра задач, в котором выполняется оркестрация.
  • appName. Имя приложения-функции. Это полезно, когда у вас есть несколько приложений-функций, использующих один и тот же экземпляр Application Insights.
  • slotName.Слот развертывания, в котором выполняется текущее приложение-функция. Это поле полезно, если вы используете слоты развертывания для управления версиями оркестраций.
  • functionName. Имя оркестратора или функции действия.
  • functionType. Тип функции, например функция оркестратора или действия.
  • InstanceId. Уникальный идентификатор экземпляра оркестрации.
  • state. Состояние выполнения жизненного цикла экземпляра. Допустимые значения:
    • Scheduled. Выполнение функции было запланировано, но еще не началось.
    • Started. Функция запущена, но еще не находится в состоянии ожидания и не была завершена.
    • Awaited. Оркестратор запланировал некоторые действия и ожидает их завершения.
    • Listening. Оркестратор прослушивает уведомления о внешних событиях.
    • Completed. Функция успешно выполнена.
    • Failed. Выполнение функции завершилось ошибкой.
  • reason. Дополнительные данные, связанные с событием отслеживания. Например, если экземпляр ожидает уведомления о внешних событиях, это поле указывает имя события, которое он ожидает. Если выполнение функции завершилось сбоем, в этом поле будут указаны сведения об ошибке.
  • isReplay. Логическое значение, указывающее, следует ли повторно выполнять событие отслеживания.
  • extensionVersion. Версия расширения устойчивых задач. Сведения о версии особенно важны при составлении отчетов о возможных ошибках в расширении. Долго выполняющиеся экземпляры могут сообщать о нескольких версиях, если возникает обновление при их выполнении.
  • sequenceNumber: порядковый номер выполнения события. В сочетании с меткой времени позволяет упорядочить события по времени выполнения. Обратите внимание на то, что это число будет сброшено до нуля при перезапуске узла, когда экземпляр работает. Поэтому важно всегда сначала сортировать по метке времени, а затем по значению sequenceNumber.

Уровень детализации данных отслеживания, переданных в Application Insights, можно настроить в разделе logger (Функции 1.x) или logging (Функции 2.0) файла host.json.

Функции 1.0

{
    "logger": {
        "categoryFilter": {
            "categoryLevels": {
                "Host.Triggers.DurableTask": "Information"
            }
        }
    }
}

Функции 2.0

{
    "logging": {
        "logLevel": {
            "Host.Triggers.DurableTask": "Information",
        },
    }
}

По умолчанию создаются все события отслеживания без воспроизведения. Объем данных можно уменьшить, задав для Host.Triggers.DurableTask значение "Warning" или "Error". В этом случае события отслеживания будут передаваться в исключительных ситуациях. Чтобы включить создание событий воспроизведения для оркестрации, задайте для свойства logReplayEvents значение true файле конфигурации host.json:

Примечание.

По умолчанию телеметрия Application Insights осуществляется средой выполнения Функций Azure, чтобы избежать частой передачи данных. Это может привести к потере сведений об отслеживании, если много событий жизненного цикла происходят за короткий период времени. Сведения о настройке этого поведения см. в разделе Настройка выборки.

Входные и выходные данные функций оркестратора, действий и сущностей не регистрируются по умолчанию. Это поведение по умолчанию рекомендуется, так как входные и выходные данные журнала могут увеличить затраты на Application Insights. Полезные входные и выходные данные функций также могут содержать конфиденциальные сведения. Вместо этого регистрируется число байт для входных и выходных данных функций, а не фактические полезные данные по умолчанию. Если вы хотите, чтобы расширение "Устойчивые функции" регистрировало полные полезные входные и выходные данные, задайте для свойства traceInputsAndOutputs значение true в файле конфигурации host.json.

Одноэкземплярный запрос

Указанный ниже запрос содержит данные отслеживания журнала для одного экземпляра оркестрации функции последовательности Hello. Он написан с использованием языка запросов Kusto. Этот экземпляр фильтрует выполнение воспроизведения, поэтому показан только логический путь выполнения. События могут быть упорядочены путем сортировки по timestamp и sequenceNumber, как показано в следующем запросе.

let targetInstanceId = "ddd1aaa685034059b545eb004b15d4eb";
let start = datetime(2018-03-25T09:20:00);
traces
| where timestamp > start and timestamp < start + 30m
| where customDimensions.Category == "Host.Triggers.DurableTask"
| extend functionName = customDimensions["prop__functionName"]
| extend instanceId = customDimensions["prop__instanceId"]
| extend state = customDimensions["prop__state"]
| extend isReplay = tobool(tolower(customDimensions["prop__isReplay"]))
| extend sequenceNumber = tolong(customDimensions["prop__sequenceNumber"])
| where isReplay != true
| where instanceId == targetInstanceId
| sort by timestamp asc, sequenceNumber asc
| project timestamp, functionName, state, instanceId, sequenceNumber, appName = cloud_RoleName

Результатом является список событий отслеживания, который отображает путь выполнения оркестрации, включая любые функции действий, упорядоченные по времени выполнения в возрастающем порядке.

Упорядоченный запрос одного экземпляра Application Insights

Сводный запрос экземпляров

Следующий запрос отображает состояние всех экземпляров оркестрации, выполненных в указанном диапазоне времени.

let start = datetime(2017-09-30T04:30:00);
traces
| where timestamp > start and timestamp < start + 1h
| where customDimensions.Category == "Host.Triggers.DurableTask"
| extend functionName = tostring(customDimensions["prop__functionName"])
| extend instanceId = tostring(customDimensions["prop__instanceId"])
| extend state = tostring(customDimensions["prop__state"])
| extend isReplay = tobool(tolower(customDimensions["prop__isReplay"]))
| extend output = tostring(customDimensions["prop__output"])
| where isReplay != true
| summarize arg_max(timestamp, *) by instanceId
| project timestamp, instanceId, functionName, state, output, appName = cloud_RoleName
| order by timestamp asc

Результатом является список идентификаторов экземпляров и их текущее состояние выполнения.

Запрос одного экземпляра Application Insights

Ведение журнала платформы устойчивых задач

Журналы расширения "Устойчивые функции" помогают понять поведение логики оркестрации. Однако эти журналы не всегда содержат достаточно информации для устранения проблем с производительностью и надежностью на уровне платформы. Начиная с версии 2.3.0 расширения "Устойчивые функции" можно также собирать создаваемые базовой платформой устойчивых задач (DTFx) журналы.

При просмотре создаваемых DTFx журналов важно понимать, что подсистема DTFx состоит из двух компонентов: основного механизма диспетчеризации (DurableTask.Core) и одного из множества поддерживаемых поставщиков хранилища (в Устойчивых функциях по умолчанию используется DurableTask.AzureStorage, но тут есть и другие параметры).

  • DurableTask.Core: основные журналы выполнения оркестрации и низкоуровневого планирования, а также телеметрия.
  • DurableTask.AzureStorage: серверные журналы, относящиеся к поставщику состояний службы хранилища Azure. Эти журналы включают подробные сведения о взаимодействиях с внутренними очередями, большими двоичными объектами и таблицами хранилища, используемыми для хранения и получения внутреннего состояния оркестрации.
  • DurableTask.Netherite: серверные журналы, относящиеся к поставщику хранилища Netherite, если параметр включен.
  • DurableTask.SqlServer: внутренние журналы, относящиеся к поставщику хранилища Microsoft SQL (MSSQL), если параметр включен.

Разрешить эти журналы можно, обновив раздел logging/logLevel в файле host.json для приложения-функции. В следующем примере показано, как разрешить журналы предупреждений и ошибок с помощью DurableTask.Core и DurableTask.AzureStorage.

{
  "version": "2.0",
  "logging": {
    "logLevel": {
      "DurableTask.AzureStorage": "Warning",
      "DurableTask.Core": "Warning"
    }
  }
}

Если служба Application Insights включена, эти журналы будут автоматически добавляться в коллекцию trace. Поиск можно выполнять таким же образом, как и поиск других журналов trace с помощью запросов Kusto.

Примечание.

Для рабочих приложений рекомендуется включить DurableTask.Core и соответствующие журналы поставщика хранилища (например, DurableTask.AzureStorage) с помощью фильтра "Warning". Фильтры с повышенным уровнем детализации вроде "Information" очень полезны при решении проблем с производительностью. Однако эти события журнала могут занимать большой объем, и это может значительно увеличить затраты на хранение данных Application Insights.

В следующем запросе Kusto показано, как запросить журналы DTFx. Наиболее важной частью запроса является where customerDimensions.Category startswith "DurableTask", так как этот параметр отвечает за фильтрацию результатов категории DurableTask.Core и DurableTask.AzureStorage в журналах.

traces
| where customDimensions.Category startswith "DurableTask"
| project
    timestamp,
    severityLevel,
    Category = customDimensions.Category,
    EventId = customDimensions.EventId,
    message,
    customDimensions
| order by timestamp asc 

В результате появляется набор журналов, созданных регистраторами платформы устойчивых задач.

Результаты запросов DTFx в Application Insights

Дополнительные сведения о доступных событиях журнала см. в статье Документация по ведению структурированного журнала для платформы устойчивых задач на сайте GitHub.

Ведение журнала приложений

Очень важно помнить о поведении воспроизведения оркестратора при записи журналов непосредственно из функции оркестратора. Например, рассмотрим следующую функцию оркестратора:

[FunctionName("FunctionChain")]
public static async Task Run(
    [OrchestrationTrigger] IDurableOrchestrationContext context,
    ILogger log)
{
    log.LogInformation("Calling F1.");
    await context.CallActivityAsync("F1");
    log.LogInformation("Calling F2.");
    await context.CallActivityAsync("F2");
    log.LogInformation("Calling F3");
    await context.CallActivityAsync("F3");
    log.LogInformation("Done!");
}

Итоговые данные журнала должны напоминать выходные данные из следующего примера.

Calling F1.
Calling F1.
Calling F2.
Calling F1.
Calling F2.
Calling F3.
Calling F1.
Calling F2.
Calling F3.
Done!

Примечание.

Помните, что хотя в журналах указаны вызовы F1, F2 и F3, эти функции фактически вызываются, только когда они встречаются впервые. Последующие вызовы, которые происходят во время воспроизведения, пропускаются, и выходные данные воспроизводятся в логике оркестратора.

Если вы хотите включать в журналы только случаи выполнения без воспроизведения, можно записывать логическое выражение в журнал только тогда, когда флагу "is replaying" присвоено значение false. Рассмотрим указанный выше пример, но на этот раз с проверкой воспроизведения.

[FunctionName("FunctionChain")]
public static async Task Run(
    [OrchestrationTrigger] IDurableOrchestrationContext context,
    ILogger log)
{
    if (!context.IsReplaying) log.LogInformation("Calling F1.");
    await context.CallActivityAsync("F1");
    if (!context.IsReplaying) log.LogInformation("Calling F2.");
    await context.CallActivityAsync("F2");
    if (!context.IsReplaying) log.LogInformation("Calling F3");
    await context.CallActivityAsync("F3");
    log.LogInformation("Done!");
}

Начиная с версии 2.0, в Устойчивых функциях при помощи функций оркестратора .NET можно создавать расширение ILogger, чтобы автоматически отфильтровывать операторы журнала во время воспроизведения. Эта автоматическая фильтрация выполняется с помощью API IDurableOrchestrationContext.CreateReplaySafeLogger(ILogger).

[FunctionName("FunctionChain")]
public static async Task Run(
    [OrchestrationTrigger] IDurableOrchestrationContext context,
    ILogger log)
{
    log = context.CreateReplaySafeLogger(log);
    log.LogInformation("Calling F1.");
    await context.CallActivityAsync("F1");
    log.LogInformation("Calling F2.");
    await context.CallActivityAsync("F2");
    log.LogInformation("Calling F3");
    await context.CallActivityAsync("F3");
    log.LogInformation("Done!");
}

Примечание.

Предыдущие примеры C# предназначены для расширения "Устойчивые функции" версии 2.x. Для расширения Устойчивые функции 1.x необходимо использовать DurableOrchestrationContext вместо IDurableOrchestrationContext. Дополнительные сведения о различиях между версиями см. в статье Версии устойчивых функций.

С учетом упомянутых выше изменений выходные данные журнала выглядят следующим образом.

Calling F1.
Calling F2.
Calling F3.
Done!

Пользовательское состояние

Эта возможность позволяет задать настраиваемое значение состояния для функции оркестратора. Затем это настраиваемое значение состояния становится видно внешним клиентам с помощью API запросов состояния HTTP или вызовов API, зависящих от языка. Настраиваемое состояние оркестрации предоставляет дополнительные возможности мониторинга для функций оркестратора. Например, с помощью кода функции оркестратора можно вызвать API для присвоения настраиваемого значения состояния, чтобы обновлять сведения о ходе выполнения длительной операции. Клиент, например веб-страница или другая внешняя система, может периодически отправлять запрос в API HTTP-запросов состояния, чтобы получить расширенные сведения о ходе выполнения. Далее приведен пример кода для настройки настраиваемого значения состояния в функции оркестратора.

[FunctionName("SetStatusTest")]
public static async Task SetStatusTest([OrchestrationTrigger] IDurableOrchestrationContext context)
{
    // ...do work...

    // update the status of the orchestration with some arbitrary data
    var customStatus = new { completionPercentage = 90.0, status = "Updating database records" };
    context.SetCustomStatus(customStatus);

    // ...do more work...
}

Примечание.

Предыдущий пример C# предназначен для расширения "Устойчивые функции" версии 2.x. Для расширения Устойчивые функции 1.x необходимо использовать DurableOrchestrationContext вместо IDurableOrchestrationContext. Дополнительные сведения о различиях между версиями см. в статье Версии устойчивых функций.

Когда выполняется оркестрация, внешние клиенты могут получить данные о таком настраиваемом значении состояния:

GET /runtime/webhooks/durabletask/instances/instance123?code=XYZ

Они получат следующий ответ:

{
  "runtimeStatus": "Running",
  "input": null,
  "customStatus": { "completionPercentage": 90.0, "status": "Updating database records" },
  "output": null,
  "createdTime": "2017-10-06T18:30:24Z",
  "lastUpdatedTime": "2017-10-06T19:40:30Z"
}

Предупреждение

Полезные данные настраиваемого значения состояния не должны превышать 16 КБ JSON-текста в кодировке UTF-16, так как они должны поместиться в столбец Хранилища таблиц Azure. Для полезных данных большего размера можно использовать внешнее хранилище.

Распределенная трассировка

Распределенная трассировка отслеживает запросы и показывает, как разные службы взаимодействуют друг с другом. В Устойчивые функции он также сопоставляет оркестрации и действия вместе. Это полезно, чтобы понять, сколько времени выполняет оркестрация относительно всего оркестрации. Также полезно понять, где у приложения возникла проблема или где возникло исключение. Эта функция поддерживается для всех языков и поставщиков хранилища.

Примечание.

Для распределенной трассировки версии 2 требуется Устойчивые функции версии 2.12.0 или более поздней версии. Кроме того, распределенная трассировка версии 2 находится в состоянии предварительной версии, поэтому некоторые Устойчивые функции шаблоны не инструментируются. Например, операции устойчивых сущностей не инструментируются и трассировки не отображаются в приложении Аналитика.

Настройка распределенной трассировки

Чтобы настроить распределенную трассировку, обновите host.json и настройте ресурс приложения Аналитика.

host.json

"durableTask": {
  "tracing": {
    "distributedTracingEnabled": true,
    "Version": "V2"
  }
}

Application Insights

Если приложение-функция не настроено с ресурсом application Аналитика, настройте его, следуя инструкциям ниже.

Проверка трассировок

В ресурсе приложения Аналитика перейдите к поиску транзакций. В результатах проверка для Request событийDependency, начинающихся с Устойчивые функции определенных префиксов (напримерorchestration:, и activity:т. д.). При выборе одного из этих событий откроется диаграмма Ганта, которая будет отображать конец распределенной трассировки.

Диаграмма Ганта с приложением Аналитика распределенной трассировки.

Устранение неполадок

Если трассировка не отображается в приложении Аналитика, обязательно подождите около пяти минут после запуска приложения, чтобы убедиться, что все данные распространяются на ресурс application Аналитика.

Отладка

Функции Azure поддерживают сценарии отладки кода функции напрямую. Та же поддержка реализуется в устойчивых функциях, работающих в Azure или локально. Однако следует помнить о некоторых особенностях поведения при выполнении отладки.

  • Replay. Функции оркестратора обычно воспроизводятся при получении новых входных данных. Такое поведение означает, что однократное логическое выполнение функции оркестратора может привести к многократному достижению одной той же точки останова. Особенно часто это происходит, когда она располагается ближе к началу кода функции.
  • Await. Каждый раз, когда в функции оркестратора возникает действие await, она снова уступает контроль диспетчеру платформы устойчивых задач. Если действие await возникает впервые, связанная задача никогда не возобновляется. Так как задача никогда не возобновляется, шаг с обходом действия await (F10 в Visual Studio) невозможен. Вы можете обойти это действие, только когда задание воспроизводится.
  • Время ожидания обмена сообщениями. Внутреннее применение в Устойчивых функциях сообщений очереди позволяет управлять выполнением функций оркестратора, функций действий и функций сущностей. В среде со множеством виртуальных машин прерывание отладки на длительное время может привести к тому, что другая виртуальная машина получит сообщение, из-за чего произойдет дублирующее выполнение. Это поведение также существует для обычных функций триггера очереди, но его очень важно отметить в этом контексте, так как очереди относятся к тонкостям реализации.
  • Остановка и запуск. Сообщения в Устойчивых функциях сохраняются в промежутках между сеансами отладки. Если остановить отладку и завершить процесс локального узла во время выполнения устойчивой функции, эта функция может быть повторно выполнена автоматически в ходе следующего сеанса отладки. Когда такое поведение непредсказуемо, оно может сбивать с толку. Чтобы избежать такого поведения, можно использовать новый центр задач или очищать содержимое центра задач между сеансами отладки.

Совет

Если вы хотите прерывать только выполнение без воспроизведения при настройке точек останова в функциях оркестратора, можно задать условную точку останова, выполняющую прерывание только тогда, когда у "is replaying" значение false.

Хранилище

По умолчанию устойчивые функции хранят состояние в службе хранилища Azure. Это поведение означает, что вы можете проверить состояние оркестраций с помощью таких средств, как Обозреватель службы хранилища Microsoft Azure.

Снимок экрана Обозревателя службы хранилища Azure

Это полезно для отладки, так как вы можете увидеть точное состояние оркестрации. Сообщения в очередях можно также проверить, чтобы узнать, какое действие находится в состоянии ожидания (или в некоторых случаях могло зависнуть).

Предупреждение

Хотя просматривать журнал выполнения в службе таблиц более удобно, избегайте использования зависимостей в таблице. Они могут измениться при развитии расширения устойчивых функций.

Примечание.

Вместо поставщика хранилища Azure по умолчанию в настройках можно выбрать других поставщиков хранилища. В зависимости от поставщика хранилища, настроенного для приложения, может потребоваться применение различных средств для проверки базового состояния. Дополнительные сведения см. в документации по поставщикам хранилища в Устойчивых функциях.

монитор Устойчивые функции

Устойчивые функции Monitor — это графическое средство для мониторинга, управления и отладки экземпляров оркестрации и сущностей. Он доступен как расширение Visual Studio Code или автономное приложение. Сведения о настройке и списке функций можно найти в этом вики-сайте.

руководство по устранению неполадок Устойчивые функции

Чтобы устранить распространенные проблемы, такие как зависание оркестрации, сбой запуска, медленное выполнение и т. д., см. в этом руководстве по устранению неполадок.

Следующие шаги