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-2015 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.admin.ClassPropertyDefinition; 029import org.opends.server.admin.std.meta.DebugLogPublisherCfgDefn; 030import org.opends.server.admin.std.server.DebugLogPublisherCfg; 031import org.opends.server.core.ServerContext; 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 /** 066 * The constructor for this class. 067 */ 068 private DebugLogger() 069 { 070 super((Class) DebugLogPublisher.class, 071 ERR_CONFIG_LOGGER_INVALID_DEBUG_LOGGER_CLASS); 072 } 073 074 /** {@inheritDoc} */ 075 @Override 076 protected ClassPropertyDefinition getJavaClassPropertyDefinition() 077 { 078 return DebugLogPublisherCfgDefn.getInstance() 079 .getJavaClassPropertyDefinition(); 080 } 081 082 /** {@inheritDoc} */ 083 @Override 084 protected Collection<DebugLogPublisher<DebugLogPublisherCfg>> getLogPublishers() 085 { 086 return loggerStorage.getLogPublishers(); 087 } 088 089 /** 090 * Update all debug tracers with the settings in the registered 091 * publishers. 092 */ 093 static void updateTracerSettings() 094 { 095 DebugLogPublisher<DebugLogPublisherCfg>[] publishers = 096 loggerStorage.getLogPublishers().toArray(new DebugLogPublisher[0]); 097 098 for(DebugTracer tracer : classTracers.values()) 099 { 100 tracer.updateSettings(publishers); 101 } 102 } 103 104 /** 105 * Indicates if debug logging is enabled. 106 * 107 * @return True if debug logging is enabled. False otherwise. 108 */ 109 public static boolean debugEnabled() 110 { 111 return enabled; 112 } 113 114 /** 115 * Retrieve the singleton instance of this class. 116 * 117 * @return The singleton instance of this logger. 118 */ 119 public static DebugLogger getInstance() 120 { 121 return instance; 122 } 123 124 /** 125 * Returns the registered Debug Tracer for a traced class. 126 * 127 * @param className The name of the class tracer to retrieve. 128 * @return The tracer for the provided class or null if there are 129 * no tracers registered. 130 */ 131 public static DebugTracer getTracer(final String className) 132 { 133 DebugTracer tracer = classTracers.get(className); 134 if (tracer == null) 135 { 136 tracer = 137 new DebugTracer(className, loggerStorage.getLogPublishers().toArray( 138 new DebugLogPublisher[0])); 139 classTracers.put(tracer.getTracedClassName(), tracer); 140 } 141 return tracer; 142 } 143 144 /** 145 * Adds a text debug log publisher that will print all messages to the 146 * provided writer, based on debug target(s) defined through system 147 * properties. 148 * <p> 149 * It is expected that one or more system properties beginning with 150 * {@code PROPERTY_DEBUG_TARGET} are set to define the properties of the debug 151 * targets used by the publisher, otherwise no publisher is added. 152 * 153 * @param writer 154 * The text writer where the message will be written to. 155 * @return the publisher. It may be {@code null} if no publisher is added. 156 */ 157 @SuppressWarnings({ "unchecked", "rawtypes" }) 158 public final TextDebugLogPublisher addPublisherIfRequired(TextWriter writer) 159 { 160 final List<String> debugTargets = getDebugTargetsFromSystemProperties(); 161 TextDebugLogPublisher publisher = null; 162 if (!debugTargets.isEmpty()) 163 { 164 publisher = TextDebugLogPublisher.getStartupTextDebugPublisher(debugTargets, writer); 165 if (publisher != null) { 166 addLogPublisher((DebugLogPublisher) publisher); 167 } 168 } 169 return publisher; 170 } 171 172 private List<String> getDebugTargetsFromSystemProperties() 173 { 174 final List<String> targets = new ArrayList<>(); 175 for (Map.Entry<Object, Object> entry : System.getProperties().entrySet()) 176 { 177 if (((String) entry.getKey()).startsWith(PROPERTY_DEBUG_TARGET)) 178 { 179 targets.add((String)entry.getValue()); 180 } 181 } 182 return targets; 183 } 184 185 @Override 186 public final synchronized void addLogPublisher(final DebugLogPublisher<DebugLogPublisherCfg> publisher) 187 { 188 loggerStorage.addLogPublisher(publisher); 189 updateTracerSettings(); 190 enabled = true; 191 adjustJulLevel(); 192 } 193 194 @Override 195 public final synchronized boolean removeLogPublisher(final DebugLogPublisher<DebugLogPublisherCfg> publisher) 196 { 197 boolean removed = loggerStorage.removeLogPublisher(publisher); 198 updateTracerSettings(); 199 enabled = !loggerStorage.getLogPublishers().isEmpty(); 200 adjustJulLevel(); 201 return removed; 202 } 203 204 @Override 205 public final synchronized void removeAllLogPublishers() 206 { 207 loggerStorage.removeAllLogPublishers(); 208 updateTracerSettings(); 209 enabled = false; 210 adjustJulLevel(); 211 } 212 213 private void adjustJulLevel() 214 { 215 final ServerContext serverContext = getServerContext(); 216 if (serverContext != null) 217 { 218 serverContext.getLoggerConfigManager().adjustJulLevel(); 219 } 220 } 221 222 /** 223 * Returns whether there is at least one debug log publisher enabled. 224 * @return whether there is at least one debug log publisher enabled. 225 */ 226 public boolean isEnabled() 227 { 228 return enabled; 229 } 230}