tifyty

pure Java, what else ?

Egy kis segédosztály debuggoláshoz

A debugger az debugger, megkönnyíti az életet, de az igazi hardcore programozó még mindig nem használ debuggert, csak loggol. Amúgy meg, esélyed sincs debuggolni éles környezetben, a fejlesztő és teszt környezetben pedig nem lehet a hibákat reprodukálni. Hogy miért nem lehet, azt senki sem tudja, de a tapasztalat az, hogy nem lehet. Ahogy az oroszok mondják, ha tudnak franciául: Act Of God.

Szóval nyomatjuk a logokat, mert mi hardcore-ok vagyunk, de persze kényelmesek is vagyunk, … Hol van már az az idő, amikor FORTRAN-ban… (Nem! Nem potencia növelő reklám követezik!) Szóval szeretnénk valamit ami loggol, és mondjuk loggolja, hogy merre járunk.

Mivel loggolunk? Na ez is megér egy misét, de most ebbe ne menjünk bele. Maradjunk abban, hogy SLF4J és mögötte, vízkereszt, vagy amit akartok. Ez a legjobb választás ma. Tegnap lehet, hogy más volt, és lehet, hogy holnap nem ez lesz a legjobb választás, de ma ez.

Sokszor csak arra vagyunk kíváncsiak, hogy merre jár a program. Teletűzdelhetjük mindenféle loggoló parancsokkal, amik ki is írják általában, hogy merre járunk, de kényelmesebb lenne ha csak annyit kellene írni, hogy Tracer.trace().

Ehhez készítettem magamnak egyszer (most meg újra) egy kis köcsögöt (gy.k.: JAR-t). Van benne egy interface, mert azért azt úgy illik Tracer meg egy gyár is (factory) TracerFactory, és néhány implementáció: NullTracer (ez nem csinál semmit) valamint SimpleTracer.

Az inteface nagyon egyszerű:

package tifyty.utility.debugtracer;
public interface Tracer {
	public abstract void trace();
	public abstract void trace(final String name, Object ... objects);
}

és az egyszerű implementáció is:

package tifyty.utility.debugtracer;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class SimpleTracer implements Tracer {
	private final Logger LOG;

	protected SimpleTracer(final String name) {
		LOG = LoggerFactory.getLogger(name);
	}

	public void trace() {
		trace(null);
	}

	public void trace(final String name, final Object... parameters) {
		final StackTraceElement[] ste = Thread.currentThread().getStackTrace();
		final StackTraceElement caller = ste[name == null ? 3 : 2];
		LOG.info("{}:{}/{}.{}({})",
				new Object[] { caller.getFileName(), caller.getLineNumber(),
						caller.getClassName(), caller.getMethodName(), name });
	}
}

A null implementáció meg aztán a legegyszerűbb, mint egy fakecske:

package tifyty.utility.debugtracer;
public class NullTracer implements Tracer {
	public void trace() {
	}
	public void trace(final String name, Object ... objects) {
	}
}

NOTE: A commentekben ne vitázzunk a loggolókról. Ha kell, szavazzatok arra, hogy kivesézzem azt a témát, és akkor majd ott. És akkor az elmaradhatatlan szavazó:

9 responses to “Egy kis segédosztály debuggoláshoz

  1. viktort július 23, 2012 12:46 du.

    Sima debug level loggolas miert nem jo? Sokkal tobbet nem kell gepelni, amugyis letezik kodkiegeszites mar manapsag.

  2. zmb július 23, 2012 12:59 du.

    Bugot jelentenek be: a getStackTrace javadocja szerint “Some virtual machines may, under some circumstances, omit one or more stack frames from the stack trace. In the extreme case, a virtual machine that has no stack trace information concerning this thread is permitted to return a zero-length array from this method.”. Szoval elofordulhat, hogy elcsattan a kod.

    • v július 23, 2012 10:09 du.

      Igen. Kösz. Ebben az esetben egy ilyen utility nem használható. Btw: ismer valaki ilyen JVM implementációt?

      • zmb július 24, 2012 8:35 de.

        Igen, pl az Oracle java neha lesporolja. Bovebben: “The compiler in the server VM now provides correct stack backtraces for all “cold” built-in exceptions. For performance purposes, when such an exception is thrown a few times, the method may be recompiled. After recompilation, the compiler may choose a faster tactic using preallocated exceptions that do not provide a stack trace. To disable completely the use of preallocated exceptions, use this new flag: -XX:-OmitStackTraceInFastThrow.”
        http://java.sun.com/j2se/1.5.0/relnotes.html HotSpot VMs szakasz, utolso elotti potty.

      • v július 24, 2012 9:29 de.

        Az exception mellé egy előre csomagolt stack trace-t rak, de ez nem befolyásolja a Thread.currentThread().getStackTrace() hívást, legalábbis erről nem mond semmit az idézett szöveg.

        Persze ez a StackTrace játék máshol is okoz gondot, és ezért is inkább csak játék ez a dolog. Például ha valamilyen konténer alatt dolgozunk, vagy AOP-t használunk akkor a StackTrace-ben benne lesznek a konténer proxy osztályai is, és nem feltétlenül ezekre vagyunk kíváncsiak.

        Ez utóbbira egyébként úgy jöttem rá, hogy írtam egy olyan utility osztályt, amelyik lekérte a megfelelő loggert úgy, hogy a strack trace-en kikereste, hogy őt ki hívta, és annak az osztálynak a loggerét kérte el. Így nem kellett belemásolni (mert ugye másolni nem szeretünk) az osztály nevét a LoggerFactory.getLogger() paraméterébe. Aztán működött is, Spring alatt huzalozva, viszont adogatta a proxy osztály loggerét. Ez pár éve volt.

      • zmb július 25, 2012 8:39 de.

        Igazad van, kicsit csaltam. Az Oracle Java java.lang.Thread.getStackTrace() metodusaba belepislantva, ha a futo szal stack tracet kered le, akkor csak siman peldanyosit egy kivetelt, es attol keri el a stack tracet. Tapasztaltuk viszont, hogy NPE eseten neha lesporolta a jvm a stack tracet. Ezert vagtam be azt az idezetet, amit.

  3. Rév Tamás július 23, 2012 9:45 du.

    Én is bugot jelentek be: A SimpleTracer.trace(final String name, final Object… parameters) implementációja ignorálja a parameters varargot. Ami érdekes meglepetéseket okozhat, ha más is elkezdi használni a libet.

    Amúgymeg githubra vele 😉

  4. v július 23, 2012 10:19 du.

    Ami a “GitHUB-ra vele” dolgot illeti, a tervekben az szerepel, hogy ha kiderül, hogy nem “melegvíz” a projekt, és nem olyasmi, amire senkinek sincs szüksége, akkor olyan implementációt szeretnék készíteni, amelyik nem csak a stack trace-t írja ki, hanem reflection-nel elkérve a field-eket is.

    De szeretném már most jelezni, hogy nem szeretek olyat fejleszteni, ami már megvan, ami felesleges, és az ilyen kutatásokban, hogy mi az ami már implementálva van, gyenge vagyok.

Vélemény, hozzászólás?

Adatok megadása vagy bejelentkezés valamelyik ikonnal:

WordPress.com Logo

Hozzászólhat a WordPress.com felhasználói fiók használatával. Kilépés / Módosítás )

Twitter kép

Hozzászólhat a Twitter felhasználói fiók használatával. Kilépés / Módosítás )

Facebook kép

Hozzászólhat a Facebook felhasználói fiók használatával. Kilépés / Módosítás )

Google+ kép

Hozzászólhat a Google+ felhasználói fiók használatával. Kilépés / Módosítás )

Kapcsolódás: %s

%d blogger ezt kedveli: