Jednoduché logování ve Springu

Tušil jsem, že to je jednoduché, ale že to je AŽ tak jednoduché, to jsem nevěděl. Dokončujeme projekt pro jednu velkou českou banku a potřebovali jsme mít podrobným logováním pokrytou co největší část aplikace pro případ, že by se vyskytly problémy na prostředí, do kterého, z bezpečnostních důvodů, nemáme a nikdy nebudeme mít přístup.

Jako principiální odpůrce manuální práce jsem ihned zavrhnul myšlenku na manuální procházení kódu a rutinní vkládání debug logování pro strýčka příhodu (krom složitějších metod, kde je to nezbytně nutné).

Další má myšlenka samozřejmě směřovala k AOP. Už jsem si napsal kostru vlastní advice a chystal se psát aspekt, když ...

... jsem objevil, že vše je již skvěle připraveno v core balíku Spring Frameworku. Pro ty, kdo tedy o tomto pokladu ještě nevíte připojuji ukázku konfigurace. Vše bylo hotovo za 5 minut:


<bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
<property name="proxyTargetClass" value="true"/>
<property name="beanNames" value="*Manager,*Storage"/>
<property name="interceptorNames" value="loggingAdvice"/>
</bean>
<bean id="loggingAdvice" class="org.springframework.aop.interceptor.CustomizableTraceInterceptor">
<property name="useDynamicLogger" value="true"/>
<property name="hideProxyClassNames" value="true"/>
<property name="enterMessage" value="Entering method '$[methodName]' of class [$[targetClassShortName]], args: $[arguments]"/>
<property name="exitMessage" value="Exiting method '$[methodName]' of class [$[targetClassShortName]], returned: $[returnValue], execution time: $[invocationTime]"/>
<property name="exceptionMessage" value="Exception $[exception] thrown in method '$[methodName]' of class [$[targetClassShortName]]"/>
</bean>

Výše uvedený snippet zajistí to, že všechny beany, které jsou ve stejném aplikačním kontextu jako tato deklarace a jejichž názvy končí řetězci "Manager" a nebo "Storage" budou automaticky owrapovány dynamickou proxy, která bude aplikovat CustomizableTraceInterceptor. Tento interceptor zajistí, že:

  • bude zalogováno volání jakékoliv public metody beany včetně vstupních argumentů
  • bude zalogována výstupní hodnota včetně času, které vykonání metody trvalo
  • v případě ukončení volání vyjímkou, bude tato vyjímka také zalogována
  • logování bude na TRACE levelu a pokud je nastaveno logování pouze na vyšší úrovni, nebude volání metod v podstatě nijak výrazně zpomaleno
  • zalogované záznamy budou aplikovat původní název třídy jako název použitého loggeru (tzn. ignorují se názvy proxy class i interceptoru)

Zajímavých interceptorů připravených rovnou k použití poskytuje Spring více:

  • ConcurrencyThrottleInterceptor - omezuje paralelní volání metod dané instance
  • PerformanceMonitorInterceptor - umožňuje jednoduché logování výkonnostních otisků (tzn. jak dlouho trval běh konkrétního volání metody instance)
  • DebugInterceptor - jednoduché (fixní) logování metod dané instance
  • CustomizableTraceInterceptor - umožňuje customizovatelné transparentní logování volání metod dané instance

Nuže pokud, jste pouze tušili a nebyli si jistí, že je to se Springem jednoduché - teď už víte ...