从Azure函数HttpTrigger返回错误详细信息

时间:2018-07-06 14:04:22

标签: c# .net azure-functions

我已经使用HTTP触发器创建了Azure函数。我希望将详细的错误信息返回给调用者。有没有办法解决未捕获的异常?奇怪的是,Azure Functions在Visual Studio中运行时会返回详细的错误信息,但在部署时却不会返回。

[FunctionName("MyAzureFunction")]
public static async Task<HttpResponseMessage> RunAsync(
    [HttpTrigger(AuthorizationLevel.Function, "post", Route = null)] HttpRequestMessage httpRequest,
    TraceWriter traceWriter,
    CancellationToken cancellationToken)
{
    try
    {                
        var response = await ProcessAsync(request, cancellationToken);

        return httpRequest.CreateResponse(HttpStatusCode.OK, response);
    }
    catch (ArgumentException ex)
    {
        traceWriter.LogWarning($"Argument error: {ex}");
        return httpRequest.CreateResponse(HttpStatusCode.BadRequest, ex.Message);
    }
    catch (Exception ex)
    {
        traceWriter.LogError($"Error: {ex}");
        throw;
    }
}

2 个答案:

答案 0 :(得分:2)

通常,从安全角度来看,将异常详细信息返回给外部调用者被认为是不好的做法。因此,默认情况下可以屏蔽此信息。

我将throw;语句替换为返回手动格式化错误的语句。如果您可以将异常消息公开给调用者,则只需

return httpRequest.CreateResponse(HttpStatusCode.InternalServerError, ex.Message);

如果调用方是外部的,我也不会这样做:相反,返回一般错误消息,然后依靠日志进行调试。

答案 1 :(得分:2)

作为最近的请求和响应解决方案,最好分别使用 HttpRequest 和 IActionResult 而不是 HttpRequestMessage 和 HttpResponseMessage。此外,您可以使用遥测客户端手动处理失败的操作而无需抛出。如果出现错误请求,此代码将在 Application Insights 上创建失败的操作。

[FunctionName(nameof(MyAzureFunction))]
public static async Task<IActionResult> RunAsync(
    [HttpTrigger(AuthorizationLevel.Function, "post", Route = null)] HttpRequest httpRequest,
    ILogger logger,
    CancellationToken cancellationToken)
{
    using var operation = _telemetryClient.StartOperation(new RequestTelemetry
    {
        Name = $"Execute MyAzureFunction"
    });

    try
    {
        var response = await ProcessAsync(request, cancellationToken);

        // NOTE: You can alternatively handle the response in a layer before and use a generic object result here: 
        //return new ObjectResult(response)
        //{
        //    StatusCode = response.Status
        //};

        return new OkObjectResult(result);
    }
    catch (ArgumentException ex)
    {
        logger.LogWarning(ex, $"Argument error: {ex.Message}");

        // NOTE: Without this, the original request would be considered as successful, although the Http response code would be 400
        operation.Telemetry.Success = false;
        operation.Telemetry.ResponseCode = HttpStatusCode.BadRequest.ToString();

        return new BadRequestObjectResult(ex.Message);
    }
    catch (Exception ex)
    {
        logger.LogError($"Error: {ex}");
        throw;
    }
}