How to setup Azure Functions Integration for Traffic Monitoring
Last updated: June 10, 2026
Introduction
This guide walks you through instrumenting an Azure Function (TypeScript) to send request and response traffic to Astra's Traffic Collector via OpenTelemetry. Once set up, API traffic from your Azure Function will be visible in the Astra dashboard for security monitoring and analysis.

Prerequisites
Access to Azure Functions in Azure cloud
Azure Functions extension installed in Visual Studio Code
Astra Traffic Collector installed and reachable
Azure Functions Integration created in Astra dashboard with sensorID copied
Instructions
Step 1:Configure the OTLP/HTTP Receiver in Astra Traffic Collector
Open config_custom.yaml in your Traffic Collector instance and add the receiver configuration.
For development or testing, use HTTP:
receivers:
otlp:
protocols:
http:
endpoint: "0.0.0.0:4318" # HTTP receiver on port 4318
processors:
#...
For production, use HTTPS by adding TLS settings with your certificate and key file paths. If your certificate is from a trusted CA like Let's Encrypt, ca_file is not required , only add it for self-signed or untrusted certificates.
Also update docker-compose.yaml to mount the certificate files as volumes into the collector container.
Save the file and restart the collector: systemctl restart astra-traffic-collector.service
Step 2: Install Dependencies
Navigate to your Azure Functions project directory and run the following commands:
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: Add the Instrumentation Code
Navigate to /src/functions/function.ts and paste the boilerplate code provided below into your file.
Once pasted, update only the two values in the config block at the top:
sensorId— use the value shown when you created the Azure Functions Integration in the Astra dashboardcollectorUrl— set this to your Astra Traffic Collector's OTLP/HTTP endpoint
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,
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 => {
// 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. Add Your Business Logic
Inside the app.http() handler, write your business logic before the withTelemetry() call. Set the following three variables to form your HTTP response:
responseBody— the content to return to the clientstatusCode— the appropriate HTTP status coderesponseHeaders— any required response headers includingContent-Type
Do not modify the telemetry setup code outside the config block. Changes there can break observability and result in missing data in the Astra dashboard.
Step 5. Deploy the Function
Deploy your updated function directory to Azure so the changes take effect on the remote environment.
Step 6. Test the Integration
Click the Get function URL button in the Azure portal top menu, copy the URL, and send a request via browser or cURL. The response will match what you defined in responseBody. Verify that traces are appearing in the Astra Traffic Collector.
Expected Outcome
After deployment, API traffic flowing through your Azure Function will be captured as OpenTelemetry traces and forwarded to the Astra Traffic Collector. Endpoints and request details will appear in your Astra dashboard.
Best Practices
Keep business logic separate from telemetry logic, following the pattern in the boilerplate
Use HTTPS for your Traffic Collector in production to ensure secure telemetry transmission
Troubleshooting
Traces not appearing in the Astra dashboard — Verify that sensorId and collectorUrl are correctly set in the config block and that the Traffic Collector is running and reachable.
Collector not receiving data — Confirm port 4318 is open and accessible from the Azure Function's network. Check that the OTLP/HTTP receiver is correctly configured in config_custom.yaml.
Deployment not reflecting changes — Ensure you deployed the function directory to the remote Azure environment and not just saved locally.
Certificate errors on HTTPS — Confirm certificate files are placed in /etc/otelcol-contrib/ with correct permissions. The private key must be readable only by the owner.