רישום רישום שוטף

1. סקירה כללית

במדריך זה נדבר על מסגרת Flogger, ממשק API רישום שוטף עבור Java שתוכנן על ידי גוגל.

2. מדוע להשתמש בפלוגר?

עם כל מסגרות הרישום הקיימות כיום בשוק, כמו Log4j ו- Logback, מדוע אנו זקוקים למסגרת רישום נוספת?

מתברר שלפלוגר יש כמה יתרונות על פני מסגרות אחרות - בואו נסתכל.

2.1. קְרִיאוּת

האופי הרהוט של ממשק ה- API של פלוגר עושה דרך ארוכה להפוך אותו לקריא יותר.

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

עם מסגרת רישום מסורתית, היינו רואים משהו כמו:

int i = 0; // ... if (i% 10 == 0) {logger.info ("יומן זה מציג כל 10 חזרות"); i ++; }

אך כעת, עם פלוגר, ניתן לפשט את האמור לעיל ל:

logger.atInfo (). כל (10) .log ("יומן זה מציג כל 10 חזרות");

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

2.2. ביצועים

חפצי רישום מותאמים כל עוד אנו נמנעים מלהתקשר toString על האובייקטים המחוברים:

משתמש משתמש = משתמש חדש (); logger.atInfo (). log ("המשתמש הוא:% s", משתמש);

אם נרשם, כפי שמוצג לעיל, ל- backend יש אפשרות לבצע אופטימיזציה של הרישום. מצד שני, אם נתקשר toString ישירות, או לשרשר את המיתרים ואז ההזדמנות הזו הולכת לאיבוד:

logger.atInfo (). log ("המשתמש הזה הוא:% s", user.toString ()); logger.atInfo (). log ("המשתמש הזה הוא:% s" + משתמש);

2.3. פְּרִישׁוּת

מסגרת Flogger כבר מכסה את רוב הפונקציונליות הבסיסית לה היינו מצפים ממסגרת רישום.

עם זאת, ישנם מקרים שנצטרך להוסיף לפונקציונליות. במקרים אלה, ניתן להרחיב את ה- API.

נכון לעכשיו, זה דורש כיתת תמיכה נפרדת. אנו יכולים, למשל, להרחיב את ה- API של Flogger על ידי כתיבת a UserLogger מעמד:

logger.at (INFO) .forUserId (id) .withUsername (username) .log ("הודעה:% s", param);

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

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

2.4. יְעִילוּת

מסגרות מסורתיות משתמשות בהרחבה בווארגס. שיטות אלה דורשות חדש לְהִתְנַגֵד[] להקצות ולמלא לפני שניתן להפעיל את השיטה. בנוסף, כל סוגי היסוד המועברים חייבים להיות בתיבות אוטומטיות.

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

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

מסגרת רישום טיפוסית כוללת את השיטות הבאות:

level (String, Object) level (String, Object ...)

איפה רָמָה יכול להיות אחד משבעה שמות ברמת יומן (חָמוּר לדוגמא), וכן יש שיטת יומן קנוני המקבלת רמת יומן נוספת:

יומן (רמה, אובייקט ...)

בנוסף לכך, בדרך כלל ישנן גרסאות לשיטות הגורמות סיבה (א זורק למשל) המשויך להצהרת היומן:

level (Throwable, String, Object) level (Throwable, String, Object ...)

ברור כי ה- API מצמד שלוש חששות לשיחת שיטה אחת:

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

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

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

logger.atInfo (). withCause (e) .log ("הודעה:% s", arg);

בואו נסתכל כיצד אנו יכולים להשתמש בו בבסיס הקוד שלנו.

3. תלות

זה די פשוט להגדיר את פלוגר. אנחנו רק צריכים להוסיף מלקה ו flogger-system-backend שלנו פום:

  com.google.flogger flogger 0.4 com.google.flogger flogger-system-backend 0.4 runtime 

עם הגדרת תלות אלה, כעת נוכל להמשיך ולחקור את ה- API העומד לרשותנו.

4. חקר ה- API השוטף

ראשית, בואו נכריז על א סטָטִי למשל עבור הלוגר שלנו:

סופי סטטי פרטי FluentLogger logger = FluentLogger.forEnclosingClass ();

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

תוצאה int = 45/3; logger.atInfo (). log ("התוצאה היא% d", תוצאה);

הודעות היומן יכולות להשתמש בכל אחת מה- Java printf מפרט פורמט, כגון % s,% d אוֹ % 016x.

4.1. הימנעות מעבודה באתרי יומן

יוצרי ה- Flogger ממליצים לנו להימנע מלעשות עבודה באתר היומן.

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

מחרוזת סטטית ציבורית collectSummaries () {longRunningProcess (); פריטי int = 110; int s = 30; return String.format ("% d שניות חלפו עד כה.% d פריטים ממתינים לעיבוד", s, פריטים); }

מפתה להתקשר collectSummaries ישירות בהצהרת היומן שלנו:

logger.atFine (). log ("stats =% s", collectSummaries ());

בלי קשר לרמות היומן המוגדרות או להגבלת התעריפים, ה- collectSummaries כעת ייקרא שיטה בכל פעם.

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

במקום זאת, עלינו להשתמש ב- LazyArgs.lazy שיטה:

logger.atFine (). log ("stats =% s", LazyArgs.lazy (() -> collectSummaries ()));

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

למרות שמותר לשמור על הצהרות יומן באמצעות isEnabled:

אם (logger.atFine (). isEnabled ()) {logger.atFine (). log ("סיכומים =% s", collectSummaries ()); }

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

4.2. התמודדות עם חריגים

מה לגבי חריגים, כיצד אנו מטפלים בהם?

ובכן, פלוגר מגיע עם withStackTrace שיטה בה אנו יכולים להשתמש כדי לרשום א זורק למשל:

נסה {int result = 45/0; } לתפוס (RuntimeException re) {logger.atInfo (). withStackTrace (StackSize.FULL) .withCause (re) .log ("הודעה"); }

איפה withStackTrace לוקח כוויכוח את גודל ערימה enum עם ערכים קבועים קטן בינוני גדול אוֹ מלא. עקבות מחסנית שנוצרו על ידי withStackTrace () יופיע כ- LogSiteStackTrace חריג ברירת המחדל java.util.logging backend. עם זאת, גיבויים אחרים עשויים להתמודד עם זה אחרת.

4.3. תצורת רישום רישומים

עד כה השתמשנו logger.atInfo ברוב הדוגמאות שלנו, אך פלוגר תומך ברמות רבות אחרות. אנו נסתכל על אלה, אך ראשית, בואו נציג כיצד להגדיר את אפשרויות הרישום.

כדי להגדיר רישום רישום, אנו משתמשים ב- LoggerConfig מעמד.

לדוגמא, כאשר אנו רוצים להגדיר את רמת הרישום בסדר גמור:

LoggerConfig.of (logger) .setLevel (Level.FINE);

ו- Flogger תומך ברמות כניסה שונות:

logger.atInfo (). log ("הודעת מידע"); logger.atWarning (). log ("הודעת אזהרה"); logger.atSevere (). log ("הודעה חמורה"); logger.atFine (). log ("הודעה בסדר"); logger.atFiner (). log ("הודעה דקה יותר"); logger.atFinest (). log ("ההודעה הטובה ביותר"); logger.atConfig (). log ("הודעת תצורה");

4.4. גבול דירוג

מה לגבי נושא הגבלת התעריפים? כיצד נתמודד עם המקרה בו איננו רוצים לתעד כל איטרציה?

פלוגר נחלץ לעזרתנו עם כל (int n) שיטה:

IntStream.range (0, 100) .forEach (value -> {logger.atInfo (). Every (40) .log ("יומן זה מציג כל 40 חזרות =>% d", ערך);});

אנו מקבלים את הפלט הבא כאשר אנו מריצים את הקוד לעיל:

18 בספטמבר 2019 17:04:02 com.baeldung.flogger.FloggerUnitTest lambda $ givenAnInterval_shouldLogAfterEveryTInterval $ 0 מידע: יומן זה מציג כל 40 חזרות => 0 [CONTEXT ratelimit_count = 40] 18 בספטמבר 2019 17:04:02 com. baeldung.flogger.FloggerUnitTest lambda $ givenAnInterval_shouldLogAfterEveryTInterval $ 0 מידע: יומן זה מציג כל 40 חזרות => 40 [CONTEXT ratelimit_count = 40] 18 בספטמבר, 2019 17:04:02 com.baeldung.flogger.FloggerUnitTestInAnaInTal_Lavda_Instal_Instagram_Instagram: יומן מראה כל 40 איטרציות => 80 [CONTEXT ratelimit_count = 40]

מה אם נרצה להיכנס להגיד כל 10 שניות? לאחר מכן, אנחנו יכולים להשתמש atMostEvery (int n, יחידת TimeUnit):

IntStream.range (0, 1_000_0000) .forEach (value -> {logger.atInfo (). AtMostEvery (10, TimeUnit.SECONDS) .log ("יומן זה מראה [כל 10 שניות] =>% d", ערך); });

עם זאת, התוצאה הופכת כעת:

18 בספטמבר 2019 17:08:06 com.baeldung.flogger.FloggerUnitTest lambda $ givenATimeInterval_shouldLogAfterEveryTimeInterval $ 1 מידע: יומן זה מראה [כל 10 שניות] => 0 [CONTEXT ratelimit_period = "10 SECONDS"] 18 בספטמבר, 2019 5:08 : 16:00 com.baeldung.flogger.FloggerUnitTest lambda $ givenATimeInterval_shouldLogAfterEveryTimeInterval $ 1 מידע: יומן זה מציג [כל 10 שניות] => 3545373 [CONTEXT ratelimit_period = "10 SECONDS [דילג: 3545372]"] 18 בספטמבר, 2019 5:08 ראש ממשלה com.baeldung.flogger.FloggerUnitTest lambda $ givenATimeInterval_shouldLogAfterEveryTimeInterval $ 1 מידע: יומן זה מראה [כל 10 שניות] => 7236301 [CONTEXT ratelimit_period = "10 שניות [דילג: 3690927]"]

5. שימוש בפלוגר עם גב גב אחר

אז מה אם נרצה הוסף את Flogger ליישום הקיים שלנו שכבר משתמש באומר Slf4j או Log4j לדוגמה? זה יכול להיות שימושי במקרים בהם נרצה לנצל את התצורות הקיימות שלנו. Flogger תומך במספר backends כפי שנראה.

5.1 פלוגר עם Slf4j

זה פשוט להגדיר קצה אחורי של Slf4j. ראשית, עלינו להוסיף את flogger-slf4j-backend תלות שלנו פום:

 com.google.flogger flogger-slf4j-backend 0.4 

בשלב הבא עלינו לומר לפלוגר שאנחנו רוצים להשתמש בקצה אחורי שונה מברירת המחדל. אנו עושים זאת על ידי רישום מפעל Flogger באמצעות מאפייני מערכת:

System.setProperty ("flogger.backend_factory", "com.google.common.flogger.backend.slf4j.Slf4jBackendFactory # getInstance");

ועכשיו היישום שלנו ישתמש בתצורה הקיימת.

5.1 פלוגר עם Log4j

אנו פועלים לפי צעדים דומים להגדרת תצורה של אחורי Log4j. בואו נוסיף את flogger-log4j-backend תלות שלנו פום:

 com.google.flogger flogger-log4j-backend 0.4 com.sun.jmx jmxri com.sun.jdmk jmxtools javax.jms jms log4j log4j 1.2.17 log4j apache-log4j-תוספות 1.2.17 

עלינו גם לרשום מפעל עורפי של Flogger ל- Log4j:

System.setProperty ("flogger.backend_factory", "com.google.common.flogger.backend.log4j.Log4jBackendFactory # getInstance");

וזהו, היישום שלנו מוגדר כעת לשימוש בתצורות Log4j קיימות!

6. מסקנה

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

ראינו גם כיצד אנו יכולים למנף את התצורות הקיימות שלנו על ידי רישום קצות אחוריים שונים כמו Slf4j ו- Log4j.

כרגיל, קוד המקור של הדרכה זו זמין ב- GitHub.


$config[zx-auto] not found$config[zx-overlay] not found