Logi wersja de luxe
Jestem leniem. Jestem leniem i nie cierpię marnowania swojego czasu na nudne i powtarzalne czynności. Podczas pracy z railsami zawsze bardzo mnie denerwowała ilość czasu potrzebna na znalezienie niezbędnej mi informacji w logach aplikacji. Mam na myśli oczywiście głównie prace w trybie development – kiedy do logów zagląda się bardzo często. Postanowiłem coś z tym zrobić...
Chciałbym aby informacje zrzucane do logów:
- zawierały informacje o miejscu z którego nastąpił zapis do logów – dzięki czemu prosto jest znaleźć fragmentu kodu z którego dany zapis został wygenerowany,
- dały się analizować za pomocą narzędzia wygodniejszego niż tail i grep – wiadomo obie te komendy to potęga – ale korzystanie z nich to nie jest dla mnie szczyt wygody,
- format logów był bardziej zbliżony do standardowych logów np. z apache’a czy log4j
log4r
Podczas pracy z Javą od niemal zawsze korzystam z biblioteki log4j. Myślę, że specjalnie przedstawiać tej biblioteki nie ma potrzeby, nawet komuś kto nie miał do czynienia z Javą, powstały bowiem już analogiczne rozwiązania dla innych popularnych języków programowania (jeżeli jednak się mylę krótka instrukcja znajduje się tutaj). Ruby także ma swój wersję biblioteki czyli - log4r, naturalnym więc wydaje się skorzystanie z już istniejących drzwi. Po zainstalowniu log4r (gem install log4r), konfiguracja aplikacji polega na dodaniu do pliku conf/environment.yml:
-
# --- logger
-
config.logger = Log4r::Logger.new('logger')
-
# Chcemy dolaczac do logow informacje o miejscu wywolania
-
config.logger.trace = true
-
# Priorytet zapisywanych informacji - tu zapisywane jest wszystko
-
config.logger.level = Log4r::DEBUG
-
-
# Co się dzieje z informacjami kierowanymi do loga - tu zapis do pliku
-
config.logger.add(Log4r::FileOutputter.new(:logger,
-
:filename => File.join(RAILS_ROOT, 'log', "#{RAILS_ENV}.log"),
-
:trunc => false,
-
:formatter => Log4r::PatternFormatter.new(:pattern => "%d %-5l %c (#{config.logger.trace ? '%t': ':'}) - %M")
-
))
W tym miejscu mam już logi które zawierają znacznie więcej informacji i to w bardziej standardowym formacie. Nadal jednak ich przeszukiwanie podczas pracy nad aplikacją jest zadaniem zbyt żmudnym jak dla mnie :)
Chainsaw
Wraz z biblioteką log4j od dłuższego czasu rozwijany jest program który stanowi rodzaj przeglądarki do logów. Początkowo był dołączany do samej biblioteki, ale od pewnego czasu istnieje jako osoby projekt – Chainsaw 2. Oto krótka lista jego możliwości:
- odbierania zdarzeń zdalnych,
- wyróżnianie kolorem poszczególnych priorytetów zgłoszonych zdarzeń,
- filtrowanie zdarzeń za pomocą filtrów treści tworzonych ad hoc,
- filtrowanie zdarzeń według kategorii.
Cechy przedstawione powyżej pozwalają na dużo sprawniejsze wyłuskanie potrzebnej informacji z logów. Jak uruchomić Chainsaw ? Najprościej jako Java Web Start (ale na stronie jest również wersja binarna do uruchomienia w zwykły sposób). Uruchominy program trzeba skonfigurować - najprościej chyba w taki sposób (taka konfiguracja potrzebna jest tylko raz):
- pobierz ten plik konfiguracyjny i umieść gdzieś na dysku,
- wybierz z menu View opcję Application-wide Preferences
- w zakładce General w polu o nazwie 'Automatic Configuration URL' wpisz scieżkę do pobranego pliku konfiguracyjnego np:
file:///D:/workspace/rails/chainsaw-config.xml
Uff, mamy więc już uruchomiony i skonfigurowany program do anlizy logów, pozostaje więc tylko...
Połączenie Chainsaw z log4r
Połączenie to realizuje chainsaw_outputter.rb (ściągnij ten plik i wrzuć go np. do katalogu lib/). Pozostaje jeszcze konfiguracja, na początku pliku conf/environment.yml dodaj linię:
-
require File.join(File.dirname(__FILE__),
-
'../lib/chainsaw_outputter')
a w pliku conf/environments/development.yml dodaj:
-
config.logger.add(Log4r::ChainsawOutputter.new(:logger))
W ten sposób połączenie z Chainsaw będzie tylko realizowane w trybie development. Po restarcie aplikacji Chainsaw powinien zacząć odbierać komunikaty z aplikacji i pokazywać je w zakładce o nazwie 'rails-app'. Warto jeszcze wyłączyć kolorowanie logów (ActiveRecord::Base.colorize_logging = false) - kody dla konsoli troche przeszkadzają w czytaniu logów.
Wyjaśnię jeszcze jedną sztuczkę jaką robi ChainsawOutputter. Pomysł na hierarchiczne kategorie jest chyba najbardziej przydatnym konceptem w całej rodzinie bibliotek log4x, niestety w przypadku railsów nie bardzo można wprost z niego skorzystać. Aby jednak nie tracić tej funkcjonalności ChainsawOutputter tworzy sztuczne kategorie ze ścieżki i nazwy skryptu. W ten sposób powstają kategorie np.: app/helper/auth_helper_rb czy lib/action_controller/cookies_rb – prawda że przydatne ? Acha żeby ta konwersja działała musi być ustawione config.logger.trace = true (tak jak w przykładowej konfiguracji powyżej)
Dla pewności podaję jeszcze raz kolejność działań:
1. uruchomienie chainsaw (+ konfiguracja jeżeli nie jest już skonfigurowany)
2. start aplikacji railsowej
Jeżeli kolejność będzie inna, albo Chainsaw nie będzie uruchomiony wcale – zauważysz znaczne spowolnienie w działaniu aplikacji – po prostu przy każdym dostępie logów będzie podejmowana próba połączenia z Chainsaw. Wystarczy jednak tylko jego uruchomienie i wszystko wraca do normy – nie ma wówczas potrzeby restartowania aplikacji.
Zakończenie
Niestety nie ma róży bez ognia, dodatkowe informacje jakie pojawiają się w logach (trace), ich formatowanie i wysyłanie przez socketa do Chainsaw to dodatkowa praca jaka musi zostać wykonana kosztem drobnego spadku wydajności railsowej aplikacji. Całe więc rozwiązanie jest przydatne tylko w trakcie developerki. Wersja produkcyjna aplikacji raczej powinna korzystać ze starego sposobu logowania informacji, a z pewnością powinna być pozbawiona komunikacji z Chainsaw.
TODO
W wolnej chwili postaram się z outputtera zrobić plugin do railsów co z pewnościa uprości instalację i korzystanie.
[config logger rails ruby]








scott said,
październik 24, 2007 @ 06:43
Chainsaw can also process regular text log files using LogFilePatternReceiver (see chainsaw-config.xml)