How-To: Setting up Azure Functions Integration for Traffic Monitoring (TypeScript)
Last updated: June 8, 2026
Introduction
help you gain full visibility into your API traffic. Astra supports OpenTelemetry-based instrumentation for Azure Functions, allowing you to monitor request and response flows seamlessly. This guide will walk you through the setup process using TypeScript as the function runtime.
To monitor Azure Functions traffic with Astra:
Configure Astra Traffic Collector to receive telemetry data via OTLP/HTTP.
Install required OpenTelemetry SDKs in your function project which will be used to instrument your Azure Function.
Add the telemetry setup code using the provided boilerplate and configure it with your
sensorIdand Astra collector endpoint.

Illustration: High-level integration flow between Azure Function and, Astra Traffic Collector
Prerequisites
Access to Azure Functions in your Azure cloud environment.
The Azure Functions extension for Visual Studio Code installed.
An active Astra Traffic Collector that is reachable from your function.
A Sensor ID copied from the Azure Functions integration you created in the Astra dashboard.
Instructions
Step 1: Set Up OTLP/HTTP Receiver
Your Astra Traffic Collector must be configured to receive telemetry data.
Update your collector's config_custom.yaml to include an OTLP HTTP receiver on port 4318.
For production, we strongly recommend using HTTPS by providing your certificate and key files in the configuration.
Restart the collector service using systemctl restart astra-traffic-collector.service.
📄 How To Set Up OTLP/HTTP Receiver in Astra Traffic Collector
Step 2: Install Required Dependencies
Navigate to your Azure Functions project directory in your terminal and run the following command to install the necessary OpenTelemetry SDKs:all the dependencies of OpenTelemetry SDK and Azure Functions:
npm install @azure/functions
npm install @opentelemetry/exporter-trace-otlp-http
npm install @opentelemetry/sdk-trace-node
npm install @opentelemetry/resources
npm install @opentelemetry/api
Step 3: Configure Instrumentation in Code
Configure Instrumentation in Your Code
Open your function file (typically src/functions/function.ts).
Add the OpenTelemetry boilerplate code provided in below
Update User Configuration: Replace the sensorId placeholder with your Astra Sensor ID and the collectorUrl with your Traffic Collector’s OTLP endpoint
Variable | Description | Example Value |
| Sensor ID from Astra dashboard. |
|
| OTLP/HTTP endpoint of the Astra Traffic Collector. |
|
import { app, HttpRequest, HttpResponseInit, InvocationContext } from "@azure/functions";
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http';
import { NodeTracerProvider } from '@opentelemetry/sdk-trace-node';
import { SimpleSpanProcessor } from '@opentelemetry/sdk-trace-node';
import { resourceFromAttributes } from '@opentelemetry/resources';
import { SpanStatusCode } from '@opentelemetry/api';
// ====================== USER CONFIGURATION - EDIT THESE VALUES ======================
const config = {
sensorId: '',
collectorUrl: '', // example: https?://collector-domain:4318/v1/traces
exporterSettings: {
timeoutMillis: 3000,
},
};
// ====================== END USER CONFIGURATION ====================================
// OpenTelemetry Setup
const setupTelemetry = () => {
console.log('Starting OpenTelemetry setup...');
const resource = resourceFromAttributes({
'sensor.id': config.sensorId,
'sensor.version': '1.0.0',
'service.name': 'astra-otel-plugin'
});
const traceExporter = new OTLPTraceExporter({
url: config.collectorUrl,
timeoutMillis: config.exporterSettings.timeoutMillis
});
const provider = new NodeTracerProvider({
resource: resource,
spanProcessors: [new SimpleSpanProcessor(traceExporter as any)]
});
provider.register();
return provider.getTracer('astra-otel-plugin');
};
const tracer = setupTelemetry();
// Telemetry wrapper function
const withTelemetry = async (
request: HttpRequest,
statusCode: number,
responseHeaders: Record<string, string>,
responseBody: any
) => {
const span = tracer.startSpan('http_trigger');
try {
// Get request headers and body
const headers = Object.fromEntries(request.headers.entries());
const body = await request.text().catch(() => '');
const url = new URL(request.url);
const target = url.pathname + url.search;
// Get client IP address from headers
const clientIp = request.headers.get('x-forwarded-for') ||
request.headers.get('x-real-ip') ||
'';
// Set request span attributes
span.setAttribute('http.method', request.method);
span.setAttribute('http.status_code', statusCode);
span.setAttribute('http.target', target);
span.setAttribute('http.host', url.host);
span.setAttribute('http.flavor', '1.1');
span.setAttribute('http.scheme', url.protocol.replace(':', ''));
span.setAttribute('http.request.headers', JSON.stringify(headers));
span.setAttribute('http.request.body', body);
span.setAttribute('net.sock.peer.addr', clientIp);
// Set response span attributes
span.setAttribute('http.response.headers', JSON.stringify(responseHeaders));
span.setAttribute('http.response.body', JSON.stringify(responseBody));
span.setStatus({ code: SpanStatusCode.OK });
} catch (error) {
span.setStatus({
code: SpanStatusCode.ERROR,
message: error instanceof Error ? error.message : 'Unknown error'
});
throw error;
} finally {
span.end();
}
};
app.http('httpTrigger1', {
methods: ['GET', 'POST'],
authLevel: 'anonymous',
handler: async (request: HttpRequest, context: InvocationContext): Promise<HttpResponseInit> => {
// First, execute business logic and get response
const responseBody = {
// 'message': 'ok'
}
const statusCode = 200;
const responseHeaders = {
// 'content-type': 'application/json',
// 'x-custom-header': 'custom-value'
};
// Start telemetry operations without awaiting them
withTelemetry(
request,
statusCode,
responseHeaders,
responseBody
).catch(error => console.error('Telemetry error:', error));
// return response to user
return {
status: statusCode,
headers: responseHeaders,
body: JSON.stringify(responseBody)
};
}
});Step 4 :Implement Telemetry Wrapping
Use the withTelemetry wrapper function to capture request metadata, headers, and bodies.
Important: Always write your core business logic before withTelemetry() is called in your handler to ensure performance isn't impacted.
Ensure your response body, status code, and headers are correctly passed to the telemetry function.
Step 5: Deploy and Test
Deploy your updated function directory to Azure.
Trigger the function using its URL via a browser, cURL, or Postman.
📄 Verifying Traces in Astra Traffic Collector
Expected Outcome
Upon a successful request, your function will return its normal JSON response. Simultaneously, you will see real-time traffic traces appearing in your Astra Traffic Collector logs and dashboard inventory.
Troubleshooting & Best Practices
Traces not appearing: Confirm that your function can reach the collector's IP and that port 4318 is open in your network security groups.
Avoid modifications: Do not alter the core telemetry setup section of the code, as incorrect changes can break observability.
Separate logic: Keep your business and telemetry logic modular to maintain clean, maintainable code.
Log Verification: If you encounter issues, you can inspect the collector logs using docker logs astra-traffic-collector to see if spans are being rejected due to authentication errors.