Azure functions Azure持久功能-诊断故障

Azure functions Azure持久功能-诊断故障,azure-functions,azure-durable-functions,Azure Functions,Azure Durable Functions,我正在测试持久的函数可以如何扇入/扇出,以及如何扩展代码。对于这个例子,我模拟了许多短时间运行的cpu密集型操作 并不是所有的活动都完成了,我不知道为什么或者在哪里查找失败日志 请参阅下面的代码: public static class ParallelLoadDurable { [FunctionName("ParallelLoadDurable")] public static async Task<string> RunOrchestra

我正在测试持久的函数可以如何扇入/扇出,以及如何扩展代码。对于这个例子,我模拟了许多短时间运行的cpu密集型操作

并不是所有的活动都完成了,我不知道为什么或者在哪里查找失败日志

请参阅下面的代码:

public static class ParallelLoadDurable
    {
        [FunctionName("ParallelLoadDurable")]
        public static async Task<string> RunOrchestrator(
            [OrchestrationTrigger] DurableOrchestrationContext context, ILogger log)
        {
            DateTime StartTimer = DateTime.Now;

            int counter = 0;
            var parallelTasks = new List<Task<string>>();
            var retryOptions = new RetryOptions(
                 firstRetryInterval: TimeSpan.FromSeconds(5),
                 maxNumberOfAttempts: 5);
            for (int i = 0; i < 1000; i++)
            {
                counter += 1;
                DurablePassModel DPM = new DurablePassModel()
                {
                    LoopNum = counter,
                    StartedOn = StartTimer
                };
                Task<string> task = context.CallActivityWithRetryAsync<string>("ParallelLoadDurable_Hello", retryOptions, DPM);
                parallelTasks.Add(task);
            }
            await Task.WhenAll(parallelTasks);

            DateTime CompleteTime = DateTime.Now;
            TimeSpan TS = CompleteTime.Subtract(StartTimer);

            string ret = $"PROCESS COMPLETED: {counter} times for: {TS.TotalMilliseconds} ms.";
            log.LogInformation(ret);
            return ret;
        }

        [FunctionName("ParallelLoadDurable_Hello")]
        public static string SayHello([ActivityTrigger] DurablePassModel val, ILogger log)
        {
            log.LogInformation($"Starting child function num {val.LoopNum.ToString()}.");
            DateTime StartTimer = DateTime.Now;

            var endTime = DateTime.Now.AddSeconds(10);

            while (true)
            {
                if (DateTime.Now >= endTime)
                    break;
            }

            DateTime CompleteTime = DateTime.Now;
            TimeSpan TS = CompleteTime.Subtract(val.StartedOn);
            TimeSpan TSThis = CompleteTime.Subtract(StartTimer);

            string ret = $"Ran this for: {TSThis.TotalSeconds}s - LoopNum: {val.LoopNum} - total time: {TS.TotalSeconds}s.";
            log.LogInformation(ret);

            return ret;
        }

        [FunctionName("ParallelLoadDurable_HttpStart")]
        public static async Task<HttpResponseMessage> HttpStart(
            [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post")]HttpRequestMessage req,
            [OrchestrationClient]DurableOrchestrationClient starter,
            ILogger log)
        {
            // Function input comes from the request content.
            string instanceId = await starter.StartNewAsync("ParallelLoadDurable", null);

            log.LogInformation($"Started orchestration with ID = '{instanceId}'.");

            return starter.CreateCheckStatusResponse(req, instanceId);
        }
    }
public静态类并行加载
{
[函数名(“并行加载”)]
公共静态异步任务RunOrchestrator(
[OrchestrationTrigger]DurableOrchestrationContext上下文,ILogger日志)
{
DateTime StartTimer=DateTime.Now;
int计数器=0;
var parallelstasks=新列表();
var retryOptions=新的retryOptions(
firstRetryInterval:TimeSpan.FromSeconds(5),
最大尝试次数:5次;
对于(int i=0;i<1000;i++)
{
计数器+=1;
DurablePassModel DPM=新的DurablePassModel()
{
LoopNum=计数器,
StartedOn=StartTimer
};
Task Task=context.CallActivityWithRetryAsync(“ParallelLoadDurable\u Hello”,retryOptions,DPM);
parallelstasks.Add(任务);
}
等待任务。WhenAll(并行任务);
DateTime CompleteTime=DateTime.Now;
TimeSpan TS=完成时间减去(起始时间);
string ret=$“进程已完成:{TS.totalmillizes}ms.{counter}次”;
日志、登录信息(ret);
返回ret;
}
[FunctionName(“ParallelLoad\u Hello”)]
公共静态字符串SayHello([ActivityTrigger]DurablePassModel val,ILogger日志)
{
log.LogInformation($“启动子函数num{val.LoopNum.ToString()}”);
DateTime StartTimer=DateTime.Now;
var endTime=DateTime.Now.AddSeconds(10);
while(true)
{
如果(DateTime.Now>=endTime)
打破
}
DateTime CompleteTime=DateTime.Now;
TimeSpan TS=CompleteTime.Subtract(val.StartedOn);
TimeSpan TSThis=CompleteTime.Subtract(起始时间);
string ret=$“为{TSThis.TotalSeconds}s运行此操作-LoopNum:{val.LoopNum}-总时间:{TS.TotalSeconds}s.”;
日志、登录信息(ret);
返回ret;
}
[FunctionName(“ParallelLoad\u HttpStart”)]
公共静态异步任务HttpStart(
[HttpTrigger(AuthorizationLevel.Anonymous,“获取”、“发布”)]HttpRequestMessage请求,
[OrchestrationClient]DurableOrchestrationClient启动器,
ILogger日志)
{
//函数输入来自请求内容。
字符串instanceId=await starter.StartNewAsync(“ParallelLoadDurable”,null);
LogInformation($“启动了ID为“{instanceId}”的业务流程”;
返回starter.CreateCheckStatusResponse(请求,实例ID);
}
}
几乎在所有情况下,我都能完成96%的预期活动。这来自历史记录表中的结果,其中EventType=TaskCompleted

此外,在“实例”表中,RuntimeStatus仅保持“正在运行”

在哪里可以找到失败列表

谢谢你的帮助


尼克

块包围你的代码,然后用
Ilogger
记录异常

它可以通过这样的方式实现

try
{
   //Do something
}
catch(Exception ex){
   log.LogError($"Error in function: {ex.Message}");
}

然后,您可以查看日志中的错误消息,也可以查看
应用程序洞察(如果有)。

我建议您为Azure功能配置应用程序洞察: 虽然存储数据需要一些成本,但在调查问题时确实会有很大帮助

此外(或当您不需要应用程序洞察时),您可以通过或查询业务流程的状态。当您在本地计算机上运行和调试时,这也非常有效

使用HTTP API,您可以执行以下查询以确定失败的实例:

@functionAppUrl = https://{{appName}}.azurewebsites.net
@code = YOUR_HOST_KEY
@taskHub = YOUR_HUB_NAME (see host.json)
@createdFrom = 2019-02-01T20:00:00Z

GET {{functionAppUrl}}/runtime/webhooks/durabletask/instances
        ?taskHub={{taskHub}}
        &code={{code}}
        &createdTimeFrom={{createdFrom}}
        &runtimeStatus=Failed
我注意到您在编排代码中使用了
DateTime.Now
。建议使用
DurableCOrchestrationContext
中的
CurrentUtcDateTime
属性,因为编排函数中的行为应该是确定性的。请参见关于编排器代码约束