Azure API Management | Enable Tracing for an API

Posted by Andrew Wilson on Sunday, June 2, 2024

Background

For a while now I have made good use of the Trace functionality in the API Management (APIM) Test Client. If you haven’t, I would highly advise having a look. The Trace functionality allows us to unveil (debug) the complexity and inner workings of our reverse proxy APIs (their routing / hierarchical policies / alternate backends / caching / etc.). With the Portal this is fairly trivial to do, you simply:

  1. Navigate to your API Management instance.
  2. Select one of your APIs that you would like to Trace.
  3. Select the Test tab.
  4. Select one of the Operations to send a request to.
  5. Select Trace.

API Tracing Portal

By enabling tracing on the API you are now able to inspect each part of the request:

  • Inbound | The original request received from the caller and the policies applied.
  • Backend | The requests API Management sent to the backend and the response it received.
  • Outbound | The policies applied to the response before sending back to the caller.
  • On error | The errors that occurred during processing of the request and any policies applied to those errors.

⚠️ Important

Be careful when enabling tracing as it can expose sensitive information in the trace data.

Problem Space

Although the APIM Test client has certainly proven useful, I have wondered if there are any other methods of enabling and obtaining the trace for a given API. More importantly, brining the development experience back to something that we are use to such as Visual Studio Code, Postman, etc.

Just over a week ago, I had a conversation with the APIM product group, of which they mentioned that the service has a REST API that can be used to enable trace functionality. After a bit of digging, I found the documentation around this and thought I would share my findings and implementation with you.

⚠️ Important

Before we get started, please bare in mind:

  • The API Management REST API version 2023-05-01-preview or later is required.
  • The Identity used to call the REST API must be assigned the Contributor or higher role on the API Management instance.

Enabling tracing on an API through the REST API is a four step process:

  1. We need to obtain trace credentials using the List Debug Credentials API.
  2. Enable Tracing on your API by adding the Trace Credential token as a header (Apim-Debug-Authorization) to your request.
  3. Given that the Trace Credential token was valid, we need to retrieve the Trace ID from the response header Apim-Trace-Id.

    Invalid Cases Include:

    • Token expired | The response will include a Apim-Debug-Authorization-Expired header with information about expiration date.

    • Token obtained for wrong API | The response will include a Apim-Debug-Authorization-WrongAPI header with an error message.

  4. We need to retrieve the trace log by calling the List Trace API using the Trace ID from the previous step.

In both steps 1 and 4, you will need to provide a valid Authorization Bearer token where the identity is assigned Contributor or higher on the APIM instance.

Given that this is not the simplicity that we know and love in the Test Client, making and orchestrating these various Rest calls can and most certainly will take time when conducted singularly. What we need is tooling or extensions to such tooling that will enable us to orchestrate these various calls so that we can obtain the trace logs with repeatable ease.

My Solution

I required a solution that would allow me to orchestrate the various calls with repeatable ease whilst also keeping me close to the tooling that I know and love. My solution is the REST Client extension in VS Code. Using this extension I can:

  1. Orchestrate the various Rest calls required.

  2. Use variables to make as much of the calls required somewhat generic.

  3. The extension provides me the ability to obtain an AAD (Entra ID) token.

    By default if a token has already been obtained, the extension will reuse the previous token for the specified directory from an in-memory cache. Expired tokens are refreshed automatically. (The token cache can be manually cleared, or is by default cleared upon closure of VS Code).

The implementation that I have come to is as follows:

# ***************************************************************************************************************
# Enable tracing for an APIM API
# ------------------------------
#
# ⚠️Note:
#    The following steps require API Management REST API version 2023-05-01-preview or later. 
#    You must be assigned the Contributor or higher role on the API Management instance to call the REST API.
#
#  Steps:
#  1. Obtain trace credentials by calling the List debug credentials API.
#  2. Call the API with the trace credentials.
#  3. Retrieve trace logs.
#
#  Author: Andrew Wilson
# ***************************************************************************************************************

# -----------------
# Custom Variables 
# -----------------

@subscriptionId = REPLACEME
@resourceGroup = REPLACEME
@apimServiceName = REPLACEME
@apiName = REPLACEME

# -----------------
#    Rest Steps
# -----------------

### 1.Obtain trace credentials by calling the List debug credentials API.

# @name TraceCreds
POST https://management.azure.com/subscriptions/{{subscriptionId}}/resourceGroups/{{resourceGroup}}/providers/Microsoft.ApiManagement/service/{{apimServiceName}}/gateways/managed/listDebugCredentials
?api-version=2023-05-01-preview
Content-Type: application/json
Authorization: {{$aadToken}}

{
    "credentialsExpireAfter": "PT1H",
    "apiId": "/subscriptions/{{subscriptionId}}/resourceGroups/{{resourceGroup}}/providers/Microsoft.ApiManagement/service/{{apimServiceName}}/apis/{{apiName}}",
    "purposes": ["tracing"]
}

### 2.Call the API with the trace credentials.

# @name ApiOperationTracing
Author your API request here but make sure to keep the following Header in place.
Apim-Debug-Authorization: {{TraceCreds.response.body.$.token}}

### 3.Retrieve Trace Logs

# @name ObtainedTraceLogs
POST https://management.azure.com/subscriptions/{{subscriptionId}}/resourceGroups/{{resourceGroup}}/providers/Microsoft.ApiManagement/service/{{apimServiceName}}/gateways/managed/listTrace
?api-version=2023-05-01-preview
Content-Type: application/json
Authorization: {{$aadToken}}

{
    "traceId": "{{ApiOperationTracing.response.headers.Apim-Trace-Id}}"
}

Have a play and see if this extends your tracing capabilities.