יום שישי, 8 בדצמבר 2017

להפיק קצת יותר מ ELK ו Kibana


ELK Stack (ראשי תיבות של Elastic Search, Logstach, and Kibana) הוא אוסף של שלושה מוצרי קוד-פתוח:
  • ElasticSearch - בסיס נתונים NoSQL המבוסס על מנוע החיפוש Lucene (נקרא: "לוסין")
  • LogStash - כלי לאיסוף לוגים ("log pipeline"),פענוח (parsing), סינון, טיוב, ושליחה שלהם הלאה (ל ElasticSearch, למשל).
  • Kibana - שכבת UI/Visualization ל ElasticSearch.

השלישייה הפכה לסט מאוד מקובל לניהול (ריכוז ופענוח) לוגים, בעיקר בחברות קטנות - תוך כדי שהיא דוחקת הצידה כלים שהיו מקובלים מאוד עד כה, כמו Splunk, או לפניו: SumoLogic. נתקלתי בנתון שטוען שכיום יש יותר הורדות כל חודש של ELK - מאשר התקנות חיות של Splunk.


כמו שייתכן ושמתם לב (או אולי קראתם את המאמר המפורסם של מרטינז) פרויקטי קוד פתוח נוטים "להפסיד" למוצרי SaaS. הערך של מוצר מנוהל הוא ברור, וגם סטאראט-אפים קצרי תקציב - מוכנים לשלם כסף עבור מוצר מנוהל.

בתחום ה "ELK המנוהל" יש מספר אלטרנטיבות כמו Logit, LogSense, או Scalyr - אך בישראל לפחות, ללא ספק המוצר המקובל ביותר הוא Logz.io - מוצר ישראלי, שגם סיים סבב גיוס לאחרונה.


שווה לציין של-ElasticSearch ישנם גם שימושים מעבר לאיסוף לוגים - אך זה איננו נושא הפוסט.

יצא לי להיתקל באנשים רבים שמשתמשים ב ELK - בצורה מאוד בסיסית ונאיבית, ומטרת הפוסט הזה היא לעזור להשתמש ב Kibana (הכלי איתו תהיה לנו הכי הרבה אינטראקציה מהשלושה) - בצורה מעט יותר טובה.

להעלות מ "רמה 3" - ל "רמה 6": משימוש מוגבל בכלי - ליכולת להפיק קצת תובנות משמעותיות.



"זה לא קשה בכלל, זה דווקא קל!"



בסיס


אני מניח שאתם מכירים את הבסיס.
אני מניח שאתם יודעים מה הכפתורים הבסיסיים על כל פרמטר עושים:

(1 - הוספת פילטר, פוזיטיבי או נגטיבי, הכולל את השדה, 2 - הוספת השדה לתצורה, 3 - הוספת פילטר המחייב את קיום השדה)


אני מניח שאתם מכירים את התחביר הסטנדרטי של לוסין לכתיבת שאילתות:

  1. אני מניח שאתם יודעים לחפש ע"פ ערך של שדה מסוים
  2. אני מניח שאתם יודעים להוסיף תנאים לוגים, וגם זוכרים שאין case sensitivity בערכים.
  3. אני מניח שאתם זוכרים ששמות השדות הם דווקא case sensitive (אחרת לא היה ניתן לזהות אותם חד-חד ערכית).
  4. ... שאתם זוכרים שאפשר להשתמש ב wildcard (למשל הביטוי הנ"ל יתאים ל Khrom וגם ל Chromium)
  5. ... אולי אתם יודעים שאפשר להשתמש ב wildcards גם בשמות של שדות (אם כי צריך escaping)
  6. .. ואני מניח שאתם זוכרים שכל הסימנים + - = && || ! ( ) { } [ ] ^ " ~ * ? : \ / - דורשים escaping. ובעצם הביטוי שאני מחפש הוא: 2=(1+1)
    1. שווה גם לציין שאין דרך לבצע escaping ל < ו >. באסה.
  7. אולי אתם מכירים גם Proximity Search, ששימושי כאשר יש חשש לשגיאת כתיב או הבדלים בין אנגלית אמריקאית לבריטית/אוסטרלית. המספר 5 מציין את "המרחק", וכמה שיהיה גבוה יותר - יותר ערכים דומים יכללו בתוצאת השאילתא.
  8. ובטח אני מניח שאתם זוכרים שאפשר לסנן ע"פ טווחים, כי בערכים מספריים (או תאריכים) - זה מאוד שימושי!


אני מניח שאתם יודעים להשתמש ב "surrounding documents" על מנת לפלטר את ההודעות שקרו לפני/אחרי ההודעה הנבחרת:

או יותר טוב - שהוספתם trackingId אפליקטיבי - שפשוט יהיה יותר מדויק.


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



אני גם מתאר לעצמי שהלכתם ל Management / Index Patterns, מצאתם את שדה הזמן (timestamp?) ושיניתם את הפורמט למבנה קצר יותר.

אין סיבה שיופיע לכם התאריך כ "December 2nd 2017, 21:41:51.155" בכל שורה - מבנה התופס שטח מסך יקר, בזמן שאתם יכולים לעבוד עם מבנה כמו "21:41:51.155 ,12/02/17" - שגם קל יותר לקריאה.


בעצם, אני רואה שיש לכם קצת בסיס!

מה שנותר לי הוא לדבר קצת על aggregation ו visualizations - שזו תחום שאפשר להפיק בו הרבה ערך, במעט מאמץ.




Visualizations & Aggregations



בדרך ליצירת ויזואליזציה יש שלושה שלבים עיקריים:
  • Sampling - בחירת הערכים עליהם נרצה לבצע את הוויזואליזציה. יש לנו הרבה רשומות מאוחסנות ב ElasticSearch - וחשוב שנסנן את אלו הרלוונטיות לוויזואליזציה.
  • Clustering - אני רוצה לקבץ את הרשומות הרלוונטיות ל"אשכולים" החשובים לתובנה העסקית. למשל: ע"פ microservice, סוג משתמש, דפדפן שבשימוש, וכו'.
  • Reduction - גם לאחר כל הסינונים הללו, ייתכנו בכל אשכול אלפים (או מאות אלפים?) של איברים - שזה יותר מדי לצרוך. נרצה להשתמש בפונקציות כגון count או average - על מנת לתמצת את המידע.

ב Kibana:
  • Sampling נקרא Query
  • Clustering נקרא Buckets 
  • ו Reduction נקרא Metrics.
נו, בסדר.

הנה דוגמה להגדרה של ויזואליזציה פשוטה, המראה את ההתרעות (warnings) הנפוצות ביותר בפרודקשיין:

  1. אני רוצה לדגום רק הודעות מסוג Level=Warning וב Production (שהן פחות מ 0.1% מכלל ההודעות במערכת).
    1. אני משתמש בשאילתא שמורה - שזה נוח וחוסך טעויות / maintenance.
    2. אני יכול להוסיף, לצורך הוויזואליזציה, פילטורים נוספים על שאילתת הבסיס. שימושי.
  2. אני מאגד (clustering) את הנתונים ע"פ מחלקה (class בקוד ממנו יצאה ההתרעה) וע"פ שם השירות ממנו יצאו ההודעות.
    1. לסדר בו אני מגדיר את האשכולים - יש משמעות, אותה אסביר בהמשך.
  3. בכל דלי ("Bucket") יש לי עכשיו עשרות או אפילו מאות הודעות, וייתכן שמסוגים שונים. על מנת להתמודד עם כמות המידע - אני סוכם את ההודעות, להלן count" aggregation" (פעולת reduction).

הערה: מבחינת UI, קיבנה שמה את ה Metrics (כלומר: ה reduction) לפני ה buckets (כלומר: clustering).
יש בזה משהו הגיוני, לכאורה - אך אני מוצא שזה הרבה יותר נוח להתחיל מ count (כלומר: reduction ברירת המחדל), לראות שיש בכלל תוצאות ושהגדרתי את ה buckets נכון - ורק בסוף לגשת להגדיר את ה reduction אם הוא מורכב יותר (למשל: ממוצע הזמנים ע"פ שדה אחר xyz). לכן סימנתי את המספרים 1,2,3 בסדר שאינו תואם לסדר ב UI.



והנה התוצאה:


  1. הנה האשכול הראשי: שם המחלקה שממנה נזרקה ההתרעה.
    1. כאן אני רואה את מספר האיברים בכל אשכול ראשי.
      בקיבנה הגדרות שונות של סכימה - מתארות גם את ה UI שיווצר. מצד אחד - זה מקצר תהליכים, מצד שני - מקשה עלי להשיג בדיוק את ה UI שאני רוצה.
  2. האשכול השני שהגדרתי הוא ע"פ ה micro-service ממנו נזרקה ההתרעה.
    1. כאן אני רואה את מספר האיברים בכל אשכול שני.
      האשכול השני מתאר חיתוך שני. כלומר: ה count שאני רואה הוא מספר האיברים שגם שייכים למחלקה שהופיעה בעמודה #1, וגם לשירות בעמודה #2 - ולכן, זהו המספר שמעניין אותי.
  3. בחוכמה, הזמן הוא ציר שאיננו מקובע בשאילתא (או sampling), ואני יכול לשחק עם הערכים מבלי לבצע שינויים בשאילתא. כלומר: אני יכול בקליק לראות את הערכים עבור שעה, יום, שבוע, וכו'. מאוד שימושי.


הנה תרשים, שמנסה לעזור ולהמחיש את מה שקורה (זה חשוב):

  • לקחנו המון נתונים - ובחרנו רק חלק מהם (מתוך כל המרחב, או חלקו). זה שלב ה Sampling.
  • ה cluster הראשון כולל חיתוך ראשוני. 
    • ויזואלית - לא נראה שה clusters לא מכסים את כל מרחב ה sampling. אפשר שכן ואפשר שלא - לצורך פשטות התרשים - ציירתי אותו כך.
      בדוגמה למעלה - ה cluster הראשון מכסה את כל המרחב, כי לכל הודעה יש ערך לשדה ה class.
  • ה cluster השני מבצע חיתוך נוסף על החיתוך הראשון.
    • ה aggregation שלו (במקרה שלנו: count), מייצג את האיברים באזור החיתוך (הסגול).
  • אפשר להוסיף גם cluster שלישי ורביעי. לוגית - זה אמור להיות מובן, אבל פשוט קשה לצייר את זה 😏.


סוגי הויזואליזציות העיקריים בקיבנה 5.5. אלו המסומנים בורוד הם אלו שאני מוצא כשימושיים ביותר.
Timelion ו Visual Builder הם יותר מורכבים - כמעט נושא בפני עצמו.



עוד כמה פרטים חשובים על Aggregations


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

בואו נחזור מעט לפרטים של הויזואליזציה (הפשוטה) מהדוגמה למעלה: רשימת ההתרעות הנפוצות. ואיך הגדרנו את האשכולות (או "דליים").



  1. ישנן כמה שיטות לקבץ נתונים לאשכולות, חלקן שימושיות יותר - חלקן פחות.
  2. השיטה השימושית ביותר, לדעתי, היא ע"פ Term.
קצת היסטוריה:
עד גרסה 5 של Elastic Stack, הטיפוס הנפוץ לשדות היה String - מחרוזת.
על שדה מסוג מחרוזת היה ניתן להגדיר תכונה בשם analyzed.

מחרוזת שהיא analyzed הייתה מפורקת למונחים (terms) בודדים, למשל "elastic stack" היה מפורק ל "elastic" ול "stack" ולכל term היה נרשמת רשומה באינדקס הפוך האומר לכל מילה - באילו מחרוזות היא נמצאה. זה חלק ממנגנון שנקרא "Full Text Search".

מחרוזת שהייתה not_analyzed - היו מתייחסים אליה כ term בודד, והיה נבנה אינדקס הפוך שמצביע באלו רשומות מופיע הביטוי השלם "elastic stack".

התכונות analyzed / not analyzed לא חלחלו יפה לכלים השונים במערכת, וגרמו לבלבול אצל המשתמשים ולכן החליטו להפסיק לעבוד ומחרוזת, ולעבוד עם 2 טיפוסי-בסיס חדשים: term ו text.

term הוא בעצם non_analyzed string ו text הוא בעצם analyzed string. לפעמים אתם תמצאו שדה המופיע בשתי הצורות. למשל: message מסוג text, ו message.term או message.raw מסוג term.

clustering ע"פ term אומר שאנו יוצרים אשכול / דלי לכל ערך אפשרי של השדה.

למשל עבור השדה class ייווצרו כ 220 אשכולות, כי יש לי במערכת לוגים מ 221 מחלקות שונות של המערכת.
220 הוא מספר גדול מידי להציג בוויזואליזציה ולכן עלי לציין כמה אשכולות אני רוצה לאסוף (3). בחרתי להתייחס בוויזואליזציה ל 25 האשכולות שמכילים הכי הרבה פריטים (descending) - כלומר רק 25 המחלקות ששלחו הכי הרבה התרעות - יכללו בוויזואליזציה.
שימו לב שב Tab ה Options יש הגדרות שעשויות להגביל את מספר הערכים המוצגים בוויזואליזציה.


עוד מושג שרק אזכיר הוא Significant Term המתייחס ל term שהנוכחות שלו בתוך ה sampling היא בולטת. למשל: ה sampling שלי מצמצם את הנתונים רק להודעות מסוג התרעה (Warning). המחלקה com.seriouscompany.Server לא שלחה הרבה הודעות לוג (רק 0.009% מכלל ההודעות), אבל בהודעות מסוג התרעה - חלקה הוא 0.4%. יש מחלקות שאחראיות גם ל1% ו 2% מכלל ההתרעות - אבל הן גם אחראיות 0.5% ו 0.7% מכלל הודעות הלוג.

יחסית לכמות ההודעות שהיא שולחת באופן כללי, המחלקה com.seriouscompany.Server שלחה אחוז גבוה ביותר של הודעות מסוג התרעה - ולכן כ significant term היא תחשב כבעלת הערך הגבוה ביותר.

significant term הוא כלי שימושי להבלטת אנומליות בהתנהגות המערכת.

אני מקווה שזה ברור.


בקצרה, ולקראת סיום, כמה מילים על סוגי ה clustering השונים בקיבנה:
  • Histogram פועלת על שדה מסוג Number ותקבץ לדליים intervals קבועים שהוגדרו. אם שדה "זמן הריצה" מכיל ערכים בין 0 ל 6553 מילי-שניות, ונקבע histogram עם internal של 100 - ייווצרו 66 clusters שיכילו טווחים כמו 0-100, 101-200, וכו'.
  • Date Histogram - היא היסטוגרמה על זמנים. היא יכולה להיות ע"פ דקות / שעות / ימים או מצב auto - בו קיבנה בוחרת interval שייצור כמה עשרות בודדות של clusters.
  • Range - טווחים קבועים שמוגדרים על ידכם. למשל 0-100, 500-101, ו 1000-10000 (תוך התעלמות מכוונות מכל הערכים בין 501 ל 999).
  • Date Range - רשימה קבועה של טווחי זמנים שהוגדרה על ידכם. לדוגמה: 9 עד 11 בבוקר, ו 16 עד 18 אחה"צ.
  • Filter - רשימה קבועה של תנאים לוגים על שדה, שכל תנאי מייצג cluster. למשל: *error, warning*, או nullPointerException.
  • IPv4 ו GeoHash הם clustering מאוד ספציפיים על השדות שבהם הם עובדים. GeoHash למשל יכול לקבץ ע"פ מיקומים גיאורגפיים (למשל: מהן מגיעות הבקשות). אפשר לייצר איתו ויזואליזציות מאוד מגניבות - ולא תמיד כ"כ שימושיות.

הדרך הכי טובה להבין את הויזואליזציות השונות, וסוגי ה clustering - היא לשחק ולהתנסות.
אני ממליץ לכם להחזיק חלון פתוח נוסף בו תוכלו לחפש את הנתונים לפיהם אתם עושים aggregations ולראות אילו סוגי ערכים הם מקבלים. לא פעם - אנו מעריכים בצורה לא נכונה את מרחב / התפלגות הערכים, ומסיקים מחוסר הבנה זו - שבוויזואליזציה שיצרנו יש בעיה.


אזהרה חשובה: ב metrics עומדים לרשותכם aggregations ע"פ אחוזונים: האחוזון ה 95 של ערך מסוים, ה 96, ואפילו ה 96.5.
זה נשמע מגניב, אפילו New Relic לא מאפשר לחתוך נתונים (למשל: זמני ריצה של פונקציה) ע"פ כל אחוזון שרירותי.

אליה וקוץ בה: LogStash לא באמת אוסף את האחוזונים השונים. הוא אוסף כמה נתונים (min, max, median, ועוד מספר סופי של "ריכוזי נקודות" על הטווח) - ויוצר קירוב של התפלגות. יהיה האלגוריתם שבשימוש TDigest או HDR Histogram - ההתפלגות היא רק קירוב להתנהגות הנתונים האמיתית, ולא משהו שבאמת אפשר להסתמך עליו לניתוח ביצועים אמיתי.

ריבוי אוכלוסיות (למשל: המשתמשים שמשתמשים בתכונה x מתפלגים נורמאלית A, ואלו שלא משתמשים בתכונה x - המתפלגים נורמאלית A') - עשוי בקלות להתפוגג תחת הקירובים, ו"להעלים מהראדר" התנהגויות חשובות.

אם אתם רוצים למדוד ביצועים - השתמשו ב New Relic או ב TimeSeries DB (גם ELK+Kibana מנסים להיכנס לתחום, להלן Timelion visualizations), לא ב percentiles של ELK.


מקור נוסף: Calculating Percentiles.



סיכום


אני יודע שיש משתמשים רבים ל ELK בישראל, וחלק גדול מהם - בעלי הכרות בסיסית בלבד עם Kibana והמנוע מאחוריה: Elastic Search. אני מקווה שהפוסט הזה יהיה שימושי ואכן יצליח לעזור לאנשים להפיק קצת יותר מהנתונים שלהם, הנמצאים ממש מרחק כמה קליקים מניתוח סביר.

כמובן שרב עדיין הנסתר על הגלוי.

בתחתית הפוסט הוספתי כמה קישורים שאני חושב שהם רלוונטיים.


שיהיה בהצלחה!




----

קישורים רלוונטיים:

על Heatmaps & Point Series - ויזואליזציות נחמדות!

Filebeat vs. logstash - אם אתם תוהים מהו "Filebeat", ומה תפקידו בכוח.

grok (כלי לפירסור לוגים) שייתכן שתתקלו בו.

Kibana official Reference - שהוא לא-רע



יום רביעי, 22 בנובמבר 2017

Evolutionary Design - הרצאה מתוך רברסים 2017


כמעט שכחתי!!

הנה ההרצאה שלי על Evolutionary Design מברברסים האחרון.

תכננתי לקחת פוסט שכתבתי על Design "ולהרצות" אותו - אך סיימתי עם משהו אחר.