This is an automated email from the ASF dual-hosted git repository.
davsclaus pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git
The following commit(s) were added to refs/heads/main by this push:
new d4792ba9226 Otel (#11909)
d4792ba9226 is described below
commit d4792ba9226cb31de91393b10fad5d6f914600d0
Author: Claus Ibsen <[email protected]>
AuthorDate: Sun Nov 5 16:22:48 2023 +0100
Otel (#11909)
CAMEL-20083: camel-opentelemtry - Make it easier to configure for camel-main
---
.../main/camel-main-configuration-metadata.json | 4 +
.../camel/observation/AttributeProcessor.java | 12 +--
.../observation/MicrometerObservationTracer.java | 2 +-
.../SetCorrelationContextProcessor.java | 3 -
.../OpenTelemetryTracerConfigurer.java | 94 +++++++++++++++++
....apache.camel.opentelemetry.OpenTelemetryTracer | 2 +
.../services/org/apache/camel/opentelemetry-tracer | 2 +
.../src/main/docs/opentelemetry.adoc | 21 +++-
.../camel/opentelemetry/OpenTelemetryTracer.java | 40 +++++---
.../main/java/org/apache/camel/tracing/Tracer.java | 4 +-
.../org/apache/camel/spi/CamelTracingService.java | 27 +++++
.../OtelConfigurationPropertiesConfigurer.java | 61 +++++++++++
.../camel-main-configuration-metadata.json | 4 +
...g.apache.camel.main.OtelConfigurationProperties | 2 +
core/camel-main/src/main/docs/main.adoc | 12 +++
.../org/apache/camel/main/BaseMainSupport.java | 65 +++++++++++-
.../camel/main/MainConfigurationProperties.java | 22 ++++
.../camel/main/OtelConfigurationProperties.java | 112 +++++++++++++++++++++
.../maven/packaging/PrepareCamelMainMojo.java | 5 +
19 files changed, 457 insertions(+), 37 deletions(-)
diff --git
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/main/camel-main-configuration-metadata.json
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/main/camel-main-configuration-metadata.json
index 3235de257b0..3a89ff173c1 100644
---
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/main/camel-main-configuration-metadata.json
+++
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/main/camel-main-configuration-metadata.json
@@ -10,6 +10,7 @@
{ "name": "camel.vault.aws", "description": "Camel AWS Vault
configurations", "sourceType": "org.apache.camel.vault.AwsVaultConfiguration" },
{ "name": "camel.vault.gcp", "description": "Camel GCP Vault
configurations", "sourceType": "org.apache.camel.vault.GcpVaultConfiguration" },
{ "name": "camel.vault.azure", "description": "Camel Azure Key Vault
configurations", "sourceType": "org.apache.camel.vault.AzureVaultConfiguration"
},
+ { "name": "camel.opentelemetry", "description": "Camel OpenTelemtry
configurations", "sourceType":
"org.apache.camel.main.OtelConfigurationProperties" },
{ "name": "camel.faulttolerance", "description": "Fault Tolerance EIP
Circuit Breaker configurations", "sourceType":
"org.apache.camel.main.FaultToleranceConfigurationProperties" },
{ "name": "camel.resilience4j", "description": "Resilience4j EIP Circuit
Breaker configurations", "sourceType":
"org.apache.camel.main.Resilience4jConfigurationProperties" },
{ "name": "camel.lra", "description": "Camel Saga EIP (Long Running
Actions) configurations", "sourceType":
"org.apache.camel.main.LraConfigurationProperties" }
@@ -177,6 +178,9 @@
{ "name": "camel.lra.coordinatorUrl", "description": "The URL for the LRA
coordinator service that orchestrates the transactions", "sourceType":
"org.apache.camel.main.LraConfigurationProperties", "type": "string",
"javaType": "java.lang.String" },
{ "name": "camel.lra.localParticipantContextPath", "description": "The
context-path for the local participant. Is default \/lra-participant",
"sourceType": "org.apache.camel.main.LraConfigurationProperties", "type":
"string", "javaType": "java.lang.String", "defaultValue": "\/lra-participant" },
{ "name": "camel.lra.localParticipantUrl", "description": "The URL for the
local participant", "sourceType":
"org.apache.camel.main.LraConfigurationProperties", "type": "string",
"javaType": "java.lang.String" },
+ { "name": "camel.opentelemetry.encoding", "description": "Sets whether the
header keys need to be encoded (connector specific) or not. The value is a
boolean. Dashes need for instances to be encoded for JMS property keys.",
"sourceType": "org.apache.camel.main.OtelConfigurationProperties", "type":
"boolean", "javaType": "boolean", "defaultValue": "false" },
+ { "name": "camel.opentelemetry.excludePatterns", "description": "Adds an
exclude pattern that will disable tracing for Camel messages that matches the
pattern. Multiple patterns can be separated by comma.", "sourceType":
"org.apache.camel.main.OtelConfigurationProperties", "type": "string",
"javaType": "java.lang.String" },
+ { "name": "camel.opentelemetry.instrumentationName", "description": "A
name uniquely identifying the instrumentation scope, such as the
instrumentation library, package, or fully qualified class name. Must not be
null.", "sourceType": "org.apache.camel.main.OtelConfigurationProperties",
"type": "string", "javaType": "java.lang.String", "defaultValue": "camel" },
{ "name":
"camel.resilience4j.automaticTransitionFromOpenToHalfOpenEnabled",
"description": "Enables automatic transition from OPEN to HALF_OPEN state once
the waitDurationInOpenState has passed.", "sourceType":
"org.apache.camel.main.Resilience4jConfigurationProperties", "type": "boolean",
"javaType": "java.lang.Boolean", "defaultValue": "false" },
{ "name": "camel.resilience4j.bulkheadEnabled", "description": "Whether
bulkhead is enabled or not on the circuit breaker.", "sourceType":
"org.apache.camel.main.Resilience4jConfigurationProperties", "type": "boolean",
"javaType": "java.lang.Boolean", "defaultValue": false },
{ "name": "camel.resilience4j.bulkheadMaxConcurrentCalls", "description":
"Configures the max amount of concurrent calls the bulkhead will support.",
"sourceType": "org.apache.camel.main.Resilience4jConfigurationProperties",
"type": "integer", "javaType": "java.lang.Integer" },
diff --git
a/components/camel-observation/src/main/java/org/apache/camel/observation/AttributeProcessor.java
b/components/camel-observation/src/main/java/org/apache/camel/observation/AttributeProcessor.java
index c551908aa4a..cdca8f440ca 100644
---
a/components/camel-observation/src/main/java/org/apache/camel/observation/AttributeProcessor.java
+++
b/components/camel-observation/src/main/java/org/apache/camel/observation/AttributeProcessor.java
@@ -30,7 +30,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
- * A processor which adds a attribute on the active {@link Observation} with
an {@link org.apache.camel.Expression}
+ * A processor which adds an attribute on the active {@link Observation} with
an {@link org.apache.camel.Expression}
*/
public class AttributeProcessor extends AsyncProcessorSupport implements
Traceable, IdAware, RouteIdAware {
@@ -99,16 +99,6 @@ public class AttributeProcessor extends
AsyncProcessorSupport implements Traceab
return expression;
}
- @Override
- protected void doStart() throws Exception {
- // noop
- }
-
- @Override
- protected void doStop() throws Exception {
- // noop
- }
-
@Override
public String toString() {
return id;
diff --git
a/components/camel-observation/src/main/java/org/apache/camel/observation/MicrometerObservationTracer.java
b/components/camel-observation/src/main/java/org/apache/camel/observation/MicrometerObservationTracer.java
index aa5baec9d4f..74f90818965 100644
---
a/components/camel-observation/src/main/java/org/apache/camel/observation/MicrometerObservationTracer.java
+++
b/components/camel-observation/src/main/java/org/apache/camel/observation/MicrometerObservationTracer.java
@@ -160,7 +160,7 @@ public class MicrometerObservationTracer extends
org.apache.camel.tracing.Tracer
@Override
protected void initContextPropagators() {
-
+ // noop
}
private static Observation getParentObservation(SpanAdapter
parentObservation) {
diff --git
a/components/camel-observation/src/main/java/org/apache/camel/observation/SetCorrelationContextProcessor.java
b/components/camel-observation/src/main/java/org/apache/camel/observation/SetCorrelationContextProcessor.java
index 80d329ffafa..9d2d86cde84 100644
---
a/components/camel-observation/src/main/java/org/apache/camel/observation/SetCorrelationContextProcessor.java
+++
b/components/camel-observation/src/main/java/org/apache/camel/observation/SetCorrelationContextProcessor.java
@@ -28,9 +28,6 @@ import org.apache.camel.util.ObjectHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-/**
- * @author rvargasp
- */
public class SetCorrelationContextProcessor extends AsyncProcessorSupport
implements Traceable, IdAware, RouteIdAware {
private static final Logger LOG =
LoggerFactory.getLogger(SetCorrelationContextProcessor.class);
diff --git
a/components/camel-opentelemetry/src/generated/java/org/apache/camel/opentelemetry/OpenTelemetryTracerConfigurer.java
b/components/camel-opentelemetry/src/generated/java/org/apache/camel/opentelemetry/OpenTelemetryTracerConfigurer.java
new file mode 100644
index 00000000000..0cd14dce133
--- /dev/null
+++
b/components/camel-opentelemetry/src/generated/java/org/apache/camel/opentelemetry/OpenTelemetryTracerConfigurer.java
@@ -0,0 +1,94 @@
+/* Generated by camel build tools - do NOT edit this file! */
+package org.apache.camel.opentelemetry;
+
+import java.util.Map;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.spi.ExtendedPropertyConfigurerGetter;
+import org.apache.camel.spi.PropertyConfigurerGetter;
+import org.apache.camel.spi.ConfigurerStrategy;
+import org.apache.camel.spi.GeneratedPropertyConfigurer;
+import org.apache.camel.util.CaseInsensitiveMap;
+import org.apache.camel.opentelemetry.OpenTelemetryTracer;
+
+/**
+ * Generated by camel build tools - do NOT edit this file!
+ */
+@SuppressWarnings("unchecked")
+public class OpenTelemetryTracerConfigurer extends
org.apache.camel.support.component.PropertyConfigurerSupport implements
GeneratedPropertyConfigurer, PropertyConfigurerGetter {
+
+ @Override
+ public boolean configure(CamelContext camelContext, Object obj, String
name, Object value, boolean ignoreCase) {
+ org.apache.camel.opentelemetry.OpenTelemetryTracer target =
(org.apache.camel.opentelemetry.OpenTelemetryTracer) obj;
+ switch (ignoreCase ? name.toLowerCase() : name) {
+ case "camelcontext":
+ case "CamelContext": target.setCamelContext(property(camelContext,
org.apache.camel.CamelContext.class, value)); return true;
+ case "contextpropagators":
+ case "ContextPropagators":
target.setContextPropagators(property(camelContext,
io.opentelemetry.context.propagation.ContextPropagators.class, value)); return
true;
+ case "encoding":
+ case "Encoding": target.setEncoding(property(camelContext,
boolean.class, value)); return true;
+ case "excludepatterns":
+ case "ExcludePatterns":
target.setExcludePatterns(property(camelContext, java.util.Set.class, value));
return true;
+ case "instrumentationname":
+ case "InstrumentationName":
target.setInstrumentationName(property(camelContext, java.lang.String.class,
value)); return true;
+ case "tracer":
+ case "Tracer": target.setTracer(property(camelContext,
io.opentelemetry.api.trace.Tracer.class, value)); return true;
+ case "tracingstrategy":
+ case "TracingStrategy":
target.setTracingStrategy(property(camelContext,
org.apache.camel.spi.InterceptStrategy.class, value)); return true;
+ default: return false;
+ }
+ }
+
+ @Override
+ public Class<?> getOptionType(String name, boolean ignoreCase) {
+ switch (ignoreCase ? name.toLowerCase() : name) {
+ case "camelcontext":
+ case "CamelContext": return org.apache.camel.CamelContext.class;
+ case "contextpropagators":
+ case "ContextPropagators": return
io.opentelemetry.context.propagation.ContextPropagators.class;
+ case "encoding":
+ case "Encoding": return boolean.class;
+ case "excludepatterns":
+ case "ExcludePatterns": return java.util.Set.class;
+ case "instrumentationname":
+ case "InstrumentationName": return java.lang.String.class;
+ case "tracer":
+ case "Tracer": return io.opentelemetry.api.trace.Tracer.class;
+ case "tracingstrategy":
+ case "TracingStrategy": return
org.apache.camel.spi.InterceptStrategy.class;
+ default: return null;
+ }
+ }
+
+ @Override
+ public Object getOptionValue(Object obj, String name, boolean ignoreCase) {
+ org.apache.camel.opentelemetry.OpenTelemetryTracer target =
(org.apache.camel.opentelemetry.OpenTelemetryTracer) obj;
+ switch (ignoreCase ? name.toLowerCase() : name) {
+ case "camelcontext":
+ case "CamelContext": return target.getCamelContext();
+ case "contextpropagators":
+ case "ContextPropagators": return target.getContextPropagators();
+ case "encoding":
+ case "Encoding": return target.isEncoding();
+ case "excludepatterns":
+ case "ExcludePatterns": return target.getExcludePatterns();
+ case "instrumentationname":
+ case "InstrumentationName": return target.getInstrumentationName();
+ case "tracer":
+ case "Tracer": return target.getTracer();
+ case "tracingstrategy":
+ case "TracingStrategy": return target.getTracingStrategy();
+ default: return null;
+ }
+ }
+
+ @Override
+ public Object getCollectionValueType(Object target, String name, boolean
ignoreCase) {
+ switch (ignoreCase ? name.toLowerCase() : name) {
+ case "excludepatterns":
+ case "ExcludePatterns": return java.lang.String.class;
+ default: return null;
+ }
+ }
+}
+
diff --git
a/components/camel-opentelemetry/src/generated/resources/META-INF/services/org/apache/camel/configurer/org.apache.camel.opentelemetry.OpenTelemetryTracer
b/components/camel-opentelemetry/src/generated/resources/META-INF/services/org/apache/camel/configurer/org.apache.camel.opentelemetry.OpenTelemetryTracer
new file mode 100644
index 00000000000..bfc37ca1862
--- /dev/null
+++
b/components/camel-opentelemetry/src/generated/resources/META-INF/services/org/apache/camel/configurer/org.apache.camel.opentelemetry.OpenTelemetryTracer
@@ -0,0 +1,2 @@
+# Generated by camel build tools - do NOT edit this file!
+class=org.apache.camel.opentelemetry.OpenTelemetryTracerConfigurer
diff --git
a/components/camel-opentelemetry/src/generated/resources/META-INF/services/org/apache/camel/opentelemetry-tracer
b/components/camel-opentelemetry/src/generated/resources/META-INF/services/org/apache/camel/opentelemetry-tracer
new file mode 100644
index 00000000000..2482cc2f2ed
--- /dev/null
+++
b/components/camel-opentelemetry/src/generated/resources/META-INF/services/org/apache/camel/opentelemetry-tracer
@@ -0,0 +1,2 @@
+# Generated by camel build tools - do NOT edit this file!
+class=org.apache.camel.opentelemetry.OpenTelemetryTracer
diff --git a/components/camel-opentelemetry/src/main/docs/opentelemetry.adoc
b/components/camel-opentelemetry/src/main/docs/opentelemetry.adoc
index c61cdd1bde8..c8768469cd2 100644
--- a/components/camel-opentelemetry/src/main/docs/opentelemetry.adoc
+++ b/components/camel-opentelemetry/src/main/docs/opentelemetry.adoc
@@ -24,7 +24,7 @@ The configuration properties for the OpenTelemetry tracer are:
[width="100%",cols="10%,10%,80%",options="header",]
|=======================================================================
|Option |Default |Description
-
+|instrumentationName| camel | A name uniquely identifying the instrumentation
scope, such as the instrumentation library, package, or fully qualified class
name. Must not be null.
|excludePatterns | | Sets exclude pattern(s) that will disable tracing for
Camel
messages that matches the pattern. The content is a Set<String> where the key
is a pattern. The pattern
uses the rules from Intercept.
@@ -34,7 +34,7 @@ Dashes need for instances to be encoded for JMS property keys.
|=======================================================================
-=== Configuration
+== Using Camel OpenTelemetry
Include the `camel-opentelemetry` component in your POM, along with any
specific dependencies associated with the
chosen OpenTelemetry compliant Tracer.
@@ -52,6 +52,23 @@ otelTracer.setTracer(...);
otelTracer.init(camelContext);
--------------------------------------------------------------------------------------------------
+You would still need OpenTelemetry to instrument your code, which can be done
via a Java agent (see further below).
+
+=== Using with standalone Camel
+
+If you use `camel-main` as standalone Camel, then you can enable and use
OpenTelemetry without Java code.
+
+Add `camel-opentelemetry` component in your POM, and configure in
`application.properties`:
+
+[source,properties]
+----
+camel.opentelemetry.enabled = true
+# you can confiure the other options
+# camel.opentelemetry.instrumentationName = myApp
+----
+
+You would still need OpenTelemetry to instrument your code, which can be done
via a Java agent (see further below).
+
== Spring Boot
If you are using Spring Boot then you can add
diff --git
a/components/camel-opentelemetry/src/main/java/org/apache/camel/opentelemetry/OpenTelemetryTracer.java
b/components/camel-opentelemetry/src/main/java/org/apache/camel/opentelemetry/OpenTelemetryTracer.java
index 2d8fe70a54a..6858d20e819 100644
---
a/components/camel-opentelemetry/src/main/java/org/apache/camel/opentelemetry/OpenTelemetryTracer.java
+++
b/components/camel-opentelemetry/src/main/java/org/apache/camel/opentelemetry/OpenTelemetryTracer.java
@@ -16,8 +16,6 @@
*/
package org.apache.camel.opentelemetry;
-import java.util.Set;
-
import io.opentelemetry.api.GlobalOpenTelemetry;
import io.opentelemetry.api.baggage.Baggage;
import io.opentelemetry.api.trace.Span;
@@ -27,18 +25,28 @@ import io.opentelemetry.api.trace.Tracer;
import io.opentelemetry.context.Context;
import io.opentelemetry.context.propagation.ContextPropagators;
import org.apache.camel.Exchange;
+import org.apache.camel.api.management.ManagedAttribute;
import org.apache.camel.api.management.ManagedResource;
import org.apache.camel.opentelemetry.propagators.OpenTelemetryGetter;
import org.apache.camel.opentelemetry.propagators.OpenTelemetrySetter;
+import org.apache.camel.spi.Configurer;
+import org.apache.camel.spi.annotations.JdkService;
+import org.apache.camel.support.CamelContextHelper;
import org.apache.camel.tracing.ExtractAdapter;
import org.apache.camel.tracing.InjectAdapter;
import org.apache.camel.tracing.SpanAdapter;
import org.apache.camel.tracing.SpanDecorator;
import org.apache.camel.tracing.decorators.AbstractInternalSpanDecorator;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+@JdkService("opentelemetry-tracer")
+@Configurer
@ManagedResource(description = "OpenTelemetryTracer")
public class OpenTelemetryTracer extends org.apache.camel.tracing.Tracer {
+ private static final Logger LOG =
LoggerFactory.getLogger(OpenTelemetryTracer.class);
+
private Tracer tracer;
private String instrumentationName = "camel";
private ContextPropagators contextPropagators;
@@ -51,6 +59,15 @@ public class OpenTelemetryTracer extends
org.apache.camel.tracing.Tracer {
this.tracer = tracer;
}
+ @ManagedAttribute
+ public String getInstrumentationName() {
+ return instrumentationName;
+ }
+
+ /**
+ * A name uniquely identifying the instrumentation scope, such as the
instrumentation library, package, or fully
+ * qualified class name. Must not be null.
+ */
public void setInstrumentationName(String instrumentationName) {
this.instrumentationName = instrumentationName;
}
@@ -81,12 +98,8 @@ public class OpenTelemetryTracer extends
org.apache.camel.tracing.Tracer {
@Override
protected void initTracer() {
if (tracer == null) {
- Set<Tracer> tracers =
getCamelContext().getRegistry().findByType(Tracer.class);
- if (tracers.size() == 1) {
- tracer = tracers.iterator().next();
- }
+ tracer = CamelContextHelper.findSingleByType(getCamelContext(),
Tracer.class);
}
-
if (tracer == null) {
// GlobalOpenTelemetry.get() is always NotNull, falls back to
OpenTelemetry.noop()
tracer = GlobalOpenTelemetry.get().getTracer(instrumentationName);
@@ -96,13 +109,8 @@ public class OpenTelemetryTracer extends
org.apache.camel.tracing.Tracer {
@Override
protected void initContextPropagators() {
if (contextPropagators == null) {
- Set<ContextPropagators> contextPropagatorsSet
- =
getCamelContext().getRegistry().findByType(ContextPropagators.class);
- if (contextPropagatorsSet.size() == 1) {
- contextPropagators = contextPropagatorsSet.iterator().next();
- }
+ contextPropagators =
CamelContextHelper.findSingleByType(getCamelContext(),
ContextPropagators.class);
}
-
if (contextPropagators == null) {
// GlobalOpenTelemetry.get() is always NotNull, falls back to
OpenTelemetry.noop()
contextPropagators = GlobalOpenTelemetry.get().getPropagators();
@@ -169,4 +177,10 @@ public class OpenTelemetryTracer extends
org.apache.camel.tracing.Tracer {
GlobalOpenTelemetry.get().getPropagators().getTextMapPropagator().inject(ctx,
adapter, new OpenTelemetrySetter());
}
+ @Override
+ protected void doStart() throws Exception {
+ super.doStart();
+
+ LOG.info("OpenTelemetryTracer enabled using instrumentation-name: {}",
instrumentationName);
+ }
}
diff --git
a/components/camel-tracing/src/main/java/org/apache/camel/tracing/Tracer.java
b/components/camel-tracing/src/main/java/org/apache/camel/tracing/Tracer.java
index 1b9c5297112..3afbeae663f 100644
---
a/components/camel-tracing/src/main/java/org/apache/camel/tracing/Tracer.java
+++
b/components/camel-tracing/src/main/java/org/apache/camel/tracing/Tracer.java
@@ -23,7 +23,6 @@ import java.util.ServiceLoader;
import java.util.Set;
import org.apache.camel.CamelContext;
-import org.apache.camel.CamelContextAware;
import org.apache.camel.Component;
import org.apache.camel.Endpoint;
import org.apache.camel.Exchange;
@@ -33,6 +32,7 @@ import org.apache.camel.RuntimeCamelException;
import org.apache.camel.StaticService;
import org.apache.camel.spi.CamelEvent;
import org.apache.camel.spi.CamelLogger;
+import org.apache.camel.spi.CamelTracingService;
import org.apache.camel.spi.InterceptStrategy;
import org.apache.camel.spi.LogListener;
import org.apache.camel.spi.RoutePolicy;
@@ -48,7 +48,7 @@ import org.apache.camel.util.StringHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-public abstract class Tracer extends ServiceSupport implements
RoutePolicyFactory, StaticService, CamelContextAware {
+public abstract class Tracer extends ServiceSupport implements
CamelTracingService, RoutePolicyFactory, StaticService {
protected static final Map<String, SpanDecorator> DECORATORS = new
HashMap<>();
static final AutoCloseable NOOP_CLOSEABLE = () -> {
};
diff --git
a/core/camel-api/src/generated/java/org/apache/camel/spi/CamelTracingService.java
b/core/camel-api/src/generated/java/org/apache/camel/spi/CamelTracingService.java
new file mode 100644
index 00000000000..e71ebc047fe
--- /dev/null
+++
b/core/camel-api/src/generated/java/org/apache/camel/spi/CamelTracingService.java
@@ -0,0 +1,27 @@
+/*
+ * 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.spi;
+
+import org.apache.camel.CamelContextAware;
+import org.apache.camel.Service;
+
+/**
+ * A Camel tracing service is a factory for telemetry tracers.
+ */
+public interface CamelTracingService extends Service, CamelContextAware {
+
+}
diff --git
a/core/camel-main/src/generated/java/org/apache/camel/main/OtelConfigurationPropertiesConfigurer.java
b/core/camel-main/src/generated/java/org/apache/camel/main/OtelConfigurationPropertiesConfigurer.java
new file mode 100644
index 00000000000..2cd0234490c
--- /dev/null
+++
b/core/camel-main/src/generated/java/org/apache/camel/main/OtelConfigurationPropertiesConfigurer.java
@@ -0,0 +1,61 @@
+/* Generated by camel build tools - do NOT edit this file! */
+package org.apache.camel.main;
+
+import java.util.Map;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.spi.ExtendedPropertyConfigurerGetter;
+import org.apache.camel.spi.PropertyConfigurerGetter;
+import org.apache.camel.spi.ConfigurerStrategy;
+import org.apache.camel.spi.GeneratedPropertyConfigurer;
+import org.apache.camel.util.CaseInsensitiveMap;
+import org.apache.camel.main.OtelConfigurationProperties;
+
+/**
+ * Generated by camel build tools - do NOT edit this file!
+ */
+@SuppressWarnings("unchecked")
+public class OtelConfigurationPropertiesConfigurer extends
org.apache.camel.support.component.PropertyConfigurerSupport implements
GeneratedPropertyConfigurer, PropertyConfigurerGetter {
+
+ @Override
+ public boolean configure(CamelContext camelContext, Object obj, String
name, Object value, boolean ignoreCase) {
+ org.apache.camel.main.OtelConfigurationProperties target =
(org.apache.camel.main.OtelConfigurationProperties) obj;
+ switch (ignoreCase ? name.toLowerCase() : name) {
+ case "encoding":
+ case "Encoding": target.setEncoding(property(camelContext,
boolean.class, value)); return true;
+ case "excludepatterns":
+ case "ExcludePatterns":
target.setExcludePatterns(property(camelContext, java.lang.String.class,
value)); return true;
+ case "instrumentationname":
+ case "InstrumentationName":
target.setInstrumentationName(property(camelContext, java.lang.String.class,
value)); return true;
+ default: return false;
+ }
+ }
+
+ @Override
+ public Class<?> getOptionType(String name, boolean ignoreCase) {
+ switch (ignoreCase ? name.toLowerCase() : name) {
+ case "encoding":
+ case "Encoding": return boolean.class;
+ case "excludepatterns":
+ case "ExcludePatterns": return java.lang.String.class;
+ case "instrumentationname":
+ case "InstrumentationName": return java.lang.String.class;
+ default: return null;
+ }
+ }
+
+ @Override
+ public Object getOptionValue(Object obj, String name, boolean ignoreCase) {
+ org.apache.camel.main.OtelConfigurationProperties target =
(org.apache.camel.main.OtelConfigurationProperties) obj;
+ switch (ignoreCase ? name.toLowerCase() : name) {
+ case "encoding":
+ case "Encoding": return target.isEncoding();
+ case "excludepatterns":
+ case "ExcludePatterns": return target.getExcludePatterns();
+ case "instrumentationname":
+ case "InstrumentationName": return target.getInstrumentationName();
+ default: return null;
+ }
+ }
+}
+
diff --git
a/core/camel-main/src/generated/resources/META-INF/camel-main-configuration-metadata.json
b/core/camel-main/src/generated/resources/META-INF/camel-main-configuration-metadata.json
index 3235de257b0..3a89ff173c1 100644
---
a/core/camel-main/src/generated/resources/META-INF/camel-main-configuration-metadata.json
+++
b/core/camel-main/src/generated/resources/META-INF/camel-main-configuration-metadata.json
@@ -10,6 +10,7 @@
{ "name": "camel.vault.aws", "description": "Camel AWS Vault
configurations", "sourceType": "org.apache.camel.vault.AwsVaultConfiguration" },
{ "name": "camel.vault.gcp", "description": "Camel GCP Vault
configurations", "sourceType": "org.apache.camel.vault.GcpVaultConfiguration" },
{ "name": "camel.vault.azure", "description": "Camel Azure Key Vault
configurations", "sourceType": "org.apache.camel.vault.AzureVaultConfiguration"
},
+ { "name": "camel.opentelemetry", "description": "Camel OpenTelemtry
configurations", "sourceType":
"org.apache.camel.main.OtelConfigurationProperties" },
{ "name": "camel.faulttolerance", "description": "Fault Tolerance EIP
Circuit Breaker configurations", "sourceType":
"org.apache.camel.main.FaultToleranceConfigurationProperties" },
{ "name": "camel.resilience4j", "description": "Resilience4j EIP Circuit
Breaker configurations", "sourceType":
"org.apache.camel.main.Resilience4jConfigurationProperties" },
{ "name": "camel.lra", "description": "Camel Saga EIP (Long Running
Actions) configurations", "sourceType":
"org.apache.camel.main.LraConfigurationProperties" }
@@ -177,6 +178,9 @@
{ "name": "camel.lra.coordinatorUrl", "description": "The URL for the LRA
coordinator service that orchestrates the transactions", "sourceType":
"org.apache.camel.main.LraConfigurationProperties", "type": "string",
"javaType": "java.lang.String" },
{ "name": "camel.lra.localParticipantContextPath", "description": "The
context-path for the local participant. Is default \/lra-participant",
"sourceType": "org.apache.camel.main.LraConfigurationProperties", "type":
"string", "javaType": "java.lang.String", "defaultValue": "\/lra-participant" },
{ "name": "camel.lra.localParticipantUrl", "description": "The URL for the
local participant", "sourceType":
"org.apache.camel.main.LraConfigurationProperties", "type": "string",
"javaType": "java.lang.String" },
+ { "name": "camel.opentelemetry.encoding", "description": "Sets whether the
header keys need to be encoded (connector specific) or not. The value is a
boolean. Dashes need for instances to be encoded for JMS property keys.",
"sourceType": "org.apache.camel.main.OtelConfigurationProperties", "type":
"boolean", "javaType": "boolean", "defaultValue": "false" },
+ { "name": "camel.opentelemetry.excludePatterns", "description": "Adds an
exclude pattern that will disable tracing for Camel messages that matches the
pattern. Multiple patterns can be separated by comma.", "sourceType":
"org.apache.camel.main.OtelConfigurationProperties", "type": "string",
"javaType": "java.lang.String" },
+ { "name": "camel.opentelemetry.instrumentationName", "description": "A
name uniquely identifying the instrumentation scope, such as the
instrumentation library, package, or fully qualified class name. Must not be
null.", "sourceType": "org.apache.camel.main.OtelConfigurationProperties",
"type": "string", "javaType": "java.lang.String", "defaultValue": "camel" },
{ "name":
"camel.resilience4j.automaticTransitionFromOpenToHalfOpenEnabled",
"description": "Enables automatic transition from OPEN to HALF_OPEN state once
the waitDurationInOpenState has passed.", "sourceType":
"org.apache.camel.main.Resilience4jConfigurationProperties", "type": "boolean",
"javaType": "java.lang.Boolean", "defaultValue": "false" },
{ "name": "camel.resilience4j.bulkheadEnabled", "description": "Whether
bulkhead is enabled or not on the circuit breaker.", "sourceType":
"org.apache.camel.main.Resilience4jConfigurationProperties", "type": "boolean",
"javaType": "java.lang.Boolean", "defaultValue": false },
{ "name": "camel.resilience4j.bulkheadMaxConcurrentCalls", "description":
"Configures the max amount of concurrent calls the bulkhead will support.",
"sourceType": "org.apache.camel.main.Resilience4jConfigurationProperties",
"type": "integer", "javaType": "java.lang.Integer" },
diff --git
a/core/camel-main/src/generated/resources/META-INF/services/org/apache/camel/configurer/org.apache.camel.main.OtelConfigurationProperties
b/core/camel-main/src/generated/resources/META-INF/services/org/apache/camel/configurer/org.apache.camel.main.OtelConfigurationProperties
new file mode 100644
index 00000000000..91c564399fe
--- /dev/null
+++
b/core/camel-main/src/generated/resources/META-INF/services/org/apache/camel/configurer/org.apache.camel.main.OtelConfigurationProperties
@@ -0,0 +1,2 @@
+# Generated by camel build tools - do NOT edit this file!
+class=org.apache.camel.main.OtelConfigurationPropertiesConfigurer
diff --git a/core/camel-main/src/main/docs/main.adoc
b/core/camel-main/src/main/docs/main.adoc
index bd0442cc8b0..3dee56918ae 100644
--- a/core/camel-main/src/main/docs/main.adoc
+++ b/core/camel-main/src/main/docs/main.adoc
@@ -332,6 +332,18 @@ The camel.vault.azure supports 11 options, which are
listed below.
|===
+=== Camel OpenTelemtry configurations
+The camel.opentelemetry supports 3 options, which are listed below.
+
+[width="100%",cols="2,5,^1,2",options="header"]
+|===
+| Name | Description | Default | Type
+| *camel.opentelemetry.encoding* | Sets whether the header keys need to be
encoded (connector specific) or not. The value is a boolean. Dashes need for
instances to be encoded for JMS property keys. | false | boolean
+| *camel.opentelemetry.exclude{zwsp}Patterns* | Adds an exclude pattern that
will disable tracing for Camel messages that matches the pattern. Multiple
patterns can be separated by comma. | | String
+| *{zwsp}camel.opentelemetry.instrumentation{zwsp}Name* | A name uniquely
identifying the instrumentation scope, such as the instrumentation library,
package, or fully qualified class name. Must not be null. | camel | String
+|===
+
+
=== Fault Tolerance EIP Circuit Breaker configurations
The camel.faulttolerance supports 13 options, which are listed below.
diff --git
a/core/camel-main/src/main/java/org/apache/camel/main/BaseMainSupport.java
b/core/camel-main/src/main/java/org/apache/camel/main/BaseMainSupport.java
index e3fc6bcdead..bbaff3f289e 100644
--- a/core/camel-main/src/main/java/org/apache/camel/main/BaseMainSupport.java
+++ b/core/camel-main/src/main/java/org/apache/camel/main/BaseMainSupport.java
@@ -57,6 +57,7 @@ import org.apache.camel.spi.AutowiredLifecycleStrategy;
import org.apache.camel.spi.BacklogDebugger;
import org.apache.camel.spi.CamelBeanPostProcessor;
import org.apache.camel.spi.CamelEvent;
+import org.apache.camel.spi.CamelTracingService;
import org.apache.camel.spi.ContextReloadStrategy;
import org.apache.camel.spi.DataFormat;
import org.apache.camel.spi.Language;
@@ -950,6 +951,7 @@ public abstract class BaseMainSupport extends BaseService {
OrderedLocationProperties threadPoolProperties = new
OrderedLocationProperties();
OrderedLocationProperties healthProperties = new
OrderedLocationProperties();
OrderedLocationProperties lraProperties = new
OrderedLocationProperties();
+ OrderedLocationProperties otelProperties = new
OrderedLocationProperties();
OrderedLocationProperties routeTemplateProperties = new
OrderedLocationProperties();
OrderedLocationProperties beansProperties = new
OrderedLocationProperties();
OrderedLocationProperties devConsoleProperties = new
OrderedLocationProperties();
@@ -1007,6 +1009,12 @@ public abstract class BaseMainSupport extends
BaseService {
String option = key.substring(10);
validateOptionAndValue(key, option, value);
lraProperties.put(loc, optionKey(option), value);
+ } else if (key.startsWith("camel.opentelemetry.")) {
+ // grab the value
+ String value = prop.getProperty(key);
+ String option = key.substring(20);
+ validateOptionAndValue(key, option, value);
+ otelProperties.put(loc, optionKey(option), value);
} else if (key.startsWith("camel.routeTemplate")) {
// grab the value
String value = prop.getProperty(key);
@@ -1114,6 +1122,11 @@ public abstract class BaseMainSupport extends
BaseService {
setLraCheckProperties(camelContext, lraProperties,
mainConfigurationProperties.isAutoConfigurationFailFast(),
autoConfiguredProperties);
}
+ if (!otelProperties.isEmpty() ||
mainConfigurationProperties.hasOtelConfiguration()) {
+ LOG.debug("Auto-configuring OpenTelemetry from loaded properties:
{}", otelProperties.size());
+ setOtelProperties(camelContext, otelProperties,
mainConfigurationProperties.isAutoConfigurationFailFast(),
+ autoConfiguredProperties);
+ }
if (!devConsoleProperties.isEmpty()) {
LOG.debug("Auto-configuring Dev Console from loaded properties:
{}", devConsoleProperties.size());
setDevConsoleProperties(camelContext, devConsoleProperties,
@@ -1198,6 +1211,11 @@ public abstract class BaseMainSupport extends
BaseService {
LOG.warn("Property not auto-configured: camel.lra.{}={}", k,
v);
});
}
+ if (!otelProperties.isEmpty()) {
+ otelProperties.forEach((k, v) -> {
+ LOG.warn("Property not auto-configured:
camel.opentelemetry.{}={}", k, v);
+ });
+ }
if (!httpServerProperties.isEmpty()) {
httpServerProperties.forEach((k, v) -> {
LOG.warn("Property not auto-configured: camel.server.{}={}",
k, v);
@@ -1342,15 +1360,39 @@ public abstract class BaseMainSupport extends
BaseService {
boolean failIfNotSet, OrderedLocationProperties
autoConfiguredProperties)
throws Exception {
+ String loc = lraProperties.getLocation("enabled");
Object obj = lraProperties.remove("enabled");
if (ObjectHelper.isNotEmpty(obj)) {
- String loc = lraProperties.getLocation("enabled");
autoConfiguredProperties.put(loc, "camel.lra.enabled",
obj.toString());
}
boolean enabled = obj != null ?
CamelContextHelper.parseBoolean(camelContext, obj.toString()) : true;
if (enabled) {
CamelSagaService css = resolveLraSagaService(camelContext);
setPropertiesOnTarget(camelContext, css, lraProperties,
"camel.lra.", failIfNotSet, true, autoConfiguredProperties);
+ // add as service so saga can be active
+ camelContext.addService(css, true, true);
+ }
+ }
+
+ private void setOtelProperties(
+ CamelContext camelContext, OrderedLocationProperties
otelProperties,
+ boolean failIfNotSet, OrderedLocationProperties
autoConfiguredProperties)
+ throws Exception {
+
+ String loc = otelProperties.getLocation("enabled");
+ Object obj = otelProperties.remove("enabled");
+ if (ObjectHelper.isNotEmpty(obj)) {
+ autoConfiguredProperties.put(loc, "camel.opentelemetry.enabled",
obj.toString());
+ }
+ boolean enabled = obj != null ?
CamelContextHelper.parseBoolean(camelContext, obj.toString()) : true;
+ if (enabled) {
+ CamelTracingService otel = resolveOtelService(camelContext);
+ setPropertiesOnTarget(camelContext, otel, otelProperties,
"camel.opentelemetry.", failIfNotSet, true,
+ autoConfiguredProperties);
+ if (camelContext.hasService(CamelTracingService.class) == null) {
+ // add as service so tracing can be active
+ camelContext.addService(otel, true, true);
+ }
}
}
@@ -1982,16 +2024,29 @@ public abstract class BaseMainSupport extends
BaseService {
}
private static CamelSagaService resolveLraSagaService(CamelContext
camelContext) throws Exception {
- // lookup in service registry first
- CamelSagaService answer =
camelContext.getRegistry().findSingleByType(CamelSagaService.class);
+ CamelSagaService answer =
camelContext.hasService(CamelSagaService.class);
+ if (answer == null) {
+ answer =
camelContext.getRegistry().findSingleByType(CamelSagaService.class);
+ }
if (answer == null) {
answer =
camelContext.getCamelContextExtension().getBootstrapFactoryFinder()
.newInstance("lra-saga-service", CamelSagaService.class)
.orElseThrow(() -> new IllegalArgumentException(
"Cannot find LRASagaService on classpath. Add
camel-lra to classpath."));
+ }
+ return answer;
+ }
- // add as service so its discover by saga eip
- camelContext.addService(answer, true, false);
+ private static CamelTracingService resolveOtelService(CamelContext
camelContext) throws Exception {
+ CamelTracingService answer =
camelContext.hasService(CamelTracingService.class);
+ if (answer == null) {
+ answer =
camelContext.getRegistry().findSingleByType(CamelTracingService.class);
+ }
+ if (answer == null) {
+ answer =
camelContext.getCamelContextExtension().getBootstrapFactoryFinder()
+ .newInstance("opentelemetry-tracer",
CamelTracingService.class)
+ .orElseThrow(() -> new IllegalArgumentException(
+ "Cannot find OpenTelemetryTracer on classpath. Add
camel-opentelemetry to classpath."));
}
return answer;
}
diff --git
a/core/camel-main/src/main/java/org/apache/camel/main/MainConfigurationProperties.java
b/core/camel-main/src/main/java/org/apache/camel/main/MainConfigurationProperties.java
index ea12f3631bf..79273789d92 100644
---
a/core/camel-main/src/main/java/org/apache/camel/main/MainConfigurationProperties.java
+++
b/core/camel-main/src/main/java/org/apache/camel/main/MainConfigurationProperties.java
@@ -53,6 +53,7 @@ public class MainConfigurationProperties extends
DefaultConfigurationProperties<
// extended configuration
private HealthConfigurationProperties healthConfigurationProperties;
private LraConfigurationProperties lraConfigurationProperties;
+ private OtelConfigurationProperties otelConfigurationProperties;
private ThreadPoolConfigurationProperties threadPoolProperties;
private Resilience4jConfigurationProperties
resilience4jConfigurationProperties;
private FaultToleranceConfigurationProperties
faultToleranceConfigurationProperties;
@@ -72,6 +73,10 @@ public class MainConfigurationProperties extends
DefaultConfigurationProperties<
lraConfigurationProperties.close();
lraConfigurationProperties = null;
}
+ if (otelConfigurationProperties != null) {
+ otelConfigurationProperties.close();
+ otelConfigurationProperties = null;
+ }
if (threadPoolProperties != null) {
threadPoolProperties.close();
threadPoolProperties = null;
@@ -151,6 +156,23 @@ public class MainConfigurationProperties extends
DefaultConfigurationProperties<
return lraConfigurationProperties != null;
}
+ /**
+ * To configure OpenTelemetry.
+ */
+ public OtelConfigurationProperties otel() {
+ if (otelConfigurationProperties == null) {
+ otelConfigurationProperties = new
OtelConfigurationProperties(this);
+ }
+ return otelConfigurationProperties;
+ }
+
+ /**
+ * Whether there has been any OpenTelemetry configuration specified
+ */
+ public boolean hasOtelConfiguration() {
+ return otelConfigurationProperties != null;
+ }
+
/**
* To configure embedded HTTP server (for standalone applications; not
Spring Boot or Quarkus)
*/
diff --git
a/core/camel-main/src/main/java/org/apache/camel/main/OtelConfigurationProperties.java
b/core/camel-main/src/main/java/org/apache/camel/main/OtelConfigurationProperties.java
new file mode 100644
index 00000000000..a41c23a1694
--- /dev/null
+++
b/core/camel-main/src/main/java/org/apache/camel/main/OtelConfigurationProperties.java
@@ -0,0 +1,112 @@
+/*
+ * 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.main;
+
+import org.apache.camel.spi.BootstrapCloseable;
+import org.apache.camel.spi.Configurer;
+import org.apache.camel.spi.Metadata;
+
+/**
+ * Global configuration for OpenTelemetry
+ */
+@Configurer(bootstrap = true)
+public class OtelConfigurationProperties implements BootstrapCloseable {
+
+ private MainConfigurationProperties parent;
+
+ @Metadata(defaultValue = "camel", required = true)
+ private String instrumentationName = "camel";
+ private boolean encoding;
+ private String excludePatterns;
+
+ public OtelConfigurationProperties(MainConfigurationProperties parent) {
+ this.parent = parent;
+ }
+
+ public MainConfigurationProperties end() {
+ return parent;
+ }
+
+ @Override
+ public void close() {
+ parent = null;
+ }
+
+ public String getInstrumentationName() {
+ return instrumentationName;
+ }
+
+ /**
+ * A name uniquely identifying the instrumentation scope, such as the
instrumentation library, package, or fully
+ * qualified class name. Must not be null.
+ */
+ public void setInstrumentationName(String instrumentationName) {
+ this.instrumentationName = instrumentationName;
+ }
+
+ public boolean isEncoding() {
+ return encoding;
+ }
+
+ /**
+ * Sets whether the header keys need to be encoded (connector specific) or
not. The value is a boolean. Dashes need
+ * for instances to be encoded for JMS property keys.
+ */
+ public void setEncoding(boolean encoding) {
+ this.encoding = encoding;
+ }
+
+ public String getExcludePatterns() {
+ return excludePatterns;
+ }
+
+ /**
+ * Adds an exclude pattern that will disable tracing for Camel messages
that matches the pattern. Multiple patterns
+ * can be separated by comma.
+ */
+ public void setExcludePatterns(String excludePatterns) {
+ this.excludePatterns = excludePatterns;
+ }
+
+ /**
+ * A name uniquely identifying the instrumentation scope, such as the
instrumentation library, package, or fully
+ * qualified class name. Must not be null.
+ */
+ public OtelConfigurationProperties withInstrumentationName(String
instrumentationName) {
+ this.instrumentationName = instrumentationName;
+ return this;
+ }
+
+ /**
+ * Sets whether the header keys need to be encoded (connector specific) or
not. The value is a boolean. Dashes need
+ * for instances to be encoded for JMS property keys.
+ */
+ public OtelConfigurationProperties withEncoding(boolean encoding) {
+ this.encoding = encoding;
+ return this;
+ }
+
+ /**
+ * Adds an exclude pattern that will disable tracing for Camel messages
that matches the pattern. Multiple patterns
+ * can be separated by comma.
+ */
+ public OtelConfigurationProperties withExcludePatterns(String
excludePatterns) {
+ this.excludePatterns = excludePatterns;
+ return this;
+ }
+
+}
diff --git
a/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/PrepareCamelMainMojo.java
b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/PrepareCamelMainMojo.java
index 3ac979cc46e..e5d80ece234 100644
---
a/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/PrepareCamelMainMojo.java
+++
b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/PrepareCamelMainMojo.java
@@ -204,6 +204,8 @@ public class PrepareCamelMainMojo extends
AbstractGeneratorMojo {
prefix = "camel.health.";
} else if (file.getName().contains("Lra")) {
prefix = "camel.lra.";
+ } else if (file.getName().contains("Otel")) {
+ prefix = "camel.opentelemetry.";
} else if (file.getName().contains("HttpServer")) {
prefix = "camel.server.";
} else if
(file.getName().contains("ThreadPoolProfileConfigurationProperties")) {
@@ -316,6 +318,9 @@ public class PrepareCamelMainMojo extends
AbstractGeneratorMojo {
"camel.vault.azure", "Camel Azure Key Vault
configurations",
"org.apache.camel.vault.AzureVaultConfiguration"));
// TODO: add more vault providers here
+ model.getGroups().add(new MainGroupModel(
+ "camel.opentelemetry", "Camel OpenTelemtry configurations",
+ "org.apache.camel.main.OtelConfigurationProperties"));
model.getGroups()
.add(new MainGroupModel(
"camel.faulttolerance", "Fault Tolerance EIP
Circuit Breaker configurations",