Возможный тупик
Глядя на исходный код, я вижу, что блокировка получается на Category
при регистрации события, а затем блокировка получается на каждом AppenderSkeleton
, для которого событиеотправляется.Если два экземпляра Category
используют один и тот же appender (что является обычным), то попытка войти в систему с Appender
(или Filter
, подключенного к этому appender) может привести к тупику.
ДляНапример, есть два Category
объекта, C1
и C2
, и один Appender
, A
.Thread
T1
получает блокировку на C1
, затем A
, затем начинает обработку цепочки Filter
на A
.
Одновременно Thread
T2
получает блокировку на C2
.Он не может получить блокировку на A
, потому что он удерживается T1
, поэтому он ждет.
Теперь предположим, что T1
направлено (фильтром) на запись сообщения в C2
.Он не может получить блокировку на C2
, потому что он удерживается T2
.Deadlock.
Если вы опубликовали дополнительную информацию из дампа потока, должно быть возможно определить, является ли это истинным тупиком и, если да, какие объекты находятся в состоянии конфликта.
Возможное решение
Если это действительно то, что происходит, кажется, что проблемы можно избежать, регистрируя «повторное» сообщение только в «текущем» регистраторе, то есть регистраторе оцениваемого события.фильтромОдин из способов сделать это - отслеживать повторы для каждого регистратора.
public class RepeatFilter
extends Filter
{
private final Map<Category, Repeat> repeats =
new HashMap<Category, Repeat>();
@Override
public int decide(LoggingEvent event)
{
String message = event.getRenderedMessage();
if ((message == null) || message.startsWith("Last message repeated "))
return Filter.NEUTRAL;
Category logger = event.getLogger();
Repeat r = repeats.get(logger);
if (r == null)
repeats.put(logger, r = new Repeat());
if (message.equals(r.message)) {
++r.count;
return Filter.DENY;
}
if (r.count > 0) {
logger.log(r.level, "Last message repeated " + r.count + " time(s).");
r.count = 0;
}
r.message = message;
r.level = event.getLevel();
return Filter.NEUTRAL;
}
private final class Repeat
{
Priority level;
String message;
int count;
}
}
Это может быть не то, что вам нужно, потому что события в других регистраторах не будут «сбрасывать» сообщение «повторяется» категории.С другой стороны, он может сжимать журнал еще более эффективно, поскольку одно и то же сообщение, вероятно, будет повторяться на том же самом регистраторе.