[[geode-samples-boot-actuator]]
= Spring Boot Actuator for Apache Geode & Pivotal GemFire
:apache-geode-version: 16
:apache-geode-docs:https://geode.apache.org/docs/guide/{apache-geode-version}
:images-dir: ../images
:spring-boot-docs: https://docs.spring.io/spring-boot/docs/current/reference/html
:spring-framework-docs: https://docs.spring.io/spring/docs/current/spring-framework-reference

This guide walks through using {spring-boot-docs}/production-ready.html[Spring Boot Actuator] to assess the state
of your running Apache Geode or Pivotal GemFire, Spring Boot application.

The goal for SBDG's Spring Boot Actuator integration is to enable users to effectively manage and monitor their
Spring Boot applications using Apache Geode or Pivotal GemFire in a production environment.

In particular, SBDG's integration with Spring Boot Actuator currently focuses on enabling
{spring-boot-docs}/production-ready-endpoints.html#production-ready-health[Health Information]
for your application.  In the future, SBDG will provide dedicated support for http://micrometer.io/[Micrometer] metrics.

This guide assumes you are already familiar with Spring Boot and Apache Geode (or Pivotal GemFire).

link:../index.html#geode-samples[Back]

[[geode-samples-boot-actuator-example]]
== Example Application

This guide additionally provides a working {github-samples-url}/boot/actuator[example application] to review some of
the Actuator Health Endpoints.

The example application is a simple Temperature Monitoring Service, simulating a real-world, Internet of Things (IOT)
Use Case (UC).  Essentially, the application collects temperature readings from different temperature sensors (devices)
and uses the readings to monitor fluctuations in temperatures so that someone or something can respond accordingly.
The sensor devices could be located around the world in multiple locations in the planet's oceans.

[[geode-samples-boot-actuator-example-temperaturereading]]
=== TemperatureReading

First, we start by modeling a temperature reading, which stores the temperature in Fahrenheit along with a timestamp
for when the reading was measured.

Clearly, a more practical example would store the temperature measurement as a `double` or `BigDecimal` along with
the ability to support different scales (Celsius, Fahrenheit, Kelvin).

However in this case, we simply model the `TemperatureReading` as:

.TemperatureReading class
[source,java]
----
include::{samples-dir}/boot/actuator/src/main/java/example/app/temp/model/TemperatureReading.java[tags=class]
----

The `TemperatureReading` class is annotated with SDG's `@Region` mapping annotation to declare the Apache Geode Region
in which `TemperatureReadings` will be persisted.

[[geode-samples-boot-actuator-example-temperatureevent]]
=== TemperatureEvent

A key concern of our application is to "monitor" temperature readings.  Therefore, we need some way to capture
temperature change events.

For that, we introduce the simple `TemperatureEvent` base class:

.TemperatureEvent class
[source,java]
----
include::{samples-dir}/boot/actuator/src/main/java/example/app/temp/event/TemperatureEvent.java[tags=class]
----

`TemperatureEvent` is a Spring `ApplicationEvent` capable of being published to to Spring `@EventListeners` registered
in the Spring application context.

Additionally, we provide 2 subclasses: `BoilingTemperatureEvent` and `FreezingTemperatureEvent` to further classify
temperature changes.

[[geode-samples-boot-actuator-example-temperaturereadingrepository]]
=== TemperatureReadingRepository

To perform basic data access operations (e.g. CRUD) and simple queries on `TemperatureReadings`, we create
a Spring Data _Repository_:

.TemperatureReadingRepository interface
[source,java]
----
include::{samples-dir}/boot/actuator/src/main/java/example/app/temp/repo/TemperatureReadingRepository.java[tags=class]
----

The _Repository_ showcases a an example, derived query methods, `findByTimestampGreaterThanAndTimestampLessThan(..)`
along with 2 `@Query` annotated query methods using raw OQL queries.

[[geode-samples-boot-actuator-example-temperaturemonitor]]
=== TemperatureMonitor service class

To receive temperature change events, we need a class to monitor changes.  This capability is built on Apache Geode's
{apache-geode-docs}/developing/continuous_querying/chapter_overview.html[Continuous Query (CQ)] functionality.

With Apache Geode (or Pivotal GemFire) you can register an (OQL) Query with the servers in the cluster that runs
continuously, sending notifications back to the client anytime data changes to match the predicate in our query,
or queries.

For our purposes, we will simply monitor the temperature anytime it rises above boiling (212 °F)
or drops below freezing (32 °F):

.TemperatureMonitor class
[source,java]
----
include::{samples-dir}/boot/actuator/src/main/java/example/app/temp/service/TemperatureMonitor.java[tags=class]
----

When the temperature changes, triggering our queries, we receive an event and publish an appropriate `TemperatureEvent`
by using the Spring container's `ApplicationEventPublisher`, which has been injected into the monitor class.

The 2 OQL queries have been defined to query the "TemperatureReadings" Region and fire anytime the temperature
rises is above boiling (212 °F) or drops below freezing (32 °F).

[[geode-samples-boot-actuator-example-temperaturesensor]]
=== TemperatureSensor service class

Of course, we need a simulator to generate temperatures.

For that we have the `TemperatureSensor` class:

.TemperatureSensor class
[source,java]
----
include::{samples-dir}/boot/actuator/src/main/java/example/app/temp/service/TemperatureSensor.java[tags=class]
----

To generate a stream of temperatures, we use Spring's {spring-framework-docs}/integration.html#scheduling[Scheduling Service]
along with a `Random` stream of `ints` provided via an `Iterator`, as seen in the `readTemperature()` method.

The `readTemperature()` method is then storing the *new* `TemperatureReading` in the "TemperatureReadings" Region
as designated by our `TemperatureReading` model class's, `@Region` annotation declaration:

.@Region declaration
[source,java]
----
@Region("TemperatureReadings")
public class TemperatureReading { ... }
----

Additionally, the `readTempeature()` method uses our `TemperatureReadingRepository` to perform the necessary
data access operations.

[[geode-samples-boot-actuator-example-server]]
=== Server

Now, we need a couple of main application classes to actually have the application do something useful.

We start with an Spring Boot, Apache Geode Server application functioning as the temperature sensor (device)
using the `TemperatureSensor` class:

.BootGeodeServerApplication main class
[source,java]
----
include::{samples-dir}/boot/actuator/src/main/java/example/app/temp/geode/server/BootGeodeServerApplication.java[tags=class]
----

This class is annotated with `@SpringBootApplication` making it a proper Spring Boot application. It uses Spring Boot's
`SpringApplicationBuilder` to configure and bootstrap the server application.

This class is also annotated with SDG's `@CacheServerApplication` making it a proper Apache Geode Server with a peer
`Cache` instance along with a `CacheServer` to accept client connections.  This effectively overrides SBDG's default
`ClientCache` instance.

Additionally, the class enables several other features, such as Spring's _Scheduling Service_, Apache Geode Statistics,
and entity-defined Regions making the creation of our server-side, partitioned "TemperatureReadings" Region simple.

By enabling Apache Geode statistics, we allow Spring Boot's Actuator, `HealthIndicators` to collect metrics about
our running Apache Geode Server as well.

Because we have enabled scheduling (with `@EnableScheduling`) and declared the `TemperatureSensor` class as a bean
in the Spring application context, the application will immediately start generating temperature readings, which are
recorded to the "TemperatureReadings" Region.

Finally, our class registers a couple Apache Geode Region Indexes to make the Actuator `HealthIndicator` information
more interesting, particularly since we are running continuous queries.

This is a Servlet-based application as well since our Actuator, `HealthIndicator` endpoints are exposed via HTTP.

TIP: There are multiple ways to configure and bootstrap an Apache Geode Server, and the server-side of our application.
Using Spring Boot is one of the easier ways.

[[geode-samples-boot-actuator-example-client]]
=== Client

Next, we need a client functioning as the "monitor" in our Temperature Service application.

.BootGeodeClientApplication main class
[source,java]
----
include::{samples-dir}/boot/actuator/src/main/java/example/app/temp/geode/client/BootGeodeClientApplication.java[tags=class]
----

Again, this class is also annotated with `@SpringBootApplication` making it a proper Spring Boot application.  It too
uses Spring Boot's `SpringApplicationBuilder` class to configure and bootstrap the client application.

Unlike our server, this class is not annotated with any SDG `@*Cache*Application` annotations since SBDG provides us
a `ClientCache` instance by default. We want this application to be a client in our setup.

Like our server, we enable entity-defined Regions to easily and quickly create the client `PROXY` Region
for "TemperatureReadings", which will send/receive data to/from the server-side Region by the same name.

And, like our server application, we declare a bean of type `TemperatureMonitor` in the Spring application context
to receive the `TemperatureReading` events. This enables the CQ registration and event handlers
to sets things in motion.

Probably the most interesting part is that we an `@EventListener` to receive the `TemperatureEvents` to log
the `TemperatureReadings` to `System.err`.

[[geode-samples-boot-actuator-example-run]]
== Run the Example

It is time to run the example.

First, we start the server:

.Run the server
[source,txt]
----
/Library/Java/JavaVirtualMachines/jdk1.8.0_192.jdk/Contents/Home/bin/java -server -ea -Dspring.profiles.active=server
  ... example.app.temp.geode.server.BootGeodeServerApplication

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.0.9.RELEASE)

TEMPERATURE READING [99 °F]
TEMPERATURE READING [-17 °F]
TEMPERATURE READING [67 °F]
TEMPERATURE READING [9 °F]
TEMPERATURE READING [102 °F]
TEMPERATURE READING [10 °F]
...
----

After the server starts and begins to log temperature readings (as shown above), then start the client:

.Run the client
[source,txt]
----
/Library/Java/JavaVirtualMachines/jdk1.8.0_192.jdk/Contents/Home/bin/java -server -ea -Dspring.profiles.active=client
  ... example.app.temp.geode.client.BootGeodeClientApplication

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.0.9.RELEASE)

COLD TEMPERATURE READING [-22 °F]
COLD TEMPERATURE READING [25 °F]
HOT TEMPERATURE READING [305 °F]
COLD TEMPERATURE READING [-82 °F]
HOT TEMPERATURE READING [295 °F]
HOT TEMPERATURE READING [326 °F]
HOT TEMPERATURE READING [378 °F]
COLD TEMPERATURE READING [-4 °F]
...
----

You should only see boiling and freezing temperatures logged to the client's console. This is because our client
only "monitors" and logs temperature readings above or below our thresholds (boiling/freezing), as defined by
the Continuous Queries (CQ).

Both the server and client will continue to run, generating and logging temperatures, until you stop the JVM processes.

[[geode-samples-boot-actuator-example-monitor]]
== Monitoring our Example with Spring Boot Actuator, HealthIndicator Endpoints

After the application has been running for some time, we can inspect the Spring Boot Actuator, HealthIndicator Endpoints
provided by SBDG to monitor our application's health and runtime performance in addition to basic configuration
meta-data used to configure Apache Geode at runtime.

[[geode-samples-boot-actuator-example-monitor-client]]
=== Client Health Information

To navigate to the client applications Actuator Health endpoints, open a Web Browser (e.g. Google Chrome) to:

`http://localhost:9191/actuator/health`

This will output a JSON document similar to:

image::{images-dir}/client-actuator-health-endpoints.png[]

We can see details on our client "TemperatureReadings" Region:

image::{images-dir}/client-actuator-health-region-endpoint.png[]

As well as our CQs:

image::{images-dir}/client-actuator-health-cq-endpoint.png[]

When you hit refresh, the metrics will update.

[[geode-samples-boot-actuator-example-monitor-server]]
=== Server Health Information

To navigate to the server applications Actuator Health endpoint, open a Web Browser (e.g. Google Chrome) to:

`http://localhost:8181/actuator/health`

This will output a JSON document similar to:

image::{images-dir}/server-actuator-health-endpoints.png[]

We can see details of the server "TemperatureReadings" Region:

image::{images-dir}/server-actuator-health-region-endpoint.png[]

As well as our Indexes:

image::{images-dir}/server-actuator-health-indexes-endpoint.png[]

And our CacheServer serving clients:

image::{images-dir}/server-actuator-health-cacheserver-endpoint.png[]

When you hit refresh, the metrics will update.

[[geode-samples-boot-actuator-enabling]]
== Enabling Spring Boot Actuator

All of this was made possible by including the following dependency on our application classpath:

.Maven POM
[source,xml]
----
<dependency>
  <groupId>org.springframework.geode</groupId>
  <artifactId>spring-geode-starter-actuator</artifactId>
</dependency
----

Additionally, in Spring Boot `application.properties`, you must enable the following:

.Spring Boot `application.properties`
[source,txt]
----
management.endpoint.health.show-details=always
----

[[geode-samples-boot-actuator-conclusion]]
== Conclusion

Hopefully this guide has shown you how to use the Spring Boot Actuator feature for Apache Geode and Pivotal GemFire.

You are encouraged to read more about {spring-boot-docs}/production-ready.html[Spring Boot's Actuator] functionality.

Additonally, you can find out more about Apache Geode Statistics
in the {apache-geode-docs}/managing/statistics/chapter_overview.html[User Guide].

link:../index.html#geode-samples[Back]
