"לעבוד" על jacoco בעזרת lambda?

TakeCtrl

New member
"לעבוד" על jacoco בעזרת lambda?

קודם כל מה המטרה..
יש לנו ערימות של if _(log.isDebugEnabled וכו' בקוד, שכמובן codecoverage מסמן אותם כלא נבדקות.
כיום הcodecovrage נמצא בסביבות 39%.
משתמשים היום בlog4j 1.2
עכשיו שעברנו לjava 8 והכלי היחידי שיכול לcovrage (שידוע לי ) שיכול לעבוד איתו הוא jacoco (בעבר השתמשנו בcobetura) ראיתי בספר, את האפשרות שימוש בConsumer במקום if isDebugEnabled כך שלא יהיה צורך לכתוב IF מבאס כל פעם ..
 

TakeCtrl

New member
אנחנו עובדים עם Log4j1.2

בעיקרון כל debug אצלנו נמצא תחת כזה דבר כזו , זה יכול להיות string סטטי, או משהו שהופך bytearray לstring.
חוץ מזה זה נכתב כבר 5-7 שנים לפני כן, :p ..
 
השם ירחם... ועכשיו במקום לעבור לספריית לוגים נורמלית

ולמחוק את כל ה if-ים המזעזעים הנ"ל, אתה מוסיף קוד כדי לשפר את ה test coverage score שלך?
אתה צריך "לעמוד בפינה ולחשוב על מה שעשית".
ביפן היית עכשיו מבקש רשות לבצע ספוקו.
 

TakeCtrl

New member
מה מוסיף? מוריד...

אה, שכחתי להגיד, הLogger של log4j עטוף, בlogger משלנו, כך שכל מה שאני צריך לעשות זה להוסיף עוד חתימה עםlambda וזהו, ואני יכול להוריד את כל הif.. (זה המון עבודה שחורה שלא יתנו לי לעשות אותה עכשיו) אבל קראתי שיש אנשים שאפילו חיפשו דרכים להוריד מcoverage חתיכות של getter setter.
&nbsp
בעיקרון log4j2 עושה את זה בשבילי
&nbsp
http://logging.apache.org/log4j/2.x/manual/api.html#LambdaSupport
&nbsp
רק הבעיה היא שאנחנו משתמשים בDOMConfigurator כדי לקנפג אותו (יש לנו אפילו Log4j.xsd מקוסטם שהיה חסר לו חלק מהדברים, כגוןfilter של appender).
&nbsp
ואתה חושב שעל זה הייתי צריך לעמוד בפינה ? הlogger מבצע בבנאי שלו את...
StackTraceElement[] stack = Thread.currentThread().getStackTrace();
StackTraceElement caller = stack[3];
caller.getClassname .. בשביל לדעת את שם המחלקה שהוא רץ
אם אני לא טועה זה לא אמור לזרוק exception בפנים כל פעם כדי לדעת את זה?
&nbsp
עוד פנינה? כשהגעתי היינו לנו עשרות מקומות שכאשר נתפסה בה exception הם רשמו רק את ההודעה של exception ללא שום stacktrace, כולל... מקרים של... NPE, בבקשה לך תמצא מאיפה זה מגיע בבלוק של 30 שורות. כשרצינו לשנות את זה גלובלית, התנגדו בטענה זה "לא נראה טוב ללקוח" או, (אני כבר לא זוכר) אבטחה.
&nbsp
כשרציתי לעשות את זה גם בwarn שנמצאים בcatch, עצרו אותי לגמרי, כי זה לא נראה טוב למישהי אצלנו וזה סתם עיצבן אותה לראות את ב console, הפשרה היחידה שהצלחתי לחלץ זה להוסיף במעטפת ה- Logger איזה systemProperty שאוכל להדליק לפחות בIDE שלי כדי שאני אוכל לראות בעיות. (זה פחות עוזר לי אם QA נתקלים בבעיות ולא אני לא יכול לראות את זה שם).
ולפני שתשאל מדוע לא להפוך כל warn של Exception ל error, יש לנו מערכות regression אוטומטיות שמפילות כל טסט על המילה error בלוג (או יותר התבנית error בלוג).
&nbsp
אני תמיד מזכיר את מקום העבודה הקודם שלי בתור חווייה מזככת שגרמה לי לגדל עור שלי פיל, אז כבר אני לא מתפלא על כלום כי "הכל שטויות" כמו שמישהו שם אמר.
&nbsp
אבל כאן המצב טוב לאין שיעור משם. כאן לפחות עברנו לjava8. כאן יש לנו wish list ארוך לשיפורים (אחת מהמשימות הייתה לעבור ולסדר את ההודעות הלוגים ולהציף פחות) ,רשימה שאני לא מאמין שנבצע אפילו שבריר ממנה, אבל זה נחמד שיש חלומות ורצון להתקדם.
&nbsp
 

choo

Active member
למה לא לשמור את הלוג בקובץ?

&nbsp
אחד המנגנונים הבסיסיים של log4X - היכולת לרשום כמה handlers ולתת להם רמות דבג שונות - למסך לרשום רק הודעת שגיאה שנועדה למשתמש, ולקובץ הלוג לרשום את כל הזבל שנועד למפתחים.
&nbsp
אם מעלים חשש של "אבטחת מידע" - אפשר לשמור את הלוג בקובץ בצורה מוצפנת (עבור הגדרה של מוצפנת שתרצה את "בוכי האבטחה").
&nbsp
נ.ב. אחת השיטות לביצוע משימות רוחביות מהסוג הזה, הוא להחליט שבכל פעם שאתה נוגע באזור X, אתה מכניס גם תיקון של ההדפסות באותו אזור (ב-commit נפרד, מן הסתם, עם כותרת מתאימה). זה מוריד את התקורה, ומאפשר לפרוס את העלות לתשלומים קטנים.
 
נשמע שיש פה מקרה של "ביצועים"


מישהו החליט שה log4wtf הזה "עושה משהו" - למשל string conversion - לפני שנבדקת רמת הלוג.
אם זה המצב - זה כשל רציני ביותר בספרייה. אם לא - לא ברור איזו תכלית משרתים ה if-ים הנ"ל.
 

TakeCtrl

New member
ברור שהוא עושה משהו, זה לא קשור ישירות לlog4j

אם אני עושה
log.debug(bigObject.toString())
&nbsp
הtoString יעבור ביצוע בלי קשר אם אתה ברמת debug או לא, כי זה פרמטר שנשלח למתודה, בדרך כלל אין שום בעיה עם זה, אלא אם כן מדובר במקרה קצה של log שאתה רוצה באופן גלובלי שיופעלו או יכובו. זה תבנית ידועה, כל כך ידועה שיש אפילו Plugin בintelij שמפליץ לך if(debugEnabled כקיצור דרך... ראיתי את זה בהמון מקומות.
 

TakeCtrl

New member
זו הייתה דוגמא, כן יש מקרים שאנחנו עושים את זה..

יש מקרים אחרים שמרכיבים string אחרים...
תאמין לי שמבחינת ביצועים לא נראה לי שזה שווה ערך למשל לשליפת תמונות attachments מsoapResponse, לעשות להם base64encoding ולהעביר אותם לתוך DomNode ולעשות להם decode ולשמור בקובץ.
או לעשות toXmlString וליפול בOOM כי אתה עושה 3 פעמים replaceAll על
t\
n\
r\
כמו שאמרתי אני מנסה לבחור את הקרבות שלי בעדינות.
אנשים אצלנו חשבו שifDebueEnabled בכלל נועד לחסוך כניסה למתודה.
חשבתי אפילו לנסות למצוא יועץ חיצוני לביצועים של java מבחינת זיכרון אחרי שהתחלתי לקרוא את java performance definitive guide...
 
אוקי הנה עצה: תתחיל בלפרמט את הלוגים שלך לצורת

logger.debug("param {0} param {1}", obj, otherObj)
אני יוצא מנק. הנחה פרועה שהתחביר הזה נתמך בג'אווה.
זה קרב קל. אח"כ תכניס את זה ל coding standard שלכם ותשלח מייל לכולם שלא מעבירים קוד רוויו עם משהו כמו:
logger.debug("using " + param1)
or
logger.debug(param1.ToString())
 

TakeCtrl

New member
השורה הראשונה הייתה בלוג הראשון שכתבתי בעבודה הזו...

לא בדיוק עבר חלק בcode review... :)
שנית, מייד יגידו שיש כבר המוני מקומות שיש שם toString גם ככה אז אין טעם לעשות את זה עכשיו כאשר הם ישנם, וזה עבודה שחורה לנסות לעקר אותם...
 

zaske

New member
יש לי יועץ מצויין לנושא, אם אתה באמת צריך

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

TakeCtrl

New member
יהיה לי קשה לשכנע אנשים אחרי היועץ האחרון שהמליצו לנו...

בשיחת טלפון איתו, אחרי שהסברנו לו מה קורה, מה אנחנו מחפשים, ניתן היה לתמצת את ההסבר שלו כ"שחקו עם הswitch של הGC" לאחר מכן הוא שלח לנו קישור על G1 ומה לחפש, שזה כבר ידעתי לפני כן (שוב, הספר), וביקשתי מאנשי הQA שלנו לחפש בלוג של GC אחרי מילות מפתח.
לא ציפיתי שייתן לנו שיחת יעוץ שלמה בחינם, אבל קיוויתי למישהו שנשמע עם קצת יותר תובנה ממני בנושא.
 

TakeCtrl

New member
ואתמול גיליתי שבדיקות אוטומציה שלנו נפלו כי שיניתי toString

של אובייקט מברירת מחדל שלו למשהו יותר קריא (לראות אותו ב debugger וגם בלוגים).
&nbsp
מה מסתבר ,הבדיקות מסמתכות על השוואת string בלוג, ואחד מהלוג entries מסתמך על toString, שמסתמך על toString של אובייקט נוסף בתוך האובייקט , שמסתמך על צירוף של toString של עוד כמה 3-4 בתוכו שלחלק מהם יש toString ברירת מחדל של object והסיבה היחידה הtoSTring ההוא נשאר קבוע שהhashcode שלו חושב לפי הID של הלוגי שלנו ולא לפי hashcode...
אנחנו במצב של FeatureFreeze, אבל הצעתי במייל לחולל את הstring הזה באופן ידני לגמרי לשים את החילול בunittest ,וגם לעשות רצה השוואתית בין החילול לבין הtoSTring בתוך "בדיקת מעבר" אני חושב ליצור ממשק חדש (AutomtionResultProvider שיחשוף רק מתודה אחת שתחזיק string כזה) בגרסה הבאה נעבור על כל המקומות שמספקים לוג לאוטומציה וכך נוכל ל"סמן" אותם.
&nbsp
חטפתי חום כשהברנש הראה לי שהוא אשכרה מחפש Map@2123221 להשוואה...
 

TakeCtrl

New member
לשם הבהרה ה"משתמש" הוא איש IT שרואה את הלוגים..

וכשאני אומר לא נראה טוב למשתמש אני מדבר על מה שרואים בקובץ הלוגים, האפליקציה היא server side לגמרי...
 

choo

Active member
פתרון אפשרי - הפרדת רמות לוגים לקבצים שונים

&nbsp
באפליקציה אחת שכתבתי, כל ההדפסות ברמת info ומעלה הולכות ללוג אחד. כל ההדפסות ברמת debug ומעלה הולכות ללוג אחר. אפשר גם שהלוג השני יכיל רק הדפסות debug (אם יש הרבה הדפסות ברמת info ומעלה) ולספק סקריפט שמבצע merge בין שני הלוגים עבור המפתחים.
&nbsp
עוד אפשרות - לכתוב הכל ללוג אחד, ולספק לאנשי ה-IT סקריפט שמפלטר מתוך הלוג רק את ההודעות ברמת הדבג שמעניינת אותם.
&nbsp
השיטה של "לא נוח למישהו אז שלא יהיו לוגים וננסה לנחש מה לא עבד בסדר" היא אנטי-פרודוקטיבית.
 

choo

Active member
שימוש בכמה handlers נפרדים

&nbsp
בכל הספריות בסגנון log4X ישנה אפשרות להצמיד כמה handlers שאתה רוצה לכל logger. את ה-log level אפשר לקבוע ברמת הלוגר, וגם ברמת ה-handloer. אז ללוגר נתתי רמת debug, ל-handler של קובץ אחד נתתי רמת info ול-handler של הקובץ השני נתתי רמת debug.
&nbsp
כדי להגיע למצב שבו קובץ הכיל רק את רמת ה-debug ולא את ההודעות ברמת ה-info ומעלה - השתמשי במכניזם של הספריה שנקרא filters. לכל handler אפשר להצמיד אובייטק פילטר, שכל הודעת לוג עוברת דרך מתודת filter שלו, שמחזירה True אם לבצע logging או False כדי לוותר על ההודעה. פונקצית הפילטר שלי זרקה לפח הודעות ברמה שמעל ל-debug.
&nbsp
נ.ב. במקרה שלי השתמשתי בספריות ה-logging של פייתון - אני משער שישנה פונקציונאליות דומה ב-log4j.
 

user32

Well-known member
מנהל
בlog4j זו פונקציונליות מובנית

אתה מגדיר בקונפיגורציה שני לוגרים, כל אחד לרמה אחרת (debug, warn וכו'). לכל לוגר אתה מצמיד את הappender הרצוי (כתיבה לקובץ, לconsole, וכו').
 
למעלה