هوش مصنوعی نحوه ساخت نرم‌افزار را تغییر داده است، اما حقیقت اساسی درباره ماشین‌ها را تغییر نداده است: آن‌ها نیز درست مانند ما، در میان نویز غرق می‌شوند. وقتی مهندسان برای اولین بار عیب‌یابی به کمک هوش مصنوعی (AI-assisted debugging) را تجربه می‌کنند، غریزه آن‌ها ساده است: همه چیز را به مدل بدهید. لاگ‌ها، ردپاها (traces) و متریک‌های خام همگی به درون پنجره بافت (context window) ریخته می‌شوند. نتیجه، بینش نیست، بلکه شکست است. حجم داده‌ها بسیار زیاد است. سیگنال از بین می‌رود. متریک‌ها در یک ابزار هستند، ردپاها در ابزاری دیگر، و مدل نمی‌تواند آن‌ها را به یک داستان منسجم متصل کند. قبل از اینکه هوش مصنوعی بتواند در مشاهده سیستم‌های شما کمک کند، خودتان باید آن‌ها را مشاهده کنید. ابتدا باید داده‌ها را شکل دهید.

چرا لاگ‌های خام خط لوله‌های هوش مصنوعی را از کار می‌اندازند

سیستم‌های مدرن تلمتری (telemetry) را با سرعتی تولید می‌کنند که هیچ انسانی قادر به خواندن آن نیست. این موضوع باید آن‌ها را برای هوش مصنوعی ایده‌آل کند، اما این‌طور نیست. پنجره بافت (context window) یک مدل زبانی بزرگ، با وجود بزرگ‌تر شدن، همچنان یک لوله محدود است. اگر آن را با لاگ‌های خامِ محیط عملیاتی پر کنید، توکن‌ها را صرف نویزهای مربوط به ضربان‌های (heartbeats) کارهای cron و بررسی‌های سلامت (health-check) می‌کنید، در حالی که حادثه اصلی را زیر انبوه داده‌ها دفن کرده‌اید. بدتر از آن، لاگ‌های خام فاقد روابط هستند. یک جهش در تأخیر (latency) در ساعت ۲:۰۰ بعد از ظهر و یک خطای اتصال پایگاه داده در لاگی با همان برچسب زمانی، آشکارا با هم مرتبط هستند، اما مگر اینکه کسی از قبل آن رابطه را ساختاریافته باشد، هوش مصنوعی مجبور است حدس بزند. حدس زدن گران، کند و اغلب اشتباه است.

راه حل، معماری است، نه الگوریتمی. قبل از اینکه بخواهید به یک مدل دستور (prompt) بدهید، باید تصمیم بگیرید چه چیزی جمع‌آوری شود، چگونه شکل داده شود و کدام بخش از بک‌اند (backend) به کدام سوال پاسخ می‌دهد.

چهار محور پایش (Monitoring)

در airCloset، تیم مهندسی از برخورد با مشاهده‌پذیری (observability) به عنوان یک شلنگ آب پرفشار (firehose) واحد خودداری کرد. آن‌ها پایش را به چهار محور متمایز تقسیم کردند. هر کدام شکل خاص خود را دارند و به سوال مشخصی پاسخ می‌دهند.

  • اپلیکیشن (Application): لاگ‌ها و ردپاها (traces) پاسخ می‌دهند به «همین الان چه اتفاقی در حال رخ دادن است؟»
  • زیرساخت (Infrastructure): متریک‌ها پاسخ می‌دهند به «آیا منابع کافی داریم؟»
  • CI: لاگ‌ها و هشدارها پاسخ می‌دهند به «چه چیزی و چه زمانی خراب شد؟»
  • LLM: متریک‌ها و سوابق ساختاریافته پاسخ می‌دهند به «چقدر هزینه می‌کنیم؟»

این جداسازی اهمیت دارد، زیرا شکل مناسب برای یک نمودار تأخیر (latency) در لحظه، برای تحلیل هزینه پس از وقوع (post-hoc) بی‌فایده است. تحمیل یک طرحواره (schema) واحد برای هر چهار حوزه، دقیقاً همان نوع نویزی را ایجاد می‌کند که کمک هوش مصنوعی را بی‌اثر می‌سازد.

مشاهده‌پذیری CI: کشیدن، نه هل دادن (Pull, Don’t Push)

یکپارچه‌سازی مداوم (CI) جایی است که کد با واقعیت روبرو می‌شود. وقتی یک Build شکست می‌خورد، توسعه‌دهندگان نیاز دارند داستان را سریع بدانند. رویکرد ساده‌لوحانه این است که runnerِ مربوط به CI، لاگ‌ها را همان‌طور که در حال اجراست، مستقیماً به بک‌اندِ مشاهده‌پذیری شما ارسال (push) کند. این کار کارآمد به نظر می‌رسد، اما در واقع خطرناک است.

در airCloset، آن‌ها این مدل را معکوس کردند. runnerِ مربوط به CI به پشته (stack) مشاهده‌پذیری دست نمی‌زند. پس از پایان گردش کار (workflow) در GitHub Actions، آن‌ها لاگ‌ها را از طریق GitHub API می‌کشند (pull) و آن‌ها را در Loki وارد می‌کنند.

این معماریِ مبتنی بر کشیدن (pull architecture)، سه مزیت ملموس دارد.

جداسازی (Decoupling). اگر خط لوله ورود داده (ingestion pipeline) دچار مشکل شود یا Grafana در دسترس نباشد، خودِ فرآیند تست بدون تغییر باقی می‌ماند. Build بر اساس شایستگی خودش موفق یا شکست می‌خورد. شکست در بخش مشاهده‌پذیری هرگز نباید باعث توقف استقرار (deployment) شود.

امنیت (Security). گردش کار CI هرگز نیازی به کلید API مربوط به Grafana ندارد. کدهای تست به دستکاری اسرار (secrets) که نباید، شهرت دارند و حذف این مواجهه، در صورت آسیب‌پذیری یک وابستگی (dependency)، شعاع انفجار (blast radius) را کاهش می‌دهد.

پرس‌وجوی متقاطع (Cross-querying). زمانی که CI