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 sensorId and Astra collector endpoint.

image_d3x21u.png

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
  1. Open your function file (typically src/functions/function.ts).

  2. Add the OpenTelemetry boilerplate code provided in below

  3. 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

sensorId

Sensor ID from Astra dashboard.

"12345678-1234-4abc-9def-987654321000"

collectorUrl

OTLP/HTTP endpoint of the Astra Traffic Collector.

"https://collector.example.com:4318/v1/traces"

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

  1. Deploy your updated function directory to Azure.

  2. 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.