
هذا النص يلامس السطح فقط لما هو ممكن باستخدام Python, Plotly Dash, وواجهات برمجة التطبيقات الخاصة بنا.
منذ ما يقرب من عام، كتب توم ماييرز، مدير نجاح العملاء في Bird، أداة مرسِل باستخدام واجهات برمجة التطبيقات من Bird. في هذه المقالة، أتابع من حيث توقف. تسمح أداة ماييرز بإرسال الوظائف في وقت محدد، ولكن ماذا لو أردنا إنشاء لوحات بيانات وسجلات أحداث خاصة بنا؟
ربما أرغب في إنشاء لوحة بيانات محددة لمجموعة تجارية أو لوحة بيانات للعميل، ولكن دون منح المستخدمين وصولاً كاملاً إلى واجهة مستخدم Bird. هذه الأداة فقط تلمس سطح المستطاع باستخدام Python، وPlotly Dash، وواجهات برمجية خاصة بنا.
عندما بدأت بحثي عبر الإنترنت، أردت العثور على المسار الذي يواجه أقل مقاومة. كان بإمكاني إنشاء جميع لوحات البيانات وواجهة المستخدم بنفسي باستخدام HTML وPython، ولكن بعد بعض البحث في جوجل، اكتشفت Plotly’s Dash، الذي يتكامل بسهولة مع Python. اخترت Dash لسببين: 1) هو مفتوح المصدر، و2) بعد قراءة الوثائق بدا لي قابلاً للتخصيص بسهولة لما كنت أحاول أن أفعله. Dash هو مكتبة مفتوحة المصدر مثالية لإنشاء ونشر تطبيقات البيانات بواجهات مستخدم مخصصة. هذا جعل إنشاء واجهة المستخدم بسيطة للغاية. ثم أصبح السؤال، ما مدى تعقيد التطبيق الذي أرغب في إنشائه؟ كلما قضيت وقتًا أطول، كلما رغبت في إضافة المزيد من الميزات.
للمشروع الأولي، أردت التأكد من أن لدي لوحة بيانات مع مقاييس قابلة للتخصيص وإطار زمني قابل للتحديد. في البداية، بدأت بلائحة بيانات حيث يمكنك اختيار مقياس واحد فقط من القائمة المنسدلة. ثم، مع تلقي الملاحظات من الزملاء، قمت بتحسين اللوحة قليلاً لإضافة اختيار متعدد وعناوين المحاور. قررت أيضًا إضافة تبويب إضافي لسجل الأحداث. وصلت إلى نقطة كنت راضيًا فيها عما لدي كنقطة انطلاق جيدة لأي شخص يرغب في بناء لوحاته الخاصة. بالطبع، وضعت المشروع على Github لتتمكن من الاستنساخ أو الإنشاء على فرعه.
البدء
للوصول إلى هذا التطبيق، ستحتاج إلى التأكد من أنك تستخدم بايثون 3.10 أو إصدار أعلى وتثبيت المكتبات التالية:
requests
dash
pandas
ثم، أدخل مفتاح API الخاص بك في App.py وقم بتشغيل التطبيق. سوف يعمل على http://localhost:8050. لمزيد من المعلومات حول نشر هذا على خادم عام (مثل AWS)، راجع الموارد التالية:
إنشاء صفحة لوحة التحكم
إنشاء صفحة تفاصيل الحدث
كانت صفحة تفاصيل الحدث أكثر صعوبة قليلاً لأنني لم أكن أعرف أفضل طريقة لعرض جميع مقاييس الأحداث بطريقة سهلة القراءة. فكرت في إضافة معايير تصفية إلى هذه الصفحة، لكنني قررت أن ذلك سيضيف وقتًا كبيرًا إلى هذا المشروع لأن الجدول سيكون ديناميكيًا بعد ذلك (جنبًا إلى جنب مع إضافة المعايير، والمكالمات المرتجعة، إلخ). استقريت على عرض جميع الأحداث ووضع الطابع الزمني أولاً (لأنه بدون وضع الطابع الزمني أولاً، لم يكن الرسم البياني سهل القراءة). في البداية، وجدت أنه باستخدام HTML الخام فقط، كان الجدول صعبًا للغاية على العينين. لم تكن هناك حدود ولا اختلافات في الألوان بين العنوان والصفوف. لجعل الجدول أسهل في القراءة، تمكنت من استخدام CSS داخل Dash.
فكرة تفاصيل الحدث تشبه تقريبًا لوحة المعلومات، باستثناء هذه المرة، أقوم باستدعاء Events API وجلب جميع الأحداث. لاحظ أن تفاصيل الحدث تعرض فقط أحدث 10 أحداث (باستخدام معايير max_rows وتصفيه API). يمكن زيادة هذا، لكنني استقريت على عرض أحدث 10 أحداث لأنه كلما زادت الأحداث الظاهرة، زاد الوقت الذي يستغرقه استدعاء API. سيكون هناك تحسن كبير يتمثل في القدرة على تقسيم الصفحات والاختيار بين الصفحة التالية والسابقة في واجهة المستخدم.
لبناء علامة أحداث (صفحة)، أولاً، أقوم باستدعاء Events API وتحليل استجابة JSON إلى إطار بيانات. ثم أقوم بفرز وإعادة ترتيب إطار البيانات لوضع الطابع الزمني كأول عمود. أخيرًا، أقوم ببناء الجدول HTML من خلال التجوال عبر إطار البيانات.
#بناء استدعاء لـ events API params = { "events" : "delivery,injection,bounce,delay,policy_rejection,out_of_band,open,click,generation_failure,generation_rejection,spam_complaint,list_unsubscribe,link_unsubscribe", "delimiter" : ",", "page" : "1", "per_page" : "10" } api_url = BASE_URL + "/events/message" response_API = requests.get(api_url, headers = {"Authorization" : API_KEY}, params=params) response_info = json.loads(response_API.text) new_df = pd.json_normalize(response_info, record_path=['results']) max_rows=10 #الحد الأقصى لعدد النتائج المعروضة في جدول الأحداث #وضع الطابع الزمني كأول عمود في الجدول new_df = new_df.reindex(sorted(new_df.columns), axis=1) cols = ['timestamp'] new_df = new_df[cols + [c for c in new_df.columns if c not in cols]] #عرض HTML الجديد مع جدول الأحداث (لاحظ، هذا الجدول يرجع إلى table.css أيضًا) return html.Div([ html.H2("تفاصيل الحدث"), html.Table([ html.Thead( html.Tr([html.Th(col) for col in new_df.columns],className="table_css") ), html.Tbody([ html.Tr([ html.Td(new_df.iloc[i][col],className="table_css") for col in new_df.columns ]) for i in range(min(len(new_df), max_rows)) ]) ]) ])
الذي يبدو هكذا في واجهة المستخدم.

الخطوات التالية
بالنسبة لشخص يتطلع إلى إنشاء لوحة المعلومات الخاصة به أو سجلات الأحداث، فإن هذا يُعد بداية جيدة. مع القدرة على التخصيص هنا، السماء هي الحد.
كما تمت مناقشته أعلاه، يمكن أن تشمل بعض التحسينات المستقبلية:
إضافة تحليلات التسليم إلى لوحة المعلومات
إضافة المزيد من الفلاتر إلى لوحة المعلومات
خيارات تخزين محتملة بحيث لا يتم استدعاء API في كل مرة لعرض الصفحات
تحسينات واجهة المستخدم
إضافة التصفية والتجزئة إلى صفحة تفاصيل الحدث
أنا مهتم بسماع أي ردود فعل أو اقتراحات لتوسيع هذا المشروع.
~ زاك سامويلز، مهندس حلول أول في Bird