Counter
Counter Metric
Counter is a monotonically increasing metric.
Characteristics
Counter:
- Only increases (or resets to 0)
- Never decreases
- Represents cumulative total
Examples:
- requests_total
- errors_total
- bytes_processed_total
Implementation
from prometheus_client import Counter
# Define counter
REQUEST_COUNT = Counter(
'http_requests_total',
'Total HTTP requests',
['method', 'endpoint', 'status']
)
# Increment
REQUEST_COUNT.labels(method='GET', endpoint='/api', status='200').inc()
# Increment by value
REQUEST_COUNT.labels(method='POST', endpoint='/api', status='200').inc(5)
Rate Calculation
# Prometheus rate() function
# Rate of requests per second over 5 minutes
rate(http_requests_total[5m])
# Increase over last hour
increase(http_requests_total[1h])
Use Cases
| Use Case | Counter Name |
|---|---|
| Request count | http_requests_total |
| Error count | errors_total |
| Messages processed | messages_processed_total |
| Bytes sent | bytes_sent_total |
Best Practices
- Suffix with _total
- Use labels for dimensions
- Use rate() for per-second
- Use increase() for time window
Gauge
Gauge Metric
Gauge is a metric that can go up or down.
Characteristics
Gauge:
- Can increase or decrease
- Represents current value
- Point-in-time measurement
Examples:
- temperature
- queue_depth
- cpu_usage
- connections_active
Implementation
from prometheus_client import Gauge
# Define gauge
QUEUE_DEPTH = Gauge('queue_depth', 'Current queue depth')
CPU_USAGE = Gauge('cpu_usage_percent', 'CPU usage', ['service'])
# Set value
QUEUE_DEPTH.set(42)
# Increment/Decrement
QUEUE_DEPTH.inc() # +1
QUEUE_DEPTH.dec() # -1
QUEUE_DEPTH.inc(5) # +5
# With labels
CPU_USAGE.labels(service='api').set(75.5)
Use Cases
| Use Case | Gauge Name |
|---|---|
| Queue depth | queue_depth |
| CPU usage | cpu_usage_percent |
| Memory usage | memory_usage_bytes |
| Active connections | connections_active |
| Temperature | temperature_celsius |
Best Practices
- Use for current state
- Don't use for rates (use Counter)
- Set, don't increment
- Label for dimensions
Histogram
Histogram Metric
Histogram measures distribution of values.
Characteristics
Histogram:
- Distribution of values
- Predefined buckets
- Calculates quantiles
Examples:
- request_duration_seconds
- response_size_bytes
- db_query_duration_seconds
Implementation
from prometheus_client import Histogram
# Define histogram
REQUEST_DURATION = Histogram(
'http_request_duration_seconds',
'Request duration',
['endpoint'],
buckets=[0.01, 0.05, 0.1, 0.5, 1.0, 5.0] # Custom buckets
)
# Observe value
REQUEST_DURATION.labels(endpoint='/api').observe(0.25) # 250ms
# Use as context manager
with REQUEST_DURATION.labels(endpoint='/api').time():
result = process_request()
Buckets
# Default buckets (seconds)
DEFAULT_BUCKETS = (0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1.0, 2.5, 5.0, 10.0)
# HTTP latency buckets
HTTP_BUCKETS = (0.01, 0.05, 0.1, 0.25, 0.5, 1.0, 2.5, 5.0, 10.0)
# Size buckets
SIZE_BUCKETS = (100, 1000, 10000, 100000, 1000000)
Quantile Queries
# P50 (median)
histogram_quantile(0.5, rate(http_request_duration_seconds_bucket[5m]))
# P95
histogram_quantile(0.95, rate(http_request_duration_seconds_bucket[5m]))
# P99
histogram_quantile(0.99, rate(http_request_duration_seconds_bucket[5m]))
Use Cases
| Use Case | Histogram Name |
|---|---|
| Request latency | http_request_duration_seconds |
| Response size | http_response_size_bytes |
| DB query time | db_query_duration_seconds |
| Queue wait time | queue_wait_duration_seconds |
Percentiles
Percentiles
What are Percentiles?
P50 (Median): 50% of requests faster than this
P95: 95% of requests faster than this
P99: 99% of requests faster than this
Example:
- P50 = 50ms (half requests < 50ms)
- P95 = 200ms (95% requests < 200ms)
- P99 = 500ms (99% requests < 500ms)
Why Percentiles?
Average can be misleading:
- 99 requests: 10ms each
- 1 request: 1000ms
- Average: 20ms (looks good!)
- P99: 1000ms (terrible!)
Percentiles show tail latency
Prometheus Queries
# P50
histogram_quantile(0.5, sum(rate(http_request_duration_seconds_bucket[5m])) by (le))
# P95
histogram_quantile(0.95, sum(rate(http_request_duration_seconds_bucket[5m])) by (le))
# P99
histogram_quantile(0.99, sum(rate(http_request_duration_seconds_bucket[5m])) by (le))
# P999
histogram_quantile(0.999, sum(rate(http_request_duration_seconds_bucket[5m])) by (le))
SLOs with Percentiles
SLOs:
latency:
P50: < 50ms
P95: < 200ms
P99: < 500ms
availability: > 99.9%
error_rate: < 0.1%
Best Practices
- Track P50, P95, P99
- Use P99 for SLOs
- Alert on P99 violations
- Dashboard all percentiles
- Compare across services
Practice Problems
Design a scalable Metrics system. Cover high-level architecture, data model, and API design.
Solution
// Complete system design:
// - Functional + Non-functional requirements
// - Capacity estimation
// - Data model (SQL/NoSQL choice)
// - API endpoints
// - Component architecture
// - Scaling strategy
// - Monitoring & reliabilityHow would you scale Metrics to handle 10x the current load? Identify bottlenecks and solutions.
Solution
// Scaling approach:
// 1. Load balancing
// 2. Database sharding/replication
// 3. Cache layer (Redis)
// 4. CDN for static assets
// 5. Async processing (queues)
// 6. Microservices decompositionAnalyze potential failure modes for Metrics and design mitigation strategies.
Solution
// Failure mitigation:
// 1. Redundancy (multi-AZ)
// 2. Circuit breakers
// 3. Retry with backoff
// 4. Dead letter queues
// 5. Health checks
// 6. Graceful degradationQuiz
1. When to use Counter vs Gauge?
2. What does P99 represent?
3. Why use Histogram over just calculating average?
4. What is the rate() function in Prometheus?
5. When to use Gauge?
Flashcards
Question
Counter vs Gauge?
Click to reveal answer
Answer
Counter: monotonically increasing (requests, errors). Gauge: can go up/down (queue depth, CPU).
Question
What is a Histogram?
Click to reveal answer
Answer
Measures distribution of values in predefined buckets, enables quantile calculations
Question
What do P50, P95, P99 represent?
Click to reveal answer
Answer
P50: 50% faster. P95: 95% faster. P99: 99% faster. Shows latency distribution.
Question
Why track percentiles?
Click to reveal answer
Answer
Average can hide tail latency; percentiles show distribution including worst-case requests
Question
rate() function purpose?
Click to reveal answer
Answer
Calculates per-second rate of increase for counters, used for dashboards and alerts
Revision Notes
Key Takeaways
- 1.Counter for cumulative totals, Gauge for current state
- 2.Histogram for distribution and percentiles
- 3.P99 shows tail latency - critical for SLOs
- 4.rate() for per-second rates on counters
- 5.Average can be misleading; use percentiles
Interview Tips
- •Know when to use each metric type
- •Explain why percentiles matter over averages
- •Discuss rate() vs increase() usage
- •Give examples of each metric type
Cheat Sheet
Cheat Sheet: Metrics
Types
- Counter: Monotonically increasing
- Gauge: Can go up/down
- Histogram: Distribution of values
Percentiles
- P50: Median
- P95: 95% faster
- P99: Tail latency
Prometheus
- rate(): per-second rate
- increase(): time window total
- histogram_quantile(): percentiles
Best Practices
- Counter: suffix _total
- Gauge: for current state
- Histogram: for latency distribution
- Track P50, P95, P99