001package com.nimbusds.common.config; 002 003 004import java.util.Collections; 005import java.util.LinkedList; 006import java.util.List; 007import java.util.Properties; 008import java.util.concurrent.TimeUnit; 009 010import com.nimbusds.common.monitor.WildCardMetricFilter; 011import com.thetransactioncompany.util.PropertyFilter; 012import com.thetransactioncompany.util.PropertyParseException; 013import com.thetransactioncompany.util.PropertyRetriever; 014import net.jcip.annotations.Immutable; 015import org.apache.logging.log4j.LogManager; 016import org.apache.logging.log4j.Logger; 017 018 019/** 020 * DropWizard metrics configuration. System property override is enabled. 021 * 022 * <p>The configuration is stored as public fields which become immutable 023 * (final) after their initialisation. 024 * 025 * <p>Property keys: monitor.* 026 * 027 * <p>Example properties: 028 * 029 * <pre> 030 * monitor.enableJMX = true 031 * monitor.graphite.enable = true 032 * monitor.graphite.host = carbon.server.com 033 * monitor.graphite.port = 2003 034 * monitor.graphite.reportInterval = 60 035 * monitor.graphite.batchSize = 100 036 * monitor.graphite.prefix = 037 * monitor.graphite.ratesTimeUnit = SECONDS 038 * monitor.graphite.durationsTimeUnit = MILLISECONDS 039 * monitor.graphite.filter.1 = authzStore.ldapConnector.* 040 * monitor.graphite.filter.2 = tokenEndpoint.code.* 041 * monitor.graphite.filter.3 = tokenEndpoint.refreshToken.* 042 * </pre> 043 */ 044@Immutable 045public final class MonitorConfiguration implements LoggableConfiguration { 046 047 048 /** 049 * The prefix for the property names. 050 */ 051 public static final String PREFIX = "monitor."; 052 053 054 /** 055 * Enables / disables JMX reporting. 056 */ 057 public final boolean enableJMX; 058 059 060 /** 061 * Graphite reporting configuration. 062 */ 063 public static final class Graphite implements LoggableConfiguration { 064 065 066 /** 067 * Enables / disables reporting. 068 */ 069 public final boolean enable; 070 071 072 /** 073 * The name / IP address of the Carbon server host. 074 */ 075 public final String host; 076 077 078 /** 079 * The port of the Carbon server. 080 */ 081 public final int port; 082 083 084 /** 085 * The report interval, in seconds. 086 */ 087 public final int reportInterval; 088 089 090 /** 091 * Controls batching (pickling) of metrics to the Carbon 092 * server, zero if disabled. 093 */ 094 public final int batchSize; 095 096 097 /** 098 * Prefix for the metrics that are sent to the Carbon server. 099 * May be used to send a password or other credential to the 100 * server. 101 */ 102 public final String prefix; 103 104 105 /** 106 * The rates time unit. 107 */ 108 public final TimeUnit ratesTimeUnit; 109 110 111 /** 112 * The durations time unit. 113 */ 114 public final TimeUnit durationsTimeUnit; 115 116 117 /** 118 * The metrics filter (white list with wild card support). 119 */ 120 public final WildCardMetricFilter filter; 121 122 123 /** 124 * Creates a new Graphite reporting configuration. 125 * 126 * @param props The properties. Must not be {@code null}. 127 * 128 * @throws PropertyParseException On a missing or invalid 129 * property. 130 */ 131 public Graphite(final Properties props) 132 throws PropertyParseException { 133 134 PropertyRetriever pr = new PropertyRetriever(props); 135 136 enable = pr.getOptBoolean(PREFIX + "graphite.enable", false); 137 138 if (! enable) { 139 host = null; 140 port = 0; 141 reportInterval = 0; 142 batchSize = 0; 143 prefix = null; 144 ratesTimeUnit = null; 145 durationsTimeUnit = null; 146 filter = null; 147 return; 148 } 149 150 host = pr.getString(PREFIX + "graphite.host"); 151 port = pr.getInt(PREFIX + "graphite.port"); 152 reportInterval = pr.getInt(PREFIX + "graphite.reportInterval"); 153 batchSize = pr.getInt(PREFIX + "graphite.batchSize"); 154 prefix = pr.getOptString(PREFIX + "graphite.prefix", null); 155 ratesTimeUnit = pr.getEnum(PREFIX + "graphite.ratesTimeUnit", TimeUnit.class); 156 durationsTimeUnit = pr.getEnum(PREFIX + "graphite.durationsTimeUnit", TimeUnit.class); 157 158 List<String> filterWhiteList = new LinkedList<>(); 159 160 for (String key: props.stringPropertyNames()) { 161 162 if (key.startsWith(PREFIX + "graphite.filter")) { 163 164 String filterEntry = props.getProperty(key); 165 166 if (filterEntry == null || filterEntry.trim().isEmpty()) { 167 continue; // skip 168 } 169 170 filterWhiteList.add(filterEntry.trim()); 171 } 172 } 173 174 filter = new WildCardMetricFilter(Collections.unmodifiableList(filterWhiteList)); 175 } 176 177 178 @Override 179 public void log() { 180 181 Logger log = LogManager.getLogger(LOG_CATEGORY); 182 183 log.info("[CM7002] Graphite reporting enabled: {}", enable); 184 185 if (! enable) { 186 return; 187 } 188 189 log.info("[CM7003] Graphite reporting host: {}", host); 190 log.info("[CM7004] Graphite reporting port: {}", port); 191 log.info("[CM7005] Graphite reporting interval: {}", reportInterval); 192 log.info("[CM7006] Graphite reporting batch size: {}", batchSize + (batchSize < 1 ? " disabled" : "")); 193 log.info("[CM7007] Graphite reporting prefix: {}", prefix); 194 log.info("[CM7008] Graphite reporting rates time unit: {}", ratesTimeUnit); 195 log.info("[CM7009] Graphite reporting durations time unit: {}", durationsTimeUnit); 196 197 final String filterSetting; 198 199 if (filter.matchesAny()) { 200 filterSetting = "ANY"; 201 } else if (filter.matchesNone()) { 202 filterSetting = "NONE"; 203 } else { 204 filterSetting = filter.getWhiteList().toString(); 205 } 206 207 log.info("[CM7010] Graphite reporting filter: {}", filterSetting); 208 } 209 } 210 211 212 /** 213 * The Graphite reporting configuration. 214 */ 215 public final Graphite graphite; 216 217 218 /** 219 * Creates a new monitoring configuration from the specified 220 * properties. 221 * 222 * @param props The properties. Must not be {@code null}. 223 * 224 * @throws ConfigurationException On a missing or invalid property. 225 */ 226 public MonitorConfiguration(final Properties props) 227 throws ConfigurationException { 228 229 PropertyRetriever pr = new PropertyRetriever(props, true); 230 231 try { 232 enableJMX = pr.getOptBoolean(PREFIX + "enableJMX", false); 233 graphite = new Graphite(props); 234 } catch (PropertyParseException e) { 235 throw new ConfigurationException(e.getMessage() + ": Property: " + e.getPropertyKey(), e); 236 } 237 } 238 239 240 /** 241 * Logs the configuration details at INFO level. 242 */ 243 @Override 244 public void log() { 245 246 Logger log = LogManager.getLogger(LOG_CATEGORY); 247 log.info("[CM7000] Overriding system properties: {}", PropertyFilter.filterWithPrefix(PREFIX, System.getProperties()).stringPropertyNames()); 248 log.info("[CM7001] JMX reporting enabled: {}", enableJMX); 249 graphite.log(); 250 } 251}