Giter VIP home page Giter VIP logo

web-api-on-az-func's Introduction

Quickstarter for web apis on Azure Function

This repository contains a few pre-built functionality that can help you build web apis on top of Azure Functions.

Error contract and handling

APIs can return errors due to multiple reasons: resource was not found, conflict, unhandled exception, validation failed. It is a good practice to define a common contract in which those are returned. The details of the contract do not matter, as long as they are consistent.

In this case, most of the work is done in the base class in which http triggered functions should inherit from:

/// <summary>
/// Returns a <see cref="ApiErrorResponse"/> containing the validation error messages.
/// Status code is <see cref="HttpStatusCode.BadRequest"/>.
/// </summary>
protected IActionResult ValidationFailed(IList<ValidationResult> validationResult) {}

/// <summary>
/// Indicates that the request has failed, returning status code 500.
/// The response body will be of type <see cref="ApiErrorResponse"/>.
/// </summary>
protected IActionResult Failed(string message, Exception ex) {}

/// <summary>
/// Indicates that application failed with an specific <see cref="HttpStatusCode"/>.
/// The response body will be of type <see cref="ApiErrorResponse"/>.
/// </summary>
protected IActionResult Failed(HttpStatusCode statusCode, string errorMessage, string errorCode) {}

/// <summary>
/// Tries to handle the error.
/// </summary>
/// <returns>
/// Returns true if a an response should be returned (where body is of type <see cref="ApiErrorResponse"/>.
/// Returns false if the exception should be bubbled up.
/// </returns>
protected virtual bool TryHandleError(Exception ex, out IActionResult response) {}

Error response format:

{
    "errorCode": "error-code",
    "error": "error-message-if-single-error",
    "errors": [ "error-1", "error-2" ]
}

Unhandled exceptions in http trigger functions will return an empty body with status code 500. In order to return a proper response we need to wrap the function body code in a try..catch block.

There are two options:

  1. Do the try..catch manually in the function body
  2. Use the base class Run/RunAsync wrapper that contain the try..catch inside
[FunctionName(nameof(GetCustomer))]
public IActionResult GetCustomer(
    [HttpTrigger(AuthorizationLevel.Function, "get", Route = "customers/{id}")] HttpRequest req,
    int id)
{
    IActionResult DoGetCustomer()
    {
        if (id <= 0)
        {
            return ValidationFailed("Id must be positive");
        }

        // Simulate does not exist
        if (id == 100)
        {
            return NotFound();
        }

        return OK(new CustomerDto
        {
            Id = id,
        });
    }

    return Run(DoGetCustomer);
}

Correlation and metadata in response

As the API starts to be used by other people we need a way to monitor it. An important point is enabling us to find instrumentation for a given request. This quickstarter contains a possible implementation that integrates with Application Insights. It works the following way:

  1. In the function settings (local.settings.json for local development) set the APPINSIGHTS_INSTRUMENTATIONKEY key to contain the Application Insights instrumentation key
  2. Enable response enrichment by registering an IFunctionInvocationFilter which will include in the response header metadata information. That happens in src/CustomersApi/Startup.cs (builder.Services.AddApiResponseHeaders<Startup>()).
  3. Set the correct log level on the application and infrastruture level (see src/CustomersApi/host.json)

Example of a response header: correlation-id-in-response

Using the correlation-id to search logs in Application Insights: search-in-app-insights

End to end tracing in Application insights: search-in-app-insights

The fact that we are logging validation results can also be handy in scenarios where an API user reports problems using it, providing a correlation-id. With this information we can locate the actual validation error:

validation-failed

Application Insights enrichment

Application Insights instrumentation can be augmented to include additional information. In this repo we are adding the cloud role and the application version by registering a ITelemetryIntializer. That happens in src/CustomersApi/Startup.cs (builder.Services.AddApiTelemetryMetadata()).

Augmented instrumentation: enriched-app-insights

With this information the Application Map of Application Insights is more readable: appmap-app-insights

Running the demo project

Easiest way to get started is to run both APIs from Visual Studio:

  1. Set application insights in both Azure Functions (see example local.settings.json)
  2. Right click on the solution then Properties
  3. Common Properties / Startup Project
  4. Select Multiple startup projects
    1. Select CustomersApi with Start action
    2. Select OrdersApi with Start action

Local.settings.json example

{
  "IsEncrypted": false,
  "Values": {
    "AzureWebJobsStorage": "UseDevelopmentStorage=true",
    "FUNCTIONS_WORKER_RUNTIME": "dotnet",
    "APPINSIGHTS_INSTRUMENTATIONKEY": "<application-insights-key>"
  }
}

What's next?

web-api-on-az-func's People

Contributors

fbeltrao avatar atifaziz avatar lborba avatar

Stargazers

 avatar  avatar

Watchers

 avatar James Cloos avatar  avatar

Forkers

lborba atifaziz

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.