Explore plans starting at ₹699/mo →
Performance & Monitoring

Application Performance Monitoring Best Practices for Cloud Applications

S
ServerRaja
9 min read
#Troubleshooting#Monitoring#Database#Latency#Best Practices#Performance#Cloud Computing
Application Performance Monitoring Best Practices for Cloud Applications

What is Application Performance Monitoring?

Application Performance Monitoring (APM) goes beyond server-level metrics like CPU and memory. It tracks the behavior of your application code itself: how long HTTP requests take, where database queries spend their time, which API calls fail, and what end users actually experience.

For applications running on ServerRaja cloud servers, APM provides the missing layer between infrastructure monitoring and user experience.

The Four Pillars of APM

Effective APM covers four key areas:

  • **Request Tracing**: Follow individual requests through your application, identifying slow code paths and bottlenecks
  • **Error Tracking**: Capture and aggregate application exceptions with full stack traces and context
  • **Metrics Collection**: Track business and technical metrics like request rate, error rate, and response time percentiles
  • **Log Correlation**: Connect application logs to specific requests for easier debugging

Golden Signals for Application Monitoring

Google's SRE book defines four golden signals that every application should monitor:

Latency

Track how long requests take to serve. Focus on the 95th and 99th percentiles rather than averages:

import time
from prometheus_client import Histogram

REQUEST_LATENCY = Histogram( 'http_request_duration_seconds', 'HTTP request latency in seconds', ['method', 'endpoint', 'status'], buckets=[0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1.0, 2.5, 5.0, 10.0] )

@app.middleware("http") async def track_latency(request, call_next): start = time.perf_counter() response = await call_next(request) duration = time.perf_counter() - start REQUEST_LATENCY.labels( method=request.method, endpoint=request.url.path, status=response.status_code ).observe(duration) return response ```

Traffic

Measure the rate of requests hitting your application:

from prometheus_client import Counter

REQUEST_COUNT = Counter( 'http_requests_total', 'Total HTTP requests', ['method', 'endpoint', 'status'] ) ```

Errors

Track the proportion of failed requests:

ERROR_COUNT = Counter(
    'http_errors_total',
    'Total HTTP errors',
    ['method', 'endpoint', 'status', 'error_type']
)

@app.exception_handler(Exception) async def global_exception_handler(request, exc): ERROR_COUNT.labels( method=request.method, endpoint=request.url.path, status=500, error_type=type(exc).__name__ ).inc() return JSONResponse(status_code=500, content={"error": "Internal server error"}) ```

Saturation

Monitor how close your application is to its resource limits:

from prometheus_client import Gauge

ACTIVE_CONNECTIONS = Gauge( 'app_active_connections', 'Number of active connections' )

DB_POOL_USAGE = Gauge( 'app_db_pool_connections', 'Database connection pool usage', ['state'] ) ```

Database Performance Monitoring

Database queries are often the biggest bottleneck. Track query performance:

import functools
import time
from prometheus_client import Histogram

DB_QUERY_DURATION = Histogram( 'db_query_duration_seconds', 'Database query duration', ['query_type', 'table'], buckets=[0.001, 0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1.0] )

def monitor_query(func): @functools.wraps(func) def wrapper(*args, **kwargs): start = time.perf_counter() try: result = func(*args, **kwargs) return result finally: duration = time.perf_counter() - start DB_QUERY_DURATION.labels( query_type=func.__name__, table=kwargs.get('table', 'unknown') ).observe(duration) return wrapper ```

Enable slow query logging in MySQL:

SET GLOBAL slow_query_log = 'ON';
SET GLOBAL long_query_time = 1;
SET GLOBAL slow_query_log_file = '/var/log/mysql/slow.log';

Enable slow query logging in PostgreSQL:

ALTER SYSTEM SET log_min_duration_statement = 1000;
ALTER SYSTEM SET log_statement = 'none';
SELECT pg_reload_conf();

Setting Up Error Tracking with Sentry

Integrate Sentry for comprehensive error tracking:

import sentry_sdk
from sentry_sdk.integrations.sqlalchemy import SqlalchemyIntegration
from sentry_sdk.integrations.redis import RedisIntegration

sentry_sdk.init( dsn="https://[email protected]/project", environment="production", traces_sample_rate=0.1, profiles_sample_rate=0.1, integrations=[ SqlalchemyIntegration(), RedisIntegration(), ], before_send=filter_sensitive_data, ) ```

Implementing Distributed Tracing

For microservices architectures, distributed tracing follows requests across service boundaries:

from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from opentelemetry.exporter.jaeger.thrift import JaegerExporter

provider = TracerProvider() jaeger_exporter = JaegerExporter(agent_host_name="jaeger", agent_port=6831) provider.add_span_processor(BatchSpanProcessor(jaeger_exporter)) trace.set_tracer_provider(provider)

tracer = trace.get_tracer(__name__)

async def process_order(order_id): with tracer.start_as_current_span("process_order") as span: span.set_attribute("order.id", order_id) with tracer.start_as_current_span("validate_payment"): await validate_payment(order_id) with tracer.start_as_current_span("update_inventory"): await update_inventory(order_id) with tracer.start_as_current_span("send_confirmation"): await send_confirmation(order_id) ```

Creating Effective Dashboards

Organize your Grafana APM dashboards into these sections:

  • **Overview**: Request rate, error rate, p95 latency, active users
  • **Latency Distribution**: Heatmap of response times with percentile lines
  • **Error Analysis**: Top errors by count, error rate over time, affected endpoints
  • **Database Performance**: Query duration by type, connection pool usage, slow queries
  • **Resource Utilization**: CPU, memory, and I/O correlated with application metrics

Alerting Strategy

Set up tiered alerts based on severity:

  • **P1 (Critical)**: Error rate > 5% for 2 minutes, server down, database unreachable
  • **P2 (Warning)**: p95 latency > 2 seconds for 5 minutes, disk space < 15%
  • **P3 (Info)**: Deployment completed, certificate expiring in 30 days

Conclusion

Effective APM combines request tracing, error tracking, metrics, and logs into a cohesive observability strategy. Start by instrumenting your application with Prometheus metrics and Sentry for error tracking. Add distributed tracing as your architecture grows. ServerRaja cloud servers provide the reliable foundation your monitored applications need.

APM Best Practices for Cloud Apps | ServerRaja