Skip to content

Commit

Permalink
feat(extensions): observability services unit and integration tests
Browse files Browse the repository at this point in the history
  • Loading branch information
squakez committed Dec 10, 2024
1 parent b66d16a commit f232b3e
Show file tree
Hide file tree
Showing 14 changed files with 639 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,67 @@ Or add the coordinates to your existing project:
ifeval::[{doc-show-user-guide-link} == true]
Check the xref:user-guide/index.adoc[User guide] for more information about writing Camel Quarkus applications.
endif::[]

[id="extensions-observability-services-usage"]
== Usage
This extension is used to provide a set of opinionated components and configuration which simplify operations such as observability on cloud environments. Although the component is mainly targeted for cloud, it can be used in any other environment, giving to the Camel application the capability to expose a set of observability features by default.

All you need to do is to add the dependency to the classpath. There's no need to add any further configuration. Each individual component will be configured using each own default settings except the endpoint which will be exposed in */observe/<service>* by default.

If you need to customize each of the different components provided within this service, then, you can specify in the *application.properties* each of the configuration as it would be done normally when you provide the individual component.

[id="extensions-observability-services-usage-components"]
== Components

The presence of this dependency will provide the following extensions:

* Camel Quarkus Microprofile
* Camel Quarkus Management
* Camel Quarkus Micrometer
* Camel Quarkus OpenTelemetry
* Quarkus Micrometer Registry Prometheus

[id="extensions-observability-services-usage-list-of-known-endpoints"]
=== List of known endpoints

The presence of this dependency will expose the following endpoints:

|====
|Endpoint | Description

| `/observe/health` | startup probe endpoint
| `/observe/health/live` | liveness probe endpoint
| `/observe/health/ready` | readiness probe endpoint
| `/observe/metrics` | metrics exposed as in Micrometer Prometheus Registry

|====

NOTE: you can configure the endpoints as you'd do normally within each extension configuration.

[id="extensions-observability-services-usage-opentelemetry-configuration"]
== OpenTelemetry configuration

The presence of this component will provide the required instrumentation to easily enable the collection of Opentelemetry metrics. The Camel Quarkus Opentelemetry extension instrument your application with a service which periodically pushes OTEL traces to the collector. This is disabled by default in order to prevent the application to push traces when no telemetry server is available.

In order to turn it on, you need to specify the following configuration explicitly:

```
quarkus.otel.sdk.disabled=false
```

Beside that, you can change any further parameter, like, for instance, the server where to push the traces (default, `http://localhost:4317`)

```
quarkus.otel.exporter.otlp.traces.endpoint=http://my-otel-collector.svc:4317
```

NOTE: Quarkus runtime defaults to gRPC protocol (port 4317).

[id="extensions-observability-services-usage-jmx-configuration"]
== JMX configuration

The presence of this component implies the presence of `camel-management` component. This is in charge to include information about Camel application status in JMX format.

NOTE: the presence of this components automatically enable the collection of the JMX metrics. This should be negligible from performance point of view, however, you may want to disable that running the application with `-Dorg.apache.camel.jmx.disabled=true` JVM option.


18 changes: 15 additions & 3 deletions extensions/observability-services/deployment/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -56,13 +56,25 @@
<groupId>org.apache.camel.quarkus</groupId>
<artifactId>camel-quarkus-opentelemetry-deployment</artifactId>
</dependency>
<dependency>
<groupId>org.apache.camel.quarkus</groupId>
<artifactId>camel-quarkus-management-deployment</artifactId>
</dependency>

<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-opentelemetry-deployment</artifactId>
<artifactId>quarkus-junit5-internal</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.camel.quarkus</groupId>
<artifactId>camel-quarkus-management-deployment</artifactId>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-security-deployment</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-vertx-http</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.camel.quarkus.component.observability.services.deployment;
package org.apache.camel.quarkus.component.observabilityservices.deployment;

import io.quarkus.deployment.annotations.BuildStep;
import io.quarkus.deployment.builditem.FeatureBuildItem;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/*
* 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.component.observabilityservices.deployment;

import io.quarkus.test.QuarkusUnitTest;
import jakarta.inject.Inject;
import org.apache.camel.CamelContext;
import org.apache.camel.health.HealthCheckRegistry;
import org.apache.camel.impl.health.ConsumersHealthCheckRepository;
import org.apache.camel.impl.health.ContextHealthCheck;
import org.apache.camel.impl.health.RoutesHealthCheckRepository;
import org.apache.camel.microprofile.health.CamelMicroProfileHealthCheckRegistry;
import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.spec.JavaArchive;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

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

public class MicroProfileHealthEnabledTest {

@RegisterExtension
static final QuarkusUnitTest CONFIG = new QuarkusUnitTest()
.setArchiveProducer(() -> ShrinkWrap.create(JavaArchive.class));

@Inject
CamelContext context;

@Test
public void healthCheckRegistryNotNull() {
HealthCheckRegistry registry = HealthCheckRegistry.get(context);
assertNotNull(registry);
assertTrue(registry instanceof CamelMicroProfileHealthCheckRegistry);
assertEquals("camel-microprofile-health", registry.getId());
}

@Test
public void contextHealthCheckNotNull() {
ContextHealthCheck contextHealthCheck = context.getRegistry().lookupByNameAndType("context", ContextHealthCheck.class);
assertNotNull(contextHealthCheck);
}

@Test
public void routesHealthCheckNotNull() {
RoutesHealthCheckRepository routesRepository = context.getRegistry().lookupByNameAndType("routes",
RoutesHealthCheckRepository.class);
assertNotNull(routesRepository);
}

@Test
public void consumersHealthCheckNotNull() {
ConsumersHealthCheckRepository consumersRepository = context.getRegistry().lookupByNameAndType("consumers",
ConsumersHealthCheckRepository.class);
assertNotNull(consumersRepository);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
/*
* 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.component.observabilityservices.deployment;

import java.util.List;
import java.util.Optional;

import io.quarkus.test.QuarkusUnitTest;
import jakarta.inject.Inject;
import org.apache.camel.CamelContext;
import org.apache.camel.component.micrometer.eventnotifier.MicrometerExchangeEventNotifier;
import org.apache.camel.component.micrometer.eventnotifier.MicrometerExchangeEventNotifierNamingStrategy;
import org.apache.camel.component.micrometer.eventnotifier.MicrometerRouteEventNotifier;
import org.apache.camel.component.micrometer.eventnotifier.MicrometerRouteEventNotifierNamingStrategy;
import org.apache.camel.component.micrometer.routepolicy.MicrometerRoutePolicyConfiguration;
import org.apache.camel.component.micrometer.routepolicy.MicrometerRoutePolicyFactory;
import org.apache.camel.component.micrometer.routepolicy.MicrometerRoutePolicyNamingStrategy;
import org.apache.camel.component.micrometer.spi.InstrumentedThreadPoolFactory;
import org.apache.camel.impl.engine.DefaultMessageHistoryFactory;
import org.apache.camel.spi.EventNotifier;
import org.apache.camel.spi.MessageHistoryFactory;
import org.apache.camel.spi.RoutePolicyFactory;
import org.apache.camel.spi.ThreadPoolFactory;
import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.spec.JavaArchive;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertInstanceOf;
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 MicrometerMetricsConfigDefaultsTest {

@RegisterExtension
static final QuarkusUnitTest CONFIG = new QuarkusUnitTest()
.setArchiveProducer(() -> ShrinkWrap.create(JavaArchive.class));

@Inject
CamelContext context;

@Test
public void testMicrometerMetricsConfiguration() {
List<RoutePolicyFactory> routePolicyFactories = context.getRoutePolicyFactories();
assertEquals(1, routePolicyFactories.size());
RoutePolicyFactory routePolicyFactory = routePolicyFactories.get(0);
assertInstanceOf(MicrometerRoutePolicyFactory.class, routePolicyFactory);
MicrometerRoutePolicyFactory micrometerRoutePolicyFactory = (MicrometerRoutePolicyFactory) routePolicyFactory;
assertEquals(MicrometerRoutePolicyNamingStrategy.DEFAULT, micrometerRoutePolicyFactory.getNamingStrategy());

MicrometerRoutePolicyConfiguration policyConfiguration = micrometerRoutePolicyFactory.getPolicyConfiguration();
assertTrue(policyConfiguration.isContextEnabled());
assertTrue(policyConfiguration.isRouteEnabled());
assertNull(policyConfiguration.getExcludePattern());

MessageHistoryFactory messageHistoryFactory = context.getMessageHistoryFactory();
assertNotNull(messageHistoryFactory);
assertInstanceOf(DefaultMessageHistoryFactory.class, messageHistoryFactory);

List<EventNotifier> eventNotifiers = context.getManagementStrategy()
.getEventNotifiers()
.stream()
.filter(eventNotifier -> !eventNotifier.getClass().getName().contains("BaseMainSupport"))
.toList();
assertEquals(3, eventNotifiers.size());

Optional<EventNotifier> optionalExchangeEventNotifier = context.getManagementStrategy()
.getEventNotifiers()
.stream()
.filter(eventNotifier -> eventNotifier.getClass().equals(MicrometerExchangeEventNotifier.class))
.findFirst();
assertTrue(optionalExchangeEventNotifier.isPresent());

MicrometerExchangeEventNotifier micrometerExchangeEventNotifier = (MicrometerExchangeEventNotifier) optionalExchangeEventNotifier
.get();
assertEquals(MicrometerExchangeEventNotifierNamingStrategy.DEFAULT,
micrometerExchangeEventNotifier.getNamingStrategy());

Optional<EventNotifier> optionalRouteEventNotifier = context.getManagementStrategy()
.getEventNotifiers()
.stream()
.filter(eventNotifier -> eventNotifier.getClass().equals(MicrometerRouteEventNotifier.class))
.findFirst();
assertTrue(optionalRouteEventNotifier.isPresent());

MicrometerRouteEventNotifier micrometerRouteEventNotifier = (MicrometerRouteEventNotifier) optionalRouteEventNotifier
.get();
assertEquals(MicrometerRouteEventNotifierNamingStrategy.DEFAULT, micrometerRouteEventNotifier.getNamingStrategy());

ThreadPoolFactory threadPoolFactory = context.getExecutorServiceManager().getThreadPoolFactory();
assertNotNull(threadPoolFactory);
assertFalse(threadPoolFactory instanceof InstrumentedThreadPoolFactory);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/*
* 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.component.observabilityservices.deployment;

import java.util.Set;

import io.quarkus.test.QuarkusUnitTest;
import jakarta.inject.Inject;
import org.apache.camel.CamelContext;
import org.apache.camel.opentelemetry.CamelQuarkusOpenTelemetryTracer;
import org.apache.camel.opentelemetry.OpenTelemetryTracer;
import org.apache.camel.opentelemetry.OpenTelemetryTracingStrategy;
import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.spec.JavaArchive;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertInstanceOf;
import static org.junit.jupiter.api.Assertions.assertTrue;

public class OpenTelemetryEnabledTest {

private static final String EXCLUDE_PATTERNS = "platform-http:*,platform-http:/prefix/.*";

@RegisterExtension
static final QuarkusUnitTest CONFIG = new QuarkusUnitTest()
.overrideConfigKey("quarkus.otel.sdk.disabled", "false")
.overrideConfigKey("quarkus.camel.opentelemetry.encoding", "true")
.overrideConfigKey("quarkus.camel.opentelemetry.exclude-patterns", EXCLUDE_PATTERNS)
.overrideConfigKey("quarkus.camel.opentelemetry.trace-processors", "true")
.setArchiveProducer(() -> ShrinkWrap.create(JavaArchive.class));

@Inject
CamelContext context;

@Test
public void camelOpenTelemetryTracerRegistryBeanNotNull() {
Set<OpenTelemetryTracer> tracers = context.getRegistry().findByType(OpenTelemetryTracer.class);
assertEquals(1, tracers.size());

OpenTelemetryTracer tracer = tracers.iterator().next();
assertInstanceOf(CamelQuarkusOpenTelemetryTracer.class, tracer);
assertInstanceOf(OpenTelemetryTracingStrategy.class, tracer.getTracingStrategy());
assertTrue(tracer.isEncoding());
assertEquals(EXCLUDE_PATTERNS, tracer.getExcludePatterns());
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
This extension is used to provide a set of opinionated components and configuration which simplify operations such as observability on cloud environments. Although the component is mainly targeted for cloud, it can be used in any other environment, giving to the Camel application the capability to expose a set of observability features by default.

== Usage

All you need to do is to add the dependency to the classpath. There's no need to add any further configuration. Each individual component will be configured using each own default settings except the endpoint which will be exposed in */observe/<service>* by default.

If you need to customize each of the different components provided within this service, then, you can specify in the *application.properties* each of the configuration as it would be done normally when you provide the individual component.
Expand All @@ -10,10 +8,11 @@ If you need to customize each of the different components provided within this s

The presence of this dependency will provide the following extensions:

* Camel Microprofile Health Quarkus extension
* Camel Management Quarkus extension
* Camel Micrometer Prometheus Quarkus extension
* Camel Opentelemetry Quarkus extension
* Camel Quarkus Microprofile
* Camel Quarkus Management
* Camel Quarkus Micrometer
* Camel Quarkus OpenTelemetry
* Quarkus Micrometer Registry Prometheus

=== List of known endpoints

Expand Down
3 changes: 1 addition & 2 deletions extensions/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,7 @@
<module>netty</module>
<module>netty-http</module>
<module>nitrite</module>
<module>observability-services</module>
<module>oaipmh</module>
<module>ognl</module>
<module>olingo4</module>
Expand Down Expand Up @@ -264,8 +265,6 @@
<module>zendesk</module>
<module>zip-deflater</module>
<module>zipfile</module>
<!-- depends on the presence of other modules -->
<module>observability-services</module>
</modules>

<dependencyManagement>
Expand Down
Loading

0 comments on commit f232b3e

Please sign in to comment.