Stacktrace ausgabe.

redX

Erfahrenes Mitglied
Hallo

Ich brauche einen anschaulichen Stacktrace, welcher ich zu Debug zwecken benutze.

Ich habe mal die beiden Funktionen debug_backtrace und debug_print_backtrace getestet. Aber beide geben jeweils alle Informationen aller Objekte aus, was in einer unentlich langer Liste ausartet. Gibts irgend eine kurze Version davon?

Denke da an sowas wie in Java, das angezeigt wird, woher der Fehler kommt. Also das man sieht, wo welche Funktion aufgerufen wurde. In welchem File und in welcher Zeile. Den Inhalt der Variablen etc muss ich nicht wissen.

So was in der art:
net.sf.hibernate.exception.GenericJDBCException: could not insert: [com.alcatel.jtm.hibernate.pojo.TestPlan#7e9da77a-7e9d-a77a-7e9da77a7e9da77a]
at net.sf.hibernate.exception.SQLStateConverter.handledNonSpecificException(SQLStateConverter.java:80)
at net.sf.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:69)
at net.sf.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:29)
at net.sf.hibernate.persister.AbstractEntityPersister.convert(AbstractEntityPersister.java:1331)
at net.sf.hibernate.persister.EntityPersister.insert(EntityPersister.java:472)
at net.sf.hibernate.persister.EntityPersister.insert(EntityPersister.java:436)
at net.sf.hibernate.impl.ScheduledInsertion.execute(ScheduledInsertion.java:37)
at net.sf.hibernate.impl.SessionImpl.execute(SessionImpl.java:2449)
at net.sf.hibernate.impl.SessionImpl.executeAll(SessionImpl.java:2435)
at net.sf.hibernate.impl.SessionImpl.execute(SessionImpl.java:2392)
at net.sf.hibernate.impl.SessionImpl.flush(SessionImpl.java:2261)
at net.sf.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:61)
at com.alcatel.jtm.HibernateDataHandler.replace(HibernateDataHandler.java:115)
at test.com.alcatel.jtm.HibernateDataHandlerTest.testDelete(HibernateDataTest.java:110)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:324)
at junit.framework.TestCase.runTest(TestCase.java:154)
at junit.framework.TestCase.runBare(TestCase.java:127)
at junit.framework.TestResult$1.protect(TestResult.java:106)
at junit.framework.TestResult.runProtected(TestResult.java:124)
at junit.framework.TestResult.run(TestResult.java:109)
at junit.framework.TestCase.run(TestCase.java:118)
at junit.framework.TestSuite.runTest(TestSuite.java:208)
at junit.framework.TestSuite.run(TestSuite.java:203)
at junit.textui.TestRunner.doRun(TestRunner.java:116)
at com.intellij.rt.execution.junit2.IdeaJUnitAgent.doRun(IdeaJUnitAgent.java:57)
at junit.textui.TestRunner.start(TestRunner.java:172)
at com.intellij.rt.execution.junit.TextTestRunner2.startRunnerWithArgs(TextTestRunner2.java:23)
at com.intellij.rt.execution.junit2.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:97)
at com.intellij.rt.execution.junit2.JUnitStarter.main(JUnitStarter.java:31)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:324)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:86)


Gibts da was?

Gruss
X
 
Habe mir nun selber was gebastelt:

PHP:
	/**
	 * Gets the stacktrace.
	 *
	 * @param Exception $exception The thrown exception.
	 * @return String Stacktrace.
	 */
	private function getStacktrace($exception = NULL) {		
		$stacktrace = debug_backtrace();
		$trace = "Stacktrace: ";
		if ($exception != NULL) {
			$trace .= get_class($exception) . ":" . str_ireplace("\n", "", $exception->getMessage());
		}
		
		for ($i = 3;$i < count($stacktrace); $i++) {
			$trace .= "\n" . $stacktrace[$i]["class"] . $stacktrace[$i]["type"] . $stacktrace[$i]["function"] . "(" . $stacktrace[$i]["file"] . "@" . $stacktrace[$i]["line"] . ")";
		}
		
		return $trace;
		
		/*
		ob_start();
		var_dump(debug_backtrace());
		$backtraceDump = ob_get_contents();
		ob_end_clean();
		return str_replace("  ", "..", $backtraceDump);
		*/
	}

	/**
	 * Prints a stacktrace to the logger.
	 */
	public function printStacktrace($priority, $exception = NULL){
		if (STACKTRACE_LOG_LEVEL >= $priority) {
			$this->logger->log($this->getStacktrace($exception),$priority);
		}
	}
Die Funktion printStacktrace übergibt ab einem bestimmten Log Level den Stacktrace an den Logger. Der Stacktrace wird mit der getStacktrace Funktion zusammengebaut.

In der Function getStacktrace habe ich eine for Schleife mit dem Offset 2. Damit werden die letzten 3 Nachrichten des debug_backtrace() übersprungen. Die letzten 3 Funktionen kommen alle vom Error Handling, und die Interessieren mich natürlich nicht. Deshalb werden die einfach nicht angezeigt.
Ich habe bei der $exception->message noch alle \n entfernt. Der Logger wandelt \n automatisch in <br /> um. Und das sieht unsexy aus, vorallem wenn dann lange Sql Query ausgegeben werden.


Die Ausgabe sieht folgendermassen aus (SQL Query und Pfadangaben wurden entfernt/gekürtzt)

[Event_History] Critical:
Stacktrace: DB_Exception:Invalid SQL query [ INSERT INTO blablabla ] Error message [Column count doesn't match value count at row 1]
Event_History->saveEvent(/blabla/bla/event_controller.php@201)
Event_Controller->executeEvent(/blabla/bla/event_controller.php@146)
Event_Controller->__construct(/blabla/bla/event_controller.php@277)
Event_Controller::getInstance(/blabla/bla/index.php@93)
main->__construct(/blabla/bla/index.php@98)

Gruss
X
 
Zurück