Sanjay Kumar
+3
Nov 19, 2025
visibility 839
star star star star star star
(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

error Please login to comment.
Latest blogs
New addon puts the optimization GUI for Optimizely Graph back in the CMS

I wanted the Graph UI for Pinned Results and Synonyms inside the CMS, so I created another addon.

Tomas Hensrud Gulla | Sep 1, 2026 |

From CMS Content to AI-Ready Content: A Practical Optimizely CMS 12 Approach

How structured content can help Optimizely CMS editors prepare content for search and AI-powered experiences Introduction The way users discover...

iliyas shaikh | Sep 1, 2026

Serving Heavy Multilingual Content Efficiently with Optimizely SaaS CMS

When building enterprise-grade applications on modern headless stacks, performance is governed by payload efficiency. Optimizely SaaS CMS and...

Vipin Banka | Aug 31, 2026

The Under-Documented Optimizely Caching API I Somehow Missed

I recently discovered some useful, but poorly documented, caching features in Optimizely CMS. Here’s how ReadThrough, ReadStrategy.Wait and master...

Dom Reilly | Aug 31, 2026 |