001/** 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.camel.component.log; 018 019import org.apache.camel.Component; 020import org.apache.camel.LoggingLevel; 021import org.apache.camel.Processor; 022import org.apache.camel.Producer; 023import org.apache.camel.impl.ProcessorEndpoint; 024import org.apache.camel.model.Constants; 025import org.apache.camel.processor.CamelLogProcessor; 026import org.apache.camel.processor.DefaultExchangeFormatter; 027import org.apache.camel.processor.DefaultMaskingFormatter; 028import org.apache.camel.processor.ThroughputLogger; 029import org.apache.camel.spi.ExchangeFormatter; 030import org.apache.camel.spi.MaskingFormatter; 031import org.apache.camel.spi.Metadata; 032import org.apache.camel.spi.UriEndpoint; 033import org.apache.camel.spi.UriParam; 034import org.apache.camel.spi.UriPath; 035import org.apache.camel.util.CamelLogger; 036import org.apache.camel.util.ServiceHelper; 037import org.slf4j.Logger; 038 039/** 040 * The log component logs message exchanges to the underlying logging mechanism. 041 * 042 * Camel uses sfl4j which allows you to configure logging to the actual logging system. 043 */ 044@UriEndpoint(firstVersion = "1.1.0", scheme = "log", title = "Log", syntax = "log:loggerName", producerOnly = true, label = "core,monitoring") 045public class LogEndpoint extends ProcessorEndpoint { 046 047 private volatile Processor logger; 048 private Logger providedLogger; 049 private ExchangeFormatter localFormatter; 050 051 @UriPath(description = "Name of the logging category to use") @Metadata(required = "true") 052 private String loggerName; 053 @UriParam(defaultValue = "INFO", enums = "ERROR,WARN,INFO,DEBUG,TRACE,OFF") 054 private String level; 055 @UriParam 056 private String marker; 057 @UriParam 058 private Integer groupSize; 059 @UriParam 060 private Long groupInterval; 061 @UriParam(defaultValue = "true") 062 private Boolean groupActiveOnly; 063 @UriParam 064 private Long groupDelay; 065 // we want to include the uri options of the DefaultExchangeFormatter 066 @UriParam(label = "advanced") 067 private DefaultExchangeFormatter exchangeFormatter; 068 @UriParam 069 private Boolean logMask; 070 071 public LogEndpoint() { 072 } 073 074 public LogEndpoint(String endpointUri, Component component) { 075 super(endpointUri, component); 076 } 077 078 public LogEndpoint(String endpointUri, Component component, Processor logger) { 079 super(endpointUri, component); 080 setLogger(logger); 081 } 082 083 @Override 084 protected void doStart() throws Exception { 085 if (logger == null) { 086 logger = createLogger(); 087 } 088 ServiceHelper.startService(logger); 089 } 090 091 @Override 092 protected void doStop() throws Exception { 093 ServiceHelper.stopService(logger); 094 } 095 096 public void setLogger(Processor logger) { 097 this.logger = logger; 098 // the logger is the processor 099 setProcessor(this.logger); 100 } 101 102 public Processor getLogger() { 103 return logger; 104 } 105 106 @Override 107 public Producer createProducer() throws Exception { 108 // ensure logger is created and started first 109 if (logger == null) { 110 logger = createLogger(); 111 } 112 ServiceHelper.startService(logger); 113 return new LogProducer(this, logger); 114 } 115 116 @Override 117 protected String createEndpointUri() { 118 return "log:" + logger.toString(); 119 } 120 121 /** 122 * Creates the logger {@link Processor} to be used. 123 */ 124 protected Processor createLogger() throws Exception { 125 Processor answer; 126 // setup a new logger here 127 CamelLogger camelLogger; 128 LoggingLevel loggingLevel = LoggingLevel.INFO; 129 if (level != null) { 130 loggingLevel = LoggingLevel.valueOf(level); 131 } 132 if (providedLogger == null) { 133 camelLogger = new CamelLogger(loggerName, loggingLevel, getMarker()); 134 } else { 135 camelLogger = new CamelLogger(providedLogger, loggingLevel, getMarker()); 136 } 137 if (getGroupSize() != null) { 138 answer = new ThroughputLogger(camelLogger, getGroupSize()); 139 } else if (getGroupInterval() != null) { 140 Boolean groupActiveOnly = getGroupActiveOnly() != null ? getGroupActiveOnly() : Boolean.TRUE; 141 Long groupDelay = getGroupDelay(); 142 answer = new ThroughputLogger(camelLogger, this.getCamelContext(), getGroupInterval(), groupDelay, groupActiveOnly); 143 } else { 144 answer = new CamelLogProcessor(camelLogger, localFormatter, getMaskingFormatter(), getCamelContext().getLogListeners()); 145 } 146 // the logger is the processor 147 setProcessor(answer); 148 return answer; 149 } 150 151 private MaskingFormatter getMaskingFormatter() { 152 if (logMask != null ? logMask : getCamelContext().isLogMask()) { 153 MaskingFormatter formatter = getCamelContext().getRegistry().lookupByNameAndType(Constants.CUSTOM_LOG_MASK_REF, MaskingFormatter.class); 154 if (formatter == null) { 155 formatter = new DefaultMaskingFormatter(); 156 } 157 return formatter; 158 } 159 return null; 160 } 161 162 /** 163 * Logging level to use. 164 * <p/> 165 * The default value is INFO. 166 */ 167 public String getLevel() { 168 return level; 169 } 170 171 /** 172 * Logging level to use. 173 * <p/> 174 * The default value is INFO. 175 */ 176 public void setLevel(String level) { 177 this.level = level; 178 } 179 180 /** 181 * An optional Marker name to use. 182 */ 183 public String getMarker() { 184 return marker; 185 } 186 187 /** 188 * An optional Marker name to use. 189 */ 190 public void setMarker(String marker) { 191 this.marker = marker; 192 } 193 194 /** 195 * An integer that specifies a group size for throughput logging. 196 */ 197 public Integer getGroupSize() { 198 return groupSize; 199 } 200 201 /** 202 * An integer that specifies a group size for throughput logging. 203 */ 204 public void setGroupSize(Integer groupSize) { 205 this.groupSize = groupSize; 206 } 207 208 /** 209 * If specified will group message stats by this time interval (in millis) 210 */ 211 public Long getGroupInterval() { 212 return groupInterval; 213 } 214 215 /** 216 * If specified will group message stats by this time interval (in millis) 217 */ 218 public void setGroupInterval(Long groupInterval) { 219 this.groupInterval = groupInterval; 220 } 221 222 /** 223 * If true, will hide stats when no new messages have been received for a time interval, if false, show stats regardless of message traffic. 224 */ 225 public Boolean getGroupActiveOnly() { 226 return groupActiveOnly; 227 } 228 229 /** 230 * If true, will hide stats when no new messages have been received for a time interval, if false, show stats regardless of message traffic. 231 */ 232 public void setGroupActiveOnly(Boolean groupActiveOnly) { 233 this.groupActiveOnly = groupActiveOnly; 234 } 235 236 /** 237 * Set the initial delay for stats (in millis) 238 */ 239 public Long getGroupDelay() { 240 return groupDelay; 241 } 242 243 /** 244 * Set the initial delay for stats (in millis) 245 */ 246 public void setGroupDelay(Long groupDelay) { 247 this.groupDelay = groupDelay; 248 } 249 250 public ExchangeFormatter getLocalFormatter() { 251 return localFormatter; 252 } 253 254 public void setLocalFormatter(ExchangeFormatter localFormatter) { 255 this.localFormatter = localFormatter; 256 } 257 258 public Logger getProvidedLogger() { 259 return providedLogger; 260 } 261 262 public void setProvidedLogger(Logger providedLogger) { 263 this.providedLogger = providedLogger; 264 } 265 266 /** 267 * The logger name to use 268 */ 269 public String getLoggerName() { 270 return loggerName; 271 } 272 273 /** 274 * The logger name to use 275 */ 276 public void setLoggerName(String loggerName) { 277 this.loggerName = loggerName; 278 } 279 280 public Boolean getLogMask() { 281 return logMask; 282 } 283 284 /** 285 * If true, mask sensitive information like password or passphrase in the log. 286 */ 287 public void setLogMask(Boolean logMask) { 288 this.logMask = logMask; 289 } 290 291}