001/** 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 */ 019package org.apache.reef.util; 020 021import java.util.Map; 022import java.util.logging.Level; 023import java.util.logging.Logger; 024 025/** 026 * Methods to log the currently active set of threads with their stack traces. This is useful to log abnormal 027 * process exit situations, for instance the Driver timeout in the tests. 028 */ 029public final class ThreadLogger { 030 031 /** 032 * This is a utility class that shall not be instantiated. 033 */ 034 private ThreadLogger() { 035 } 036 037 /** 038 * Same as <code>logThreads(logger, level, prefix, "\n\t", "\n\t\t")</code> 039 */ 040 public static void logThreads(final Logger logger, final Level level, final String prefix) { 041 logThreads(logger, level, prefix, "\n\t", "\n\t\t"); 042 } 043 044 /** 045 * Logs the currently active threads and their stack trace to the given Logger and Level. 046 * 047 * @param logger the Logger instance to log to. 048 * @param level the Level to log into. 049 * @param prefix a prefix of the log message. 050 * @param threadPrefix logged before each thread, e.g. "\n\t" to create an indented list. 051 * @param stackElementPrefix logged before each stack trace element, e.g. "\n\t\t" to create an indented list. 052 */ 053 public static void logThreads( 054 final Logger logger, final Level level, final String prefix, 055 final String threadPrefix, final String stackElementPrefix) { 056 logger.log(level, getFormattedThreadList(prefix, threadPrefix, stackElementPrefix)); 057 } 058 059 /** 060 * Produces a String representation of the currently running threads. 061 * 062 * @param prefix The prefix of the string returned. 063 * @param threadPrefix Printed before each thread, e.g. "\n\t" to create an indented list. 064 * @param stackElementPrefix Printed before each stack trace element, e.g. "\n\t\t" to create an indented list. 065 * @return a String representation of the currently running threads. 066 */ 067 public static String getFormattedThreadList( 068 final String prefix, final String threadPrefix, final String stackElementPrefix) { 069 final StringBuilder message = new StringBuilder(prefix); 070 for (final Map.Entry<Thread, StackTraceElement[]> entry : Thread.getAllStackTraces().entrySet()) { 071 message.append(threadPrefix).append("Thread '").append(entry.getKey().getName()).append("':"); 072 for (final StackTraceElement element : entry.getValue()) { 073 message.append(stackElementPrefix).append(element.toString()); 074 } 075 } 076 return message.toString(); 077 } 078 079 /** 080 * Same as <code>getFormattedThreadList(prefix, "\n\t", "\n\t\t")</code> 081 */ 082 public static String getFormattedThreadList(final String prefix) { 083 return getFormattedThreadList(prefix, "\n\t", "\n\t\t"); 084 } 085 086 /** 087 * An example how to use the above methods. 088 * 089 * @param args ignored. 090 */ 091 public static void main(final String[] args) { 092 logThreads(Logger.getAnonymousLogger(), Level.INFO, "Threads active:"); 093 } 094}