Home > Polish > Nom, nom, nom. Yummie logs

Nom, nom, nom. Yummie logs

Dziś lightowo będzie. Ostatnio nie miałem czasu pisać to chcę nadrobić kilkoma krótszymi wpisami.

Większość z nas wie, że logowanie jest dobre. Wprawdzie są osoby, które uważają, że każda linia kodu do tworzenia logów to linia stracona, ale ja się z tym nie mogę zgodzić. By to wyjaśnić zacznijmy od mojej historii, by łatwiej było zrozumieć dlaczego dla mnie ten temat jest istotny.

Pan Michał uczył się programować w Javie na studiach, głównie z książki Core Java I i II oraz korzystając z pomocy Jakuba Neumana (z którym miałem laborki). Pojęcie debuggera było mi całkowicie obce, ba pojęcie IDE było obce. Do dziś pamiętam jak dziwiłem się po co w eclipsie trzeba tworzyć projekty. Przecież wystarczy wszystko skompilować i działa :P

Niestety, ale wtedy nie cały mój kod był tak doskonały jak jest teraz ;) Zdarzał się błędy :( Na szczęście to już za mną :E Wtedy trzeba było jednak znaleźć miejsce w którym aplikacja postąpiła źle (no bo wiadomo, że to nie ja się pomyliłem). Naturalnym rozwiązaniem było System.out.println(); najlepiej co drugą linijkę by zbierać informacje na temat stanu obiektu i możliwych przyczyn błędu. W pracy zacząłem szybko sam zauważać wady takiego podejścia i pojawiła się potrzeba posiadania jakiegoś lepszego medium do logowania. Wpierw próby z przekierowaniem System.out do pliku logów, następnie żmudna nauka log4j i kolejnych frameworków wspierających mnie w tym zadaniu. W moim kodzie znaleźć można przeważnie dużo log.trace/.debug , ponieważ nie jestem nauczony korzystać z debbugera. Walczę z sobą by korzystać z niego częściej, ale logi są przydatne i dla mnie wygodnie się z nimi pracuje. Ponadto są niemal nic nie kosztują przy odpowiednim zastosowaniu.

Log4j znać winien każdy, slf4j powinno się znać, jak nie znamy to polecam nadrobić, gdyż jest to świetna biblioteka, znacząco ułatwiająca logowanie. Tworząc ten wpis zakładam, że rozumiesz drogi czytelniku, po co tworzy się logi.

A gdzie w tym wszystkim Tapestry? Ano dziś pokażę wsparcie dla logowania. Przed, bądź po lekturze tego tekstu polecam wszystkim, którzy nie czytali, zapoznać się z serią wpisów  Tomasza Nurkiewicza na temat tworzenia logów. Teksty te wybiegają daleko ponad to co ja pokażę, tu wystarczy nam wiedzieć czym i po co są logi

No to zaczynajmy, spójrzmy na nasz projekt. Na stronie guessGame wyświetlamy aktualnie poprawny wynik. Nie jest to szczególnie mądre, gdybyśmy teraz wprowadzili opłaty i wygraną za poprawne trafienie, to szybko zostalibyśmy bankrutami. No, ale trzeb przecież sprawdzić czy aplikacja działa i co wylosowała, inaczej skąd mamy wiedzieć, że to w ogóle działa.

Po pierwsze wstrzykujemy instancję org.slf4j.Logger do naszej klasy

@Inject
private Logger log;

I tyle. Tapestry samo zadba o zainicjalizowanie loggera, jako że slf4j jest natywnie wspierany przez framework. Podczas poprawiania nawigacji, wyekstrahowaliśmy z metody setupRender metodę restet(). Wypada sprawdzić co zostało wylosowane

void reset() {
	numberToGuess = new Random().nextInt(10) + 1; // moved from setupRender
	log.debug("{} is drawed number", numberToGuess);
}

Wynik jest przewidywalny: [DEBUG] pages.GuessGame 6 is drawed number

No, ale mamy też bardziej typowe potrzeby logujące, np potrzebujemy sprawdzić co użytkownik kliknął by wiedzieć czy dobra wartość jest przekazywana do kolejnej strony.

Object onActionFromGuess(int guess) {
	log.debug("[Enter] onActionFromGuess with param '{}'", guess);
	final boolean isCorrectAnswer = numberToGuess == guess;
	resultPage.setCorrectAnswer(isCorrectAnswer);
	resultPage.setPlayerGuess(guess);
	log.debug("[Exit] onActionFromGuess to page '{}'", resultPage);
	return resultPage;
}

Wynik znów przewidywalny (kliknięty link nr 7)
[DEBUG] pages.GuessGame [Enter] onActionFromGuess with param ‘7’
[DEBUG] pages.GuessGame [Exit] onActionFromGuess to page ‘pl.rits.blog.projektBlogowy.pages.GuessResult@b52f79’

Problemem jest to, że  takich linii Enter – Exit w kodzie może się zrobić dużo. Do tego wyglądają niemal identycznie i idealnie zaśmiecają nam kod. W tym miejscu przychodzi nam z pomocą mała adnotacja @Log

Usuwamy obie linijki log.debug(…); z metody onActionFromGuess i wstawiamy nad nią adnotację @Log. Otrzymamy takie coś

@Log
Object onActionFromGuess(int guess) {
	final boolean isCorrectAnswer = numberToGuess == guess;
	resultPage.setCorrectAnswer(isCorrectAnswer);
	resultPage.setPlayerGuess(guess);
	return resultPage;
}

A wynikiem dla kliknięcia w 7 będzie
[DEBUG] pages.GuessGame [ENTER] onActionFromGuess(7)
[DEBUG] pages.GuessGame [ EXIT] onActionFromGuess [pl.rits.blog.projektBlogowy.pages.GuessResult@13d99c]

Czyli odrobinę inaczej niż ja sam napisałem, ale daje tyle samo informacji.

Adnotować można wszystkie metody na stronach, bez względu na ich widoczność. Adnotacja w pełni respektuje nasze ustawienia dla loggera więc gdy przenosimy się na produkcję, to nic nie będzie wyświetlane. Poziom logowania jest domyślnie ustawiony na Debug, ale można to zmienić.

To przyjemnego logowania i do następnego razu.

Advertisements
Categories: Polish Tags:
  1. No comments yet.
  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: