مشاهدهپذیری و کارایی
هر Feature پیش از انتشار باید از روی Log، Metric و Trace قابل عیبیابی باشد. بهینهسازی فقط با اندازهگیری انجام میشود و Telemetry نباید Secret، PII یا Cardinality کنترلنشده ایجاد کند.
سه ستون Telemetry
| سیگنال | استاندارد | کاربرد |
|---|---|---|
| Log | log/slog با JSON |
رخداد قابل جستوجو و Context عملیاتی |
| Metric | OpenTelemetry/Prometheus | نرخ، خطا، زمان و Saturation |
| Trace | OpenTelemetry و W3C Trace Context | مسیر درخواست میان API، DB، Worker و Provider |
Trace و Metric در OpenTelemetry Go پایدارند. Log با slog تولید و در صورت نیاز با Trace ID مرتبط میشود؛ استفاده از API آزمایشی Log در OpenTelemetry نباید Core کد را قفل کند.
Log ساختیافته
- فیلد پایه شامل
timestamp،level،service،version،environment،request_id،trace_idوeventاست. - Error یک
error_codeپایدار و در صورت امن بودن Chain خلاصه دارد؛ Stack فقط در Error داخلی و محیط کنترلشده ثبت میشود. - شماره موبایل، Token، OTP، Cookie، متن Ticket، Query Parameter حساس، URL امضاشده و payload Provider Redact میشوند.
- Log موفق هر Request در بار بالا Sample میشود، اما Error، Audit و رخداد امنیتی بدون از دسترفتن نگهداری میشوند.
- Levelها معنا دارند:
debugبرای Development،infoبرای تغییر عادی وضعیت،warnبرای اختلال قابل تحمل وerrorبرای شکست نیازمند اقدام. - Health Check موفق Log نمیشود تا Noise ایجاد نکند.
Metric
برای API از RED و برای Resource از USE استفاده میشود:
- Rate، Error و Duration درخواست HTTP بر اساس Route Template و Status Class
- Utilization، Saturation و Error برای CPU، Memory، Disk، Network و Connection Pool
- Query Duration، Pool Wait، Transaction Rollback و Slow Query
- Queue Depth، Oldest Job Age، Retry، Dead Letter و Handler Duration
- Login Success/Failure، OTP Send/Verify و Refresh Reuse بدون Label موبایل یا Account
- Provider Duration، Error Class و Rate Limit بر اساس نام Provider و Operation محدود
- Object Upload/Download، Rejection و Scan Duration
Label شامل user_id، building_id، request_id، Object Key یا Error Text ممنوع است. Route به Template مانند /buildings/{id} تبدیل میشود. Cardinality هر Metric پیش از Merge بررسی میشود.
Trace
- ورودی HTTP Trace Context معتبر را میپذیرد و Correlation داخلی جدید در صورت نبود آن میسازد.
- Span برای Use Case، Query مهم، Job و تماس Provider ساخته میشود؛ Functionهای کوچک Span جدا نمیگیرند.
- Attributeها Allowlist دارند و PII یا Payload کامل ثبت نمیشود.
- Sampling در Head برای حالت عادی و نگهداری بیشتر Error/Latency در Collector تنظیم میشود.
- Propagation به Provider فقط وقتی قرارداد و ریسک افشای Header روشن باشد انجام میشود.
Health و آمادگی
/livezفقط زندهبودن Process را نشان میدهد و Dependency بیرونی را Check نمیکند./readyzآمادگی پذیرش Traffic و Dependencyهای ضروری مانند PostgreSQL را با Timeout کوتاه بررسی میکند./startupzدر صورت نیاز شروع طولانی را از Liveness جدا میکند.- پاسخ Health بدون نسخه Secret، DSN، Topology یا جزئیات خطای داخلی است.
- شکست SMS، Push یا Object Storage لزوما API را Unready نمیکند؛ مسیر Durable باید Backlog و Alert ایجاد کند.
SLO و بودجه خطا
| شاخص | هدف اولیه Production |
|---|---|
| Availability API | 99.9 درصد ماهانه برای درخواستهای واجد SLI |
| p95 خواندن | حداکثر 200ms Server-side |
| p95 نوشتن | حداکثر 400ms Server-side |
| Error Rate داخلی | کمتر از 0.5 درصد درخواستهای واجد SLI |
| Age صف OTP در p95 | کمتر از 5 ثانیه پیش از تماس Provider |
| RPO | حداکثر 5 دقیقه |
| RTO | حداکثر 60 دقیقه |
این هدفها پس از Load Test و انتخاب Topology نهایی تصویب میشوند. یک VPS Single Point of Failure است و ممکن است Availability یا RTO را تامین نکند؛ داشبورد باید فاصله واقعی با هدف را نشان دهد، نه اینکه عدد را تضمینشده فرض کند.
Error Budget برای اولویتدادن Reliability به Feature استفاده میشود. سوختن سریع Budget، Deploy خودکار Development را متوقف و برای Production Release Gate ایجاد میکند.
Alert
- Alert باید Symptom قابل اقدام را هدف بگیرد، نه هر Metric غیرعادی را.
- Alert دارای Severity، مالک، Dashboard و Runbook است.
- Multi-window Burn Rate برای SLO و Threshold پایدار برای ظرفیت استفاده میشود.
- نبود Telemetry، توقف Backup، رشد Queue، Refresh Reuse، افزایش Cross-tenant Deny و Disk کم Alert مستقل دارند.
- Alert بدون اقدام مشخص حذف یا اصلاح میشود تا Alert Fatigue ایجاد نکند.
Profiling و Optimization
- Profile و Benchmark فقط در محیط کنترلشده و با داده غیرحساس اجرا میشوند.
- Endpointهای
pprofعمومی نیستند و پشت شبکه یا Authentication عملیاتی قرار میگیرند. - ترتیب کارایی: اندازهگیری، یافتن Bottleneck، تغییر کوچک، مقایسه و ثبت نتیجه است.
- ابتدا Query، تعداد Round Trip، Serialization و Allocationهای پرتکرار بررسی میشوند.
- Cache فقط با مالکیت، TTL، Invalidation و Consistency مشخص اضافه میشود؛ Redis در نسخه اول پیشفرض نیست.
sync.Pool، Query پیچیده، Denormalization و Goroutine بیشتر بدون Profile و Benchmark ممنوعاند.- Standard Library یا حذف Dependency بهتنهایی ادعای Performance نیست؛ اثر تغییر Router، Middleware یا Allocation فقط با Benchmark و Load Test همان Workload پذیرفته میشود.
- مسیر موفق HTTP برای تشخیص 404/405 نباید Response Body را Buffer یا فهرست Routeها را Scan کند؛ کار اضافه تشخیص Method فقط در مسیر Unmatched مجاز است.
Capacity
- Headroom هدف برای CPU، Memory، Disk، Connection و Queue در بار معمول حداقل 30 درصد است.
- Disk PostgreSQL، WAL و Object Cache جداگانه پایش و Forecast میشوند.
- Load Test ظرفیت هر Replica و Database را پیش از تغییر Traffic تعیین میکند.
- Limit Container کمتر از نیاز واقعی و بیشتر از ظرفیت Host تنظیم نمیشود؛ OOM و CPU Throttling Metric دارند.
- افزایش Replica نباید مجموع Connection Pool را از ظرفیت Database عبور دهد.
معیار پذیرش
- داشبورد API، PostgreSQL، Worker، Provider و Host پیش از Release وجود دارد.
- هر Alert بحرانی Runbook و مالک دارد.
- هیچ Label یا Log حاوی PII و Secret نیست.
- Load Test بودجه p95 و ظرفیت Headroom را با Artifact قابل تکرار اثبات میکند.
- Restore Metric و Queue Age از ابتدا قابل مشاهدهاند.