Nie lubię logowania
Nie lubię logowania — brudzi mi w kodzie; narzekam, gdy podczas ratowania produkcji brak logów — jak żyć?!
Jestem leniwy, nie lubię pamiętać o tym i tamtym — lubię, gdy rzeczy dzieją się same i nie muszę sobie zawracać tym głowy. Ale bez przesady! Logi to najgorsze i najlepsze co może spotkać programistów — z jednej strony logi zaśmiecają kod, z drugiej strony dają podgląd na to, co użytkownicy wymyślili na produkcji.
AOP
Logowanie przy pomocy AOP oczyszcza kod w przypadku typowego i klasycznego podejścia do logów, ok — może to zrobić. Często szukam w logach tego, co zostało uruchomione i z jakim parametrem, aby zrozumieć, co poszło nie tak. Nie lubię ^C^V takiego kodu na początku każdej metody. Niestety nie znalazłem dobrego rozwiązania AOP (czytaj darmowego) a interfejs IIntercept
z jakiegoś powodu nie chce zostać uruchomiony (ale jest tworzony — kiedyś to zrozumiem); z tego powodu przy pomocy internetów znalazłem DispatchProxy
które świetnie robi swoją robotę.
DispatchProxy
Otóż chciałbym mieć możliwość logowania tego, co i jak się wywołuje z możliwością włączenia / wyłączenia detali (poziomy logowania w moim przypadku, lub inna forma konfiguracji). Chce móc przeczytać logi i dowiedzieć się co się wywołuje i z jakim parametrami, dla każdej metody, dodatkowo bez potrzeby modyfikacji kodu, gdy dana metoda się zmieni.
Można to zrobić przy pomocy DispatchProxy
które przechwyci wywołanie metody i umożliwi wykonanie dowolnego kodu; przed; po czy też podczas błędu.
Otóż taka klasa opina ładnie swoją docelową klasę T
, a następnie podczas tworzenia zwraca takie proxy, udając klasę typu podstawowego. Tutaj uwaga: konstruktor musi być pusty, a ewentualne przekazanie parametrów i ich przypisanie następuje w metody fabrykującej (wewnątrz if)
Gdy użytkownik takiej klasy wywołuje metodę docelową, na proxy wcześniej zostanie zawołane Invoke
gdzie można czynić cuda.
Ja na przykład na poziomie `Information` loguje nazwę wywoływanej metody, a na poziomie Debug dorzucam także nazwy i wartości przekazanych argumentów.
Rejestracja
Piękne jest to, że DispatchProxy
nie wymaga zewnętrznych bibliotek i działa na czysto z .net. Zależność do klasy rejestruje w taki sposób:
Akcja
Działa to tak:
Tutaj przykład konsumpcji oraz wykorzystania przykładowego serwisu
A tutaj logi:
Serwis jest nudny do bólu i prawie o nim zapomniałem:
Siup
W tak przygotowanym kodzie, zależności rejestrowane z pomocą logera powinny samodzielnie wrzucać informację o tym, co i jak się wykonało. Oczywiście można dodać sobie flagi do optymalizacji tego, czy przed, czy po co w sytuacjach wyjątkowych ma się logować i na jakim poziomie. Warto także pomyśleć o tym, jak takie logi ze sobą łączyć za pomocy correlationId – ale to pozostawiam już waszej wyobraźni.
ps.
dzisiaj bez obrazka