פענוח לוגים: היכן הפענוח נשבר ומה הצוות מפסיד
צינור איסוף הלוגים נראה תקין עד לרגע שבו שירות נוסף משנה את פורמט הפלט. הסוכן קורא את הקובץ, החוצץ מחליק את השיאים, המפענח מפרק את השורה לשדות, והאינדקס מקבל מבנה — ובדיוק בשלב הזה מתחיל הפער בין מה שהצוות מצפה לראות לבין מה שבאמת נמצא במאגר.
זה נשבר בדרך כלל בשלושה מקומות. מחסניות חריגים מרובות שורות מתפצלות לעשרות שורות נפרדות, כי הסוכן לא יודע היכן הרשומה מסתיימת. פורמט לא תקני של שירות אחד עובר דרך מסיכה שנכתבה עבור אחר, והאירוע עובר לאירועים שלא פוענחו עם סימון שגיאת פענוח. חתימת זמן בלי אזור זמן מפורש מזיזה את הרשומה בשעות, וכרונולוגיית התקלה נאספת בסדר שגוי.
אחר כך נכנסת העלות. שורות לוג פגומות תופסות נפח, אבל לא עונות על שאלות: בהן אי אפשר לסנן לפי קוד תגובה, משך או מזהה בקשה — רק לחפש מחרוזת משנה ידנית. אי-מבניות של הלוגים, שלא קרתה, מתורגמת לאובדן הקשר של התקלה: רשומות מכמה שירותים צריך לאחד לפי זמן ולקוות שחתימות הזמן יתאימו. ניפוי מסיכה לוקח דקות, ופענוח תקלה בלי מבנה — שעות.
להלן נפרט כיצד זה נסגר: היכן לתקן את הפענוח, כיצד להחזיק רשומות מרובות שורות בשלמותן ואילו בדיקות להציב על הצינור עצמו, כדי שאירוע שלא פוענח ייראה מיד, ולא ברגע הכשל.
האפקט של פענוח והעשרה: מה משתנה בעבודה
כל עוד האירועים מונחים כשורות גולמיות, חיפוש סיבת התקלה הופך למעבר על תבניות בטקסט: לכל שירות יש פורמט זמן משלו, שמות רמות משלו וסדר שדות משלו.
את אותה תקלה צריך לחפש בכמה שאילתות, וחלק מהשורות בכלל לא מזוהה על ידי המפענח ונשאר כמשקל מת — לפיהן לא ניתן לאחר מכן לשחזר את הכרונולוגיה.
נרמול שדות מכניס מקורות הטרוגניים לסכימת אירועים אחידה: ברשומה מופיעים אותם תגי שירות, סביבה, רמה ומזהה בקשה. לאחר מכן החיפוש נעשה בשאילתה אחת על כל המקורות, ואירועים משירותים שונים מתחברים לפי סימן משותף — שרשרת הקריאות נאספת בלי התאמה ידנית של פורמטים.
העשרת אירועים מוסיפה לרשומה את מה שאין בשורה עצמה: צומת וגרסת שחרור, אזור זמינות, בעל השירות. קונפיגורציית המפענחים והמסננים נמצאת לצד תיאור המקור ומנוהלת בגרסאות יחד איתו — ב-Elastic זה נעשה באותם כללים דקלרטיביים כמו בקולטים חלופיים. אז סיבת התקלה נמצאת באמצעות סינון לפי מאפיינים, ולא לפי הזיכרון של מי כותב לוגים ואיך.
בתפעול האפקט נראה בגדלים מדידים: שיעור השורות המזוהות מגיע ל-98-99%, הדרך מאות התראה של ניטור ועד סיבה מובנת מתקצרת משעות לדקות, ונפח האחסון מפסיק לגדול, כי שורות אשפה נחתכות בכניסה.
בנפרד נסגרים סוגי כשל של הלוגים עצמם — תבנית לא מזוהה, פיגור באספקה ופער בין המקור ליעד הופכים למדדים גלויים, ולא להפתעה ברגע הפענוח.
פענוח לוגים: פענוח בצומת או צינור מרכזי
ניתן למקם פענוח לוגים בשלוש נקודות: על הצומת עצמו לפני השליחה, בצינור מרכזי לעיבוד זורם של אירועים, או מאוחר יותר — לפי נתונים גולמיים שכבר נשמרו. נקודת הפענוח קובעת היכן נשרף המעבד, איזה נפח יוצא ברשת וכמה מהר שדות חדשים נעשים זמינים לחיפוש, להתראות ולקורלציה.
האפשרויות לעיתים רחוקות מתחרות ישירות: סכימות עבודה משלבות פענוח בצומת לשדות חמים ופענוח מרכזי לתבניות כבדות. גבולות היישום של כל אחת:
| אפשרות | מתי מתאימה | מגבלות |
|---|---|---|
| פענוח בצומת | שירותים אחידים, פורמט יציב, ערוץ תקשורת צר | צורך מעבד וזיכרון של מארח הייצור; יש לסנכרן תבניות בכל הצמתים; שגיאה נראית רק בתעבורה אמיתית |
| פענוח מרכזי | מקורות רבים והטרוגניים, העשרה וניתוב משותפים | הצינור הופך לנקודת כשל: בזמן קפיצה גדלה ההשהיה ומופיעים אובדנים; חומר הגלם בכל זאת עובר ברשת |
| עיבוד זורם של אירועים | השדות נדרשים מיד — להתראות, מדדים, קורלציה | דרישות קשיחות לסכימה ולחציצה; העשרה תוך כדי תנועה יקרה יותר מאחסון נתונים גולמיים |
| פענוח דחוי | ארכיון, חקירות, לוגים שנקראים לעיתים רחוקות | השדות מופיעים בהשהיה, לא ניתן לבנות עליהם התראות, פענוח לפי דרישה מאט את המענה |
מגבלות הצינור מתבטאות לא בפענוח עצמו, אלא בגרסאות של תבניות ובבקרת אובדנים. אם אי אפשר לשחזר אירועים שפוענחו מתוך חומר הגלם, שינוי פורמט לוגים יוצר שטחים עיוורים — לכן לוג גולמי נשמר בדרך כלל גם כשהפענוח נעשה בצומת.
כיצד אנו מיישמים פענוח והעשרה של אירועים: שלבים
סדר העבודות בנוי כך שלא נצטרך לכתוב את סכימת הפענוח פעמיים. תחילה מתעדים מה ובאיזה צורה כבר מגיע מהמקורות, ורק אחר כך כותבים כללים — אחרת המפענחים מתכסים בחריגים לכל שירות, ואחרי חודש מפסיקים לתחזק אותם.
- מיפוי מלאי מקורות לוגים. עוברים על אפליקציות, שירותים, מאזני עומס, מתזמני משימות ומסדי נתונים: פורמט רשומה (מובנה או טקסט חופשי), אזור זמן, נפח יומי, קיום מזהה בקשה. התוצאה — מרשם מקורות עם אחראי לכל אחד.
- סכימת פענוח. לכל סוג אירוע מתארים מערך שדות, וביטויים רגולריים משאירים רק במקום שבו המקור עצמו לא מוסר מבנה. את הסכימה בודקים על מדגם של רשומות אמיתיות, כולל עקבות שגיאה מרובות שורות.
- כללי העשרה. מוסיפים את מה שאין במקור: שיוך לשירות ולצוות הבעלים, פענוח קודי שגיאה, סימון סביבה, התאמת רמות חשיבות למילון משותף. את ההעשרה עושים בקולט, ולא במערכת האחסון — הכללים חיים במקום אחד.
- בדיקה בזרם. את הסכימה החדשה מפעילים במקביל לנוכחית ומשווים שדות ושיעור אירועים שפוענחו בתעבורה חיה. אם שיעור הרשומות שלא פוענחו גבוה מהסף, הכלל עובר לתיקון, ולא לענף הראשי.
- הגנה מפני קפיצות ואובדנים. מגדירים גודל תור, התנהגות בזמן הצפה ובקרת השהיית אספקה. אובדנים וחזרות נספרים כמדדים נפרדים — הצינור לא צריך לאבד אירועים בשקט.
- העברת הצינור. קונפיגורציות, בדיקות ותיאור שדות מכניסים למערכת בקרת גרסאות, שינויים עוברים בדיקה. לצוות מוסרים נוהל: כיצד לחבר מקור חדש, כיצד לשנות כלל, מי תורן ומה לבדוק בעת אי-התאמה.
קונפיגורציות, סכימות ונוהלים: מה נשאר לצוות
אנחנו מוסרים לא סט של תיקונים חד-פעמיים, אלא מתאר איסוף עובד שהצוות מתחזק בעצמו. כל מה שמתאר את התנהגות הצינור נמצא במערכת בקרת גרסאות ומתואם כמו קוד רגיל: היסטוריית השינויים ניתנת לשחזור, וחזרה לגרסה קודמת לוקחת דקות.
- קונפיגורציית הצינור — תיאור קליטה, פענוח וניתוב אירועים בקבצים נפרדים, עם תבניות לכל סוג מקור וסט הודעות בקרה לבדיקת תיקונים.
- סכימת זרמי אירועים — מהיכן מגיעים הנתונים, דרך אילו חוליות הם עוברים, היכן הם שוקעים ומה קורה כשאחד מהם לא זמין; נקודות כשל מסומנות במפורש.
- תבניות פענוח — כללים לכל פורמט מקור: JSON מובנה, יומן מערכת, טקסט חופשי. בנפרד מתוארת ההתנהגות כשמופיעים שדות לא מוכרים, כדי שפורמט חדש לא ישבור את הפענוח כולו.
- מדיניות גישה לאירועים — תפקידים ואזורי ראייה: אילו זרמים זמינים לאיזה צוות, כמה זמן הם נשמרים ובאיזה סדר ניתן גישה למשתתף חדש.
- כללי מיסוך שדות רגישים — מה מוחלף או עובר hash בכניסה, לפני ההגעה למאגר: פרטי התחברות, מזהי משתמשים, מידע אישי.
- נוהל שינויים — מי מציע תיקון, מי בודק, כיצד הוא נבדק במתאר בדיקות, באילו תנאים מבצעים חזרה לאחור ומי אחראי בזמן תקלה.
- סט בדיקות ומדדים — אירועי בקרה שמועברים דרך הצינור לאחר כל שינוי, והתראות על אובדן אירועים או גדילת התור.
לאחר ההעברה מנתחים עם הצוות תקלות אמיתיות: היכן להסתכל, מה לתקן וכיצד לוודא שהתיקון לא שבר את הפענוח. בהמשך המתאר חי בלעדינו — אנחנו מתחברים נקודתית כשמשתנה מקור או גדל הזרם.
מקרה בוחן: פענוח והעשרה של אירועים בשירות בעומס גבוה
שירות בעומס גבוה כתב אירועים למאגר כטקסט גולמי: שורה אחת ערבבה רמת חשיבות, מזהה בקשה, קוד תגובה ונתוני משתמש. הפענוח בוצע כבר בזמן החיפוש, בתבניות של ביטויים רגולריים, שנשברו בכל הודעה לא תקנית.
מה היה לפני השינויים
שליש מהאירועים לא פוענח: השדות נשארו ריקים, ומסננים לפי קוד תגובה ושירות החזירו תמונה חלקית. המהנדס התורן חיפש את הסיבה ידנית, תוך השוואת שורות בעיניים, והמאגר גדל מהר יותר מהתעבורה — מטא-נתונים כפולים נשמרו בכל רשומה.
מה שינו
הפענוח הועבר לשלב קליטת הזרם: Grok מפרק את ההודעה לשדות בעלי שם, אירועים שלא התאימו עוברים לאינדקס נפרד עם תג, ולא הולכים לאיבוד. רשומות מועשרות במילוני שירותים ובעלים, ושדות מיותרים נזרקים לפני הכתיבה לדיסק.
| מדד | לפני | אחרי |
|---|---|---|
| שיעור אירועים שלא פוענחו | 34% | 1.2% |
| חיפוש סיבת התקלה | ~40 דקות | 4 דקות |
| נפח המאגר לאותו זרם | גדל ליניארית | קטן פי שלושה |
| עומק פענוח התקלה | סלקטיבי | כל הזרם |
שארית האירועים שלא פוענחו כעת צפויה: פורמטים חדשים של הודעות נתפסים בבדיקה בשלב הבנייה, ולא על ידי התורן בזמן כשל.
מה לעשות אם שירותים כותבים אירועים בפורמטים לא מתואמים
פורמטים הטרוגניים של לוגים הם נורמה במוצר בוגר: שירות אחד כותב JSON מובנה, אחר — טקסט שטוח עם זוגות מפתח-ערך, שלישי — עקבות שגיאה מרובות שורות.
אף אחד לא ישכתב אותם לשם אחידות, לכן התאמה לסכימה אחידה נעשית בשכבת האיסוף: Fluentd או Logstash מפענח את האירוע בכניסה, ולמאגר נכנסת רשומה מנורמלת.
השלב הראשון — לתעד מינימום חובה של שדות: זמן, שם שירות, רמה, מזהה בקשה; השאר נשאר חלק מתרחב. כבסיס לשמות ניקח את המוסכמות הסמנטיות של OpenTelemetry — אז את הפלט יכול לקרוא כל מהנדס, ולא רק מחבר השירות.
כללי התאמת שדות מחזיקים באופן דקלרטיבי: טבלה שבה לכל מקור מתואר מאיזה מפתח נלקח הזמן, כיצד נפרשת הקינון, מה משמעות הרמה. אירועים שלא מתאימים לאף כלל לא זורקים, אלא שמים בזרם נפרד — והוא גם הופך לתור משימות לשיפור הפענוח.
את הסכימה מנהלים בגרסאות: מספר גרסה מוטבע באירוע עצמו בזמן הפענוח, והצרכנים קוראים במשך זמן מה את שתי הגרסאות במקביל. זה מסיר את הסיכון המרכזי — מעבר בלי לעצור שירותים ובלי לתקן בו-זמנית את כל הלוחות וכללי ההתראה.
בהמשך — מיגרציה מדורגת: תחילה מפעילים את הפענוח החדש במצב קריאה ומשווים את התוצאה לישנה, אחר כך מעבירים את הצרכנים, ורק לאחר מכן מכבים את הכללים הישנים. שיעור האירועים שפוענחו לפי כללים מפורשים גדל עד כיסוי מלא, ושירותים חדשים כותבים מיד לסכימת היעד.
ספקות טכניים: ביצועים, אובדנים וכפילויות
מאחורי הספקות האלה עומד סיכון אחד: איסוף הלוגים מפסיק להיות משני ומתחיל להשפיע על השירותים או על תקציב האחסון. להלן כיצד כל תרחיש נסגר בקונפיגורציה של הסוכן והקולט.
האם הסוכן בכל צומת לא יאט את השירותים עצמם?
הקריאה נעשית בתהליך נפרד מהדיסק, שיא הכתיבה עובר לחוצץ, ולא לאפליקציה. אנחנו מגבילים את חלק המעבד ואת רוחב הפס לשליחה, ובזמן הצפה דוחקים החוצה זרמים בעדיפות נמוכה — אירועים טרנזקציוניים נשארים.
מה יקרה לאירועים אם צומת או קולט ייפלו?
אספקה עם אישור וחזרות: מה שלא נשלח נשמר בחוצץ מקומי. לאחר הפעלה מחדש הסוכן משלים קריאה של הקובץ מהמיקום המאושר האחרון.
האם חזרות לא ייצרו כפילויות בדוחות?
בזמן חזרות כפילויות אפשריות — זה המחיר של הבטחת אספקה. סוגרים זאת באידמפוטנטיות: מפתח מורכב מהמקור וההיסט בקובץ, חזרות נזרקות בזמן האינדוקס, ומדדים נספרים לפי אירועים ייחודיים.
כיצד האיסוף שורד קפיצה חדה בעומס?
תור על הדיסק מחליק את הקפיצה: אירועים ממתינים, ולא הולכים לאיבוד. מגדירים מגבלות נפח וזמן המתנה, כדי שהתור לא יאכל את הדיסק.
האם נפח האחסון לא יגדל מהר יותר מהתועלת?
פענוח בצד הסוכן זורק שדות מיותרים לפני הכתיבה, וכללי lifecycle מחזיקים נתונים חמים בנפרד מהפושרים ומנקים ישן. מקורות רועשים מעבירים לאיסוף סלקטיבי — המרשם מפסיק לגדול ליניארית.
נדון במשימה: פענוח לזרם האירועים ולמבנה הנתונים שלכם
כדי לחזור עם הערכה, ולא עם מילים כלליות, אנחנו צריכים את הנתונים המקוריים שלכם: מהם רואים פורמטים אמיתיים של אירועים, שיעורי רשומות «פגומות» וצווארי בקבוק, ולא מקרה ממוצע. להלן סט מינימלי שמאיץ את פענוח הזרם ומאפשר להרכיב צינור למקרה שלכם במעבר ראשון.
- 5–10 דוגמאות של אירועים גולמיים מכל מקור — כפי שהם, יחד עם רשומות מרובות שורות ושורות לא תקניות בעליל: לפיהם מתאימים תבניות פענוח ובודקים את עמידותן.
- סכימת הצינור כיום: מהיכן מגיעים האירועים, היכן נמצא הקולט (Logstash או Fluentd), האם יש חוצץ ביניים ומי קורא את התוצאה — מאגר, ניטור או אנליטיקה.
- רשימת השדות הנדרשים בצורה מפוענחת ומועשרת, וכללי קישור: לפי כתובת, מזהה בקשה, מילוני התאמה, מאפיינים גאוגרפיים ושירותיים.
- פרופיל עומס: תדירות אירועים ממוצעת ושיאית, גידול יומי, עומק אחסון נדרש וזמן השהיה מותר עד להופעת רשומה במאגר.
- דרישות לנתונים רגישים: מה למסך בכניסה, מה לחתוך לחלוטין, כמה להחזיק בגלוי ומי בעל גישה.
- הרשאות לסגמנט פיילוט: קריאה של מקור אחד-שניים וסביבה שבה נפרוס את המתאר, בלי לפגוע בזרם העבודה.
- מגבלות קשיחות: חלונות תחזוקה, דרישות לחזרה לאחור, ומתארים שאליהם אסור שהנתונים יגיעו.
לאחר הפענוח נחזור עם סכימת הצינור, סדר שלבי תוכנית היישום והערכת עבודה מפוצלת לפי שלבים. סגמנט פיילוט מפעילים על מקור אחד-שניים — איכות הפענוח נבדקת בעומס חי לפני פריסה על כל הזרם. תארו את המשימה — נשלח הערכה ותוכנית.







