חיפוש
  • יניב אור

Grafana - פאנל ומקור מידע - מותאמים אישית

עודכן ב: אפר 25

ללא ספק, גרפאנה היא המערכת המובילה והמרשימה כיום להצגת מידע של מדדים (metrics) בפאנלים מסוגים שונים כגון טבלאות, גרפים, שעונים וכדומה. את הפאנלים מחברים למקורות מידע שונים כמו למשל: Prometheus, MySQL, MongoDB, Graphite, ElasticSearch ואחרים. הכל נעשה בממשק נוח לשימוש שאינו דורש כתיבת קוד.


כנסו לאתר: https://play.grafana.org ותוכלו לשחק עם מערכת מוכנה


יש לא מעט מדריכים וסרטונים להקמת מערכת גרפאנה ושימוש בה. מה שאני מעוניין בפוסט הזה זה להראות איך יוצרים פאנל מותאם אישית ואיך יוצרים מקור מידע מותאם אישית. על כך אין כמעט מידע ברשת.


התקנת גרפאנה לצורך פיתוח

יש מספר דרכים להתקנת גרפאנה, אנחנו מעוניינים בצורה שתאפשר סביבה נוחה לפיתוח. לכן, ניכנס לדף של גרפאנה ב-Github ונפעל לפי ההוראות המוצגות באתר.


https://github.com/grafana/grafana

https://github.com/grafana/grafana/blob/master/contribute/developer-guide.md


להרצת גרפאנה יש צורך ב-go, ב-nodejs וב-yarn. התקינו לפי מערכת ההפעלה שלכם.


נגדיר את המיקום אליו נרצה ש-go יוריד את גרפאנה בצורה הבאה (יש אפשרות לבחור מיקום אחר, כמובן).


נוסיף את השורה:

export GOPATH=$HOME/go/


לקובץ:

$HOME/.bashrc


או לקובץ הבא (בהתאם למערכת הפעלה):

$HOME/.bash_profile


ונריץ:

$ go get github.com/grafana/grafana


נריץ את השרת בחלון טרמינל נפרד:

$ cd go/src/github.com/grafana/grafana $ make run


אם קיבלתם שגיאה, משהו בסגנון של:

can't load package: package github.com/unknwon/bra: cannot find package "github.com/unknwon/bra"


כנראה שהגירסת go שלכם ישנה מדי. אצלי השגיאה הופיעה עם גירסה 1.10. התקינו גירסה חדשה יותר. למשל 1.14.1.


אם הגירסה תקינה, לאחר סיום ההרצה תופיע השורה שאומרת שהשרת מאזין לפורט 3000. ניתן לשנות את הפורט - http_port - בקובץ:

conf/defaults.ini


את הפרונטאנד נתקין ונריץ בחלון טרמינל נפרד בצורה הבאה:

$ cd go/src/github.com/grafana/grafana $ yarn install --pure-lockfile $ yarn start


המתינו בסבלנות עד לסיום בניית הקוד ופתחו את הדפדפן בכתובת:

http://localhost:3000


הזינו שם וסיסמא admin admin ובהתאם להוראות שנו את הסיסמא. מזל טוב, יש לכם גרפאנה מוכנה להמשך פיתוח.


אנו זקוקים לשלושה רכיבים או תתי-פרויקטים על מנת להשלים את המשימה שלנו. הרכיב הראשון הוא פאנל מותאם אישית שאת הבוילרפלייט שלו אוריד מ-Github, מה-repo הרשמי של גרפאנה. הוא עשוי 100% קוד ריאקט. רכיב נוסף הוא הפרונטאנד ל-datasource. יש אחד רשמי ב-repo של גרפאנה אך הוא בלתי שמיש ולא ניתן לבנות את הקוד, לכן אשתמש בבוילרפלייט אחר שמבוסס עליו. עשוי מאנגולר. הרכיב השלישי הוא השרת שישלח JSON-ים לפרונטאנד של מקור המידע. נתחיל ב-datasource.


יצירת מקור מידע מותאם אישית

אז כמו שציינתי, הבוילרפלייט ל-datasource מה-repo של גרפאנה שנמצא בכתובת הבאה:

https://github.com/grafana/simple-json-datasource

לא שמיש מבחינת בניית הקוד. מצאתי את הקוד הבא שעובד מצויין:

https://github.com/simPod/grafana-json-datasource


ניכנס לתיקיית התוספים ונוריד את הקוד מ-Github:

$ cd go/src/github.com/grafana/grafana/data/plugins $ git clone https://github.com/simPod/grafana-json-datasource.git


ניכנס לתיקיית ה-datasource, נתקין מודולים ונבנה את הקוד:

$ cd grafana-json-datasource $ yarn install $ yarn run build

אם נרצה לפתח את הקוד, נריץ את הפקודה הבאה שבכל שינוי תבנה מחדש את הקוד:

$ yarn watch


אתחלו את שרת ה-go של גרפאנה, רפרשו את האתר והקליקו על Add data source שנמצא בדף הראשי או דרך גלגל השיניים בתפריט צד.


ה-datasource נקרא JSON כפי שניתן לראות בתמונה. ברגע שנקליק עליו נעבור לדף הגדרות שבו נצטרך להגדיר לפחות URL לשרת שישלח JSON. את השרת ניצור בשלב הבא. אם אתם מעוניינים להשתמש בשרתים מוכנים לעבודה עם מקור המידע הזה, כנסו לדף הבא ותמצאו מספר שרתים מוכנים לשימוש:

https://github.com/grafana/simple-json-datasource#example-backend-implementations


יצירת שרת NodeJS לעבודה מול ה-datasource

את בסיס הקוד לשרת אני מייצר בעזרת express-generator

$ npx express-generator grafana-node-server


ה-repo נמצא כאן:

https://github.com/YanivOr/grafana-node-server


ה-datasource מחייב לממש לפחות 4 ראוטים ויש אפשרות ל-2 נוספים. מהאתר הרשמי:

Your backend needs to implement 4 urls:

1. / - should return 200 ok. Used for "Test connection" on the datasource config page. 2. /search - used by the find metric options on the query tab in panels. 3. /query - should return metrics based on input. 4. /annotations - should return annotations. Those two urls are optional: /tag-keys should return tag keys for ad hoc filters. /tag-values should return tag values for ad hoc filters.


מחקתי את ה-route של ברירת המחדל שהיה קשור ל-users מהקובץ app.js ומתיקיית routes.

ערכתי את index.js בתיקיית routes והוספתי את ארבעת ה-URL-ים. בתור התחלה כולם מחזירים 200. בהמשך נפתח את העניינים.

routes/index.js

נריץ את השרת ונחזור לממשק של הגרפאנה. הפעם נקליק על האייקון של מקור המידע שיצרנו - JSON - נגיע לדף ההגדרות, נזין את הכתובת של השרת ונקליק על Save & Test.


המשך פיתוח ה-datasource

הדבר הבא שנעשה זה ליצור dashboard, לאחר מכן פאנל ו-visualization כשבברירת המחדל נקבל גרף. עברו ל-queries.

קיבלנו שגיאה משום שקריאת ה-API שלנו ל-query מחזירה רק קוד 200 ולא דאטא. נטפל בעניין בהמשך. דבר נוסף, שימו לב לשני ה-dropdown-ים ב-query. הראשון Format as הוא הארד-קודד בקוד הפרונטאנד (אנגולר) ומכיל שני סוגים: Time series ו-Table. אלו שני הסוגים היחידים שגרפאנה תומכת בהם וכל אחד מהם מצפה למבנה דאטא מסויים שיגיע מהשרת. הדרופדאון השני Metric מצפה לקבל מערך של נתונים מקריאת ה-API ל-search.


data/plugins/grafana-json-datasource/src/query_ctrl.ts

שימו לב ל-this.types שהוא מערך של אובייקטים לצורך הדרופדאון הראשון ו-findMetrics, פונקציה שתמלא את הדרופדאון השני.


data/plugins/grafana-json-datasource/src/partials/query.editor.html

בהתאמה, ctrl.types בדרופדאון הרלוונטי ב-HTML ו-ctrl.findMetrics($query) בדרופדאון הרלוונטי האחר.


נוסיף בשרת ל-search מערך שאותו נרצה להעביר לדרופדאון של Metric.


routes/index.js (החלק הרלוונטי)

נריץ מחדש את השרת ונרפרש את הגרפאנה. הפעם הדרופדאון של ה-Metric טעון במידע.

ברגע שאנחנו בוחרים אפשרות כלשהי ב-query או מזינים מידע כלשהו - למשל ב-Additional JSON Data - נשלחת קריאת query לשרת. החלק הרלוונטי לנו כרגע נראה כך:

שימו לב ל-targets. מערך של אובייקטים. ה-item הראשון (0) תואם ל-query שנקרא A בממשק הגרפי. יש אפשרות להוסיף queries נוספים והם יהיו item-ים נוספים במערך.

כרגע, מה שרלוונטי לנו זה target שבדוגמא שלנו הוא metric-1 ו-type שבדוגמא שלנו הוא timeseries.


נוסיף מעט קוד לקריאת API של query בשרת.

routes/index.js (החלק הרלוונטי)

באופן שרירותי בחרתי לכתוב את הקוד כך שברגע שהמשתמש בוחר timeseries ו-metric-1 השרת מחזיר מערך של אובייקטים עם item אחד בודד בפורמט שמתאים ל-timeseries לפי החוקיות של גרפאנה. אין קוד ספציפי ל-metric-2 והשרת יחזיר מערך ריק. לאפשרות שקראתי metric-3 and metric-4 השרת יחזיר מערך עם שני item-ים.

מבחינת המידע הטבלאי, בחרתי להחזיר את אותו מידע ללא תלות ב-Metric שנשלח. שימו לב למבנה הנתונים עם ה-columns ו-rows. זה המבנה נתונים שגרפאנה - לא ה-datasource - מצפה שנשלח כשמדובר על טבלה.


נעבור לתצוגה טבלאית והתוצאה נראית בתמונה הבאה.

אגב, אם נישאר בתצוגה הטבלאית ונחזור ל-Format של timeseries נקבל את התוצאה הבאה.

מבחינת הקוד של ה-datasource, אין צורך כרגע לבצע שינויים וניתן להשתמש בתוסף כמו שהוא. אם תרצו לערוך את הקוד, הריצו בתיקייה yarn watch.


בחלק של ה-annotaions וכל מה שקשור ב-tag-keys ו-tag-values נטפל בהמשך, נעבור לבניית פאנל מותאם אישית בנוי בריאקט.


פאנל מותאם אישית

את הבוילרפלייט לפאנל נתקין מה-repo הבא:

https://github.com/grafana/simple-react-panel

$ cd go/src/github.com/grafana/grafana/data/plugins $ git clone https://github.com/grafana/simple-react-panel.git $ cd simple-react-panel $ yarn install $ yarn watch


נאתחל את ה-go, ריפרש לגרפאנה והפאנל יופיע ברשימת הפאנלים

שימו לב לקובץ:

simple-react-panel/src/SimplePanel.tsx

זה הקובץ הראשי של הרכיב. בברירת מחדל הערך היחיד שמשוייך ל-datasource הוא data.series.length ומציג את מספר סדרות המידע שקיבלנו ובמקרה שלנו יציג 1 ב-metric-1 יציג 0 ב-metric-2 ו-2 ב-metric-3 and metric-4. בכל מקרה, data.series מכיל את המידע הרלוונטי.



המשך יבוא...


© 2023 by DO IT YOURSELF. Proudly created with Wix.com