Skip to content

Commit

Permalink
Fix #5824 to add camel trace config properties (#6130)
Browse files Browse the repository at this point in the history
* Fix #5824 to add camel trace config properties

* Add a test for BacklogTracer configuration
  • Loading branch information
zhfeng authored May 31, 2024
1 parent 349bbda commit bb721ff
Show file tree
Hide file tree
Showing 5 changed files with 333 additions and 2 deletions.
86 changes: 85 additions & 1 deletion docs/modules/ROOT/pages/reference/extensions/core.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -307,10 +307,94 @@ Note that this configuration item only has any effect when observers configured

|icon:lock[title=Fixed at build time] [[quarkus.camel.source-location-enabled]]`link:#quarkus.camel.source-location-enabled[quarkus.camel.source-location-enabled]`

Build time configuration options for enable/disable camel source location
Build time configuration options for enable/disable camel source location.
| `boolean`
| `false`

|icon:lock[title=Fixed at build time] [[quarkus.camel.trace.enabled]]`link:#quarkus.camel.trace.enabled[quarkus.camel.trace.enabled]`

Enables tracer in your Camel application.
| `boolean`
| `false`

|icon:lock[title=Fixed at build time] [[quarkus.camel.trace.standby]]`link:#quarkus.camel.trace.standby[quarkus.camel.trace.standby]`

To set the tracer in standby mode, where the tracer will be installed, but not automatically enabled. The tracer can then be enabled explicitly later from Java, JMX or tooling.
| `boolean`
| `false`

|icon:lock[title=Fixed at build time] [[quarkus.camel.trace.backlog-size]]`link:#quarkus.camel.trace.backlog-size[quarkus.camel.trace.backlog-size]`

Defines how many of the last messages to keep in the tracer.
| `int`
| `1000`

|icon:lock[title=Fixed at build time] [[quarkus.camel.trace.remove-on-dump]]`link:#quarkus.camel.trace.remove-on-dump[quarkus.camel.trace.remove-on-dump]`

Whether all traced messages should be removed when the tracer is dumping. By default, the messages are removed, which means that dumping will not contain previous dumped messages.
| `boolean`
| `true`

|icon:lock[title=Fixed at build time] [[quarkus.camel.trace.body-max-chars]]`link:#quarkus.camel.trace.body-max-chars[quarkus.camel.trace.body-max-chars]`

To limit the message body to a maximum size in the traced message. Use 0 or negative value to use unlimited size.
| `int`
| `131072`

|icon:lock[title=Fixed at build time] [[quarkus.camel.trace.body-include-streams]]`link:#quarkus.camel.trace.body-include-streams[quarkus.camel.trace.body-include-streams]`

Whether to include the message body of stream based messages. If enabled then beware the stream may not be re-readable later. See more about Stream Caching.
| `boolean`
| `false`

|icon:lock[title=Fixed at build time] [[quarkus.camel.trace.body-include-files]]`link:#quarkus.camel.trace.body-include-files[quarkus.camel.trace.body-include-files]`

Whether to include the message body of file based messages. The overhead is that the file content has to be read from the file.
| `boolean`
| `true`

|icon:lock[title=Fixed at build time] [[quarkus.camel.trace.include-exchange-properties]]`link:#quarkus.camel.trace.include-exchange-properties[quarkus.camel.trace.include-exchange-properties]`

Whether to include the exchange properties in the traced message.
| `boolean`
| `true`

|icon:lock[title=Fixed at build time] [[quarkus.camel.trace.include-exchange-variables]]`link:#quarkus.camel.trace.include-exchange-variables[quarkus.camel.trace.include-exchange-variables]`

Whether to include the exchange variables in the traced message.
| `boolean`
| `true`

|icon:lock[title=Fixed at build time] [[quarkus.camel.trace.include-exception]]`link:#quarkus.camel.trace.include-exception[quarkus.camel.trace.include-exception]`

Whether to include the exception in the traced message in case of failed exchange.
| `boolean`
| `true`

|icon:lock[title=Fixed at build time] [[quarkus.camel.trace.trace-rests]]`link:#quarkus.camel.trace.trace-rests[quarkus.camel.trace.trace-rests]`

Whether to trace routes that is created from Rest DSL.
| `boolean`
| `false`

|icon:lock[title=Fixed at build time] [[quarkus.camel.trace.trace-templates]]`link:#quarkus.camel.trace.trace-templates[quarkus.camel.trace.trace-templates]`

Whether to trace routes that is created from route templates or kamelets.
| `boolean`
| `false`

|icon:lock[title=Fixed at build time] [[quarkus.camel.trace.trace-pattern]]`link:#quarkus.camel.trace.trace-pattern[quarkus.camel.trace.trace-pattern]`

Filter for tracing by route or node id.
| `string`
|

|icon:lock[title=Fixed at build time] [[quarkus.camel.trace.trace-filter]]`link:#quarkus.camel.trace.trace-filter[quarkus.camel.trace.trace-filter]`

Filter for tracing messages.
| `string`
|

|icon:lock[title=Fixed at build time] [[quarkus.camel.main.shutdown.timeout]]`link:#quarkus.camel.main.shutdown.timeout[quarkus.camel.main.shutdown.timeout]`

A timeout (with millisecond precision) to wait for `CamelMain++#++stop()` to finish
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,21 @@ public void registerCamelEventBridges(
}
}

/**
* Enable camel tracer if quarkus.camel.trace.enabled=true
*
* @param recorder the recorder
* @param producer producer of context customizer build item
*/
@Record(ExecutionTime.STATIC_INIT)
@BuildStep(onlyIf = TraceEnabled.class)
public void enableCamelTrace(
CamelConfig config,
CamelContextRecorder recorder,
BuildProducer<CamelContextCustomizerBuildItem> producer) {
producer.produce(new CamelContextCustomizerBuildItem(recorder.createBacklogTracerCustomizer(config)));
}

public static final class EventBridgeEnabled implements BooleanSupplier {
CamelConfig config;

Expand All @@ -196,4 +211,13 @@ public boolean getAsBoolean() {
return config.sourceLocationEnabled;
}
}

public static final class TraceEnabled implements BooleanSupplier {
CamelConfig config;

@Override
public boolean getAsBoolean() {
return config.trace.enabled || config.trace.standby;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
/*
* 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.quarkus.core.runtime;

import java.io.IOException;
import java.io.StringWriter;
import java.io.Writer;
import java.util.Map;
import java.util.Properties;

import io.quarkus.test.QuarkusUnitTest;
import jakarta.inject.Inject;
import org.apache.camel.CamelContext;
import org.apache.camel.impl.debugger.BacklogTracer;
import org.apache.camel.spi.Registry;
import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.asset.Asset;
import org.jboss.shrinkwrap.api.asset.StringAsset;
import org.jboss.shrinkwrap.api.spec.JavaArchive;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

import static org.assertj.core.api.Assertions.assertThat;

public class CamelTraceTest {
@RegisterExtension
static final QuarkusUnitTest CONFIG = new QuarkusUnitTest()
.setArchiveProducer(() -> ShrinkWrap.create(JavaArchive.class)
.addAsResource(applicationProperties(), "application.properties"));

@Inject
Registry registry;

@Inject
CamelContext camelContext;

public static Asset applicationProperties() {
Writer writer = new StringWriter();

Properties props = new Properties();
props.setProperty("quarkus.camel.trace.enabled", "true");
props.setProperty("quarkus.camel.trace.backlog-size", "100");

try {
props.store(writer, "");
} catch (IOException e) {
throw new RuntimeException(e);
}

return new StringAsset(writer.toString());
}

@Test
public void testTraceConfiguration() {
BacklogTracer tracer = getBacklogTracer(camelContext);

assertThat(camelContext.isBacklogTracing()).isTrue();
assertThat(camelContext.isBacklogTracingStandby()).isFalse();
assertThat(camelContext.isBacklogTracingTemplates()).isFalse();
assertThat(tracer).isNotNull();
assertThat(tracer.getBacklogSize()).isEqualTo(100);
assertThat(tracer.getTracePattern()).isNull();
assertThat(tracer.getTraceFilter()).isNull();
}

private BacklogTracer getBacklogTracer(CamelContext camelContext) {
BacklogTracer tracer = null;
if (registry != null) {
// lookup in registry
Map<String, BacklogTracer> map = registry.findByTypeWithName(BacklogTracer.class);
if (map.size() == 1) {
tracer = map.values().iterator().next();
}
}
if (tracer == null) {
tracer = camelContext.getCamelContextExtension().getContextPlugin(BacklogTracer.class);
}
return tracer;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -80,11 +80,17 @@ public enum FailureRemedy {
public EventBridgeConfig eventBridge;

/**
* Build time configuration options for enable/disable camel source location
* Build time configuration options for enable/disable camel source location.
*/
@ConfigItem(defaultValue = "false")
public boolean sourceLocationEnabled;

/**
* Build time configuration options for the Camel tracing.
*/
@ConfigItem
public TraceConfig trace;

@ConfigGroup
public static class BootstrapConfig {
/**
Expand Down Expand Up @@ -406,4 +412,96 @@ public static class EventBridgeConfig {
@ConfigItem(defaultValue = "true")
public boolean enabled;
}

@ConfigGroup
public static class TraceConfig {

/**
* Enables tracer in your Camel application.
*/
@ConfigItem(defaultValue = "false")
public boolean enabled;

/**
* To set the tracer in standby mode, where the tracer will be installed, but not automatically enabled. The tracer can
* then be enabled explicitly later from Java, JMX or tooling.
*/
@ConfigItem(defaultValue = "false")
public boolean standby;

/**
* Defines how many of the last messages to keep in the tracer.
*/
@ConfigItem(defaultValue = "1000")
public int backlogSize;

/**
* Whether all traced messages should be removed when the tracer is dumping. By default, the messages are removed,
* which means that dumping will not contain previous dumped messages.
*/
@ConfigItem(defaultValue = "true")
public boolean removeOnDump;

/**
* To limit the message body to a maximum size in the traced message. Use 0 or negative value to use unlimited size.
*/
@ConfigItem(defaultValue = "131072")
public int bodyMaxChars;

/**
* Whether to include the message body of stream based messages. If enabled then beware the stream may not be
* re-readable later. See more about Stream Caching.
*/
@ConfigItem(defaultValue = "false")
public boolean bodyIncludeStreams;

/**
* Whether to include the message body of file based messages. The overhead is that the file content has to be read
* from the file.
*/
@ConfigItem(defaultValue = "true")
public boolean bodyIncludeFiles;

/**
* Whether to include the exchange properties in the traced message.
*/
@ConfigItem(defaultValue = "true")
public boolean includeExchangeProperties;

/**
* Whether to include the exchange variables in the traced message.
*/
@ConfigItem(defaultValue = "true")
public boolean includeExchangeVariables;

/**
* Whether to include the exception in the traced message in case of failed exchange.
*/
@ConfigItem(defaultValue = "true")
public boolean includeException;

/**
* Whether to trace routes that is created from Rest DSL.
*/
@ConfigItem(defaultValue = "false")
public boolean traceRests;

/**
* Whether to trace routes that is created from route templates or kamelets.
*/
@ConfigItem(defaultValue = "false")
public boolean traceTemplates;

/**
* Filter for tracing by route or node id.
*/
@ConfigItem
public Optional<String> tracePattern;

/**
* Filter for tracing messages.
*/
@ConfigItem
public Optional<String> traceFilter;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import org.apache.camel.CamelContext;
import org.apache.camel.ExtendedCamelContext;
import org.apache.camel.catalog.RuntimeCamelCatalog;
import org.apache.camel.impl.debugger.BacklogTracer;
import org.apache.camel.impl.engine.DefaultVariableRepositoryFactory;
import org.apache.camel.spi.CamelContextCustomizer;
import org.apache.camel.spi.ComponentNameResolver;
Expand Down Expand Up @@ -107,4 +108,34 @@ public void registerManagementEventBridge(RuntimeValue<CamelContext> camelContex
.getManagementStrategy()
.addEventNotifier(new CamelManagementEventBridge(observedManagementEvents));
}

public RuntimeValue<CamelContextCustomizer> createBacklogTracerCustomizer(CamelConfig config) {
return new RuntimeValue<>(context -> {
// must enable source location so tracer tooling knows to map breakpoints to source code
context.setSourceLocationEnabled(true);

// enable tracer on camel
context.setBacklogTracing(config.trace.enabled);
context.setBacklogTracingStandby(config.trace.standby);
context.setBacklogTracingTemplates(config.trace.traceTemplates);

BacklogTracer tracer = BacklogTracer.createTracer(context);
tracer.setEnabled(config.trace.enabled);
tracer.setStandby(config.trace.standby);
tracer.setBacklogSize(config.trace.backlogSize);
tracer.setRemoveOnDump(config.trace.removeOnDump);
tracer.setBodyMaxChars(config.trace.bodyMaxChars);
tracer.setBodyIncludeStreams(config.trace.bodyIncludeStreams);
tracer.setBodyIncludeFiles(config.trace.bodyIncludeFiles);
tracer.setIncludeExchangeProperties(config.trace.includeExchangeProperties);
tracer.setIncludeExchangeVariables(config.trace.includeExchangeVariables);
tracer.setIncludeException(config.trace.includeException);
tracer.setTraceRests(config.trace.traceRests);
tracer.setTraceTemplates(config.trace.traceTemplates);
tracer.setTracePattern(config.trace.tracePattern.orElse(null));
tracer.setTraceFilter(config.trace.traceFilter.orElse(null));

context.getCamelContextExtension().addContextPlugin(BacklogTracer.class, tracer);
});
}
}

0 comments on commit bb721ff

Please sign in to comment.