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

> كيفية تتبّع ملف سجل وإرساله إلى ClickHouse باستخدام Vector

# تكامل Vector مع ClickHouse

export const PartnerBadge = () => {
  return <div className="PartnerBadge">
            <div className="PartnerBadgeIcon">
                <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
                    <polyline points="12.5 9.5 10 12 6 11 2.5 8.5" stroke="currentColor" strokeLinecap="round" strokeLinejoin="round" strokeWidth="1" />
                    <polyline points="4.54 4.41 8 3.5 11.46 4.41" stroke="currentColor" strokeLinecap="round" strokeLinejoin="round" strokeWidth="1" />
                    <path d="M2.15,3.78 L0.55,6.95 A0.5,0.5 0,0,0 0.77,7.62 L2.5,8.5 L4.54,4.41 L2.82,3.55 A0.5,0.5 0,0,0 2.15,3.78 Z" stroke="currentColor" strokeLinecap="round" strokeLinejoin="round" strokeWidth="1" />
                    <path d="M13.5,8.5 L15.23,7.62 A0.5,0.5 0,0,0 15.45,6.95 L13.85,3.78 A0.5,0.5 0,0,0 13.18,3.55 L11.46,4.41 Z" stroke="currentColor" strokeLinecap="round" strokeLinejoin="round" strokeWidth="1" />
                    <path d="M11.5,4.5 L9,4.5 L6.15,7.27 A0.5,0.5 0,0,0 6.24,8.05 C7.33,8.74 8.81,8.72 10,7.5 L12.5,9.5 L13.5,8.5" stroke="currentColor" strokeLinecap="round" strokeLinejoin="round" strokeWidth="1" />
                    <polyline points="7.75 13.5 5.15 12.85 3.5 11.67" stroke="currentColor" strokeLinecap="round" strokeLinejoin="round" strokeWidth="1" />
                </svg>
            </div>
            تكامل شريك
        </div>;
};

export const Image = ({img, alt, size = "lg"}) => {
  const normalizedSize = ["sm", "md", "lg"].includes(size) ? size : "lg";
  return <div className={`ch-image-${normalizedSize}`}>
      <Frame>
        <img src={img} alt={alt} />
      </Frame>
    </div>;
};

<PartnerBadge />

تُعدّ القدرة على تحليل السجلات في الوقت الفعلي أمرًا بالغ الأهمية لتطبيقات الإنتاج.
ويتميّز ClickHouse في تخزين بيانات السجلات وتحليلها بفضل إمكانات الضغط الممتازة لديه (حتى [170x](https://clickhouse.com/blog/log-compression-170x) للسجلات)
وقدرتِه على تجميع كميات كبيرة من البيانات بسرعة.

يوضح لك هذا الدليل كيفية استخدام خط أنابيب البيانات الشائع [Vector](https://vector.dev/docs/introduction/) لمراقبة ملف سجل Nginx وإرساله إلى ClickHouse.
والخطوات أدناه متشابهة عند مراقبة أي نوع من ملفات السجل.

**المتطلبات الأساسية:**

* لديك بالفعل ClickHouse قيد التشغيل
* لديك Vector مثبت

<Steps>
  <Step title="أنشئ قاعدة بيانات وجدولًا" id="1-create-a-database-and-table">
    عرّف جدولًا لتخزين أحداث السجل:

    1. ابدأ بإنشاء قاعدة بيانات جديدة باسم `nginxdb`:

    ```sql theme={null}
    CREATE DATABASE IF NOT EXISTS nginxdb
    ```

    2. أدرِج حدث السجل بالكامل كسلسلة نصية واحدة. من الواضح أن هذا ليس تنسيقًا مناسبًا جدًا لإجراء التحليلات على بيانات السجل، لكننا سنعالج هذا الجزء أدناه باستخدام ***العروض المُجسَّدة***.

    ```sql theme={null}
    CREATE TABLE IF NOT EXISTS  nginxdb.access_logs (
      message String
    )
    ENGINE = MergeTree()
    ORDER BY tuple()
    ```

    <Note>
      تم تعيين **ORDER BY** إلى **tuple()** (tuple فارغ) لعدم الحاجة إلى مفتاح أساسي بعد.
    </Note>
  </Step>

  <Step title="تهيئة Nginx" id="2--configure-nginx">
    في هذه الخطوة، ستتعرّف على كيفية تهيئة logging في Nginx.

    1. تُرسل الخاصية `access_log` التالية السجلات إلى `/var/log/nginx/my_access.log` بتنسيق **combined**.
       توضع هذه القيمة في قسم `http` من ملف `nginx.conf`:

    ```bash theme={null}
    http {
      include       /etc/nginx/mime.types;
      default_type  application/octet-stream;
      access_log  /var/log/nginx/my_access.log combined;
      sendfile        on;
      keepalive_timeout  65;
      include /etc/nginx/conf.d/*.conf;
    }
    ```

    2. احرص على إعادة تشغيل Nginx إذا اضطررت إلى تعديل `nginx.conf`.

    3. أنشئ بعض السجلات في سجل الوصول من خلال زيارة صفحات على خادم الويب لديك.
       تبدو السجلات بتنسيق **combined** كما يلي:

    ```bash theme={null}
    192.168.208.1 - - [12/Oct/2021:03:31:44 +0000] "GET / HTTP/1.1" 200 615 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.63 Safari/537.36"
    192.168.208.1 - - [12/Oct/2021:03:31:44 +0000] "GET /favicon.ico HTTP/1.1" 404 555 "http://localhost/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.63 Safari/537.36"
    192.168.208.1 - - [12/Oct/2021:03:31:49 +0000] "GET / HTTP/1.1" 304 0 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.63 Safari/537.36"
    ```
  </Step>

  <Step title="تكوين Vector" id="3-configure-vector">
    يجمع Vector السجلات والمقاييس والتتبعات، ويحوّلها ويوجّهها (ويُشار إليها باسم **المصادر**) إلى العديد من المزوّدين المختلفين (ويُشار إليهم باسم **الوجهات**)؛ بما في ذلك التوافق الجاهز مع ClickHouse.
    تُعرَّف المصادر والوجهات في ملف تكوين باسم **vector.toml**.

    1. يحدّد ملف **vector.toml** التالي **مصدرًا** من النوع **file** يتابع نهاية ملف **my\_access.log**، كما يحدّد **وجهة** بوصفها جدول **access\_logs** المعرَّف أعلاه:

    ```bash theme={null}
    [sources.nginx_logs]
    type = "file"
    include = [ "/var/log/nginx/my_access.log" ]
    read_from = "end"

    [sinks.clickhouse]
    type = "clickhouse"
    inputs = ["nginx_logs"]
    endpoint = "http://clickhouse-server:8123"
    database = "nginxdb"
    table = "access_logs"
    skip_unknown_fields = true
    ```

    2. ابدأ تشغيل Vector باستخدام configuration أعلاه. راجع [وثائق](https://vector.dev/docs/) Vector لمزيد من التفاصيل حول تعريف المصادر والمصارف.

    3. تحقّق من إدراج سجلات الوصول في ClickHouse عبر تشغيل الاستعلام التالي. ينبغي أن ترى سجلات الوصول في جدولك:

    ```sql theme={null}
    SELECT * FROM nginxdb.access_logs
    ```

    <Image img="https://mintcdn.com/private-7c7dfe99/pIetLsS_hOGHqoPJ/images/integrations/data-ingestion/etl-tools/vector_01.webp?fit=max&auto=format&n=pIetLsS_hOGHqoPJ&q=85&s=17d0b62d95271cb39b27558a8391172a" size="lg" border alt="عرض سجلات ClickHouse بتنسيق جدولي" width="2364" height="776" data-path="images/integrations/data-ingestion/etl-tools/vector_01.webp" />
  </Step>

  <Step title="تحليل السجلات" id="4-parse-the-logs">
    يُعدّ تخزين السجلات في ClickHouse أمرًا رائعًا، غير أن تخزين كل حدث كسلسلة نصية واحدة لا يتيح إجراء تحليل يُذكر للبيانات.
    سنتناول بعد ذلك كيفية تحليل أحداث السجلات باستخدام [طريقة العرض المُجسَّدة](/docs/ar/concepts/features/materialized-views/incremental-materialized-view).

    تعمل **المشاهدة المادية** بطريقة مشابهة لمحفّز الإدراج في SQL. عند إدراج صفوف البيانات في جدول المصدر، تُجري المشاهدة المادية تحويلاً على هذه الصفوف وتُدرج النتائج في جدول الهدف.
    يمكن تهيئة المشاهدة المادية لتوليد تمثيل مُحلَّل لأحداث السجلات في **access\_logs**.
    يظهر أدناه مثال على أحد هذه الأحداث:

    ```bash theme={null}
    192.168.208.1 - - [12/Oct/2021:15:32:43 +0000] "GET / HTTP/1.1" 304 0 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.63 Safari/537.36"
    ```

    تتوفر في ClickHouse دوال متعددة لتحليل السلسلة النصية المذكورة أعلاه. تعمل الدالة [`splitByWhitespace`](/docs/ar/reference/functions/regular-functions/splitting-merging-functions#splitByWhitespace) على تحليل السلسلة النصية بالمسافات البيضاء، وتُعيد كل رمز في مصفوفة.
    للتوضيح، نفّذ الأمر التالي:

    ```sql title="Query" theme={null}
    SELECT splitByWhitespace('192.168.208.1 - - [12/Oct/2021:15:32:43 +0000] "GET / HTTP/1.1" 304 0 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.63 Safari/537.36"')
    ```

    ```text title="Response" theme={null}
    ["192.168.208.1","-","-","[12/Oct/2021:15:32:43","+0000]","\"GET","/","HTTP/1.1\"","304","0","\"-\"","\"Mozilla/5.0","(Macintosh;","Intel","Mac","OS","X","10_15_7)","AppleWebKit/537.36","(KHTML,","like","Gecko)","Chrome/93.0.4577.63","Safari/537.36\""]
    ```

    بعض السلاسل النصية تحتوي على أحرف إضافية، ولم يكن ثمة حاجة إلى تحليل user agent (تفاصيل المتصفح)، غير أن المصفوفة الناتجة قريبة مما هو مطلوب.

    على غرار `splitByWhitespace`، تُقسِّم الدالة [`splitByRegexp`](/docs/ar/reference/functions/regular-functions/splitting-merging-functions#splitByRegexp) سلسلةً نصيةً إلى مصفوفة بناءً على تعبير نمطي.
    نفِّذ الأمر التالي، الذي يُعيد سلسلتين نصيتين.

    ```sql theme={null}
    SELECT splitByRegexp('\S \d+ "([^"]*)"', '192.168.208.1 - - [12/Oct/2021:15:32:43 +0000] "GET / HTTP/1.1" 304 0 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.63 Safari/537.36"')
    ```

    لاحظ أن السلسلة الثانية المُعادة هي user agent الذي جرى تحليله واستخراجه بنجاح من السجل:

    ```text theme={null}
    ["192.168.208.1 - - [12/Oct/2021:15:32:43 +0000] \"GET / HTTP/1.1\" 30"," \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.63 Safari/537.36\""]
    ```

    قبل الاطلاع على أمر `CREATE MATERIALIZED VIEW` النهائي، لنستعرض بعض الدوال الإضافية المستخدمة لتنظيف البيانات.
    على سبيل المثال، قيمة `RequestMethod` هي `"GET` وتحتوي على علامة اقتباس مزدوجة غير مرغوب فيها.
    يمكنك استخدام الدالة [`trimBoth` (alias `trim`)](/docs/ar/reference/functions/regular-functions/string-functions#trimBoth) لإزالة علامة الاقتباس المزدوجة:

    ```sql theme={null}
    SELECT trim(LEADING '"' FROM '"GET')
    ```

    تحتوي سلسلة الوقت على رمز `[` في بدايتها، كما أنها ليست بتنسيق يستطيع ClickHouse تحليله إلى تاريخ.
    غير أنه إذا استبدلنا الفاصل من نقطتين (**:**) بفاصلة (**,**)، فإن عملية التحليل تعمل بشكل ممتاز:

    ```sql theme={null}
    SELECT parseDateTimeBestEffort(replaceOne(trim(LEADING '[' FROM '[12/Oct/2021:15:32:43'), ':', ' '))
    ```

    نحن الآن جاهزون لتعريف الـ materialized view.
    يتضمن التعريف أدناه `POPULATE`، مما يعني أن الصفوف الموجودة في **access\_logs** ستُعالَج وتُدرَج على الفور.
    نفِّذ عبارة SQL التالية:

    ```sql theme={null}
    CREATE MATERIALIZED VIEW nginxdb.access_logs_view
    (
      RemoteAddr String,
      Client String,
      RemoteUser String,
      TimeLocal DateTime,
      RequestMethod String,
      Request String,
      HttpVersion String,
      Status Int32,
      BytesSent Int64,
      UserAgent String
    )
    ENGINE = MergeTree()
    ORDER BY RemoteAddr
    POPULATE AS
    WITH
      splitByWhitespace(message) as split,
      splitByRegexp('\S \d+ "([^"]*)"', message) as referer
    SELECT
      split[1] AS RemoteAddr,
      split[2] AS Client,
      split[3] AS RemoteUser,
      parseDateTimeBestEffort(replaceOne(trim(LEADING '[' FROM split[4]), ':', ' ')) AS TimeLocal,
      trim(LEADING '"' FROM split[6]) AS RequestMethod,
      split[7] AS Request,
      trim(TRAILING '"' FROM split[8]) AS HttpVersion,
      split[9] AS Status,
      split[10] AS BytesSent,
      trim(BOTH '"' from referer[2]) AS UserAgent
    FROM
      (SELECT message FROM nginxdb.access_logs)
    ```

    تحقق الآن من نجاح العملية.
    يجب أن تظهر لك سجلات الوصول مُحللَّةً وموزَّعةً بشكل أنيق في أعمدة:

    ```sql theme={null}
    SELECT * FROM nginxdb.access_logs_view
    ```

    <Image img="https://mintcdn.com/private-7c7dfe99/pIetLsS_hOGHqoPJ/images/integrations/data-ingestion/etl-tools/vector_02.webp?fit=max&auto=format&n=pIetLsS_hOGHqoPJ&q=85&s=975c0592f270bafe012c4fdbae48fb49" size="lg" border alt="اعرض سجلات ClickHouse المُحلَّلة بتنسيق جدولي" width="2824" height="1180" data-path="images/integrations/data-ingestion/etl-tools/vector_02.webp" />

    <Note>
      في الدرس أعلاه، جرى تخزين البيانات في جدولين، لكن يمكنك تغيير الجدول الأولي `nginxdb.access_logs` لاستخدام محرك الجدول [`Null`](/docs/ar/reference/engines/table-engines/special/null).
      ستظل البيانات المُحلَّلة تنتهي في الجدول `nginxdb.access_logs_view`، لكن البيانات الخام لن تُخزَّن في أي جدول.
    </Note>
  </Step>
</Steps>

> باستخدام Vector، الذي لا يتطلب سوى تثبيت بسيط وإعداد سريع، يمكنك إرسال السجلات من خادم Nginx إلى جدول في ClickHouse. وباستخدام عرض مادي، يمكنك تحليل هذه السجلات إلى أعمدة لتسهيل إجراء التحليلات.
