001/* 002 * The contents of this file are subject to the terms of the Common Development and 003 * Distribution License (the License). You may not use this file except in compliance with the 004 * License. 005 * 006 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the 007 * specific language governing permission and limitations under the License. 008 * 009 * When distributing Covered Software, include this CDDL Header Notice in each file and include 010 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL 011 * Header, with the fields enclosed by brackets [] replaced by your own identifying 012 * information: "Portions Copyright [year] [name of copyright owner]". 013 * 014 * Copyright 2007-2009 Sun Microsystems, Inc. 015 * Portions Copyright 2013-2016 ForgeRock AS. 016 */ 017package org.opends.server.loggers; 018 019import static org.opends.messages.ConfigMessages.*; 020import static org.opends.server.util.ServerConstants.*; 021 022import java.util.ArrayList; 023import java.util.Collection; 024import java.util.List; 025import java.util.Map; 026import java.util.concurrent.ConcurrentHashMap; 027 028import org.opends.server.core.ServerContext; 029import org.forgerock.opendj.config.ClassPropertyDefinition; 030import org.forgerock.opendj.server.config.meta.DebugLogPublisherCfgDefn; 031import org.forgerock.opendj.server.config.server.DebugLogPublisherCfg; 032 033/** 034 * A logger for debug and trace logging. DebugLogger provides a debugging 035 * management access point. It is used to configure the Tracers, as well as 036 * to register a per-class tracer. 037 * 038 * Various stub debug methods are provided to log different types of debug 039 * messages. However, these methods do not contain any actual implementation. 040 * Tracer aspects are later weaved to catch alls to these stub methods and 041 * do the work of logging the message. 042 * 043 * DebugLogger is self-initializing. 044 */ 045public class DebugLogger extends AbstractLogger 046 <DebugLogPublisher<DebugLogPublisherCfg>, DebugLogPublisherCfg> 047{ 048 049 /** The set of all DebugTracer instances. */ 050 private static Map<String, DebugTracer> classTracers = new ConcurrentHashMap<>(); 051 052 /** 053 * Trace methods will use this static boolean to determine if debug is enabled 054 * so to not incur the cost of calling debugPublishers.isEmpty(). 055 */ 056 private static boolean enabled; 057 058 private static final LoggerStorage 059 <DebugLogPublisher<DebugLogPublisherCfg>, DebugLogPublisherCfg> 060 loggerStorage = new LoggerStorage<>(); 061 062 /** The singleton instance of this class. */ 063 static final DebugLogger instance = new DebugLogger(); 064 065 /** The constructor for this class. */ 066 private DebugLogger() 067 { 068 super((Class) DebugLogPublisher.class, 069 ERR_CONFIG_LOGGER_INVALID_DEBUG_LOGGER_CLASS); 070 } 071 072 @Override 073 protected ClassPropertyDefinition getJavaClassPropertyDefinition() 074 { 075 return DebugLogPublisherCfgDefn.getInstance() 076 .getJavaClassPropertyDefinition(); 077 } 078 079 @Override 080 protected Collection<DebugLogPublisher<DebugLogPublisherCfg>> getLogPublishers() 081 { 082 return loggerStorage.getLogPublishers(); 083 } 084 085 /** Update all debug tracers with the settings in the registered publishers. */ 086 static void updateTracerSettings() 087 { 088 DebugLogPublisher<DebugLogPublisherCfg>[] publishers = 089 loggerStorage.getLogPublishers().toArray(new DebugLogPublisher[0]); 090 091 for(DebugTracer tracer : classTracers.values()) 092 { 093 tracer.updateSettings(publishers); 094 } 095 } 096 097 /** 098 * Indicates if debug logging is enabled. 099 * 100 * @return True if debug logging is enabled. False otherwise. 101 */ 102 public static boolean debugEnabled() 103 { 104 return enabled; 105 } 106 107 /** 108 * Retrieve the singleton instance of this class. 109 * 110 * @return The singleton instance of this logger. 111 */ 112 public static DebugLogger getInstance() 113 { 114 return instance; 115 } 116 117 /** 118 * Returns the registered Debug Tracer for a traced class. 119 * 120 * @param className The name of the class tracer to retrieve. 121 * @return The tracer for the provided class or null if there are 122 * no tracers registered. 123 */ 124 public static DebugTracer getTracer(final String className) 125 { 126 DebugTracer tracer = classTracers.get(className); 127 if (tracer == null) 128 { 129 tracer = 130 new DebugTracer(className, loggerStorage.getLogPublishers().toArray( 131 new DebugLogPublisher[0])); 132 classTracers.put(tracer.getTracedClassName(), tracer); 133 } 134 return tracer; 135 } 136 137 /** 138 * Adds a text debug log publisher that will print all messages to the 139 * provided writer, based on debug target(s) defined through system 140 * properties. 141 * <p> 142 * It is expected that one or more system properties beginning with 143 * {@code PROPERTY_DEBUG_TARGET} are set to define the properties of the debug 144 * targets used by the publisher, otherwise no publisher is added. 145 * 146 * @param writer 147 * The text writer where the message will be written to. 148 * @return the publisher. It may be {@code null} if no publisher is added. 149 */ 150 @SuppressWarnings({ "unchecked", "rawtypes" }) 151 public final TextDebugLogPublisher addPublisherIfRequired(TextWriter writer) 152 { 153 final List<String> debugTargets = getDebugTargetsFromSystemProperties(); 154 TextDebugLogPublisher publisher = null; 155 if (!debugTargets.isEmpty()) 156 { 157 publisher = TextDebugLogPublisher.getStartupTextDebugPublisher(debugTargets, writer); 158 if (publisher != null) { 159 addLogPublisher((DebugLogPublisher) publisher); 160 } 161 } 162 return publisher; 163 } 164 165 private List<String> getDebugTargetsFromSystemProperties() 166 { 167 final List<String> targets = new ArrayList<>(); 168 for (Map.Entry<Object, Object> entry : System.getProperties().entrySet()) 169 { 170 if (((String) entry.getKey()).startsWith(PROPERTY_DEBUG_TARGET)) 171 { 172 targets.add((String)entry.getValue()); 173 } 174 } 175 return targets; 176 } 177 178 @Override 179 public final synchronized void addLogPublisher(final DebugLogPublisher<DebugLogPublisherCfg> publisher) 180 { 181 loggerStorage.addLogPublisher(publisher); 182 updateTracerSettings(); 183 enabled = true; 184 adjustJulLevel(); 185 } 186 187 @Override 188 public final synchronized boolean removeLogPublisher(final DebugLogPublisher<DebugLogPublisherCfg> publisher) 189 { 190 boolean removed = loggerStorage.removeLogPublisher(publisher); 191 updateTracerSettings(); 192 enabled = !loggerStorage.getLogPublishers().isEmpty(); 193 adjustJulLevel(); 194 return removed; 195 } 196 197 @Override 198 public final synchronized void removeAllLogPublishers() 199 { 200 loggerStorage.removeAllLogPublishers(); 201 updateTracerSettings(); 202 enabled = false; 203 adjustJulLevel(); 204 } 205 206 private void adjustJulLevel() 207 { 208 final ServerContext serverContext = getServerContext(); 209 if (serverContext != null) 210 { 211 serverContext.getLoggerConfigManager().adjustJulLevel(); 212 } 213 } 214 215 /** 216 * Returns whether there is at least one debug log publisher enabled. 217 * @return whether there is at least one debug log publisher enabled. 218 */ 219 public boolean isEnabled() 220 { 221 return enabled; 222 } 223}