Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -297,9 +297,12 @@ protected Processor createLogger() {
Long groupDelay = getGroupDelay();
answer = new ThroughputLogger(camelLogger, this.getCamelContext(), getGroupInterval(), groupDelay, groupActiveOnly);
} else {
answer = new CamelLogProcessor(
CamelLogProcessor clp = new CamelLogProcessor(
camelLogger, localFormatter, getMaskingFormatter(),
getCamelContext().getCamelContextExtension().getLogListeners());
clp.setRouteLogMaskAware(true);
clp.setEndpointLogMask(logMask);
answer = clp;
}
// the logger is the processor
setProcessor(answer);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.camel.component.log;

import org.apache.camel.CamelContext;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.component.mock.MockEndpoint;
import org.apache.camel.impl.DefaultCamelContext;
import org.apache.camel.spi.MaskingFormatter;
import org.apache.camel.spi.Registry;
import org.apache.camel.support.DefaultRegistry;
import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;

public class LogMaskRouteOverrideTest {

protected Registry registry;

protected CamelContext createCamelContext() throws Exception {
registry = new DefaultRegistry();
CamelContext context = new DefaultCamelContext(registry);
context.addRoutes(createRouteBuilder());
return context;
}

@Test
public void testRouteLogMaskFalseOverridesContextTrue() throws Exception {
CamelContext context = createCamelContext();
TrackingMaskingFormatter tracker = new TrackingMaskingFormatter();
registry.bind(MaskingFormatter.CUSTOM_LOG_MASK_REF, tracker);
context.setLogMask(true);
context.start();

MockEndpoint masked = context.getEndpoint("mock:masked", MockEndpoint.class);
masked.expectedMessageCount(1);
MockEndpoint noMask = context.getEndpoint("mock:noMask", MockEndpoint.class);
noMask.expectedMessageCount(1);

// send to the route WITH masking (context default)
tracker.received = null;
context.createProducerTemplate().sendBody("direct:masked", "password=secret123");
masked.assertIsSatisfied();
assertNotNull(tracker.received, "Masking formatter should have been called for the masked route");

// send to the route with logMask=false override
tracker.received = null;
context.createProducerTemplate().sendBody("direct:noMask", "password=secret123");
noMask.assertIsSatisfied();
assertNull(tracker.received, "Masking formatter should NOT have been called for the noMask route");

context.stop();
}

@Test
public void testRouteLogMaskTrueOverridesContextFalse() throws Exception {
CamelContext context = createCamelContext();
TrackingMaskingFormatter tracker = new TrackingMaskingFormatter();
registry.bind(MaskingFormatter.CUSTOM_LOG_MASK_REF, tracker);
context.setLogMask(false);
context.start();

MockEndpoint forceMask = context.getEndpoint("mock:forceMask", MockEndpoint.class);
forceMask.expectedMessageCount(1);

tracker.received = null;
context.createProducerTemplate().sendBody("direct:forceMask", "password=secret123");
forceMask.assertIsSatisfied();
assertNotNull(tracker.received, "Masking formatter should have been called for the forceMask route");
assertTrue(tracker.received.contains("password=secret123"));

context.stop();
}

protected RouteBuilder createRouteBuilder() {
return new RouteBuilder() {
@Override
public void configure() {
from("direct:masked").routeId("masked")
.to("log:masked.logger")
.to("mock:masked");

from("direct:noMask").routeId("noMask").logMask("false")
.to("log:noMask.logger")
.to("mock:noMask");

from("direct:forceMask").routeId("forceMask").logMask("true")
.to("log:forceMask.logger")
.to("mock:forceMask");
}
};
}

public static class TrackingMaskingFormatter implements MaskingFormatter {
private String received;

@Override
public String format(String source) {
received = source;
return source;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,15 @@
import org.apache.camel.Exchange;
import org.apache.camel.LoggingLevel;
import org.apache.camel.Processor;
import org.apache.camel.Route;
import org.apache.camel.spi.CamelLogger;
import org.apache.camel.spi.ExchangeFormatter;
import org.apache.camel.spi.IdAware;
import org.apache.camel.spi.LogListener;
import org.apache.camel.spi.MaskingFormatter;
import org.apache.camel.spi.RouteIdAware;
import org.apache.camel.spi.StepIdAware;
import org.apache.camel.spi.UnitOfWork;
import org.apache.camel.support.AsyncProcessorSupport;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand All @@ -51,6 +53,8 @@ public class CamelLogProcessor extends AsyncProcessorSupport implements IdAware,
private ExchangeFormatter formatter;
private MaskingFormatter maskingFormatter;
private final Set<LogListener> listeners;
private boolean routeLogMaskAware;
private Boolean endpointLogMask;

public CamelLogProcessor() {
this(new CamelLogger(CamelLogProcessor.class.getName()));
Expand Down Expand Up @@ -109,7 +113,7 @@ public void setStepId(String stepId) {
public boolean process(Exchange exchange, AsyncCallback callback) {
if (logger.shouldLog()) {
String output = formatter.format(exchange);
if (maskingFormatter != null) {
if (shouldMask(exchange)) {
output = maskingFormatter.format(output);
}
output = fireListeners(exchange, output);
Expand All @@ -123,7 +127,7 @@ public boolean process(Exchange exchange, AsyncCallback callback) {
public void process(Exchange exchange, Throwable exception) {
if (logger.shouldLog()) {
String output = formatter.format(exchange);
if (maskingFormatter != null) {
if (shouldMask(exchange)) {
output = maskingFormatter.format(output);
}
output = fireListeners(exchange, output);
Expand All @@ -135,7 +139,7 @@ public void process(Exchange exchange, Throwable exception) {
public void process(Exchange exchange, String message) {
if (logger.shouldLog()) {
String output = formatter.format(exchange) + message;
if (maskingFormatter != null) {
if (shouldMask(exchange)) {
output = maskingFormatter.format(output);
}
output = fireListeners(exchange, output);
Expand Down Expand Up @@ -204,6 +208,56 @@ public void setMaskingFormatter(MaskingFormatter maskingFormatter) {
this.maskingFormatter = maskingFormatter;
}

public void setRouteLogMaskAware(boolean routeLogMaskAware) {
this.routeLogMaskAware = routeLogMaskAware;
}

public void setEndpointLogMask(Boolean endpointLogMask) {
this.endpointLogMask = endpointLogMask;
}

private boolean shouldMask(Exchange exchange) {
if (!routeLogMaskAware) {
return maskingFormatter != null;
}

// endpoint-level explicit setting takes highest priority
if (endpointLogMask != null) {
if (!endpointLogMask) {
return false;
}
if (maskingFormatter == null) {
resolveMaskingFormatter(exchange);
}
return maskingFormatter != null;
}

// check route-level logMask (falls back to context-level)
UnitOfWork uow = exchange.getUnitOfWork();
if (uow != null) {
Route route = uow.getRoute();
if (route != null) {
if (!route.isLogMask()) {
return false;
}
if (maskingFormatter == null) {
resolveMaskingFormatter(exchange);
}
return maskingFormatter != null;
}
}

return maskingFormatter != null;
}

private void resolveMaskingFormatter(Exchange exchange) {
maskingFormatter = exchange.getContext().getRegistry()
.lookupByNameAndType(MaskingFormatter.CUSTOM_LOG_MASK_REF, MaskingFormatter.class);
if (maskingFormatter == null) {
maskingFormatter = new DefaultMaskingFormatter(exchange.getContext());
}
}

/**
* {@link ExchangeFormatter} that calls <tt>toString</tt> on the {@link Exchange}.
*/
Expand Down