مدخل إلى سجلّ أحداث Windows وETW ── وضع سجلّات تطبيق الأعمال على آليّة نظام التشغيل القياسيّة
· آخر تحديث: · غو كومورا · CSharp, .NET, سجل الأحداث, ETW, EventSource, تصميم السجلّات, تحقيق الأعطال, تطوير Windows
عند تطوير تطبيقات أعمال أو خدمات Windows بلغة C#، غالباً ما تُخرَج السجلّات اليوميّة عبر مسجِّل ملفّات ذاتيّ الصنع أو مكتبة مثل Serilog وNLog. فهل يعني ذلك أنّ سجلّ أحداث Windows وETW (Event Tracing for Windows) لم يعودا ضروريّين؟ ليس كذلك. فهاتان الوسيلتان ليستا «بديلاً لسجلّ الملفّات»، بل سجلّ طبقة مختلفة يراه القائمون على التشغيل وأدوات نظام التشغيل القياسيّة.
في هذا المقال، نرتّب كيفيّة التمييز بين سجلّ الملفّات وسجلّ الأحداث وETW، وطرق تنفيذها في .NET، وأدنى ما يلزم فهمه عن ETW، والممارسة العمليّة للتجميع والتحقيق، وحتّى المطبّات التي يقع فيها العمل الفعليّ كثيراً.
1. الخلاصة أوّلاً
- الوسائل الثلاث ليست بديلة لبعضها، بل تقسيم أدوار. سجلّ الملفّات هو سجلّ يتتبّع فيه المطوِّر التفاصيل لاحقاً، وسجلّ الأحداث سجلّ يلاحظ به القائمون على التشغيل وعارض الأحداث القياسيّ وأدوات المراقبة الحالات الشاذّة، وETW تتبّع عالي التردّد يُفعَّل عند الطلب لتحقيقات الأداء والأعطال يصعب إعادة إنتاجها. الأساس هو الجمع بينها، مع تغيير كمّيّة المعلومات المكتوبة في كلّ منها.
- اكتب في سجلّ الأحداث فقط «التشغيل والإيقاف والأخطاء الفادحة». إن دفقتَ كلّ السجلّات إلى سجلّ الأحداث أيضاً، تُدفَن الحالات الشاذّة التي ينبغي أن يراها القائمون على التشغيل فعلاً. اجعل سجلّ الملفّات مفصَّلاً كما كان، وضيِّق نطاق سجلّ الأحداث.
- تسجيل مصدر الحدث (event source) يتطلّب صلاحيّة المسؤول. لا يمكن استدعاء
EventLog.CreateEventSourceمنذ Windows Vista فما بعد إلا بصلاحيّة المسؤول. تجنَّب تصميماً يحاول التسجيل عند أوّل وصول وقت التشغيل، وسجِّله مسبقاً عبر برنامج التثبيت.1 - ETW ليس «تجميعاً دائماً». حتّى لو عرَّفتَ أحداثاً عبر
EventSource، لن يُسجَّل شيء ما لم يكن هناك مشترِك (dotnet-trace، PerfView، أدوات قائمة على ETW). الاستخدام الأساسيّ هو التجميع فقط عند تحليل الأداء أو التحقيق في عطل معيّن، بتحديد المزوِّد (provider) المستهدَف.2 - اكتب الرسائل بصيغة قالب (template)، لا بتسلسل النصوص أو الاستيفاء (interpolation). فإذا كُتب
logger.LogInformation("Order {OrderId} failed", orderId)، يمكن البحث عن OrderId كسجلّ مهيكل مع اسم عنصر نائب (placeholder). أمّا التسلسل أو الاستيفاء فيفقدان هذه المعلومات البنيويّة.3 - تضخّم السجلّات غالباً ما يعود إلى صغر القيمة الافتراضيّة. الحدّ الأقصى الافتراضيّ لسجلّ الأحداث هو 512 كيلوبايت فقط، فإن استخدم التطبيق سجلّ الأحداث يوميّاً، وسِّعه صراحةً، وحدِّد أيضاً وقت التصميم سلوك الوصول إلى الحدّ الأقصى (سواء بالكتابة فوق القديم أو تجاهله).4
فيما يلي جدول القرار.
| المحور | سجلّ الملفّات | سجلّ الأحداث | ETW |
|---|---|---|---|
| القارئ الرئيسيّ | المطوِّر/المسؤول عن الصيانة | القائمون على التشغيل، أدوات المراقبة، عارض الأحداث القياسيّ في نظام التشغيل | المسؤولون عن تحقيقات الأداء، مهندسو الدعم الفنّيّ |
| مقدار الإخراج التقريبيّ | مفصَّل (يمكن أن يشمل Trace/Debug) | قليل (التشغيل والإيقاف والأخطاء الفادحة فقط) | كبير فقط عند التفعيل. لا يُسجَّل شيء بالإعداد الافتراضيّ |
| العمر/الاحتفاظ | سهل الاحتفاظ به طويلاً حسب إعداد التدوير (rotation) | يُكتَب فوق الأقدم أو يُتخلَّص منه عند بلوغ حدّ حجم السجلّ | لكلّ جلسة. يُحفَظ كملفّ .etl/.nettrace بعد انتهاء التجميع |
| التكامل مع أدوات نظام التشغيل القياسيّة | لا يوجد (يلزم عارض ذاتيّ الصنع) | يُرى بشكل قياسيّ عبر عارض الأحداث وwevtutil وGet-WinEvent | يُرى بـdotnet-trace وPerfView وWPR/WPA |
| الصلاحيّات | صلاحيّة كتابة مستخدم تشغيل التطبيق فقط | تسجيل المصدر يتطلّب صلاحيّة مسؤول (الكتابة نفسها ممكنة لمستخدم قياسيّ إن كان المصدر مسجَّلاً) | غالباً ما يتطلّب بدء التجميع صلاحيّة مسؤول |
2. أساسيّات سجلّ أحداث Windows
يملك Windows افتراضيّاً ثلاثة سجلّات هي Application وSystem وSecurity، وSecurity للقراءة فقط. تكتب تطبيقات وخدمات الأعمال إلى سجلّ Application، أو إلى سجلّ مخصَّص (قناة) خاصّ بالتطبيق. أمّا برامج تشغيل الأجهزة فمن المعتاد أن تكتب إلى سجلّ System.5
وحدة الكتابة هي «مصدر الحدث (event source)». المصدر اسم يميِّز التطبيق، ويُسجَّل مسبقاً عبر EventLog.CreateEventSource. منذ Windows Vista، يتطلّب تسجيل المصدر صلاحيّة المسؤول. والسبب أنّه يلزم البحث في جميع سجلّات الأحداث بما فيها سجلّ Security للتحقّق من فرادة اسم المصدر، والمستخدم القياسيّ لا يملك صلاحيّة الوصول إلى سجلّ Security.1
using System.Diagnostics;
// نفِّذه أثناء برنامج التثبيت أو الإعداد، حين تتوفّر صلاحيّة المسؤول
const string SourceName = "KomuraSoft.OrderService";
const string LogName = "Application";
if (!EventLog.SourceExists(SourceName))
{
EventLog.CreateEventSource(SourceName, LogName);
}
إن حاولتَ إنشاء المصدر عند أوّل وصول في وقت التشغيل، سيفشل هذا الاستدعاء في تشغيلات يعمل فيها التطبيق بمستخدم قياسيّ. النظرة العامّة حول متى تلزم صلاحيّة المسؤول مرتَّبة في «متى تلزم صلاحيّة المسؤول في Windows»، وتسجيل مصدر الحدث هو بالضبط نفس هذا النمط، والتصميم الآمن هو التسجيل عبر برنامج التثبيت، بحيث يكتفي التطبيق نفسه بالكتابة إلى مصدر مسجَّل مسبقاً.
يُلحَق بكلّ حدث نوعان من معلومات التمييز: «المستوى (level)» و«معرِّف الحدث (event ID)». المستوى هو EventLogEntryType (Information وWarning وError وSuccessAudit وFailureAudit)، ويُستخدَم في أيقونات عارض الأحداث والفلاتر الافتراضيّة. أمّا معرِّف الحدث فرقم صحيح يحدِّده التطبيق، ويصبح مفتاحاً للبحث والتجميع لاحقاً حول نفس نوع الحدث.
3. الكتابة إلى سجلّ الأحداث من .NET
يوجد مساران رئيسيّان للكتابة إلى سجلّ الأحداث من .NET.
3.1 استخدام System.Diagnostics.EventLog مباشرةً
واجهة برمجيّة منخفضة المستوى، تناسب الحالات التي تحتاج تحكّماً دقيقاً (كالفئة (category) وإرفاق بيانات ثنائيّة). في .NET (غير .NET Framework) يلزم الرجوع إلى حزمة NuGet باسم System.Diagnostics.EventLog.
using System.Diagnostics;
public sealed class OrderServiceEventLog
{
private const string SourceName = "KomuraSoft.OrderService";
public void WriteServiceStarted()
{
EventLog.WriteEntry(SourceName, "تمّ تشغيل OrderService.",
EventLogEntryType.Information, eventID: 1000);
}
public void WriteFatalError(Exception ex)
{
EventLog.WriteEntry(SourceName,
$"حدث خطأ فادح ولا يمكن متابعة المعالجة. راجع سجلّ الملفّات للاطّلاع على التفاصيل. {ex.GetType().Name}: {ex.Message}",
EventLogEntryType.Error, eventID: 1999);
}
}
3.2 استخدام ILogger + AddEventLog
إن كنتَ قد بنيتَ سجلّاً مهيكلاً عبر ILogger بالفعل، فاستخدام AddEventLog من حزمة Microsoft.Extensions.Logging.EventLog يناسب خطّ أنابيب التسجيل القائم بسلاسة أكبر. في ASP.NET Core وWorker Service المبنيّة على Generic Host، يكون مزوِّد EventLog مُفعَّلاً افتراضيّاً عند التشغيل على Windows.6
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.EventLog;
HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);
builder.Logging.AddEventLog(settings =>
{
settings.SourceName = "KomuraSoft.OrderService";
settings.LogName = "Application";
// إضافةً إلى فلتر الفئة الافتراضيّ، مرِّر إلى سجلّ الأحداث
// فقط ما هو من مستوى Warning فأعلى (اترك التفاصيل لسجلّ الملفّات)
settings.Filter = (_, level) => level >= LogLevel.Warning;
});
using IHost host = builder.Build();
await host.RunAsync();
عند إغفال EventLogSettings، يكون LogName افتراضيّاً "Application"، ويكون SourceName افتراضيّاً ".NET Runtime".7 وإن بقيتَ على اسم مصدر عامّ كـ.NET Runtime، يصعب التمييز في عارض الأحداث بين سجلّ تطبيقك وسجلّ تطبيق .NET آخر، لذا حدِّد SourceName دائماً باسم مخصَّص لتطبيقك.
في خدمات Windows أو معالجة الدفعات (batch) التي تعمل عبر جدولة المهام، فإنّ كتابة «التشغيل» و«الإيقاف» و«الأخطاء الفادحة» فقط إلى سجلّ الأحداث، وترك التفاصيل الأخرى لسجلّ الملفّات، هو التوازن العمليّ المعتمَد. طريقة بناء الخدمة وتشغيلها مشروحة في «كيفيّة بناء خدمات Windows وتشغيلها»، ومشكلات التنفيذ عبر جدولة المهام في «مهام جدولة المهام لا تُنفَّذ وتنتهي بـ0x1». وفي كلتا الحالتين، غالباً ما يكون سجلّ الأحداث هو أوّل ما يراه القائم على التشغيل عند حدوث شذوذ، ووجود النقاط الجوهريّة فيه من عدمه يغيِّر سرعة التحقيق الأوّليّ.
4. ما هو ETW ── بنية تتبّع تخترق نظام التشغيل بأكمله
Event Tracing for Windows (ETW) آليّة تتبّع تتيح القياس (instrumentation) بأساس مشترَك بدءاً من النواة وصولاً إلى تطبيقات وضع المستخدم. أبرز ميزاتها هي إمكانيّة تسجيل وتحليل أحداث النواة (مثل إدخال/إخراج القرص وإنشاء العمليّات) وأحداث التطبيق الخاصّة معاً على نفس الخطّ الزمنيّ.8
في .NET، يمكن تعريف مزوِّد ETW خاصّ بإنشاء فئة ترث من System.Diagnostics.Tracing.EventSource. يعمل ETW بنمط النشر والاشتراك (publish-subscribe)، فإن لم يوجد مشترِك لا يُسجَّل أيّ حدث. أي أنّ مجرّد تنفيذ EventSource لا يُحدِث شيئاً، ولا تُسجَّل الأحداث إلا بعد تفعيلها صراحةً بأداة تجميع.2
using System.Diagnostics.Tracing;
[EventSource(Name = "KomuraSoft-OrderService")]
internal sealed class OrderServiceEventSource : EventSource
{
public static readonly OrderServiceEventSource Log = new();
[Event(1, Level = EventLevel.Informational, Message = "بدأت معالجة الطلب. OrderId={0}")]
public void OrderProcessingStart(string orderId)
{
if (IsEnabled())
{
WriteEvent(1, orderId);
}
}
[Event(2, Level = EventLevel.Informational, Message = "اكتملت معالجة الطلب. OrderId={0}")]
public void OrderProcessingStop(string orderId)
{
if (IsEnabled())
{
WriteEvent(2, orderId);
}
}
}
يستخدمه طرف الاستدعاء كما يلي. التحقّق عبر IsEnabled() قبل كتابة الحدث فعليّاً يتجنَّب التكلفة الزائدة حين لا يكون التجميع فعّالاً.
OrderServiceEventSource.Log.OrderProcessingStart(order.Id);
try
{
ProcessOrder(order);
}
finally
{
OrderServiceEventSource.Log.OrderProcessingStop(order.Id);
}
أسهل طريقة لتجميع هذا الحدث هي استخدام أداة dotnet-trace العابرة للمنصّات.9
dotnet-trace collect --providers KomuraSoft-OrderService -- OrderService.exe
يُفتَح ملفّ .nettrace المُجمَّع في Visual Studio أو PerfView للتحقّق من محتواه. أمّا لتحليل أداء أكثر جدّيّة، كتحليل يشمل أحداث النواة، فيُستخدَم Windows Performance Recorder (WPR) الموجود ضمن Windows Assessment and Deployment Kit (ADK)، ويُرى الناتج عبر Windows Performance Analyzer (WPA).10 غير أنّ نطاق هذا المقال يقتصر على «ما الذي يمكن فعله بـETW ومتى يُستخدَم»، ولا يتطرّق إلى خطوات التحليل التفصيليّة في PerfView أو WPA. من زاوية تطوير تطبيقات الأعمال وصيانتها، يكفي إتقان تعريف المزوِّد الخاصّ بك عبر EventSource وتجميعه عبر dotnet-trace.
5. الممارسة العمليّة للسجلّ المهيكل
تُكتَب قوالب رسائل ILogger كسلسلة نصّيّة ثابتة تتضمّن عناصر نائبة مُسمّاة على شكل {PlaceHolder}. هذا ليس مجرّد أسلوب شكليّ، بل يعني أنّه بترك القالب نفسه دون تغيير وتمرير الوسائط فقط، تستطيع بنية السجلّ الاحتفاظ بالعلاقة بين اسم العنصر النائب والقيمة (البيانات المهيكلة).11
// موصى به: القالب ثابت، والوسائط تُمرَّر منفصلة
logger.LogWarning("فشل حجز المخزون للطلب {OrderId}. المستودع={WarehouseId}", orderId, warehouseId);
// غير موصى به: التسلسل والاستيفاء يكسران العلاقة بين القالب والقيمة
logger.LogWarning("فشل حجز المخزون للطلب " + orderId + ". المستودع=" + warehouseId);
logger.LogWarning($"فشل حجز المخزون للطلب {orderId}. المستودع={warehouseId}");
قاعدة أداة التحليل الساكن CA2254 تكتشف هذا النمط غير المستحسَن (الكتابة التي يتغيّر فيها القالب في كلّ استدعاء).3 وفي المسارات الساخنة ذات التردّد العالي، استخدام LoggerMessageAttribute عبر التوليد المصدريّ (source generation) يتجنَّب أيضاً تكلفة التغليف (boxing) وتحليل القالب.12
using Microsoft.Extensions.Logging;
internal static partial class Log
{
[LoggerMessage(
EventId = 2001,
Level = LogLevel.Warning,
Message = "فشل حجز المخزون للطلب {OrderId}. المستودع={WarehouseId}")]
public static partial void StockReservationFailed(
this ILogger logger, string orderId, string warehouseId);
}
// من جانب الاستدعاء
logger.StockReservationFailed(orderId, warehouseId);
بهذا التكوين، يمكن من نفس استدعاء السجلّ توزيع التفاصيل إلى سجلّ الملفّات (وجهات مثل Serilog/NLog)، والمحتوى المُضيَّق إلى سجلّ الأحداث، والتتبّع منخفض الكلفة إلى ETW عبر EventSourceLoggerProvider، لكلّ منها على حدة. الشكل الأساسيّ هو تسجيل عدّة ILoggerProvider وتغيير مستوى الإخراج لكلّ مزوِّد عبر Filter. الحدّ الأدنى لمتطلّبات المسجِّل الذاتيّ مشروح في «الحدّ الأدنى لمتطلّبات المسجِّل الذاتيّ وقائمة تحقّق الاختبار التكامليّ»، وكيفيّة ربط السجلّات بملفّات تفريغ الذاكرة (dump) عند الانهيار في «تصميم الاحتفاظ بالسجلّات والتفريغ عند انهيار تطبيق Windows».
6. التجميع والتحقيق ── حديث عن قراءة ما كُتب
في عارض الأحداث، يمكن استخدام «الفلتر» أو «العرض المخصَّص (custom view)» لاستخراج مصدر أو مستوى أو معرِّف حدث معيّن فقط من قائمة السجلّات. إذا حفظتَ الشروط التي تستخدمها كثيراً كعرض مخصَّص، يصبح التحقيق التالي أسرع. تُعرَّف العروض المخصَّصة باستعلامات XPath، فمثلاً يأخذ استعلام يستخرج اسم حدث معيّن فقط الشكل التالي.13
<QueryList>
<Query Id="0" Path="Application">
<Select Path="Application">
*[System[Provider[@Name='KomuraSoft.OrderService'] and (Level=2 or Level=3)]]
</Select>
</Query>
</QueryList>
من سطر الأوامر، يمكن استخدام wevtutil لتصدير السجلّ وتغيير إعداداته. يمكن أيضاً استخدامه ضمن إجراءات التحقيق في الأعطال، بتصدير سجلّ الأحداث قبل وبعد لحظة وقوع الحادثة وإرساله إلى الدعم الفنّيّ.14
:: تصدير سجلّ Application بأكمله إلى ملفّ evtx
wevtutil epl Application C:\logs\application_20260707.evtx
:: عرض أحداث مصدر معيّن فقط (آخر 10 أحداث)
wevtutil qe Application /q:"*[System[Provider[@Name='KomuraSoft.OrderService']]]" /c:10 /rd:true /f:text
الأساس في تحقيقات الانهيار هو مضاهاة سجلّ الأحداث وسجلّ الملفّات وملفّ تفريغ الانهيار (crash dump) الثلاثة بالتوقيت. انطلاقاً من الطابع الزمنيّ لـ«خطأ فادح» المتبقّي في سجلّ الأحداث، تُقارَن تفاصيل سجلّ الملفّات في نفس التوقيت مع الملفّ الذي جُمِع عبر WER/ProcDump. طريقة جمع الملفّات مشروحة في «مدخل إلى جمع ملفّات تفريغ انهيار Windows - WER/ProcDump/WinDbg»، وخطوات التحليل الفعليّة للملفّ المجموع في «قراءة ملفّات تفريغ الانهيار عبر WinDbg + SOS».
7. المطبّات
- محاولة الكتابة دون تسجيل المصدر فتفشل. إذا كُتب باسم مصدر غير مسجَّل بما يعادل استدعاء
RegisterEventSource، يُكتَب الحدث نفسه إلى سجلّ Application، لكن بسبب عدم وجود مكتبة موارد الرسائل (message resource DLL) المقابلة، يعجز عارض الأحداث عن عرض نصّ الوصف ويظهر كخطأ.15 والأدهى أنّ التصميم الذي يحاول التسجيل الذاتيّ عبرCreateEventSourceوقت التشغيل يتسبّب غالباً بحادثة سقوط بالاستثناء عند أوّل تشغيل لعمليّة تعمل بمستخدم غير مسؤول. أنجِز تسجيل المصدر دائماً عبر برنامج التثبيت. - ارتباك «يمكن الكتابة باسم مصدر آخر». يمكن لسجلّ الأحداث أن يُكتَب باسم مصدر آخر لم يسجّله التطبيق نفسه إطلاقاً، طالما توفّرت صلاحيّة الكتابة. يلزم أن يكون اسم المصدر فريداً على الحاسوب، لكن لا توجد آليّة في نظام التشغيل تفرض ذلك، والأمر متروك لانضباط التطبيق نفسه.5 اختيار اسم مصدر عامّ جدّاً (اسم قصير لا يتضمّن اسم الشركة أو المنتج) قد يتسبّب بتصادم مع تطبيقات موردين آخرين، أو باستخدام اسم مصدر تطبيق آخر دون قصد.
- تضخّم السجلّ وسياسة الاحتفاظ. الحدّ الأقصى الافتراضيّ لسجلّ الأحداث لا يتجاوز 512 كيلوبايت.4 إن استخدم تطبيق أعمال سجلّ الأحداث يوميّاً، وسِّع الحجم صراحةً عبر
wevtutil slأو برنامج التثبيت، وحدِّد بوعي، عند بلوغ الحدّ الأقصى، هل «يُكتَب فوق الأقدم» أم «يُتخلَّص من الجديد». يجدر الانتباه أيضاً إلى أنّOverwriteOlderأصبح مُهمَلاً (deprecated)، وقد يؤول تحديده فعليّاً إلى سلوك «لا يُكتَب فوقه».16 - عرض الرسائل في البيئات متعدّدة اللغات. إذا اعتُمد تكوين يستخدم ملفّ موارد رسائل مترجَم (
MessageResourceFile)، فعرض السجلّ في بيئة لا تتوفّر فيها مكتبة الموارد تلك أو تختلف نسختها يظهر كـ«تعذّر العثور على وصف معرِّف الحدث كذا». هذه مشكلة تحدث كثيراً عند عرض سجلّ أحداث مُوجَّه (forwarded) على خادم آخر، أو عند بقاء السجلّ وحده بعد إزالة تثبيت التطبيق. أمّا التكوين الذي يكتب النصّ مباشرةً عبرWriteEntry(دون استخدام ملفّ موارد) فيتجنَّب هذا النوع من المشكلات من أساسه. - حالة تعذّر الكتابة بسبب نقص الصلاحيّات. يُساء فهم هذا كثيراً، لكن بينما يتطلّب تسجيل المصدر صلاحيّة المسؤول، فإنّ الكتابة إلى مصدر مسجَّل بالفعل ممكنة حتّى بمستخدم قياسيّ. قبل أن تستعجل بجعل التطبيق كلّه يعمل بصلاحيّات المسؤول لمجرّد افتراض «لا يعمل بدون صلاحيّة المسؤول»، ميِّز فعليّاً أيّ عمليّة هي التي تحتاج الصلاحيّة.
مقالات ذات صلة
- متى تلزم صلاحيّة المسؤول في Windows - UAC والمناطق المحميّة وطرق التمييز في التصميم
- كيفيّة بناء خدمات Windows وتشغيلها ── من التمييز عن جدولة المهام إلى تحويل BackgroundService إلى خدمة
- مهام جدولة المهام لا تُنفَّذ وتنتهي بـ0x1 ── تمييز السبب وتصميم تشغيل آمن
- الحدّ الأدنى لمتطلّبات المسجِّل الذاتيّ وقائمة تحقّق الاختبار التكامليّ
- تصميم الاحتفاظ بالسجلّات والتفريغ عند انهيار تطبيق Windows
- مدخل إلى جمع ملفّات تفريغ انهيار Windows - WER/ProcDump/WinDbg
- قراءة ملفّات تفريغ الانهيار عبر WinDbg + SOS ── مدخل إلى التحليل العمليّ بعد الجمع
مجالات الاستشارة ذات الصلة
تتعامل شركة Komura Soft LLC مع الاستشارات التقنيّة لتصميم بنية السجلّات وسجلّ الأحداث وETW في تطبيقات أعمال Windows، وتصميم نقاط المراقبة (observability) بهدف التحقيق في الأعطال.
- تطوير تطبيقات Windows
- التحقيق في الأعطال وتحليل الأسباب
- الاستشارة التقنيّة ومراجعة التصميم
- التواصل معنا
المراجع
-
Microsoft Learn, EventLog.CreateEventSource Method. عن سبب حاجة إنشاء مصدر الحدث إلى صلاحيّة المسؤول منذ Windows Vista فما بعد (لضرورة البحث في كلّ السجلّات بما فيها سجلّ Security). ↩ ↩2
-
Microsoft Learn, Getting Started with EventSource. عن عمل EventSource بنمط النشر والاشتراك، وعدم تسجيل الأحداث دون مشترِك (ETW أو EventPipe)، وطريقة التجميع عبر dotnet-trace collect. ↩ ↩2
-
Microsoft Learn, CA2254: Template should be a static expression. عن فقدان العلاقة بين اسم العنصر النائب والقيمة عند استخدام تسلسل النصوص أو الاستيفاء في قالب رسالة السجلّ. ↩ ↩2
-
Microsoft Learn, EventLog.MaximumKilobytes Property. عن كون الحدّ الأقصى الافتراضيّ لحجم سجلّ الأحداث 512 كيلوبايت. ↩ ↩2
-
Microsoft Learn, EventLog Class. عن السجلّات الافتراضيّة الثلاثة Application/System/Security، ووجوب فرادة المصدر على حاسوب واحد، وإمكانيّة الكتابة بأيّ اسم مصدر مسجَّل طالما تتوفّر صلاحيّة الكتابة. ↩ ↩2
-
Microsoft Learn, Logging providers in .NET. عن تضمّن مزوِّدي التسجيل الافتراضيّين في Generic Host لـConsole وDebug وEventSource وEventLog (على Windows فقط). ↩
-
Microsoft Learn, EventLogSettings Class. عن القيم الافتراضيّة لـAddEventLog (LogName يساوي “Application”، وSourceName يساوي “.NET Runtime”). ↩
-
Microsoft Learn, Event Tracing. عن كون Event Tracing for Windows (ETW) آليّة لبدء وإيقاف وقياس واستهلاك أحداث تتبّع التطبيقات. ↩
-
Microsoft Learn, dotnet-trace performance analysis utility. عن نظرة عامّة على أداة تجميع التتبّع العابرة للمنصّات dotnet-trace المبنيّة على EventPipe وأمر collect. ↩
-
Microsoft Learn, Introduction to WPR. عن كون Windows Performance Recorder (WPR) أداة توسِّع ETW وتوفِّر تسجيلاً تفصيليّاً للنظام والتطبيقات. ↩
-
Microsoft Learn, Logging in C# and .NET. عن صياغة {PlaceHolder} في قالب رسالة السجلّ، وآليّة تحوّل أسماء المفاتيح الواردة في القالب إلى أسماء خصائص السجلّ. ↩
-
Microsoft Learn, High-performance logging in .NET. عن تجنّب سجلّات التوليد المصدريّ عبر LoggerMessageAttribute لتكلفة التغليف (boxing) وتحليل القالب. ↩
-
Microsoft Learn, Comparison of ETW and EventLog logger functionality. عن طريقة إنشاء عرض مخصَّص (custom view) باستعلامات XPath في عارض الأحداث، كالتصفية باسم حدث معيّن. ↩
-
Microsoft Learn, wevtutil. عن عمليّات سطر الأوامر لتصدير سجلّ الأحداث (epl) والاستعلام (qe) وتغيير الإعدادات (sl) وغيرها. ↩
-
Microsoft Learn, Event Sources. عن كون الكتابة باسم مصدر غير مسجَّل تؤول إلى سجلّ Application، لكن يظهر خطأ في عارض الأحداث لعدم وجود ملفّ الرسائل المقابل. ↩
-
Microsoft Learn, OverflowAction Enum. عن سلوك سجلّ الأحداث عند بلوغ الحدّ الأقصى للحجم (الكتابة فوق القديم أو التخلّص منه)، وإهمال (deprecation) قيمة OverwriteOlder. ↩
مقالات ذات صلة
أحدث المقالات التي تشترك في نفس الوسوم. عمّق فهمك بمواضيع مرتبطة.
تحديد سبب «البطء» باستخدام PerfView وdotnet-trace ── مدخل عمليّ لتحقيق أداء .NET
عندما يصبح تطبيق الأعمال «بطيئاً» أو «يستهلك المعالج بالكامل»، ما الأداة التي تستخدمها وما الذي تنظر إليه؟ ننظِّم توزيع الأدوار بين PerfV...
تعدد اللغات في تطبيقات WinForms/WPF ── الممارسة العملية لملفات resx وتجميعات الأقمار الصناعية (Satellite Assemblies) وتبديل الثقافة (Culture)
نستعرض من منظور عملي تعدد اللغات في تطبيقات سطح المكتب على Windows، بما في ذلك الفرق بين CurrentCulture وCurrentUICulture، وآلية الموارد ...
ملف CSV ليس مجرد نص عادي ── الممارسة العملية لملفات CSV في تطبيقات C# (ترميز الأحرف وتوافق Excel والحماية من الحقن)
نستعرض بمنظور عملي الأنماط النموذجية للأعطال في إدخال وإخراج CSV بتطبيقات الأعمال ── التحليل اليدوي باستخدام Split(',')، وتشوّه النصوص في...
لا تُحِط HttpClient بـ using ── الممارسة العمليّة للاتّصال عبر HTTP في تطبيقات C# للأعمال (أنماط الإنشاء، وضبط المهلة، وإعادة المحاولة)
إنشاء HttpClient داخل using في كلّ مرّة يؤدّي إلى استنزاف المقابس (sockets)، وجعله static يجعله لا يتابع تغيّر DNS ── نشرح آليّة هاتين ال...
ليس appsettings.json وحده ── الممارسة العمليّة لإدارة الإعدادات في تطبيقات Windows للأعمال (الإعدادات حسب البيئة، المعلومات السرّيّة، وجهة الكتابة)
نُنظّم هنا إدارة الإعدادات لتطبيقات Windows للأعمال. نشرح تدرّج appsettings.json، والتمييز بين IOptions/IOptionsMonitor، والإعدادات حسب ا...
أين يتصل هذا الموضوع
ترتبط هذه المقالة بشكل طبيعي بصفحات الخدمات التالية.
تطوير تطبيقات ويندوز
تصميم بنية السجلّات وسجلّ الأحداث وETW يدخل ضمن نطاق استشارات تطوير تطبيقات Windows.
التحقيق في الأخطاء وتحليل السبب الجذري
تصميم السجلّات بهدف التحقيق في الأعطال يتّصل مباشرةً باستشارات التحقيق في الأعطال وتحليل الأسباب.
الأسئلة الشائعة
أسئلة شائعة حول موضوع هذه المقالة.
- إن وُجد سجلّ ملفّات، فهل نحن بغنى عن سجلّ الأحداث؟
- لأغراض التحقيق التفصيليّ، غالباً ما يكفي سجلّ الملفّات وحده. لكن إن أردتَ تمكين القائمين على التشغيل من ملاحظة أعطال التطبيق عبر عارض الأحداث القياسيّ في نظام التشغيل أو أدوات المراقبة (كإشعارات فشل جدولة المهام أو SCOM)، فالجمع بين ذلك وإخراج نقاط جوهريّة فقط إلى سجلّ الأحداث خيار عمليّ. لا تنظر إلى الوسيلتين كبديلتين لبعضهما، بل اعتبرهما سجلّين في طبقتين مختلفتين لقارئين مختلفين.
- كيف نحدِّد قاعدة ترقيم معرِّفات الأحداث (Event ID)؟
- لا توجد إجابة قطعيّة، لكنّ الالتزام بثلاث نقاط عمليّاً يقلِّل الحوادث: «تقسيم النطاقات حسب المجال الوظيفيّ (المجال 1000 لأحداث التشغيل، والمجال 2000 لأحداث الاتّصال، وهكذا)»، و«عدم تغيير معنى معرِّف صُرِف مرّة، وعدم إعادة استخدامه»، و«تقبّل وجود أرقام مفقودة». بما أنّ EventId في ILogger يُستخدَم أيضاً كمفتاح بحث في السجلّات المهيكلة، فإنّ نظام ترقيم يسهُل توثيقه لاحقاً يفيد عند الصيانة.
- نستخدم Serilog أو NLog، فما علاقة ذلك بمحتوى هذا المقال؟
- Serilog وNLog هما أحد أشكال التنفيذ التي توزِّع نفس السجلّ، تحت ILogger، إلى عدّة وجهات (sinks) مثل الملفّات وسجلّ الأحداث وETW وSaaS خارجيّ. سياسة التصميم التي تناولها هذا المقال ─ «إخراج النقاط الجوهريّة فقط إلى سجلّ الأحداث» و«عدم كسر قالب الرسالة (message template)» ─ تنطبق بالتساوي سواء استخدمتَ ILogger مباشرةً أو عبر Serilog/NLog. أمّا استخدام وجهة (sink) مخصَّصة لسجلّ الأحداث (مثل Serilog.Sinks.EventLog) أو استخدام AddEventLog القياسيّ فهو خيار تنفيذيّ.
- إلى أيّ مدى ينبغي تعلّم ETW؟
- إن كان الهدف الرئيسيّ تطوير تطبيقات الأعمال وصيانتها، يكفي إتقان إنشاء مزوِّد (provider) خاصّ عبر EventSource، وتجميع أحداث ذلك المزوِّد عبر dotnet-trace. أمّا تحليل مكدّس الاستدعاءات (call stack) عبر PerfView وجمع أحداث النواة عبر WPR فمجال يكفي تعلّمه عند التخصّص في تحقيقات الأداء، وقد استُبعِد عمداً من نطاق هذا المقال.
الملف الشخصي للمؤلف
صفحة الملف الشخصي لمؤلف المقالة.
غو كومورا
مؤسّس شركة كومورا سوفت ذ.م.م.
يركّز على تطوير برامج ويندوز، والاستشارات التقنية، والتحقيق في الأخطاء، ويتميّز في المشاريع التي تبقى فيها الأصول القديمة ناشطة، وفي تشخيص الأعطال التي يصعب تحديد سببها.
روابط عامة