> ## Documentation Index
> Fetch the complete documentation index at: https://docs.logbrew.co/llms.txt
> Use this file to discover all available pages before exploring further.

# سجلات Flask ومعالجة استثناءات Flask باستخدام LogBrew

> اضبط سجلات Flask، والتقط الاستثناءات غير المعالَجة وتتبّعات الطلبات، وتحقّق باستخدام LogBrew CLI من وصول كل إشارة إلى الخدمة المستضافة.

استخدم `logbrew-flask` 0.1.6 أو أحدث. فهو يلتقط Spans الطلبات والاستثناءات غير
المعالَجة. ويربط معالج السجلات الاختياري سجلات Python بتتبّع الطلب. ومقاييس مدة
الطلبات اختيارية أيضًا.

تتطلب الحزمة Python 3.10 أو أحدث وFlask 3.1 أو أحدث.

<Note>
  استخدم في التطبيق مفتاح استيعاب للخادم خاصًا بالمشروع. لا تستخدم بيانات اعتماد
  الحساب التي تأذن للـ CLI.
</Note>

استبدل `<project_id>` و`<trace_id>` و`<issue_id>` بمعرّفات من LogBrew. استخدم
مشروعًا للتطوير في الطلبات التجريبية. تستخدم أمثلة الطرفية Bash.

## أرسل الطلب الأول

<Steps>
  <Step title="أنشئ مفتاحًا للمشروع أو اختره">
    سجّل الدخول باستخدام [الـ CLI](/ar/guides/cli). ثم استخدم مشروعًا جديدًا أو
    مشروعًا موجودًا. لا تشغّل المثالين كليهما. للمشروع الجديد، خزّن مفتاح
    الاستيعاب الخاص به في ملف جديد لا يقرؤه إلا مالكه:

    ```bash theme={null}
    install -d -m 700 "$HOME/.logbrew"
    logbrew projects create my-flask-app \
      --runtime flask \
      --environment development \
      --ingest-key-file "$HOME/.logbrew/my-flask-app.ingest" \
      --json
    ```

    للمشروع الموجود، احصل على معرّفه من `logbrew projects --json`. ثم أنشئ
    مفتاحًا منفصلًا للخادم:

    ```bash theme={null}
    logbrew projects keys create "<project_id>" \
      --kind server \
      --label "Flask server" \
      --ingest-key-file "$HOME/.logbrew/my-flask-app.ingest" \
      --json
    ```

    يخزّن الـ CLI مفتاح الاستيعاب بصلاحيات تقصر الوصول على المالك. ولا يطبع
    المفتاح ولا مسار ملفه. في بيئة الإنتاج، استخدم مدير الأسرار في منصة النشر
    لديك بدلًا من هذا الملف المحلي.

    إذا كانت نتيجة طلب الإنشاء غير مؤكدة، فشغّل الأمر نفسه تمامًا مرة أخرى.
  </Step>

  <Step title="ثبّت التكامل المنشور">
    أنشئ البيئة الافتراضية للتطبيق أو فعّلها، ثم ثبّت حزمة إطار العمل. فهي تثبّت
    حزمة الـ SDK الأساسية المتوافقة بوصفها اعتمادية.

    ```bash theme={null}
    python3 -m pip install "logbrew-flask>=0.1.6,<0.2"
    ```
  </Step>

  <Step title="اضبط هوية النشر">
    حمّل مفتاح المشروع محليًا دون أن تطبعه. اضبط خدمة وبيئة وإصدارًا ثابتة حتى
    تحمل كل إشارة سياق نشر مفيدًا.

    ```bash theme={null}
    export LOGBREW_SERVER_API_KEY="$(tr -d '\r\n' < "$HOME/.logbrew/my-flask-app.ingest")"
    export LOGBREW_SERVICE_NAME="my-flask-app"
    export LOGBREW_ENVIRONMENT="development"
    export LOGBREW_RELEASE="my-flask-app@1.0.0"
    ```

    يفحص `init_logbrew()` الوسيطات الصريحة أولًا، ثم إعدادات تطبيق Flask، ثم
    متغيرات البيئة هذه. إذا لم يُضبط اسم للخدمة، فإنه يستخدم اسم الاستيراد في
    Flask.
  </Step>

  <Step title="هيّئ Flask مرة واحدة">
    لتطبيق جديد، احفظ المثال باسم `app.py`. أضف المُهيّئ بعد أن تنشئ تطبيق
    Flask. معالج السجلات اختياري. وهو يسمح لسجلات التطبيق بمشاركة تتبّع الطلب
    النشط والـ Span النشط.

    ```python theme={null}
    import logging

    from flask import Flask
    from logbrew_flask import init_logbrew
    from logbrew_sdk import LogBrewLoggingHandler

    app = Flask(__name__)
    logbrew = init_logbrew(app, capture_request_metrics=True)

    logger = logging.getLogger("my-flask-app")
    logger.setLevel(logging.INFO)
    logger.addHandler(LogBrewLoggingHandler(logbrew.client))


    @app.get("/health")
    def health() -> dict[str, bool]:
        logger.info("health check completed")
        return {"ok": True}
    ```

    تُرجع الاستدعاءات المتكررة لـ `init_logbrew(app)` امتداد Flask نفسه. ولا
    تثبّت خطافات مكررة للطلبات أو الاستثناءات. لا يضيف المُهيّئ معالجات سجلات.
    أضف المعالج إلى المسجِّل (logger) الذي يملكه التطبيق مرة واحدة.
  </Step>

  <Step title="شغّل طلبًا واحدًا">
    شغّل التطبيق واستدعِ المسار من طرفية أخرى. استبدل `app` في الأمر إذا كان
    تطبيقك يستخدم اسم وحدة مختلفًا.

    ```bash theme={null}
    flask --app app run
    ```

    ```bash theme={null}
    curl -fsS http://127.0.0.1:5000/health
    ```

    يجري الإرسال في عامل في الخلفية، ولا يُبقي الاستجابة مفتوحة.
  </Step>

  <Step title="تحقّق من الأدلة المستضافة">
    اقرأ نطاق المشروع والنشر نفسه تمامًا. ابحث عن تتبّع طلب فحص السلامة وعن السجل
    المرتبط به الصادر عن معالج السجلات في المثال.

    ```bash theme={null}
    logbrew read traces \
      --project "<project_id>" \
      --service my-flask-app \
      --environment development \
      --release my-flask-app@1.0.0 \
      --since 1h \
      --json

    logbrew read logs \
      --project "<project_id>" \
      --service my-flask-app \
      --environment development \
      --release my-flask-app@1.0.0 \
      --search "health check completed" \
      --since 1h \
      --json
    ```

    انسخ معرّف التتبّع المُرجَع إلى أمر التحقيق المحدود:

    ```bash theme={null}
    logbrew explain trace "<trace_id>" --json
    ```

    القراءة المطابقة تؤكد أن LogBrew خزّن الإشارة. أما الاستجابة المحلية `200`
    فلا تُثبت إلا أن Flask عالج الطلب.
  </Step>
</Steps>

## اختر الإشارات التي تحتاجها

يبدأ المُهيّئ وقد فُعّلت تتبّعات الطلبات والاستثناءات غير المعالَجة. أما مقاييس
الطلبات وتمرير سجلات Python فخياران منفصلان.

| الخيار | الافتراضي | استخدمه عندما |
| - | - | - |
| `capture_successful_requests` | `True` | تريد Span واحدًا لكل طلب مكتمل. وتظل الاستجابة ذات الحالة `500` أو أعلى تنشئ Span عندما يكون هذا الخيار معطّلًا. |
| `capture_exceptions` | `True` | تريد مشكلة مصنّفة حسب النوع وSpan خطأ مطابقًا للاستثناءات التي يُبلغ عنها Flask على أنها غير معالَجة. |
| `capture_request_metrics` | `False` | تريد مخطط histogram للمدة للطلبات المكتملة. |
| `LogBrewLoggingHandler` | غير مرفق | تريد أن تتحول قيود سجلات Python المختارة إلى سجلات في LogBrew. |
| `flush_on_response` | `False` | أبقِ هذا الإعداد الافتراضي للإرسال في الخلفية. لا تفعّله إلا لتشخيص مضبوط يجب أن يكشف الإرسال في مسار الاستجابة. |

ابدأ بالإعدادات الافتراضية. أضف مقاييس الطلبات عندما تحتاج إلى عرض لزمن
الاستجابة. ولا تضف معالج السجلات إلا إلى المسجِّلات التي تفيد التحقيق.

افتراضيًا، يملك المُهيّئ وسيلة نقل HTTP. فهو يضع كل حدث في طابور، ويبدأ عامل
في الخلفية الإرسال بمجرد وجود حدث واحد في القائمة. لا يُبقي الإرسال الاستجابة
مفتوحة. ولا تُفسد إخفاقات النقل استجابة Flask.

يرسل `flush_on_response=True` الأحداث المنتظرة في مسار الاستجابة بدلًا من ذلك.
ومع هذا الخيار، يرفع `raise_flush_errors=True` أخطاء الإرسال. لا تستخدم الخيارين
إلا لتشخيص مضبوط.

## تحكّم في محتوى السجلات

أضف `LogBrewLoggingHandler` واحدًا إلى المسجِّل الذي يملك الرسائل التي تحتاجها.
لا يحل المعالج محل معالجات وحدة التحكم أو الملفات في التطبيق. ولا يعدّل Flask أو
وحدة السجلات في Python. إضافة المعالج نفسه مرتين تكرّر السجلات. إذا كان التطبيق
يستخدم المسجِّل الجذري أيضًا، فتحقّق من انتشار السجلات (propagation) قبل أن ترفق
معالجًا ثانيًا.

يرث السجل داخل الطلب التتبّع والـ Span النشطين. أما السجل خارج الطلب فليس له تتبّع
طلب.

يرسل المعالج الرسالة المنسَّقة واسم المسجِّل ومستوى LogBrew. ويرسل أيضًا اسم
الملف المصدري، والوحدة، والدالة، والسطر، وأسماء الخيط والعملية، لكن ليس المسار
المصدري الكامل. تصبح القيم البسيطة من `extra={...}` بيانات وصفية. راجع هذه القيم
قبل أن تسجّل من طلب يواجه المستخدم.

تصبح قيود Python بالمستوى `DEBUG` بالمستوى `info` في LogBrew. ويصبح `WARNING`
`warning`، ويصبح `CRITICAL` `critical`. ويبقى اسم مستوى Python الأصلي ورقمه في
البيانات الوصفية. لإرسال قيود أقل، امنح المعالج مستواه الخاص، مثل
`LogBrewLoggingHandler(logbrew.client, level=logging.WARNING)`.

يمكن أن تستقبل وحدة التحكم وLogBrew القيد نفسه. مثلًا، اضبط وحدة التحكم قبل أن
تنشئ تطبيق Flask:

```python theme={null}
logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s %(levelname)s %(message)s",
)
```

تحصل وحدة التحكم على نص منسَّق. ويحتفظ LogBrew بالرسالة والمستوى والمسجِّل
والبيانات الوصفية في حقول منفصلة.

يتضمن قيد السجل الذي يحمل `exc_info` نوع الاستثناء ورسالته. ولا يُرسَل نص
الاستثناء الكامل إلا عندما يحمل المعالج `include_exception_text=True`. وهذا منفصل
عن الالتقاط التلقائي للاستثناءات، الذي لا يرسل رسالة الاستثناء أبدًا. لا تضع
بيانات الاعتماد أو البيانات الشخصية أو نصوص الطلبات في رسائل السجلات أو
الاستثناءات.

## ما يلتقطه التكامل

| الإشارة | السلوك الافتراضي |
| - | - |
| تتبّع الطلب | Span خادم واحد يحمل الطريقة، وقالب مسار Flask، ورمز الحالة، والمدة. |
| مشكلة الاستثناء | العنوان `<METHOD> <route template> failed`، ونوع الاستثناء غير المعالَج، والملخص الثابت `Unhandled exception`، والآلية `flask.middleware`، وحالة المعالجة، وما يصل إلى 32 إطارًا بعد تنقيتها. |
| سجل التطبيق | اختياري باستخدام `LogBrewLoggingHandler`؛ ويرث السجل داخل الطلب التتبّع والـ Span النشطين. |
| مقياس الطلب | اختياري باستخدام `capture_request_metrics=True`؛ ويُصدر histogram التغيّر `http.server.duration` بالوصف `Duration of one completed server request.` |
| التتبّع الوارد | يواصل `traceparent` صالحًا بمعيار W3C بـ Span فرعي جديد. |

تستخدم أسماء الـ Spans طريقة HTTP وقالب المسار المطابق. مثلًا، يشترك
`/orders/100` و`/orders/200` في `GET /orders/<int:order_id>`. ويستخدم الطلب غير
المطابق التسمية الثابتة `<unmatched>`. ويبدأ `traceparent` المفقود أو غير الصالح
تتبّعًا جديدًا.

تحتوي البيانات الوصفية للـ Span على الطريقة وقالب المسار ونقطة النهاية ورمز الحالة
والمدة. ولا تحتوي على المسار الفعلي أو سلسلة الاستعلام.

في الإصدار 0.1.6 والأحدث، يغطي Span الطلب عملية التوجيه الكاملة في Flask. وتشترك
خطافات ما قبل الطلب ومعالجات الأخطاء وخطافات الإنهاء (teardown) في تتبّع الطلب.
وتنهي الاستجابة المتدفقة الـ Span الخاص بها عندما ينتهي نص الاستجابة أو يُغلق.

### اختبر التقاط الاستثناءات

تظهر الحالة `4xx` أو `5xx` على Span الطلب. والحالة وحدها لا تُثبت أن استثناءً وقع.
اقرأ التتبّعات والمشكلات كلتيهما قبل أن تشخّص الإخفاق. لا يحل LogBrew محل معالجات
الأخطاء في Flask، ولا يغيّر حالة الاستجابة.

في مشروع للتطوير، أضف مسارًا مؤقتًا. استدعه مرة واحدة. أزِله قبل أن تنشر:

```python theme={null}
@app.get("/logbrew-test-error")
def handle_test_error() -> None:
    raise RuntimeError("local capture check")
```

يُرجع الطلب الحالة `500`. اعثر على المشكلة الجديدة ومقياس الطلب:

```bash theme={null}
logbrew read issues --project "<project_id>" --since 1h --json
logbrew explain issue "<issue_id>" --json

logbrew explain metric http.server.duration \
  --project "<project_id>" \
  --service my-flask-app \
  --environment development \
  --release my-flask-app@1.0.0 \
  --since 1h \
  --json
```

تحقّق من خدمة المشكلة وبيئتها وإصدارها ونوع الاستثناء وتتبّع الطلب. يجب ألا تحتوي
المشكلة على النص `local capture check`.

### اربط العمل الصادر بالطلب

يحتوي SDK الخاص بـ Python على دوال مساعدة يملكها التطبيق لعمليات `requests`
و`urllib` و`httpx` و`aiohttp` وقواعد البيانات وذاكرة التخزين المؤقت وقوائم
الانتظار. تنشئ كل دالة مساعدة Span فرعيًا لتتبّع الطلب النشط. ولا يعدّل الـ SDK
هذه المكتبات على المستوى العام. وتعرض
[حزمة `logbrew-flask`](https://pypi.org/project/logbrew-flask/) أمثلة على ذلك.

امنح كل دالة مساعدة اسم عملية ثابتًا وقالبًا للمسار أو للاستعلام. لا تضع في هذه
الأسماء معرّفات القيود أو قيم العملاء أو قيم الربط في SQL أو حمولات الرسائل. لا
تضف Spans فرعية إلا حيث تهم الاعتمادية للطلب. فإنشاء Span لكل استدعاء صغير يجعل
قراءة التتبّع أصعب. تضيف الدوال المساعدة لطلبات HTTP الصادرة ترويسة `traceparent`
واحدة بمعيار W3C. ولا تلتقط عناوين URL الكاملة أو سلاسل الاستعلام أو نصوص الطلبات أو
ملفات تعريف الارتباط أو الترويسات العشوائية. ولا تلتقط الدوال المساعدة لقواعد
البيانات وذاكرة التخزين المؤقت والطوابير قيم الربط أو النتائج أو القيم
المخزّنة مؤقتًا أو حمولات الطوابير.

## الخصوصية ودورة حياة العملية

يحذف الالتقاط التلقائي في Flask مسارات الطلبات الفعلية، وسلاسل الاستعلام، ونصوص
الطلبات والاستجابات، وملفات تعريف الارتباط، والترويسات العشوائية، وقيم
`traceparent` الخام، وbaggage، وtracestate.

لا يقرأ الالتقاط التلقائي للاستثناءات `str(error)` ولا يرسله أبدًا. فهو يستخدم
الملخص الثابت `Unhandled exception`، ويضع على كل رسالة في سلسلة الاستثناءات علامة
«محجوب». تحتوي الإطارات على الاسم الأساسي للملف وهوية محدودة للشيفرة. ولا تحتوي
على نص traceback الخام أو الشيفرة المصدرية أو المتغيرات المحلية أو المسارات
المطلقة.

أنشئ التطبيق وعميل LogBrew داخل كل عملية عامل. يعمل التحميل الافتراضي للتطبيق لكل
عامل في Gunicorn. لا تستخدم `--preload` في Gunicorn مع عميل أُنشئ في العملية
الأم. وفي uWSGI، استخدم تحميل التطبيق لكل عامل، مثل `--lazy-apps`. يرفض عميل
Python إعادة استخدامه بعد تفرّع العملية (fork).

استدعِ `logbrew.client.shutdown()` من خطاف الإيقاف لكل عامل في مدير العمليات.
فهو يرسل الأحداث المتبقية في الطابور ويغلق العميل. لا تستدعه بعد كل طلب.
بعد الإيقاف، يرفض العميل الأحداث الجديدة من ذلك العامل.

قد تنتهي الاستجابة قبل أن يرسل العامل آخر الأحداث في الطابور. أثناء النشر
أو تقليص عدد العمال، يمنح الإيقاف السلس هذه الأحداث محاولة إرسال أخيرة.

## الاستعادة من مشكلات الإعداد

| العَرَض | الفحص | الإجراء التالي |
| - | - | - |
| `LOGBREW_SERVER_API_KEY is required` | لم يتلقَّ المُهيّئ مفتاح مشروع غير فارغ. | اضبط مفتاح الخادم الخاص بالمشروع عبر إعدادات Flask، أو وسيطة صريحة، أو متغيرات البيئة. |
| لا يظهر أي تتبّع | عوامل تصفية المشروع أو الخدمة أو البيئة أو الإصدار أو الوقت لا تتطابق. | شغّل `logbrew doctor --project "<project_id>" --json`، ثم كرّر قراءة التتبّع ضمن النطاق. |
| تظهر التتبّعات ولا تظهر السجلات | لا ترفق أدوات قياس الطلبات معالج سجلات Python تلقائيًا. | أضف `LogBrewLoggingHandler` واحدًا إلى المسجِّل الذي يملكه التطبيق. |
| تعمل الطلبات لكن الأحداث الأخيرة تُفقد أثناء الإيقاف | تنتهي العملية قبل أن يرسل العامل في الخلفية الأحداث المتبقية لديه. | استدعِ `logbrew.client.shutdown()` من خطاف إيقاف العامل. |
| يُبلغ العامل عن `process_ownership_error` | أُنشئ العميل قبل تفرّع عملية العامل. | حمّل التطبيق لكل عامل وأنشئ عميلًا جديدًا في تلك العملية. |

لأخطاء الوصول إلى الحساب والمفاتيح وقراءة البيانات المُرسَلة، راجع
[استكشاف الأخطاء وإصلاحها](/ar/guides/troubleshooting). ولبيئات التشغيل الأخرى،
راجع [دمج SDK](/ar/guides/sdk-ingestion).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.