
August 29, 2026
12 min read
Table of Contents
By Kokil Thapa | Last reviewed: August 2026
When your Laravel API runs on AWS EC2, your queue workers sit on a DigitalOcean droplet, and your staging cluster lives in Azure, a single-cloud dashboard cannot tell you why checkout failed at 2 a.m. Multi-Cloud Observability: Metrics, Logs, Traces is the practice of collecting the three telemetry pillars — time-series metrics, structured logs, and distributed traces — into one correlated view that works regardless of where each workload runs. On production systems I maintain, observability is not a luxury add-on; it is how you survive failed deployments, payment gateway timeouts, and slow database queries without guessing. This guide covers what to instrument, how to ship telemetry across providers, and which stacks actually work for small teams in 2026.
What is multi-cloud observability and why do metrics, logs, and traces matter?
Observability answers questions you did not know to ask before an outage. Monitoring tells you a threshold was breached; observability lets you follow a failed request from the load balancer through three microservices to a dead Redis connection. In a multi-cloud setup, that request might cross an AWS ALB, a Laravel app on a VPS, and a PostgreSQL read replica in another region — each with its own native tooling (CloudWatch, Azure Monitor, Google Cloud Operations).
The three pillars serve distinct roles:
- Metrics — numeric time-series data: request rate, error rate, latency percentiles (p50, p95, p99), CPU, memory, queue depth. You alert on metrics.
- Logs — discrete events with context: stack traces, payment callback payloads (redacted), authentication failures. You search logs during incidents.
- Traces — end-to-end request paths across services, showing where time was spent and which span failed. You use traces to find bottlenecks and cascading failures.
Without correlation between the three, you end up with three tabs open and a spreadsheet of timestamps. The goal of Multi-Cloud Observability: Metrics, Logs, Traces is a shared context — typically a trace_id and span_id injected into every log line and attached to every metric data point where possible.
A common mistake is treating native cloud monitoring as sufficient. CloudWatch, Azure Monitor, and Google Cloud Operations are excellent within their own boundaries, but they do not automatically correlate a trace from your GCP Cloud Run function with a Laravel queue job on a bare-metal VPS. You need a vendor-neutral instrumentation layer. That is where OpenTelemetry becomes the foundation of any serious multi-cloud observability strategy.
How do you instrument applications for metrics, logs, and traces?
Instrumentation is the code and agents that produce telemetry. In 2026, OpenTelemetry (OTel) is the standard. It replaces the old pattern of installing separate Prometheus client libraries, Jaeger agents, and custom log formatters with one SDK and one collector pipeline.
Laravel and PHP instrumentation
For Laravel 11 or 12 on PHP 8.2+, install the OpenTelemetry PHP extension and auto-instrumentation packages via Composer:
composer require open-telemetry/opentelemetry open-telemetry/exporter-otlp
composer require open-telemetry/opentelemetry-auto-laravel Configure the OTLP exporter in your .env so every environment sends to the same collector endpoint, regardless of hosting provider:
OTEL_SERVICE_NAME=checkout-api
OTEL_EXPORTER_OTLP_ENDPOINT=https://otel-collector.internal:4318
OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf
OTEL_TRACES_EXPORTER=otlp
OTEL_METRICS_EXPORTER=otlp
OTEL_LOGS_EXPORTER=otlp
OTEL_RESOURCE_ATTRIBUTES=deployment.environment=production,cloud.provider=aws The cloud.provider resource attribute is critical in multi-cloud setups. It lets you filter dashboards by AWS vs Azure vs a VPS without maintaining separate service names per provider.
Structured logging with trace correlation
Switch from plain-text logs to JSON. In Laravel, configure the stack channel to output JSON and inject trace context via a custom processor or Monolog formatter:
// config/logging.php — json channel
'json' => [
'driver' => 'monolog',
'handler' => StreamHandler::class,
'formatter' => Monolog\Formatter\JsonFormatter::class,
'with' => ['stream' => 'php://stderr'],
], Every log line should include trace_id, span_id, service.name, and deployment.environment. When you click a slow span in Grafana Tempo, you jump directly to the log lines from that exact request — no manual timestamp matching.
Metrics: RED method for HTTP services
For each HTTP endpoint, track:
- Rate — requests per second
- Errors — count of 5xx responses and unhandled exceptions
- Duration — histogram of response times with p50, p95, p99 buckets
OTel auto-instrumentation captures these for Laravel routes out of the box. For queue workers and scheduled tasks, add manual spans around php artisan queue:work jobs and Schedule callbacks so background work appears in the same trace graph as the HTTP request that dispatched it.
How should you collect and route telemetry across AWS, Azure, and GCP?
The OpenTelemetry Collector is the hub of multi-cloud observability. Deploy it as a DaemonSet in Kubernetes, a sidecar in ECS, or a standalone service on your VPS fleet. Applications send OTLP to the nearest collector; the collector handles batching, filtering, PII redaction, and routing to backends.
A production collector config splits telemetry by signal type. Here is a minimal but functional example:
receivers:
otlp:
protocols:
grpc:
endpoint: 0.0.0.0:4317
http:
endpoint: 0.0.0.0:4318
processors:
batch:
timeout: 5s
send_batch_size: 1024
attributes:
actions:
- key: cloud.region
action: upsert
from_attribute: host.id
exporters:
prometheus:
endpoint: 0.0.0.0:8889
otlp/tempo:
endpoint: tempo.internal:4317
tls:
insecure: true
loki:
endpoint: http://loki.internal:3100/loki/api/v1/push
service:
pipelines:
metrics:
receivers: [otlp]
processors: [batch, attributes]
exporters: [prometheus]
traces:
receivers: [otlp]
processors: [batch]
exporters: [otlp/tempo]
logs:
receivers: [otlp]
processors: [batch]
exporters: [loki] Handling cloud-native agents without double-paying
You do not need to abandon CloudWatch or Azure Monitor entirely. Many teams run a hybrid model: native agents for infrastructure metrics (EBS IOPS, AKS node health), OTel for application-level signals. Use the collector's awscloudwatch or azuremonitor receivers to pull cloud metrics into Grafana alongside application traces — one dashboard, two data sources.
For log shipping from VPS servers where you cannot install a collector on every host, Fluent Bit or Vector agents tail /var/log/ files and forward JSON logs to Loki or Elasticsearch. Tag each agent with cloud.provider=vps and host.name so you can distinguish a DigitalOcean droplet from an AWS EC2 instance at query time.
What is the best observability stack for multi-cloud in 2026?
There is no single winner — the right stack depends on team size, budget, and compliance requirements. Here is an honest comparison of the four approaches I see most often on real projects.
| Stack | Metrics | Logs | Traces | Best for | Typical cost (small team) |
|---|---|---|---|---|---|
| Grafana LGTM (self-hosted) | Mimir / Prometheus | Loki | Tempo | Teams with DevOps capacity, data sovereignty needs | Rs 15,000–40,000/mo infra (~USD 110–295) |
| Grafana Cloud | Hosted Mimir | Hosted Loki | Hosted Tempo | Small teams, multi-cloud without ops overhead | Free tier → Rs 25,000+/mo (~USD 185+) |
| Datadog | Native | Native | APM | Fastest time-to-value, budget available | Rs 50,000–200,000/mo (~USD 370–1,480) |
| Cloud-native only | CloudWatch / Azure Monitor / GCP Ops | Same | X-Ray / App Insights / Cloud Trace | Single-cloud or low observability maturity | Included in cloud bill (fragmented across providers) |
For a Nepal-based startup running Laravel on a VPS plus a few AWS services, Grafana Cloud with OpenTelemetry is the sweet spot in 2026. You get correlated metrics, logs, and traces without maintaining Mimir, Loki, and Tempo yourself. Datadog is excellent but the per-host pricing adds up fast when you count queue workers, cron containers, and staging environments separately.
Whichever backend you pick, standardise on OpenTelemetry instrumentation from day one. I have migrated observability backends without touching application code because the OTel SDK stayed constant while only the collector exporters changed. That portability is the entire point of multi-cloud observability.
How do you troubleshoot production incidents with correlated metrics, logs, and traces?
During an incident, you need a repeatable workflow — not improvisation. The pattern I use on production Laravel applications follows five steps, and it works whether the failing service runs on AWS, Azure, or a VPS.
- Check the SLO dashboard — Is error rate or latency breaching your SLO threshold? Identify which service and which cloud provider label is affected.
- Drill into traces — Filter Tempo or your APM trace view by
status=errorand the last 15 minutes. Find the slowest or most frequent failing span. - Jump to logs — Click the trace ID to pull correlated log lines. Look for exceptions, timeout messages, or third-party API error codes.
- Cross-reference metrics — Check if CPU, memory, or database connection pool metrics spiked at the same timestamp. A queue backlog metric often explains trace latency better than the trace itself.
- Document in a postmortem — Capture the trace ID, root cause, and fix in a blameless postmortem so the next engineer does not start from zero.
Example: payment gateway timeout across clouds
Imagine checkout fails on a Laravel eCommerce app. Metrics show http_server_duration_p99 spiking on the payment-api service tagged cloud.provider=aws. Traces reveal the Khalti callback span timing out after 30 seconds. Logs for that trace_id show cURL error 28: Connection timed out. Infrastructure metrics on the VPS running the queue worker show normal CPU — the problem is external, not resource exhaustion.
Without trace-log correlation, you would grep Laravel logs across three servers, manually match timestamps, and still miss the connection. With Multi-Cloud Observability: Metrics, Logs, Traces wired correctly, that investigation takes minutes instead of an hour.
Service maps and dependency graphs
Modern backends auto-generate service maps from trace data. These maps show which services call which, average latency between nodes, and error rates on edges. In a multi-cloud architecture, the service map immediately reveals that your Azure-hosted API gateway is routing 40% of traffic to an AWS RDS instance with 200ms higher latency — a topology problem visible only when traces span providers.
How much does multi-cloud observability cost and how do you control it?
Observability costs scale with data volume, not server count alone. Traces are the most expensive signal because each request generates multiple spans. Logs are second — verbose debug logging in production can double your bill overnight. Metrics are the cheapest per data point but add up with high-cardinality labels.
Cost control tactics that actually work
- Sample traces — Use head-based sampling (e.g., 10% of requests) in the OTel Collector for normal traffic. Always capture error traces at 100%.
- Drop debug logs in production — Set log level to
infoorwarningin production; reservedebugfor staging. - Limit metric cardinality — Never put user IDs, order IDs, or unbounded URL paths in metric labels. High-cardinality labels explode storage costs in Prometheus and Mimir.
- Set retention tiers — Hot storage for 7 days (incident response), warm for 30 days (trend analysis), cold/archive for compliance if required.
- Use recording rules — Pre-aggregate expensive queries in Prometheus rather than scanning raw data on every dashboard refresh.
For a typical small business running Laravel across two cloud providers plus a VPS, budget Rs 15,000–50,000 per month (~USD 110–370) for a managed observability platform with reasonable retention. Self-hosted LGTM on a dedicated server costs less at scale but requires someone who can maintain it — a hidden cost if that person is you after hours.
Alerting should follow the same discipline. Use Prometheus Alertmanager or Grafana unified alerting with SLO-based rules, not raw threshold alerts on every metric. Page a human only when customer-facing error budget is burning. Everything else goes to Slack or email during business hours.
Build multi-cloud observability before you need it
Multi-Cloud Observability: Metrics, Logs, Traces is not something you bolt on after the third production outage. Instrument with OpenTelemetry from the first deployment, standardise structured JSON logging with trace correlation, deploy a collector that routes all three signals to one backend, and practice the incident workflow before an alert wakes you at 3 a.m. The teams that debug multi-cloud failures in minutes instead of hours all share one trait: they correlated metrics, logs, and traces early, while the system was still simple.
If you are running Laravel or PHP workloads across AWS, Azure, VPS hosting, or a hybrid setup and need help designing an observability pipeline that fits a small-team budget, get in touch — or explore the Grafana dashboards guide and microservices observability patterns for deeper implementation detail.

