Sanjay Kumar
Nov 19, 2025
  680
(3 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 Opal: How to Build Effective Workflow Agents

If you're building workflow agents in Optimizely Opal, this post covers how specialized agents pass context to each other, why keeping agents small...

Andre | May 20, 2026

ReviewPR: An Azure Function That Reviews Your Azure DevOps Pull Requests With Claude

A while back I wrote about an  Azure Function App for PDF creation that we use to offload PDF rendering from our Optimizely DXP site. That same...

KennyG | May 19, 2026

Accelerating Optimizely CMS and Commerce upgrades with agentic AI (Part 2 of 2)

The Real Transformation in Optimizely CMS 13: Why the Upgrade Itself Is the Easy Part. A field-tested playbook for enterprise teams moving from...

Hung Le Hoang | May 18, 2026

Is the most powerful AI model really the best value?

Artificial Intelligence is already becoming part of everyday software development. Developers now use AI tools to generate code, write documentatio...

K Khan | May 16, 2026

Optimizely London Dev Meetup 2026

Well, everyone, it's that time of the year again, and we have another London Developer meet up coming for this summer. The date is set for the 2nd ...

Scott Reed | May 15, 2026

Semantic Search - Deep Dive

Deep dive into semantic search with Optimizely Graph

Michał Mitas | May 14, 2026 |