/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.solr.logging.log4j; import java.util.Arrays; import java.util.Collection; import java.util.Date; import java.util.Enumeration; import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.log4j.AppenderSkeleton; import org.apache.log4j.Level; import org.apache.log4j.Logger; import org.apache.log4j.spi.LoggingEvent; import org.apache.log4j.spi.ThrowableInformation; import org.apache.solr.common.SolrDocument; import org.apache.solr.common.cloud.ZkStateReader; import org.apache.solr.common.util.SuppressForbidden; import org.apache.solr.logging.CircularList; import org.apache.solr.logging.ListenerConfig; import org.apache.solr.logging.LogWatcher; import org.apache.solr.logging.LoggerInfo; import com.google.common.base.Throwables; @SuppressForbidden(reason = "class is specific to log4j") public class Log4jWatcher extends LogWatcher<LoggingEvent> { final String name; AppenderSkeleton appender = null; public Log4jWatcher(String name) { this.name = name; } @Override public String getName() { return "Log4j ("+name+")"; } @Override public List<String> getAllLevels() { return Arrays.asList( org.apache.log4j.Level.ALL.toString(), org.apache.log4j.Level.TRACE.toString(), org.apache.log4j.Level.DEBUG.toString(), org.apache.log4j.Level.INFO.toString(), org.apache.log4j.Level.WARN.toString(), org.apache.log4j.Level.ERROR.toString(), org.apache.log4j.Level.FATAL.toString(), org.apache.log4j.Level.OFF.toString()); } @Override public void setLogLevel(String category, String level) { org.apache.log4j.Logger log; if(LoggerInfo.ROOT_NAME.equals(category)) { log = org.apache.log4j.LogManager.getRootLogger(); } else { log = org.apache.log4j.Logger.getLogger(category); } if(level==null||"unset".equals(level)||"null".equals(level)) { log.setLevel(null); } else { log.setLevel(org.apache.log4j.Level.toLevel(level)); } } @Override public Collection<LoggerInfo> getAllLoggers() { org.apache.log4j.Logger root = org.apache.log4j.LogManager.getRootLogger(); Map<String,LoggerInfo> map = new HashMap<>(); Enumeration<?> loggers = org.apache.log4j.LogManager.getCurrentLoggers(); while (loggers.hasMoreElements()) { org.apache.log4j.Logger logger = (org.apache.log4j.Logger)loggers.nextElement(); String name = logger.getName(); if( logger == root) { continue; } map.put(name, new Log4jInfo(name, logger)); while (true) { int dot = name.lastIndexOf("."); if (dot < 0) break; name = name.substring(0, dot); if(!map.containsKey(name)) { map.put(name, new Log4jInfo(name, null)); } } } map.put(LoggerInfo.ROOT_NAME, new Log4jInfo(LoggerInfo.ROOT_NAME, root)); return map.values(); } @Override public void setThreshold(String level) { if(appender==null) { throw new IllegalStateException("Must have an appender"); } appender.setThreshold(Level.toLevel(level)); } @Override public String getThreshold() { if(appender==null) { throw new IllegalStateException("Must have an appender"); } return appender.getThreshold().toString(); } @Override public void registerListener(ListenerConfig cfg) { if(history!=null) { throw new IllegalStateException("History already registered"); } history = new CircularList<>(cfg.size); appender = new EventAppender(this); if(cfg.threshold != null) { appender.setThreshold(Level.toLevel(cfg.threshold)); } else { appender.setThreshold(Level.WARN); } Logger log = org.apache.log4j.LogManager.getRootLogger(); log.addAppender(appender); } @Override public long getTimestamp(LoggingEvent event) { return event.timeStamp; } @Override public SolrDocument toSolrDocument(LoggingEvent event) { SolrDocument doc = new SolrDocument(); doc.setField("time", new Date(event.getTimeStamp())); doc.setField("level", event.getLevel().toString()); doc.setField("logger", event.getLogger().getName()); doc.setField("message", event.getRenderedMessage()); ThrowableInformation t = event.getThrowableInformation(); if(t!=null) { doc.setField("trace", Throwables.getStackTraceAsString(t.getThrowable())); } // Will be null if not present doc.setField("core", event.getMDC(ZkStateReader.CORE_NAME_PROP)); doc.setField("collection", event.getMDC(ZkStateReader.COLLECTION_PROP)); doc.setField("replica", event.getMDC(ZkStateReader.REPLICA_PROP)); doc.setField("shard", event.getMDC(ZkStateReader.SHARD_ID_PROP)); return doc; } }