protected String formatOutput(final String logService, final LogLevel l,
		final String msg, final Throwable t)
	{
		final StringBuffer b = new StringBuffer(150);
		final int yr;
		final int mth;
		final int day;
		final int hr;
		final int min;
		final int sec;
		final int ms;
		synchronized (c) {
			c.setTimeInMillis(System.currentTimeMillis());
			yr = c.get(Calendar.YEAR);
			mth = c.get(Calendar.MONTH) + 1;
			day = c.get(Calendar.DAY_OF_MONTH);
			hr = c.get(Calendar.HOUR_OF_DAY);
			min = c.get(Calendar.MINUTE);
			sec = c.get(Calendar.SECOND);
			ms = c.get(Calendar.MILLISECOND);
		}
		b.append(yr);
		b.append('-').append(pad2Digits(mth));
		b.append('-').append(pad2Digits(day));
		b.append(' ').append(pad2Digits(hr));
		b.append(':').append(pad2Digits(min));
		b.append(':').append(pad2Digits(sec));
		b.append(',');
		if (ms < 99)
			b.append('0');
		b.append(pad2Digits(ms));
		b.append(' ').append(l.toString());
		if (logService.length() > 0)
			b.append(", ");
		// get index after last dot character
		final int dot = logService.lastIndexOf('.') + 1;
		// if dot is in character sequence but followed by a digit, append unmodified name
		// otherwise, append only name part after dot
		if (dot > 0 && dot < logService.length() && Character.isDigit(logService.charAt(dot)))
			b.append(logService);
		else
			b.append(logService.substring(dot));

		b.append(": ").append(msg);
		if (t != null) {
			b.append(" (").append(msgFromThrowable(t)).append(")");

			if (logLevel.equals(LogLevel.FATAL)) {
				final StackTraceElement[] trace = t.getStackTrace();
				for (int i = 0; i < trace.length; ++i)
					b.append("\n").append("\t").append(trace[i]);
			}
		}
		return b.toString();
	}