زیرساختهای مدرن به شدت به متریکها وابستهاند، اما بخش قابل توجهی از عملکرد حیاتی سازمانها هنوز بر روی برنامههای قدیمی اجرا میشود. این سیستمها که اغلب دههها پیش ساخته شدهاند، اغلب شفاف نیستند و فاقد نقاط پایانی API بومی برای ابزارهای مشاهده مدرن هستند. این شکاف نقاط کوری ایجاد میکند که میتواند منجر به از دسترس خارج شدنهای غیرمنتظره و کاهش عملکرد شود. در این راهنما، ما بررسی خواهیم کرد که چگونه میتوان این شکاف را با ساخت صادرکنندههای سفارشی Prometheus پر کرد. با پوشش منطق قدیمی در یک لایه متریک، میتوانید شاخصهای حیاتی سلامت را به داشبوردهای موجود Grafana و Prometheus خود بدون تغییر در کد اصلی برنامه، در دسترس قرار دهید.
درک الگوی صادرکننده (Exporter)
یک صادرکننده Prometheus یک سرویس جداگانه است که متریکها را در قالبی که Prometheus میتواند اسکن (scrape) کند، در دسترس قرار میدهد. برخلاف خود برنامه که ممکن است با COBOL، Delphi یا یک نسخه قدیمی از Java نوشته شده باشد، صادرکننده به عنوان یک پوشش نازک عمل میکند. این صادرکننده از طریق رابطهای موجود—مانند SNMP، APIهای HTTP یا کوئریهای پایگاه داده—با سیستم قدیمی تعامل دارد و پاسخهای آنها را به قالب نمایش سازگار با Prometheus ترجمه میکند.
این جدایی دغدغهها (Separation of Concerns) حیاتی است. این امر به شما امکان میدهد سلامت برنامه قدیمی را به طور مستقل از منطق برنامه مدیریت کنید. اگر صادرکننده شکست بخورد، مجموعه پایش شما پایدار میماند. اگر برنامه قدیمی شکست بخورد، صادرکننده به سادگی وضعیت صفر یا خطا را گزارش میدهد و تیم شما را قبل از کاربران هشدار میدهد.
انتخاب زبان مناسب
هنگام ساخت یک صادرکننده، انتخاب زبان برنامهنویسی اغلب بر سهولت نگهداری و عملکرد تأثیر میگذارد. دو زبان در این حوزه پیشرو هستند: Go و Python.
Go استاندارد صنعتی برای نوشتن صادرکنندهها است. کتابخانه رسمی prometheus/client_golang قوی، دارای ایمنی نوع (type-safe) است و به یک باینری استاتیک واحد کامپایل میشود که استقرار آن را در محیطهای کانتینری بسیار ساده میکند. این زبان عملکرد بالایی دارد و با همزمانی (Concurrency) به خوبی مدیریت میشود.
Python برای نمونهسازی سریع عالی است، به ویژه اگر تیم شما از قبل با کتابخانههای دستکاری داده مانند Pandas برای تجمیع متریکها آشنا باشد. بسته prometheus_client استفاده آسانی دارد اما در سناریوهای با عبور داده بالا (high-throughput) میتواند کندتر باشد.
مثال پیادهسازی با Go
بیایید یک مثال عملی با استفاده از Go را بررسی کنیم. فرض کنید شما یک پایگاه داده موجودات قدیمی دارید که سطوح موجودی را ذخیره میکند. شما میخواهید تعداد اقلام با موجودی کم را در دسترس قرار دهید. در اینجا نحوه ساختاردهی صادرکننده آورده شده است:
package main
import (
"log"
"net/http"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
)
// LowStockCollector رابط prometheus.Collector را پیادهسازی میکند.
type LowStockCollector struct {
LowStockCount *prometheus.Desc
}
// NewLowStockCollector یک جمعآورنده جدید را مقداردهی اولیه میکند.
func NewLowStockCollector() *LowStockCollector {
return &LowStockCollector{
LowStockCount: prometheus.NewDesc(
"legacy_inventory_low_stock",
"تعداد اقلام با موجودی کم در پایگاه داده قدیمی",
nil, nil,
),
}
}
// Describe توصیفگرهای هر متریک مرتبط با این جمعآورنده را ارسال میکند.
func (c *LowStockCollector) Describe(ch chan<- *prometheus.Desc) {
ch <- c.LowStockCount
}
// Collect زمانی که توسط رجیستری Prometheus برای جمعآوری متریکها فراخوانی میشود.
func (c *LowStockCollector) Collect(ch chan<- prometheus.Metric) {
// شبیهسازی دریافت داده از سیستم قدیمی
count := fetchLowStockCountFromLegacyDB()
ch <- prometheus.MustNewConstMetric(
c.LowStockCount,
prometheus.GaugeValue,
float64(count),
)
}
func main() {
registry := prometheus.NewRegistry()
collector := NewLowStockCollector()
registry.MustRegister(collector)
http.Handle("/metrics", promhttp.HandlerFor(registry, promhttp.HandlerOpts{}))
log.Fatal(http.ListenAndServe(":9100", nil))
}
func fetchLowStockCountFromLegacyDB() int {
// منطق کوئری از پایگاه داده قدیمی در اینجا قرار میگیرد
return 42
}
در این مثال، ما یک جمعآورنده سفارشی تعریف میکنیم که روشهای Describe و Collect را پیادهسازی میکند. روش Collect جایی است که شما با سیستم قدیمی تعامل دارید. با قرار دادن این مورد در /metrics، Prometheus میتواند دادهها را اسکن کند بدون اینکه نیاز به تغییر در برنامه قدیمی باشد.
مدیریت احراز هویت و امنیت
سیستمهای قدیمی اغلب فاقد مکانیزمهای احراز هویت مدرن هستند. با این حال، خود صادرکننده باید ایمنسازی شود. از آنجا که صادرکننده یک سرویس جداگانه است، میتوانید آن را پشت یک پراکسی معکوس مانند Nginx یا Apache قرار دهید و احراز هویت پایه (basic authentication) یا mTLS را اضافه کنید. این اطمینان حاصل میکند که حتی اگر رابط قدیمی ناامن باشد، نقطه پایانی متریکها از دسترسی غیرمجاز محافظت شود.
نتیجهگیری
گسترش قابلیت مشاهده به برنامههای قدیمی نه تنها یک ضرورت فنی، بلکه یک ضرورت تجاری است. با ساخت صادرکنندههای سفارشی Prometheus، شما به سیستمهایی دسترسی پیدا میکنید که در غیر این صورت به عنوان جعبههای سیاه باقی میماندند. چه برای عملکرد Go را انتخاب کنید و چه برای سادگی Python، کلید این است که صادرکننده سبک و متمرکز نگه داشته شود. این رویکرد به شما امکان میدهد تا مجموعه پایش خود را به تدریج مدرنسازی کنید در حالی که پایداری زیرساختهای حیاتی قدیمی خود را حفظ میکنید. کوچک شروع کنید، یک متریک را در دسترس قرار دهید و از آنجا گسترش دهید.