در بخش سوم متریکها را اضافه کردیم؛ متریکها به ما میگویند «چهقدر» و «چه زمانی» چیزی تغییر کرده است. اما وقتی نرخ خطا بالا میرود، برای فهمیدن «چرا»، به جزئیات نیاز داریم. اینجاست که لاگها وارد میشوند. در این بخش لاگهای اپلیکیشن را با Loki جمعآوری و بررسی میکنیم.
Loki چگونه کار میکند؟
Loki یک سامانهی ذخیرهی لاگ از خانوادهی Grafana است. نکتهی کلیدی طراحی آن این است که برخلاف بسیاری از سامانههای دیگر، کل متن لاگها را ایندکس نمیکند؛ فقط مجموعهای کوچک از برچسبها (labels) مانند namespace، pod و container را ایندکس میکند و خود متن را فشرده ذخیره میکند. نتیجه، هزینه و منابع بسیار کمتر است و مدل کار آن هم شبیه Prometheus میماند.
جمعآوری لاگ با Alloy
خبر خوب این است که به جمعکنندهی جدیدی نیاز نداریم؛ همان Grafana Alloy که در بخش قبل متریکها را جمع میکرد، میتواند لاگ pod ها را هم بخواند. کافی است دو جزء به پیکربندی اضافه کنیم: یکی لاگها را از Kubernetes میخواند و دیگری آنها را به Loki میفرستد:
loki.source.kubernetes "pods" {
targets = discovery.relabel.pod_logs.output
forward_to = [loki.write.default.receiver]
}
loki.write "default" {
endpoint {
url = "http://loki.observability.svc:3100/loki/api/v1/push"
}
}
هر خط لاگ بههمراه برچسبهایی مانند namespace، pod، container و app به Loki میرسد. همین برچسبها بعداً امکان فیلترکردن دقیق را میدهند.
نمایش لاگ در Grafana
Loki را هم بهعنوان یک datasource به Grafana معرفی میکنیم و مانند بخش قبل، یک داشبورد لاگ بهشکل کد میسازیم: یک نمودار میلهای از حجم لاگ در طول زمان و یک پنل که خطوط لاگ زنده را نشان میدهد. با تولید ترافیک روی اپلیکیشن (شامل درخواستهای موفق و درخواستهایی به مسیرهای ناموجود)، لاگهای واقعی نمایش داده میشوند:
فیلترکردن با LogQL
Loki زبان پرسوجوی خودش را دارد به نام LogQL که ساختاری شبیه PromQL دارد. ابتدا با برچسبها مجموعهی لاگ را محدود میکنیم و سپس با عملگرهای متنی، خطوط موردنظر را فیلتر میکنیم؛ برای نمونه فقط درخواستهایی که با خطای 404 پاسخ گرفتهاند:
{namespace="guestbook"} # همهی لاگهای اپلیکیشن
{namespace="guestbook"} |= "404" # فقط درخواستهای ناموفق
چون لاگها و متریکها هر دو با برچسبهای مشترکی مانند namespace و pod نشانهگذاری شدهاند، میتوانیم بهسادگی از یک جهش در نمودار نرخ خطا به لاگهای دقیق همان لحظه و همان pod برسیم؛ این همان چیزی است که یافتن ریشهی مشکل را سریع میکند.
جمعبندی و بخش بعد
در این بخش زنجیرهی لاگ را ساختیم: خواندن لاگ pod ها با Alloy، ذخیره در Loki و بررسی و فیلتر با LogQL در Grafana. حالا دو سیگنال از سه سیگنال اصلی را داریم: متریکها میگویند مشکلی هست و لاگها میگویند چرا.
در بخش بعد سیگنال سوم را اضافه میکنیم: با Tempo مسیر یک درخواست را از ابتدا تا انتها ردیابی میکنیم تا ببینیم زمان دقیقاً کجا صرف میشود.
بخشهای این مجموعه
- بخش ۱: پیشنیاز، یک Kubernetes ساده با k0s
- بخش ۲: استقرار اپلیکیشن Django با GitOps و Argo CD
- بخش ۳: متریکها با Mimir
- بخش ۴: لاگها با Loki (همین بخش)
- بخش ۵: ردیابی (Tracing) با Tempo
- بخش ۶: پروفایلینگ پیوسته با Pyroscope