الخوارزميات التجريبية المخصّصة
نستخدم مصطلح الخوارزميات التجريبية (heuristics) للإشارة إلى الخوارزميات البسيطة والمتينة المستخدمة لاكتشاف مشكلات مثل ارتفاع استخدام وحدة المعالجة المركزية (CPU) أو click rage. سنستخدم هنا مثالاً واحداً لفهم كيفية عمل الخوارزميات التجريبية وكيفية إنشاء أداة الكشف الخاصة بك ورؤية نتائجها في DevTools.
القوالب
Section titled القوالبيوجد قالب للخوارزميات التجريبية في المسار openreplay/backend/pkg/handlers/custom.
package custom
import . "openreplay/backend/pkg/messages"
type CustomHandler struct {
lastTimestamp uint64
}
func (h *CustomHandler) Handle(message Message, messageID uint64, timestamp uint64) Message {
h.lastTimestamp = timestamp
return nil
}
func (h *CustomHandler) Build() Message {
return nil
}
عند إنشاء طريقة الخوارزمية التجريبية، يمكن إضافتها عن طريق تعديل الملف main.go في المسار
openreplay/backend/cmd/heuristics، وذلك باستيراد الوحدة المخصّصة وإضافة الدالة المخصّصة إلى معالج (handler) معالِج الرسائل (message processor).
package main
import (
"log"
"openreplay/backend/internal/config/heuristics"
"openreplay/backend/pkg/handlers"
web2 "openreplay/backend/pkg/handlers/web"
"openreplay/backend/pkg/intervals"
logger "openreplay/backend/pkg/log"
"openreplay/backend/pkg/messages"
"openreplay/backend/pkg/queue"
"openreplay/backend/pkg/queue/types"
"openreplay/backend/pkg/sessions"
"os"
"os/signal"
"syscall"
"time"
// Import custom modules here
)
func main() {
log.SetFlags(log.LstdFlags | log.LUTC | log.Llongfile)
// Load service configuration
cfg := heuristics.New()
// HandlersFabric returns the list of message handlers we want to be applied to each incoming message.
handlersFabric := func() []handlers.MessageProcessor {
return []handlers.MessageProcessor{
// web handlers
&web2.ClickRageDetector{},
&web2.CpuIssueDetector{},
&web2.DeadClickDetector{},
&web2.MemoryIssueDetector{},
&web2.NetworkIssueDetector{},
&web2.PerformanceAggregator{},
// Add custom handlers here
}
}
...
}
مثال Quick Return
Section titled مثال Quick Returnفي هذا المثال، سننشئ الخوارزمية التجريبية Quick Return، التي سترسل إشارة في كل مرة نعود فيها إلى نفس الـ url خلال أقل من خمس ثوانٍ. ستستفيد الطريقة المنفّذة لاكتشاف مثل هذا الحدث من الحدثين SetPageLocation و MouseClick. في كل مرة يحدث فيها نقر بالماوس، نقوم بتحديث الطابع الزمني الحالي، وإذا تم استلام رسالة SetPageEvent خلال الثواني الخمس التالية تشير إلى صفحة الويب الحالية، فإننا نُرجع حدث QuickReturn.
للبدء، لننشئ الملف quickreturn.go في المسار openreplay/backend/pkg/handlers/custom يحتوي على الكود الموضّح أدناه
package custom
import (
"log"
"encoding/json"
. "openreplay/backend/pkg/messages"
)
type QuickReturnDetector struct {
timestamp uint64
currentPage string
lastPage string
}
type CustomPayload struct {
Timestamp uint64 `json:"timestamp"`
CurrentPage string `json:"current_page"`
}
// If received SetPageLocation on same
func (h *QuickReturnDetector) HandleSetPageLocation(msg *SetPageLocation, messageID uint64, timestamp uint64) Message {
if (h.timestamp + 5000 >= msg.NavigationStart && h.lastPage == msg.URL) {
h.timestamp = msg.NavigationStart
return h.Build()
}
h.lastPage = h.currentPage
h.currentPage = msg.URL
h.timestamp = msg.NavigationStart
return nil
}
// detect when a button is clicked (selector must have string 'button' in it)
func (h *QuickReturnDetector) HandleMouseClick(msg *MouseClick, messageID uint64, timestamp uint64) {
h.timestamp = timestamp
}
func (h *QuickReturnDetector) Handle(message Message, messageID uint64, timestamp uint64) Message {
switch msg := message.(type) {
case *SetPageLocation:
if msg.NavigationStart != 0 {
return h.HandleSetPageLocation(msg, messageID, timestamp)
}
case *MouseClick:
h.HandleMouseClick(msg, messageID, timestamp)
}
return nil
}
func (h *QuickReturnDetector) Build() Message {
payload := &CustomPayload{
CurrentPage: h.currentPage,
Timestamp: h.timestamp,
}
payloadData, err := json.Marshal(payload)
if err != nil {
log.Println("JSON encoding error", err)
return nil
}
payloadString := string(payloadData)
event := &CustomEvent {
MessageID: 122,
Timestamp: h.timestamp,
Name: "quickreturn",
Payload: payloadString,
}
return event
}
الآن وقد تم إنشاء الخوارزمية التجريبية، لم يبقَ سوى تفعيلها. وللقيام بذلك، علينا إضافة الخوارزمية التجريبية إلى الملف main.go في المسار openreplay/backend/cmd/heuristics على النحو التالي:
package main
import (
"log"
"openreplay/backend/internal/config/heuristics"
"openreplay/backend/pkg/handlers"
web2 "openreplay/backend/pkg/handlers/web"
"openreplay/backend/pkg/intervals"
logger "openreplay/backend/pkg/log"
"openreplay/backend/pkg/messages"
"openreplay/backend/pkg/queue"
"openreplay/backend/pkg/queue/types"
"openreplay/backend/pkg/sessions"
"os"
"os/signal"
"syscall"
"time"
// Add custom module
custom "openreplay/backend/pkg/custom"
)
func main() {
log.SetFlags(log.LstdFlags | log.LUTC | log.Llongfile)
// Load service configuration
cfg := heuristics.New()
// HandlersFabric returns the list of message handlers we want to be applied to each incoming message.
handlersFabric := func() []handlers.MessageProcessor {
return []handlers.MessageProcessor{
// web handlers
&web2.ClickRageDetector{},
&web2.CpuIssueDetector{},
&web2.DeadClickDetector{},
&web2.MemoryIssueDetector{},
&web2.NetworkIssueDetector{},
// The new handler
&custom.QuickReturnDetector{},
}
}
...
}
أصبحت الخوارزمية التجريبية متاحة الآن، ويتم إرسال الرسائل بوصفها Custom Event. لاحظ أنك ستحتاج إلى إعادة نشر الـ back-end الخاص بك قبل أن تتمكن من الاستفادة من الخوارزمية التجريبية الجديدة. وللقيام بذلك، اتبع الخطوات الواردة في قسم build and deploy من صفحة deploy from source.
الاستفادة من الحدث المخصّص
Section titled الاستفادة من الحدث المخصّصالآن وقد أصبحت خوارزميتك التجريبية المخصّصة ترسل حدثاً مخصّصاً جديداً، فإن الشيء التالي الذي عليك القيام به هو استخدام هذا الحدث بطريقة ما. مع المثال السابق، لديك خياران:
- يمكنك تصفية الجلسات حسب الحدث المخصّص، مع التأكد من أنك تُدرج فقط تلك التي تعاني من تلك “المشكلة” (في حالتنا، مشكلة quick return).
- يمكنك العثور على الحدث داخل علامة التبويب Events في قسم DevTools الخاص بالمشغّل. وبهذه الطريقة يمكنك تحديد اللحظة الدقيقة التي يُطلَق فيها الحدث.
تصفية الجلسات حسب الحدث المخصّص
Section titled تصفية الجلسات حسب الحدث المخصّصلتصفية الجلسات حسب حدثك المخصّص الجديد، ما عليك سوى استخدام ميزة Omnisearch، بالنقر على شريط البحث واختيار “Custom Events” كنوع للتصفية. بمجرد الانتهاء من ذلك، ستتمكن من إدخال اسم الحدث؛ ومن المفترض أن يُكمَل الاسم تلقائياً بمجرد أن تبدأ الكتابة، كما يمكنك أن ترى في الصورة أدناه:

لاحظ أنه إذا لم يعمل الإكمال التلقائي أو لم يُرجِع اسم الحدث الذي تبحث عنه، فهذا يعني أنه لا يوجد حدث بهذا الاسم في قاعدة البيانات. في هذه الحالة، ينبغي أن تتحقق مرة أخرى من منطقك للتأكد من أنك تُطلق إرسال الحدث المخصّص بشكل صحيح.
العثور على الحدث المخصّص في DevTools
Section titled العثور على الحدث المخصّص في DevToolsإذا كنت ترغب في فهم اللحظة الدقيقة التي يُطلَق فيها الحدث المخصّص، فسيتعين عليك إعادة تشغيل جلسة والنقر على علامة التبويب “Events” في DevTools. ستجدها في الزاوية السفلية اليمنى من الشاشة. بمجرد النقر عليها، ستُفتح وسترى قائمة الأحداث، بما في ذلك حدثك المخصّص، كما هو موضّح في الصورة أدناه:

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