/** * Signal that this thread will not log any more messages in the multithreaded * environment */ public static void finishThread(){ //--Create Task final long threadId = Thread.currentThread().getId(); Runnable finish = () -> releaseThreadControl(threadId); //--Run Task if(isThreaded){ //(case: multithreaded) attemptThreadControl( threadId, finish ); } else { //(case: no threading) Redwood.log(Flag.WARN, "finishThreads() called outside of threaded environment"); } }
Redwood.log(Flag.WARN, "endThreads() called, but thread " + currentThread + " has not finished (exception in thread?)"); if(backlog.isEmpty()){ Redwood.log(Flag.WARN, "Forgot to call finishThread() on thread " + currentThread); } assert !control.isHeldByCurrentThread(); backlog.poll().run(); assert ! threadsWaiting.isEmpty(); control.lock(); attemptThreadControlThreadsafe(-1); control.unlock(); endTrack("Threads( "+check+" )");
Redwood.log("hello world!"); Redwood.log(Redwood.ERR, "an error!"); final int fI = i; tasks.add(() -> { startTrack("Runnable " + fI); log(Thread.currentThread().getId()); log("message " + fI + ".1"); log("message " + fI + ".2"); log("message " + fI + ".3"); log(FORCE,"message " + fI + ".4"); log("message " + fI + ".5"); forceTrack("Runnable " + fI + ".1"); endTrack("Runnable " + fI + ".1"); forceTrack("Runnable " + fI + ".2"); log("a message"); endTrack("Runnable " + fI + ".2"); forceTrack("Runnable " + fI + ".3"); log("a message"); log(FORCE,"A forced message"); endTrack("Runnable " + fI + ".3"); endTrack("Runnable " + fI); }); startTrack("Wrapper"); for(int i=0; i<100; i++){ Util.threadAndRun(tasks, 100); endTrack("Wrapper");
/** * Clear any custom configurations to Redwood * @return this */ public RedwoodConfiguration clear(){ this.tasks = new LinkedList<>(); this.tasks.add(() -> { Redwood.clearHandlers(); Redwood.restoreSystemStreams(); }); this.outputHandler = Redwood.ConsoleHandler.out(); return this; }
Redwood.log(Redwood.DBG, "at the top"); Redwood.startTrack("Adaptor test controlled by redwood"); topLogger.info("FYI"); Redwood.log(Redwood.DBG, "adapting"); JavaUtilLoggingAdaptor.adapt(); topLogger.warning("I'm warning you in Redwood!"); topLogger.severe("We shouldn't see this message."); Redwood.log(Redwood.DBG, "at the bottom"); Redwood.endTrack("Adaptor test controlled by redwood"); } else { logger.log(Level.INFO, "Hello from the class logger"); Redwood.log("Hello from Redwood!"); Redwood.rootHandler().addChild( RedirectOutputHandler.fromJavaUtilLogging(topLogger)); Redwood.log("Hello from Redwood -> Java!"); Redwood.log("Hello from Redwood -> Java again!"); logger.log(Level.INFO, "Hello again from the class logger"); Redwood.startTrack("a track"); Redwood.log("Inside a track"); logger.log(Level.INFO, "Hello a third time from the class logger"); Redwood.endTrack("a track"); logger.log(Level.INFO, "Hello a fourth time from the class logger");
@Override public void run(){ startTrack("Runnable " + fI); log(Thread.currentThread().getId()); log("message " + fI + ".1"); log("message " + fI + ".2"); log("message " + fI + ".3"); log(FORCE,"message " + fI + ".4"); log("message " + fI + ".5"); forceTrack("Runnable " + fI + ".1"); endTrack("Runnable " + fI + ".1"); forceTrack("Runnable " + fI + ".2"); log("a message"); endTrack("Runnable " + fI + ".2"); forceTrack("Runnable " + fI + ".3"); log("a message"); log(FORCE,"A forced message"); endTrack("Runnable " + fI + ".3"); endTrack("Runnable " + fI); } });
@Override public void run() { startTrack("Thread " + theI + " (" + Thread.currentThread().getId() + ")"); for(int time=0; time<5; time++){ log("tick " + time + " from " + theI + " (" + Thread.currentThread().getId() + ")"); try { Thread.sleep(50); } catch (Exception e) {} } endTrack("Thread " + theI + " (" + Thread.currentThread().getId() + ")"); finishThread(); } });
/** * {@inheritDoc} */ @Override @SuppressWarnings("unchecked") public void prettyLog(RedwoodChannels channels, String description) { Redwood.startTrack(description); // sort keys by class name List<Class> sortedKeys = new ArrayList<>(this.keySet()); sortedKeys.sort(Comparator.comparing(Class::getCanonicalName)); // log key/value pairs for (Class key : sortedKeys) { String keyName = key.getCanonicalName().replace("class ", ""); Object value = this.get(key); if (PrettyLogger.dispatchable(value)) { PrettyLogger.log(channels, keyName, value); } else { channels.logf("%s = %s", keyName, value); } } Redwood.endTrack(description); }
private static void attemptThreadControl(long threadId, Runnable r){ //(get lock) boolean tookLock = false; if(!control.isHeldByCurrentThread()){ control.lock(); tookLock = true; } //(perform action) attemptThreadControlThreadsafe(threadId); if(threadId == currentThread){ r.run(); } else { queueTask(threadId, r); } //(release lock) assert control.isHeldByCurrentThread(); if(tookLock){ control.unlock(); } }
log(Flag.ERROR, "Track names do not match: expected: " + expected + " found: " + title); attemptThreadControl( threadId, endTrack ); } else {
public static String formatTimeDifference(long diff){ StringBuilder b = new StringBuilder(); formatTimeDifference(diff, b); return b.toString(); }
private static Redwood.RedwoodChannels logger = Redwood.channels(ParserGrammar.class);
public RedwoodConfiguration restore(final OutputStream stream) { if (stream == System.out) { tasks.add(() -> Redwood.captureSystemStreams(false, Redwood.realSysErr == System.err)); } else if (stream == System.err) { tasks.add(() -> Redwood.captureSystemStreams(Redwood.realSysOut == System.out, false)); } else { throw new IllegalArgumentException("Must capture one of stderr or stdout"); } return this; }
attemptThreadControl( threadId, startTrack ); } else {
/** * A utility method for closing calls to the anonymous startTrack() call. */ public static void endTrack(){ endTrack(""); }
public static void finishThread(){ Redwood.finishThread(); } public static void endThreads(String check){ Redwood.endThreads(check); }
public static void endThreads(String check){ Redwood.endThreads(check); }