protected function fetchTrace(array $trace, &$file = null, &$line = null, $ignoreTraceCalls = 0) {
		$ignoreByNumber = is_numeric($ignoreTraceCalls) ? $ignoreTraceCalls : 0;
		$ignoreByClassPrefixes = is_array($ignoreTraceCalls) ? array_merge($ignoreTraceCalls, array(__NAMESPACE__)) : null;

		foreach($trace as $i => $call) {
			if(!$file && $i == $ignoreTraceCalls && isset($call['file'])) {
				$file = $call['file'];
				$line = $call['line'];
			}
			if($ignoreByClassPrefixes && isset($call['class'])) {
				foreach($ignoreByClassPrefixes as $classPrefix) {
					if(strpos($call['class'], $classPrefix) !== false) {
						unset($trace[$i]);
						continue;
					}
				}
			}
			if($i < $ignoreByNumber || (isset($call['file']) && $call['file'] == $file && $call['line'] == $line)) {
				unset($trace[$i]);
			}
		}

		$traceCalls = array();
		foreach(array_reverse($trace) as $call) {
			$args = array();
			if(isset($call['args'])) {
				foreach($call['args'] as $arg) {
					if(is_object($arg)) {
						$args[] = get_class($arg);
					}
					elseif(is_array($arg)) {
						$args[] = 'Array[' . count($arg) . ']';
					}
					else {
						$arg = var_export($arg, 1);
						$args[] = strlen($arg) > 15 ? substr($arg, 0, 15) . '...\'' : $arg;
					}
				}
			}

			if(strpos($call['function'], '{closure}')) {
				$call['function'] = '{closure}';
			}

			$traceCall = new TraceCall();
			$traceCall->call = (isset($call['class']) ? $call['class'] . $call['type'] : '') . $call['function'] . '(' . implode(', ', $args) . ')';
			if(isset($call['file'])) {
				$traceCall->file = $call['file'];
			}
			if(isset($call['line'])) {
				$traceCall->line = $call['line'];
			}
			$traceCalls[] = $traceCall;
		}
		return $traceCalls;
	}