عن المشروع

vitals هو مراقب نظام لأجهزة Apple Silicon Macs التي تعمل بنظام macOS 14 أو الإصدارات الأحدث. يقوم ملف Rust ثنائي واحد بأخذ عينات من وحدة المعالجة المركزية (CPU)، ووحدة معالجة الرسوميات (GPU)، والذاكرة، والطاقة، والحالة الحرارية داخل العملية نفسها: فهو لا يلجأ إلى powermetrics، ولا يتطلب صلاحيات sudo، ولا يشغل أي عمليات فرعية من أي نوع. المخرجات تكون بتنسيق JSON مهيكل يمكن للسكربت أو العميل أو الشخص قراءته مباشرة. كما أن الملف الثنائي نفسه، عند تشغيله بدون وسائط، يعمل كعنصر في شريط القوائم (menu bar tray) مع لوحة تحكم محلية اختيارية. أوامر سطر الأوامر يقوم الأمر snapshot بطباعة عينة كاملة من SoC: شريحة المضيف وعدد النوى، واستخدام CPU على مستوى النظام، ومدخلات لكل نواة مع نوع النواة (كفاءة أو أداء)، والتردد والاستخدام، واستخدام وتردد GPU، وإجمالي واستخدام الذاكرة والتبديل (swap)، وضغط ذاكرة النواة (kernel memory pressure)، وأرقام الطاقة لـ CPU و GPU و ANE و RAM والنظام، ودرجات حرارة CPU و GPU، وسرعات المراوح مع الحد الأقصى، ومتوسطات الحمل، ووقت التشغيل والحالة الحرارية. يغير خيار الفاصل الزمني (interval) نافذة أخذ العينات التي يتم من خلالها دمج استهلاك CPU و GPU والطاقة. يقوم الأمر top بترتيب العمليات حسب CPU وحسب الذاكرة، بشكل مستقل ومع عدد صفوف قابل للتكوين، لذا قد تظهر العملية نفسها في كلتا القائمتين. نسبة CPU تكون لكل عملية بدلاً من أن تكون على مستوى النظام، ويمكن أن تتجاوز 100% في حالة العمل على نوى متعددة، تماماً مثل ps. يعيد الأمر pressure حكماً بدلاً من الأرقام الخام: حالة، وعلامة توضح ما إذا كان هناك سجل متاح للاستخدام، وقائمة بالأسباب مع الرموز والشدة، وقائمة بالعمليات المشبوهة مع سبب تحديد كل منها، وملخص من سطر واحد. وبحسب التصميم، يخرج الأمر بالقيمة صفر عند الإبلاغ عن حالة سيئة، لأن الإبلاغ في حد ذاته ليس فشلاً. تقوم علامة رمز الخروج (exit-code flag) بدمج شدة الحكم في الحالة بدلاً من ذلك (0 اسمي، 3 تحذير، 4 حرج)، بينما يخرج فشل وقت التشغيل بالقيمة 1 والاستدعاء غير الصحيح بالقيمة 2. الأمر watch هو الأمر الوحيد الذي لا يخرج من تلقاء نفسه. فهو يصدر كائن JSON مضغوطاً واحداً لكل سطر، ويتم تفريغه بعد كل سطر، ويستمر في العمل حتى يتم مقاطعته أو حتى يتم إصدار عدد العينات المطلوب. يحدد الفاصل الزمني كلاً من الإيقاع ونافذة أخذ العينات. ولأن المخرجات يتم تفريغها لكل سطر، فإن المستهلك الذي يقرأ سطراً واحداً ويغلق الأنبوب (pipe) يحصل على خروج نظيف. المخرجات دائماً تكون JSON محددة بسطر جديد وترفض علامة JSON. تنسيق JSON هو الافتراضي لأوامر snapshot و top و pressure؛ ويقبل كل منها أيضاً صيغة نصية قابلة للقراءة من قبل البشر لمحطات الطرفية (terminals)، وتُقبل علامة JSON كعملية لا تؤدي إلى تغيير (no-op). تحمل كل استجابة إصدار المخطط (schema version). توجد الوحدات في أسماء المفاتيح (الذاكرة بالميجابايت MB، الطاقة بالواط watts، درجات الحرارة بالدرجة المئوية Celsius) بدلاً من حقول منفصلة، ويتم حذف الحقول الاختيارية الغائبة بدلاً من إصدارها كقيم null. تطبيق شريط القوائم ولوحة التحكم عند تشغيله بدون وسائط، يكون vitals عبارة عن أيقونة في شريط القوائم مع نص مباشر وقائمة منسدلة مخصصة تغطي CPU (رسم بياني خطي sparkline بالإضافة إلى شريط واحد لكل نواة، مع تلوين نوى الكفاءة والأداء بشكل مختلف)، و GPU، والذاكرة التي يتم تقييمها بواسطة إشارة ضغط النواة، والطاقة. تتغير ألوان القيم الرئيسية عند الوصول إلى عتبات معينة، ولا يتم إعادة رسم أي شيء أثناء إغلاق القائمة المنسدلة، وينخفض إيقاع أخذ العينات أثناء نوم الشاشة. يعرف التطبيق نفسه كملحق (accessory)، لذا ليس له أيقونة في Dock ولا إدخال في مبدل التطبيقات حتى يتم طلب نافذة. يمكن فتح لوحة التحكم من القائمة المنسدلة أو عن طريق إعادة فتح التطبيق الذي يعمل، وتفتح في نافذة أصلية مدعومة بـ web view، كعملية مستقلة. وأثناء فتحها، يكون لها بلاطة في Dock وقائمة تطبيقات؛ وعند إغلاقها، تخرج تلك العملية، مما يحافظ على لوحة التحكم المغلقة بتكلفة صفرية. إذا توقف التطبيق في شريط القوائم أو تعطل، تلاحظ النافذة ذلك عبر مراقبة واصف الملف (file-descriptor watch) وتخرج فوراً. يعمل خادم HTTP داخل عملية شريط القوائم ويبدأ عند الطلب، لذا فإن التطبيق الذي لم يُطلب منه فتح لوحة التحكم ليس لديه مستمع (listener) ولا جامع عينات ثانٍ. تم بناء صفحة لوحة التحكم ليتم قراءتها من الأعلى إلى الأسفل: نفس الحكم الذي ينتجه أمر pressure، وأربعة مربعات لـ CPU و GPU والذاكرة والطاقة مع رقم رئيسي، ونقطة حالة، وسطر سياق واتجاه، وعنصر تحكم في النطاق لـ 2 أو 5 أو 15 دقيقة يحدد نطاق كل ما تحته، ومخططات CPU و GPU بمرور الوقت مع مؤشر تقاطع وتلميح أداة (tooltip)، وشريط واحد لكل نواة محدد بموقعه مع سرعة الساعة عند تمرير الماوس، ومقاييس الذاكرة والتبديل التي يتبع ملؤها إشارة ضغط النواة، وأهم العمليات مع أشرطة مدمجة. يحتوي كل مخطط على زر تبديل بين المخطط أو الجدول لنفس البيانات، ويتوقف الاستطلاع عندما تكون الصفحة مخفية، ويبقى آخر عرض جيد على الشاشة بشكل باهت إذا توقف الخادم، ويتبع المظهر الفاتح أو الداكن إعدادات النظام. التثبيت والتغليف هناك مساران مستقلان للتثبيت ينتهيان بوجود vitals في PATH. عملية البناء المتبوعة بالتثبيت تقوم بإنشاء رابط رمزي (symlink) للملف الثنائي للإصدار في دليل bin التمهيدي (يمكن تجاوز التمهيد لتجنب sudo، وهناك هدف إلغاء التثبيت لإزالة الرابط الرمزي). أما مسار تثبيت التطبيق فيقوم بالبناء، والتغليف، ونسخ التطبيق إلى مجلد Applications، وتثبيت وكيل تشغيل (launch agent) لكل مستخدم بحيث يبدأ التطبيق في شريط القوائم عند كل تسجيل دخول، ويعيد توجيه نفس الرابط الرمزي إلى نسخة الحزمة؛ ويقوم هدف إلغاء التثبيت المطابق بعكس كل ذلك. الحزمة موقعة بشكل مؤقت (ad-hoc signed) بدلاً من توثيقها (notarized)، وهو أمر كافٍ لتنفيذ وكيل التشغيل؛ قد يتطلب فتح التطبيق عبر Finder النقر بزر الماوس الأيمن على "فتح" لمرة واحدة أو الموافقة في إعدادات النظام. التطوير توجد أهداف make لعمليات البناء، والاختبار، و clippy (مع اعتبار التحذيرات أخطاء)، والتنسيق. لوحة التحكم هي تطبيق Vite و React يتم دمج مخرجات بناء الإنتاج الخاصة به في الملف الثنائي وقت التجميع، لذا يجب إعادة بناء الملف الثنائي بعد تعديل الصفحة. يقوم خادم التطوير مع التحديث المباشر (hot reload) بتوجيه طلبات API إلى المنفذ المحلي، لذا فهو يعمل مع أي نسخة تعمل، بما في ذلك النسخة الموجودة داخل شريط القوائم. تتم المساهمة من خلال تقارير الأخطاء، والقياسات، وطلبات السحب (pull requests)، مع قناة منفصلة للثغرات الأمنية. المشروع مرخص بموجب رخصة MIT.