Take the community feedback survey now.

Sanjay Kumar
Nov 19, 2025
  32
(1 votes)

Operational observability using application insights to trace checkout end to end

You can’t fix what you can’t see. In a modern, distributed e‑commerce system, the checkout flow touches multiple services from the front-end UI to backend APIs, payment gateways, and inventory systems. Failures, performance issues, or unexpected latencies often hide in the gaps between these components.

This is where operational observability becomes critical. By leveraging Azure Application Insights together with your existing structured logging, you can achieve actionable, end-to-end visibility into every checkout transaction.

What to trace

  • Page/controller actions: enter/exit, validation failures.
  • Payment orchestration: gateway called, result, latency, timeouts.
  • Business events: cart created, booking info saved, order created.
  • Correlation keys: cartReference, paymentMethod, user/device attributes.

Let's Configure and Code

  • Application Insights is configured:
ApplicationInsights":{
  "ConnectionString": "InstrumentationKey={my_key};IngestionEndpoint= {applicationinsights_endpoint}"
}
  • Checkout logs key breadcrumbs with a cart reference (great for correlation)
    Note: In this implementation, cartReference is used as a meta‑key to identify and track each cart / checkout session across telemetry. You are free to replace it with any custom key / value that suits your domain model (e.g., orderId, sessionId, checkoutId).

Entry:

_fluentLogger
    .Data(("CartReference", cart.GetCartReference()),
          ("BookingInfo", model.BookingInfo))
    .LogInfo("Booking calendar");
return View(GetViewPath(currentPage), model);

Exit:

_fluentLogger
    .Data((nameof(checkoutBookingInfo), checkoutBookingInfo),
          ("CartReference", cart.GetCartReference()))
    .LogInfo("Booking POST");

Add rich telemetry with correlation

Use cartReference as your primary correlation property across logs, traces, and metrics. If you’re already using ILogger (or Serilog) with AI export, enrich the scope; otherwise, send custom events via TelemetryClient.New code (example pattern):

using Microsoft.ApplicationInsights;
using Microsoft.ApplicationInsights.DataContracts;

public class CheckoutTelemetryService
{
    private readonly TelemetryClient _telemetryClient;

    public CheckoutTelemetryService(TelemetryClient telemetryClient)
    {
        _telemetryClient = telemetryClient ?? throw new ArgumentNullException(nameof(telemetryClient));
    }

    /// <summary>
    /// Tracks a specific step in the checkout process.
    /// </summary>
    /// <param name="stepName">Name of the checkout step (e.g., "cartValidation").</param>
    /// <param name="cartReference">Unique identifier for the cart.</param>
    /// <param name="properties">Optional custom properties.</param>
    /// <param name="durationMs">Optional duration of the step in milliseconds.</param>
    public void TrackCheckoutStep(
        string stepName, 
        string cartReference, 
        IDictionary<string, string>? properties = null, 
        double? durationMs = null)
    {
        var telemetryEvent = new EventTelemetry($"checkout_{stepName}");
        telemetryEvent.Properties["cartReference"] = cartReference;

        if (properties != null)
        {
            foreach (var kvp in properties)
            {
                telemetryEvent.Properties[kvp.Key] = kvp.Value;
            }
        }

        if (durationMs.HasValue)
        {
            telemetryEvent.Metrics["duration_ms"] = durationMs.Value;
        }

        _telemetryClient.TrackEvent(telemetryEvent);
    }

    /// <summary>
    /// Starts a dependency telemetry operation, such as payment or inventory check.
    /// </summary>
    /// <param name="dependencyName">Name of the dependency operation.</param>
    /// <param name="cartReference">Cart reference ID.</param>
    /// <param name="dependency">Outputs the created DependencyTelemetry object.</param>
    /// <returns>IDisposable to stop the operation when disposed.</returns>
    public IDisposable StartDependencyOperation(
        string dependencyName, 
        string cartReference, 
        out DependencyTelemetry dependency)
    {
        dependency = new DependencyTelemetry("checkoutDependency", dependencyName, DateTimeOffset.UtcNow, TimeSpan.Zero, success: true);
        dependency.Properties["cartReference"] = cartReference;

        return new TelemetryOperation(_telemetryClient, dependency);
    }

    /// <summary>
    /// Helper class to manage the lifetime of telemetry operations.
    /// </summary>
    private sealed class TelemetryOperation : IDisposable
    {
        private readonly TelemetryClient _telemetryClient;
        private readonly IOperationHolder<DependencyTelemetry> _operationHolder;

        public TelemetryOperation(TelemetryClient telemetryClient, DependencyTelemetry telemetry)
        {
            _telemetryClient = telemetryClient ?? throw new ArgumentNullException(nameof(telemetryClient));
            _operationHolder = _telemetryClient.StartOperation(telemetry);
        }

        public void Dispose()
        {
            _telemetryClient.StopOperation(_operationHolder);
        }
    }
}

Use it in checkout/payment paths:

var cartRef = cart.GetCartReference();
_checkoutTelemetry.TrackCheckoutStep("shipping_viewed", cartRef, new Dictionary<string,string> {
    ["device"] = Request.Headers["User-Agent"].ToString().Contains("Mobile") ? "mobile" : "desktop"
});

Around a payment call

using (_checkoutTelemetry.StartDependencyOperation("bank_charge", cartRef, out var dep))
{
    var sw = Stopwatch.StartNew();
    var result = await _paymentService.ProcessBankCheckoutAsync(chargeId, transactionId, cartRef);
    sw.Stop();
    dep.Duration = sw.Elapsed;
    dep.Success = result.Success;
    dep.Properties["paymentMethod"] = "CreditCard";
    dep.Properties["timeout"] = result.Timeout.ToString();
    _checkoutTelemetry.TrackStep("payment_processed", cartRef, new Dictionary<string,string>{
        ["paymentMethod"] = "CreditCard",
        ["errorType"] = result.ErrorType.ToString()
    }, sw.Elapsed.TotalMilliseconds);
}

 

Kusto queries (copy‑paste in Logs) examples:  

  • End‑to‑end for a single cart:
union traces, customEvents, dependencies, requests
| extend cartReference = tostring(customDimensions.cartReference)
| where isnotempty(cartReference) and cartReference == "<CART_REF>"
| project timestamp, itemType = itemType, name, message, resultCode, success, duration, cartReference, customDimensions
| order by timestamp asc
  • Payment gateway health:
dependencies
| where type == "payment"
| summarize count(), failures = countif(success == false), p95=percentile(duration,95) by name, bin(timestamp, 5m)
| extend failureRate = todouble(failures) / todouble(count())
  • Checkout bottlenecks by step:
customEvents
| where name startswith "checkout_"
| summarize p95=percentile(todouble(tostring(customMeasurements["duration_ms"])),95)
          , count() by name
| order by p95 desc

Guardrails

  • Don’t log PII, whitelist properties. Treat cartReference as non‑PII.
  • Sample high‑volume events if needed; never drop error paths.
  • Secure the AI connection string via secrets/Key Vault; avoid plain text in config.

Outcomes

  • Fast root cause: correlate a customer’s failed payment through controller, dependency, and custom events.
  • Trend insights: detect gateway degradation and timeouts before conversion drops.
  • Measurable improvements: reducing MTTR (Mean Time To Resolve/Recover) and payment‑related abandonment with targeted fixes.



Nov 19, 2025

Comments

Please login to comment.
Latest blogs
Optimizely Web Experimentation on Single Page Applications

  Introduction Most of the modern web applications are built as Single Page applications (SPA) which provides a quick and smooth experience to the...

Ratish | Nov 16, 2025 |

Optimizely CMS - Learning by Doing: EP07 - Create Controller/View for Pages

  Episode 7  is Live!! The latest installment of my  Learning by Doing: Build Series  on  Optimizely CMS 12  is now available on YouTube! This vide...

Ratish | Nov 16, 2025 |

Multiple Languages in Optimizely CMS

I was exploring multi-languages in Optimizely CMS 12 – able to figure it out quickly in a few steps. Let’s get started. 1. Enable Languages... The...

Madhu | Nov 15, 2025 |