Event Hub Policy
Use scalable, policy-based logging for Azure API Management with Nodinite. This guide helps you set up Event Hub logging, configure loggers, and implement policies so you can securely and efficiently track all requests and responses.
✅ Log requests and responses with full payload and headers
✅ Integrate with Azure Event Hub for scalable, asynchronous logging
✅ Monitor and manage loggers directly from Nodinite
✅ Use policy-based logging for flexibility and security
✅ Prevent data loss with robust pickup and monitoring agents
Info
This guide shows you how to apply a Nodinite-specific policy to enable logging from the Azure API Management platform to Nodinite.
Warning
The Event Hub logging option enforces a 200 KB limit. If you log messages larger than this, the event will not be logged. For large messages, use the Blob Storage Policy.
Diagram: Event Hub policy-based logging from Azure API Management to Nodinite.
Event Hub Overview
You create a Nodinite Log Event and send it to Azure Event Hub as intermediate storage. The Nodinite Pickup Log Events Service Logging Agent transfers the data to your Nodinite instance for use in self-service Log Views.
To enable Nodinite logging from your APIs in Azure API Management:
- Configure one or more Event Hub Loggers
- Configure the policy within your API
- Install and configure the Nodinite Pickup Log Events Service Logging Agent
- Configure it to fetch the Nodinite JSON Log Event from the target Event Hub. Provide the connection string (create or reuse from 'Shared access policies' in the Azure portal).
When you activate the policy, Azure API Management creates a Nodinite-specific JSON Log Event and posts it to the named Event Hub. The Nodinite Pickup Log Events Service Logging Agent asynchronously moves the JSON Log Event to Nodinite.
Event Hub Logger
To log using Azure Event Hub, create a named Event Hub Logger. Reference this logger by name in your policy. You cannot rename a logger—delete and recreate it if needed. Create it using Nodinite or tools like Insomnia.
Tip
Use the Nodinite Azure Monitoring Agent to manage and monitor your Event Hub Loggers.
Important
If you use Postman, review Security Risks of Postman.
- Use the ApplicationId/ClientID you created by following the Azure Application Access guide
- Download Azure REST API Template for Postman
You can also create the Event Hub Logger by performing a PUT method with a Body; a template is provided below:
- {{subscriptionId}}
The {loggerName}
uniquely identifies this logger in your API Management Service ({{APIMGMTServiceName}}
). Use a unique name per Event Hub and environment (Prod, QA, Test, ...).
Important
Once you reference a Logger in any APIM Policy, you cannot remove it. To change the name, remove all references, drop the old one, and recreate it with the new name.
{
"properties": {
"loggerType": "azureEventHub",
"description": "{description}",
"resourceId": "{resourceId}",
"credentials": {
"name": "{`eventHubEntityName`}",
"connectionString": "Endpoint=sb://{namespace}.servicebus.windows.net/;SharedAccessKeyName={sharedAccessKeyName};SharedAccessKey={sharedAccessKey};EntityPath={entityPath}"
}
}
}
Use this Body as a template and modify it for your needs.
Field | Variable | Value | Description |
---|---|---|---|
loggerType |
- | azureEventHub |
Hard coded value. DO NOT CHANGE! |
description |
{description} |
Doing good |
Add a user-friendly description for this Event Hub Logger |
resourceId |
{resourceId} |
/subscriptions/{SubscriptionId}/resourceGroups/{ResourceGroupName}/providers/Microsoft.EventHub/namespaces/{EventHubNamespaceName}/eventhubs/{eventhubName} |
NOTE: The target Event Hub Entity may be in another subscription/resource group. Enter values accordingly |
name |
{eventHubEntityName} |
eventHubEntityName |
OPTIONAL: Name of the Event Hub Entity if not provided in the connection string |
connectionString |
{namespace} |
The namespace with the target Event Hub | |
connectionString |
{sharedAccessKeyName} |
Name of the shared access key | |
connectionString |
{sharedAccessKey} |
The shared access key for the provided key name | |
connectionString |
{entityPath} |
Name of the target event hub entity for Nodinite JSON Log Event. If you provide {entityPath} , you do not need to specify {eventHubEntityName} |
Tip
Use a SAS key with Manage permission to create the Event Hub Logger. The Send permission is not enough. We recommend a dedicated SAS key for each Event Hub Logger for easy revocation and best security.
API Policy Configuration
Decide what to log (Request and/or Response) and add the configuration to your policy in the inbound, outbound, or both sections.
Direction | Type | |
---|---|---|
Inbound | Request | |
Outbound | Response |
The template below logs:
- Mandatory properties for a Nodinite Log Event (modify as needed for your business)
- HTTP Headers as context properties
Info
Some properties are excluded in the sample code
- Body
Replace '{loggerName}
' in both the API management logger and the code snippets below for the Policy configuration.
The example below creates a basic Nodinite JSON Log Event with common, mandatory, and optional properties.
- Context is optional
- Body is optional (note the 200 KB limit on the JSON using the Event Hub Logger; consider Blob Storage Policy[] for larger messages).
<log-to-eventhub logger-id='{loggerName}'>
@{
var body = context.Request.Body.As<string>(preserveContent: true);
var bodyToLog = System.Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(body));
var headers = context.Request.Headers
.Where(h => h.Key != "Authorization" && h.Key != "Ocp-Apim-Subscription-Key");
Dictionary<string, string> contextProperties = new Dictionary<string, string>();
foreach (var h in headers) {
contextProperties.Add(string.Format("Header#{0}", h.Key), String.Join(", ", h.Value));
}
var requestLogMessage = new {
LogAgentValueId = 15,
EndPointName = context.Deployment.ServiceName + "/" + context.Api.Name + "/" + context.Operation.Name,
EndPointUri = context.Deployment.ServiceName + "/" + context.Api.Name + "/" + context.Operation.Name,
EndPointDirection = 10,
EndPointTypeId = 71,
OriginalMessageTypeName = "Nodinite.Schemas/Nodinite.Demo/5.0#Orders",
LogDateTime = DateTime.UtcNow,
Context = contextProperties,
Body = bodyToLog
};
return JsonConvert.SerializeObject(requestLogMessage);
}
</log-to-eventhub>
Example Azure Event Hub Policy
This complete policy logs both inbound (Request) and outbound (Response) information.
In this example, you add a clientTrackingId (guid) if not provided in the x-ms-client-tracking-id HTTP header, plus other optional properties for a Nodinite Log Event.
x-ms-client-tracking-id
<policies>
<inbound>
<!-- creating a tracking/correlation id -->
<set-variable name="clientTrackingId" value="@{
return Guid.NewGuid().ToString();
}" />
<!-- if x-ms-client-tracking-id exists use it, if not, use clientTrackingId -->
<set-header name="x-ms-client-tracking-id" exists-action="skip">
<value>@(context.Variables.GetValueOrDefault<string>("clientTrackingId"))</value>
</set-header>
<!-- Put on logger -->
<log-to-eventhub logger-id="{loggerName}">
@{
var body = context.Request.Body.As<string>(preserveContent: true); // in case we need it later...
var bodyToLog = System.Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(body));
var headers = context.Request.Headers
.Where(h => h.Key != "Authorization" && h.Key != "Ocp-Apim-Subscription-Key");
var correlationId = headers.Any(h=>h.Key == "x-ms-client-tracking-id") ? headers.First(h => h.Key == "x-ms-client-tracking-id").Value[0] : context.Variables.GetValueOrDefault<string>("clientTrackingId");
Dictionary<string, string> contextProperties = new Dictionary<string, string>();
contextProperties.Add("Correlation Id", correlationId);
foreach (var h in headers) {
contextProperties.Add(string.Format("Header#{0}", h.Key), String.Join(", ", h.Value));
}
var requestLogMessage = new {
LogAgentValueId = 15,
EndPointName = context.Deployment.ServiceName + "/" + context.Api.Name + "/" + context.Operation.Name,
EndPointUri = context.Deployment.ServiceName + "/" + context.Api.Name + "/" + context.Operation.Name,
EndPointDirection = 10,
EndPointTypeId = 71,
EventDirection=21,
OriginalMessageTypeName = "Nodinite.Schemas/Nodinite.Demo/5.0#Orders",
LogDateTime = DateTime.UtcNow,
LogStatus = 0,
ApplicationInterchangeId = correlationId,
Context = contextProperties,
LogText = "Hello World from Nodinite API mgmt logging policy",
Body = bodyToLog
};
return JsonConvert.SerializeObject(requestLogMessage);
}
</log-to-eventhub>
</inbound>
<backend>
<forward-request />
</backend>
<outbound>
<!-- if x-ms-client-tracking-id exists use it, if not, use clientTrackingId -->
<set-header name="x-ms-client-tracking-id" exists-action="skip">
<value>@(context.Variables.GetValueOrDefault<string>("Correlation Id"))</value>
</set-header>
<log-to-eventhub logger-id="{loggerName}">
@{
var body = context.Response.Body.As<string>(preserveContent: true); // in case we need it later...
var bodyToLog = System.Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(body));
var headers = context.Response.Headers
.Where(h => h.Key != "Authorization" && h.Key != "Ocp-Apim-Subscription-Key");
var correlationId = headers.Any(h=>h.Key == "x-ms-client-tracking-id") ? headers.First(h => h.Key == "x-ms-client-tracking-id").Value[0] : context.Variables.GetValueOrDefault<string>("clientTrackingId");
Dictionary<string, string> contextProperties = new Dictionary<string, string>();
contextProperties.Add("Correlation Id", correlationId);
foreach (var h in headers) {
contextProperties.Add(string.Format("Header#{0}", h.Key), String.Join(", ", h.Value));
}
string logText = "";
if (context.Response.StatusCode > 300)
{
logText = "Guru meditation";
}
var requestLogMessage = new {
LogAgentValueId = 15,
EndPointName = context.Deployment.ServiceName + "/" + context.Api.Name + "/" + context.Operation.Name,
EndPointUri = context.Deployment.ServiceName + "/" + context.Api.Name + "/" + context.Operation.Name,
EndPointDirection = 10,
EndPointTypeId = 71,
EventDirection=25,
OriginalMessageTypeName = "Nodinite.Schemas/Nodinite.Demo/5.0#OrderResponses",
LogDateTime = DateTime.UtcNow,
ApplicationInterchangeId = correlationId,
Context = contextProperties,
Body = bodyToLog,
LogStatus = context.Response.StatusCode,
LogText = logText
};
return JsonConvert.SerializeObject(requestLogMessage);
}
</log-to-eventhub>
</outbound>
<on-error />
</policies>
Troubleshooting
Contact our Support if you need help implementing Logging.
Next Step
Related Topics
Azure Application Access
JSON Log Event
Managing
Monitoring
Non Events Agent
Pickup Log Events Service Logging Agent
Interested in logging from other Azure Related Services?