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