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