Observability در Backend چیست؟ وقتی سرور کند شده از کجا بفهمیم چرا؟
مقدمه؛ وقتی سرور کند شده، مشکل دقیقاً کجاست؟
فرض کنید کاربران گزارش میدهند که سایت یا اپلیکیشن شما کند شده است.
بررسی اولیه را انجام میدهید:
Server: Running ✓
Database: Running ✓
API: Running ✓
CPU: 45%
Memory: 60%همهچیز ظاهراً سالم است.
اما کاربران همچنان با این وضعیت مواجهاند:
GET /api/products
→ 1800msدر حالی که همین API چند ساعت قبل:
→ 120msزمان پاسخ داشته است.
حالا سؤال اصلی این است:
مشکل از کجاست؟
آیا Database کند شده؟
آیا یک Query خاص مشکل دارد؟
آیا یک API خارجی پاسخ نمیدهد؟
آیا Connection Pool پر شده؟
آیا CPU درگیر یک پردازش سنگین است؟
یا اصلاً مشکل از Network است؟
اینجاست که مفهوم Observability اهمیت پیدا میکند.
Observability به ما کمک میکند از روی رفتار و دادههای سیستم بفهمیم داخل سیستم چه اتفاقی در حال رخ دادن است.
Observability چیست؟
Observability یا «قابلیت مشاهدهپذیری» به توانایی یک سیستم برای ارائه اطلاعات کافی درباره وضعیت داخلی خود گفته میشود؛ به شکلی که بتوانیم رفتار، خطاها و مشکلات آن را از بیرون بررسی و علت آنها را پیدا کنیم.
به زبان ساده:
Monitoring به شما میگوید چه چیزی خراب شده؛ Observability کمک میکند بفهمید چرا خراب شده است.
فرض کنید:
API Latency ↑Monitoring میتواند نشان دهد:
API Response Time = 2.1sاما Observability کمک میکند مسیر Request را بررسی کنیم:
Request
↓
Authentication 15ms
↓
Database Query 80ms
↓
External API 1700ms
↓
Serialization 20msحالا مشخص است که بخش عمده زمان در External API مصرف شده است.
Monitoring و Observability چه تفاوتی دارند؟
این دو مفهوم بسیار نزدیکاند، اما یکسان نیستند.
Monitoring
Monitoring بیشتر برای مشاهده وضعیت شناختهشده سیستم استفاده میشود.
مثلاً:
CPU > 80%
Memory > 90%
Error Rate > 5%
Latency > 500msدر این حالت سیستم میتواند Alert ارسال کند.
Observability
Observability سؤالهای عمیقتری را پاسخ میدهد:
چرا Latency افزایش پیدا کرده؟
کدام Endpoint مشکل دارد؟
کدام Database Query کند شده؟
کدام سرویس خارجی پاسخ نمیدهد؟
کدام Requestها بیشتر خطا میدهند؟
مشکل فقط در یک Region اتفاق افتاده؟پس میتوان ساده گفت:
Monitoring
↓
What happened?
Observability
↓
Why did it happen?البته این تفکیک یک سادهسازی مفهومی است؛ Monitoring و Observability در عمل همپوشانی زیادی دارند.
سه ستون اصلی Observability
معمولاً Observability را با سه نوع داده اصلی توضیح میدهند:
Observability
│
┌───────┼───────┐
↓ ↓ ↓
Logs Metrics Tracesاین سه مورد عبارتاند از:
Logs
Metrics
Traces
هرکدام دید متفاوتی از سیستم به ما میدهند.
۱. Logs؛ چه اتفاقی افتاد؟
Log گزارشی از یک رویداد در سیستم است.
مثلاً:
2026-09-21 20:31:10
GET /api/orders
status=200
duration=842msیا:
Database connection timeoutLogs برای فهمیدن جزئیات یک اتفاق بسیار مفید هستند.
مثلاً:
Request received
User authenticated
Order fetched
Payment API called
Payment failedاما Log ساده میتواند خیلی سریع تبدیل به یک مشکل شود.
اگر در Production میلیونها Log تولید کنید:
INFO
INFO
INFO
INFO
ERROR
INFO
INFO
INFOپیدا کردن اطلاعات موردنظر سخت خواهد شد.
به همین دلیل Logging باید Structured باشد.
Structured Logging چیست؟
به جای اینکه Log را به صورت متن ساده بنویسیم:
User 42 requested order 123میتوانیم داده ساختاریافته تولید کنیم:
{
"level": "info",
"event": "order.request",
"userId": 42,
"orderId": 123,
"duration": 184,
"requestId": "abc123"
}حالا ابزارهای Log Management میتوانند بر اساس فیلدهای مختلف جستجو کنند.
مثلاً:
duration > 1000یا:
event = "order.request"یا:
requestId = "abc123"این موضوع در سیستمهای بزرگ اهمیت زیادی دارد.
۲. Metrics؛ سیستم در چه وضعیتی قرار دارد؟
Metrics دادههای عددی هستند که وضعیت سیستم را در طول زمان نشان میدهند.
مثلاً:
CPU Usage
Memory Usage
Request Count
Error Rate
Request Duration
Database Connections
Queue Lengthفرض کنید نمودار زیر را داریم:
API Latency
100ms ────────────────
150ms ────────────────
200ms ────────────╮
500ms │
1s │
2s ╰────────این نمودار به ما میگوید که در یک بازه مشخص، Latency افزایش پیدا کرده است.
اما هنوز نمیدانیم چرا.
برای پاسخ به این سؤال باید سراغ Logs و Traces برویم.
۳. Tracing؛ مسیر کامل یک Request
Tracing یکی از مهمترین قسمتهای Observability در معماریهای مدرن است.
فرض کنید یک Request وارد Backend میشود:
Client
↓
API Gateway
↓
Auth Service
↓
Order Service
↓
Database
↓
Payment Serviceاگر Response Time برابر با 2 ثانیه باشد، سؤال این است:
کدام بخش 2 ثانیه زمان برده است؟
Distributed Tracing میتواند مسیر Request را به شکل زیر نشان دهد:
Request 2000ms
│
├── API Gateway 20ms
│
├── Auth Service 30ms
│
├── Order Service 100ms
│
├── Database 50ms
│
└── Payment Service 1800msحالا Bottleneck تقریباً مشخص است.
مشکل اصلی:
Payment Service
≈ 1800msاست.
Trace و Span چیست؟
در سیستمهای Distributed معمولاً یک Request به یک Trace تبدیل میشود.
Trace مسیر کلی یک عملیات را نشان میدهد.
هر قسمت از این مسیر یک Span است.
مثلاً:
Trace
│
├── HTTP Request
│
├── Authentication Span
│
├── Database Span
│
├── External API Span
│
└── Response Spanدر یک سیستم Microservices ممکن است یک Trace بین چند سرویس حرکت کند.
این قابلیت کمک میکند بفهمیم یک Request دقیقاً چه مسیری را طی کرده است.
Trace ID و Correlation ID چیست؟
فرض کنید یک Request وارد سیستم شده است:
Trace ID:
7f9c2a1bهمین شناسه میتواند در سرویسهای مختلف همراه Request حرکت کند:
API Gateway
Trace ID: 7f9c2a1b
Order Service
Trace ID: 7f9c2a1b
Payment Service
Trace ID: 7f9c2a1b
Database Operation
Trace ID: 7f9c2a1bحالا اگر مشکلی ایجاد شود، میتوانیم تمام اطلاعات مرتبط با همان Request را پیدا کنیم.
این موضوع در سیستمهایی که چند سرویس دارند بسیار ارزشمند است.
وقتی API کند شده، از کجا شروع کنیم؟
فرض کنید:
GET /api/dashboard
Before:
120ms
Now:
2100msبه جای تغییر تصادفی کد، یک فرآیند مشخص را دنبال میکنیم.
مرحله اول: بررسی Metrics
ابتدا بررسی میکنیم:
Latency
Error Rate
Request Rate
CPU
Memory
Database Connectionsمثلاً متوجه میشویم:
CPU = 35%
Memory = 55%
Latency = 2.1sپس احتمالاً مشکل CPU نیست.
مرحله دوم: بررسی Endpoint
ممکن است فقط یک Endpoint مشکل داشته باشد.
مثلاً:
/api/users → 120ms
/api/products → 140ms
/api/orders → 150ms
/api/dashboard → 2100msاین اطلاعات دامنه جستجو را محدود میکند.
مرحله سوم: بررسی Trace
حالا Trace مربوط به /api/dashboard را باز میکنیم:
Dashboard API
│
├── Auth 15ms
├── User Query 40ms
├── Orders Query 80ms
├── Analytics 1900ms
└── Serialize 20msحالا مشکل تقریباً مشخص است:
Analytics
≈ 1900msمرحله چهارم: بررسی Database یا سرویس مربوطه
حالا میتوانیم دقیقتر بررسی کنیم.
مثلاً Query:
SELECT *
FROM analytics
WHERE user_id = 42;با بررسی Execution Plan متوجه میشویم Query روی حجم زیادی از دادهها Scan انجام میدهد.
ممکن است مشکل مربوط به:
Missing Index
Large Dataset
Expensive JOIN
Bad Query Planباشد.
در اینجا Observability ما را از:
"سرور کند شده"به:
"این Query خاص باعث افزایش Latency شده"میرساند.
p95 و p99؛ چرا Average کافی نیست؟
یکی از اشتباهات رایج این است که فقط Average Latency را بررسی کنیم.
فرض کنید:
Average = 150msبه نظر خوب میرسد.
اما اگر دادهها اینطور باشند:
p50 = 90ms
p95 = 400ms
p99 = 1800msمیبینیم که بخشی از کاربران با Latency بسیار بیشتری مواجهاند.
p50
نقطه میانی دادهها را نشان میدهد.
p95
نشان میدهد حدود 95٪ دادهها در این مقدار یا کمتر قرار دارند.
p99
Tail Latency را بهتر نشان میدهد و برای پیدا کردن Requestهای بسیار کند اهمیت دارد.
به همین دلیل در سیستمهای Production بهتر است به جای یک عدد، Distribution مربوط به Latency را بررسی کنیم.
Observability و Database
Database یکی از مهمترین قسمتهایی است که باید در Observability تحت نظر باشد.
Metrics مهم میتوانند شامل:
Query Duration
Connection Pool Usage
Active Connections
Slow Queries
Cache Hit Ratio
Transaction Duration
Lock Wait Timeباشند.
مثلاً:
API Latency
↑
│
Database Query
↑
Connection Pool
↑
Connection Waitگاهی خود Query سریع است، اما Request مدت زیادی منتظر Connection میماند.
بدون Instrumentation مناسب ممکن است این تفاوت را متوجه نشویم.
Observability و External API
فرض کنید Backend شما به سرویس پرداخت متصل است.
Metrics:
Payment API Latencyناگهان افزایش پیدا میکند:
200ms
↓
400ms
↓
900ms
↓
1800msهمزمان API شما نیز کند میشود.
Tracing میتواند نشان دهد:
Your API 1900ms
↓
Payment API 1750msدر این حالت مشکل لزوماً از کد Backend شما نیست.
این یکی از مزیتهای مهم Observability است:
میتوانیم مرز بین مشکل داخلی سیستم و وابستگی خارجی را بهتر تشخیص دهیم.
OpenTelemetry چیست؟
OpenTelemetry یکی از پروژههای مهم برای Instrumentation و جمعآوری دادههای Observability است.
به کمک آن میتوان دادههایی مانند:
Traces
Metrics
Logsرا در سیستمهای مختلف جمعآوری و به Backendهای Observability ارسال کرد.
معماری مفهومی:
Application
│
↓
OpenTelemetry
│
├── Metrics
├── Logs
└── Traces
│
↓
Observability Backendمزیت مهم OpenTelemetry این است که Instrumentation را از ابزار نهایی Observability تا حد زیادی جدا میکند.
یعنی میتوانید دادهها را به زیرساخت مناسب خود ارسال کنید، بدون اینکه کل کد Application به یک Vendor خاص وابسته شود.
Observability فقط برای Microservices نیست
گاهی تصور میشود Observability فقط برای سیستمهای بسیار بزرگ یا Microservices لازم است.
در حالی که یک Monolith هم میتواند از Observability بهره ببرد.
مثلاً:
Monolith
│
├── API
├── Database
├── Cache
├── External Services
└── Background Jobsحتی در یک پروژه نسبتاً ساده نیز دانستن اینکه:
Request → 20ms
Database → 500ms
External API → 700msبسیار ارزشمند است.
بنابراین Observability بیشتر از اینکه به اندازه پروژه وابسته باشد، به پیچیدگی رفتار سیستم و اهمیت آن در Production وابسته است.
Alerting؛ قبل از کاربران متوجه مشکل شویم
Observability بدون Alerting میتواند ناقص باشد.
فرض کنید:
p95 Latency > 1sبرای مدت مشخصی ادامه داشته باشد.
سیستم میتواند Alert ایجاد کند:
⚠ API Latency increased
Endpoint: /api/orders
p95: 1.4sیا:
⚠ Error Rate increased
Current: 8.2%
Normal: 1.1%هدف این است که تیم قبل از تبدیل شدن یک مشکل کوچک به Incident بزرگ، از آن مطلع شود.
اما Alert زیاد نیز مشکلساز است.
اگر برای هر اتفاق کوچک Alert ارسال شود:
Alert
Alert
Alert
Alert
Alertتیم ممکن است دچار Alert Fatigue شود.
پس Alertها باید برای شرایطی طراحی شوند که واقعاً نیاز به بررسی یا اقدام دارند.
چه چیزهایی را در Backend اندازهگیری کنیم؟
یک چکلیست کاربردی:
HTTP
Request Count
Response Time
Status Code
Error Rate
Request Size
Response SizeDatabase
Query Duration
Active Connections
Pool Utilization
Slow Queries
Lock Wait
Transaction DurationInfrastructure
CPU
Memory
Disk
Network
Container RestartsApplication
Queue Length
Job Duration
Cache Hit Rate
Background Job Failures
External API LatencyDistributed Systems
Trace Duration
Span Duration
Service Errors
Service Dependenciesیک سناریوی واقعی؛ API از 100ms به 2 ثانیه رسیده
فرض کنیم کاربران گزارش دادهاند:
صفحه سفارشها خیلی کند شده است.
ابتدا Metrics را بررسی میکنیم:
p95:
100ms → 2100msCPU:
42%Memory:
58%پس مشکل واضحی در CPU و Memory دیده نمیشود.
حالا Trace را بررسی میکنیم:
GET /api/orders
│
├── Authentication 12ms
├── Orders Query 70ms
├── Product Query 50ms
├── Shipping API 1850ms
└── Serialization 18msمشکل مشخص شد.
Shipping API
≈ 1850msحالا میتوانیم راهکار مناسب را بررسی کنیم:
Timeout
Caching
Parallel Requests
Fallback
Queue
Circuit Breakerراهکار نهایی به رفتار واقعی سیستم و نیاز Business بستگی دارد.
اما نکته مهم این است که بدون Observability ممکن بود ساعتها Database یا CPU را بررسی کنیم، در حالی که مشکل در یک سرویس خارجی بود.
Observability چه مشکلاتی را حل میکند؟
Observability میتواند در پیدا کردن مشکلاتی مانند موارد زیر کمک کند:
افزایش ناگهانی API Latency
Slow Database Queries
Memory Leak
افزایش Error Rate
مشکلات Connection Pool
کندی سرویسهای خارجی
Queueهای طولانی
خطاهای یک Microservice خاص
مشکلات مربوط به Deployment
افزایش Tail Latency
خطاهای وابسته به یک Region یا سرویس خاص
اما Observability به خودی خود مشکل را حل نمیکند.
این ابزار اطلاعات لازم برای تشخیص و تصمیمگیری فنی را فراهم میکند.
اشتباهات رایج در پیادهسازی Observability
۱. Log کردن همه چیز
Log بیشتر همیشه به معنی Observability بهتر نیست.
Logهای زیاد میتوانند:
Storage Cost ↑
Noise ↑
Search Difficulty ↑را افزایش دهند.
۲. نداشتن Context
این Log:
Request failedاطلاعات زیادی نمیدهد.
اما:
requestId
traceId
endpoint
user/session context
statusCode
duration
errorمیتواند برای Debugging بسیار مفیدتر باشد؛ البته بدون ثبت اطلاعات حساس و شخصی غیرضروری.
۳. فقط بررسی CPU و Memory
ممکن است:
CPU = 30%
Memory = 50%باشد ولی API همچنان 2 ثانیه طول بکشد.
چون مشکل میتواند در:
Database
Network
External API
Connection Pool
Queue
Lockباشد.
۴. نداشتن Distributed Tracing در سیستمهای چندسرویسی
در معماری Microservices اگر Trace بین سرویسها منتقل نشود، پیدا کردن علت یک خطای زنجیرهای دشوارتر میشود.
۵. Alertهای بیش از حد
Alert زیاد میتواند باعث شود Alertهای مهم در میان هشدارهای کماهمیت گم شوند.
معماری پیشنهادی ساده برای Observability
یک معماری مفهومی میتواند چنین باشد:
┌──────────────┐
│ Client │
└──────┬───────┘
↓
┌──────────────┐
│ Backend │
└──────┬───────┘
│
┌───────────┼───────────┐
↓ ↓ ↓
Logs Metrics Traces
│ │ │
└───────────┼───────────┘
↓
Observability Platform
↓
Dashboards / Alertsهدف این نیست که از روز اول دهها ابزار اضافه کنیم.
هدف این است که بتوانیم به سؤالهای مهم پاسخ دهیم:
چه چیزی خراب شده؟
کجا خراب شده؟
از چه زمانی؟
چند کاربر تحت تأثیر قرار گرفتهاند؟
علت احتمالی چیست؟چکلیست Observability برای یک Backend
اگر بخواهید یک Backend را از نظر Observability بررسی کنید، این موارد شروع خوبی هستند:
Logs
Structured Logging
Log Levels
Error Context
Request ID
Trace ID
Metrics
Request Rate
Error Rate
Latency
p50 / p95 / p99
CPU
Memory
Database Connections
Tracing
HTTP Requests
Database Queries
External APIs
Internal Service Calls
Background Jobs
Alerting
High Error Rate
High Latency
Service Down
Database Problems
Queue Backlog
Security
عدم ثبت Password
عدم ثبت Secret
عدم ثبت Tokenهای حساس
محدود کردن اطلاعات شخصی غیرضروری در Logs
جمعبندی
وقتی یک Backend کند میشود، مهمترین سؤال این نیست که:
«کدام خط کد را تغییر دهیم؟»
سؤال بهتر این است:
«دادههای سیستم دقیقاً چه چیزی درباره علت کندی به ما میگویند؟»
Observability این امکان را فراهم میکند که به جای حدس زدن، رفتار سیستم را از طریق سه منبع اصلی بررسی کنیم:
Logs
↓
جزئیات اتفاقات
Metrics
↓
وضعیت و روند سیستم
Traces
↓
مسیر و زمان مصرفشده در هر بخشترکیب این سه دیدگاه میتواند یک API مبهم و کند را به یک مسئله قابل اندازهگیری تبدیل کند.
مثلاً:
API = 2.1s
↓
Trace
↓
Database = 80ms
External API = 1.8s
↓
Bottleneck مشخص شدو این دقیقاً ارزش Observability است.
در یک Backend حرفهای، هدف فقط این نیست که وقتی سیستم خراب شد بفهمیم چه چیزی خراب شده است؛ بلکه باید بتوانیم با داده کافی بفهمیم کجا، چه زمانی و چرا این اتفاق افتاده است.
Monitoring به شما دیدن وضعیت سیستم را میدهد؛ Observability کمک میکند از روی شواهد، علت رفتار سیستم را پیدا کنید.
