Blog Post

Azure Infrastructure Blog
5 MIN READ

Service Mesh-Aware Request Tracing in AKS with Istio and Application Insights

Siddhi_Singh's avatar
Siddhi_Singh
Icon for Microsoft rankMicrosoft
Apr 10, 2026

Introduction

As platforms evolve toward microservice‑based architectures, observability becomes more complex than ever. In Azure Kubernetes Service (AKS), teams often rely on Istio to manage service‑to‑service communication and Azure Application Insights for application‑level telemetry.

While both are powerful, they operate at different layers and without deliberate configuration, correlating a single request across the service mesh and the application layer is not straightforward.

This blog walks through a practical, production‑ready solution to enable Istio (Envoy) access logging in AKS and correlate those logs with Application Insights telemetry, allowing engineers to trace a request end‑to‑end for faster troubleshooting and deeper visibility.

Platform Observability Context

The environment consists of:

  • AKS with managed Istio enabled
  • Envoy sidecars injected into application pods
  • Azure Application Insights SDK running inside workloads
  • Log Analytics as the centralized log store

Istio is responsible for traffic management, while Application Insights captures application‑level telemetry. The goal was to align these layers using a common trace context, without introducing additional tracing systems or custom agents.

Enabling Istio Access Logging at the Mesh Level

The first step is to ensure that Envoy access logs are emitted consistently across the service mesh. Istio provides the Telemetry API, which allows access logging to be enabled centrally without modifying individual workloads.

Apply a Telemetry resource in the Istio system namespace to enable Envoy access logging:

apiVersion: telemetry.istio.io/v1
kind: Telemetry
metadata:
  name: mesh-access-logs
  namespace: aks-istio-system
spec:
  accessLogging:
  - providers:
    - name: envoy

This configuration ensures that:

  • All Envoy sidecars emit access logs
  • Logging behavior is uniform across the mesh
  • The setup remains compatible with AKS managed Istio

Standardizing Envoy Logs Using EnvoyFilter

Access logs must be structured to be useful at scale. In AKS managed Istio, direct Envoy configuration is restricted, so EnvoyFilter is used to customize logging behavior.

EnvoyFilters are configured to:

  • Emit logs in structured JSON format
  • Write logs to /dev/stdout
  • Include trace and request correlation headers

To achieve full visibility, separate EnvoyFilters are applied for inbound and outbound sidecar traffic.

apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
  name: json-access-logs
  namespace: aks-istio-system
spec:
  configPatches:
  - applyTo: NETWORK_FILTER
    match:
      context: SIDECAR_INBOUND
      listener:
        filterChain:
          filter:
            name: envoy.filters.network.http_connection_manager
    patch:
      operation: MERGE
      value:
        typed_config:
          "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
          access_log:
          - name: envoy.access_loggers.file
            typed_config:
              "@type": type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog
              path: /dev/stdout
              log_format:
                json_format:
                  timestamp: "%START_TIME%"
                  method: "%REQ(:METHOD)%"
                  path: "%REQ(X-ENVOY-ORIGINAL-PATH?:PATH)%"
                  response_code: "%RESPONSE_CODE%"
                  response_flags: "%RESPONSE_FLAGS%"
                  duration_ms: "%DURATION%"
                  downstream_remote_address: "%DOWNSTREAM_REMOTE_ADDRESS%"
                  x_request_id: "%REQ(X-REQUEST-ID)%"
                  traceparent: "%REQ(TRACEPARENT)%"
                  tracestate: "%REQ(TRACESTATE)%"
                  x_b3_traceid: "%REQ(X-B3-TRACEID)%"

This configuration ensures inbound traffic logs contain both request metadata and correlation identifiers.

Configuring Outbound Envoy Access Logs

Outbound logging is required to observe downstream calls made by a service. Apply a second EnvoyFilter for outbound traffic:

apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
  name: json-access-logs-outbound
  namespace: aks-istio-system
spec:
  configPatches:
  - applyTo: NETWORK_FILTER
    match:
      context: SIDECAR_OUTBOUND
      listener:
        filterChain:
          filter:
            name: envoy.filters.network.http_connection_manager
    patch:
      operation: MERGE
      value:
        typed_config:
          "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
          access_log:
          - name: envoy.access_loggers.file
            typed_config:
              "@type": type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog
              path: /dev/stdout
              log_format:
                json_format:
                  timestamp: "%START_TIME%"
                  method: "%REQ(:METHOD)%"
                  path: "%REQ(X-ENVOY-ORIGINAL-PATH?:PATH)%"
                  response_code: "%RESPONSE_CODE%"
                  response_flags: "%RESPONSE_FLAGS%"
                  duration_ms: "%DURATION%"
                  downstream_remote_address: "%DOWNSTREAM_REMOTE_ADDRESS%"
                  x_request_id: "%REQ(X-REQUEST-ID)%"
                  traceparent: "%REQ(TRACEPARENT)%"
                  tracestate: "%REQ(TRACESTATE)%"
                  x_b3_traceid: "%REQ(X-B3-TRACEID)%"

Inbound and outbound logs now follow the same schema, enabling consistent querying and analysis.

Automating the Configuration with PowerShell

To standardize and repeat the setup across environments, wrap the configuration in a PowerShell script. The script should:

  • Validate the Istio system namespace
  • Apply the Telemetry resource
  • Apply inbound and outbound EnvoyFilters
$MeshRootNamespace = "aks-istio-system"
$TelemetryName    = "mesh-access-logs"
$EnvoyFilterName  = "json-access-logs"

kubectl get ns $MeshRootNamespace --ignore-not-found

$telemetryYaml | kubectl apply -f -
$envoyFilterYaml | kubectl apply -f -
$envoyFilterOutboundYaml | kubectl apply -f -

Log Ingestion into Azure Monitor

Because Envoy access logs are written to standard output:

  • AKS automatically collects them
  • Logs are ingested into Log Analytics
  • Data appears in the ContainerLogV2 table

No additional agents or custom log pipelines are required.

Aligning with Application Insights Telemetry

Application Insights uses W3C Trace Context, where the operation_Id represents the trace identifier. Since Envoy access logs capture the traceparent header, both systems expose the same trace ID.

This alignment allows service mesh logs and application telemetry to be correlated without changing application code.

Correlating Requests Using KQL

To analyze request flow:

  • Parse JSON access logs from ContainerLogV2
  • Extract the trace ID from traceparent
  • Join with Application Insights request telemetry

To validate end‑to‑end tracing, use Log Analytics to query Istio access logs collected in the ContainerLogV2 table. Since Envoy access logs include the traceparent header, the trace‑id embedded in it directly maps to the Application Insights operation_Id. By filtering istio-proxy logs on this trace‑id, it becomes possible to view the full Envoy request record for a specific application request and trace it across the service mesh and application layers.

KQL (filter Istio access logs using an Application Insights operation_Id)

let operationId = "<OperationID>"; // Replace with your actual operation_Id
ContainerLogV2
| where TimeGenerated >= ago(24h)
| where ContainerName == "istio-proxy"
| where LogSource == "stdout"
| where LogMessage startswith "{"
| extend AccessLog = parse_json(LogMessage)
| extend ExtractedOperationId = extract(@"00-([a-f0-9]{32})-", 1, tostring(AccessLog.traceparent))
| where ExtractedOperationId == operationId
| project 
    TimeGenerated,
    PodName,
    Method = tostring(AccessLog.method),
    Path = tostring(AccessLog.path),
    ResponseCode = toint(AccessLog.response_code),
    RequestId = tostring(AccessLog.x_request_id),
    TraceParent = tostring(AccessLog.traceparent),
    TraceState = tostring(AccessLog.tracestate),
    Authority = tostring(AccessLog.authority),
    RawLogMessage = LogMessage
| order by TimeGenerated asc

Closing Thoughts

End‑to‑end request tracing in AKS is achieved by aligning service mesh logging and application telemetry around shared standards. By enabling structured Istio access logs and correlating them with Application Insights, platforms gain clear visibility into request flow across networking and application layers using Azure‑native tools.

This process scales well in managed Istio environments and provides meaningful observability without adding platform complexity.

Published Apr 10, 2026
Version 1.0

1 Comment

  • r3verse's avatar
    r3verse
    Copper Contributor

    Mentioning shared standards in the context of a logging post, without mentioning OpenTelemetry, is pretty bold.