Skip to content
Snippets Groups Projects
Unverified Commit c86d510e authored by Antoine Rey's avatar Antoine Rey Committed by GitHub
Browse files

Merge branch 'master' into feature/Greenwich

parents 2114cf7c b86d8a04
No related branches found
No related tags found
No related merge requests found
Showing
with 158 additions and 13 deletions
...@@ -85,17 +85,42 @@ ENV SPRING_PROFILES_ACTIVE docker,mysql ...@@ -85,17 +85,42 @@ ENV SPRING_PROFILES_ACTIVE docker,mysql
In the `mysql section` of the `application.yml` from the [Configuration repository], you have to change In the `mysql section` of the `application.yml` from the [Configuration repository], you have to change
the host and port of your MySQL JDBC connection string. the host and port of your MySQL JDBC connection string.
## Custom metrics monitoring
@todo Add default custom dashboards to grafana
Grafana and Prometheus are included in the `docker-compose.yml` configuration, and the public facing applications have been instrumented with [MicroMeter](https://micrometer.io) to collect JVM and custom business metrics.
### Using Prometheus
* Prometheus can be accessed from your local machine at http://localhost:9091
### Using Grafana with Prometheus
* Login to Grafana at http://localhost:3000, the default user/pass is `admin:admin`, you will be prompted to change your password.
* Setup a prometheus datasource and point the URL to `http://prometheus-server:9090`, leave all the other options set to their default.
* Add the [Micrometer/SpringBoot dashboard](https://grafana.com/dashboards/4701) via the Import Dashboard menu item. The id for the dashboard is `4701`
### Custom metrics implementation
* `customers-service` application has the following custom metrics enabled:
* counter: `create.owner`
* counter: `update.owner`
* counter: `create.pet`
* counter: `update.pet`
* `visits-service` application has the following custom metrics enabled:
* counter: `create.visit`
## Looking for something in particular? ## Looking for something in particular?
| Spring Cloud components | Resources | | Spring Cloud components | Resources |
|-------------------------|------------| |---------------------------------|------------|
| Configuration server | [Config server properties](spring-petclinic-config-server/src/main/resources/application.yml) and [Configuration repository] | | Configuration server | [Config server properties](spring-petclinic-config-server/src/main/resources/application.yml) and [Configuration repository] |
| Service Discovery | [Eureka server](spring-petclinic-discovery-server) and [Service discovery client](spring-petclinic-vets-service/src/main/java/org/springframework/samples/petclinic/vets/VetsServiceApplication.java) | | Service Discovery | [Eureka server](spring-petclinic-discovery-server) and [Service discovery client](spring-petclinic-vets-service/src/main/java/org/springframework/samples/petclinic/vets/VetsServiceApplication.java) |
| API Gateway | [Zuul reverse proxy](spring-petclinic-api-gateway/src/main/java/org/springframework/samples/petclinic/api/ApiGatewayApplication.java) and [Routing configuration](https://github.com/spring-petclinic/spring-petclinic-microservices-config/blob/master/api-gateway.yml) | | API Gateway | [Zuul reverse proxy](spring-petclinic-api-gateway/src/main/java/org/springframework/samples/petclinic/api/ApiGatewayApplication.java) and [Routing configuration](https://github.com/spring-petclinic/spring-petclinic-microservices-config/blob/master/api-gateway.yml) |
| Docker Compose | [Spring Boot with Docker guide](https://spring.io/guides/gs/spring-boot-docker/) and [docker-compose file](docker-compose.yml) | | Docker Compose | [Spring Boot with Docker guide](https://spring.io/guides/gs/spring-boot-docker/) and [docker-compose file](docker-compose.yml) |
| Circuit Breaker | [Circuit Breaker with Hystrix guide](https://spring.io/guides/gs/circuit-breaker/) and [fallback method configuration](spring-petclinic-api-gateway/src/main/java/org/springframework/samples/petclinic/api/application/VisitsServiceClient.java) | | Circuit Breaker | TBD |
| Graphite Monitoring | TBD | | Grafana / Prometheus Monitoring | [Micrometer implementation](https://micrometer.io/) |
Front-end module | Files | Front-end module | Files |
|-------------------|-------| |-------------------|-------|
......
version: '2' version: '2'
volumes:
graf-data:
services: services:
config-server: config-server:
image: mszarlinski/spring-petclinic-config-server image: mszarlinski/spring-petclinic-config-server
...@@ -91,3 +95,22 @@ services: ...@@ -91,3 +95,22 @@ services:
entrypoint: ["./dockerize","-wait=tcp://discovery-server:8761","-timeout=60s","--","java", "-XX:+UnlockExperimentalVMOptions", "-XX:+UseCGroupMemoryLimitForHeap", "-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"] entrypoint: ["./dockerize","-wait=tcp://discovery-server:8761","-timeout=60s","--","java", "-XX:+UnlockExperimentalVMOptions", "-XX:+UseCGroupMemoryLimitForHeap", "-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]
ports: ports:
- 7979:7979 - 7979:7979
## Grafana / Prometheus
grafana-server:
image: grafana/grafana:5.2.4
container_name: grafana-server
mem_limit: 256M
ports:
- 3000:3000
volumes:
- graf-data:/var/lib/grafana
prometheus-server:
build: ./docker/prometheus
image: prometheus-local:v2.4.2
container_name: prometheus-server
mem_limit: 256M
ports:
- 9091:9090
FROM prom/prometheus:v2.4.2
ADD prometheus.yml /etc/prometheus/
# my global config
global:
scrape_interval: 15s # Set the scrape interval to every 15 seconds. Default is every 1 minute.
evaluation_interval: 15s # Evaluate rules every 15 seconds. The default is every 1 minute.
# scrape_timeout is set to the global default (10s).
# A scrape configuration containing exactly one endpoint to scrape:
# Here it's Prometheus itself.
scrape_configs:
- job_name: prometheus
static_configs:
- targets: ['localhost:9090']
- job_name: api-gateway
metrics_path: /actuator/prometheus
static_configs:
- targets: ['api-gateway:8080']
- job_name: customers-service
metrics_path: /actuator/prometheus
static_configs:
- targets: ['customers-service:8081']
- job_name: visits-service
metrics_path: /actuator/prometheus
static_configs:
- targets: ['visits-service:8082']
- job_name: vets-service
metrics_path: /actuator/prometheus
static_configs:
- targets: ['vets-service:8083']
...@@ -32,6 +32,7 @@ ...@@ -32,6 +32,7 @@
<spring-boot.version>2.1.2.RELEASE</spring-boot.version> <spring-boot.version>2.1.2.RELEASE</spring-boot.version>
<spring-cloud.version>Greenwich.RELEASE</spring-cloud.version> <spring-cloud.version>Greenwich.RELEASE</spring-cloud.version>
<micrometer.version>1.0.5</micrometer.version>
<maven-surefire-plugin.version>2.22.0</maven-surefire-plugin.version> <maven-surefire-plugin.version>2.22.0</maven-surefire-plugin.version>
...@@ -69,6 +70,19 @@ ...@@ -69,6 +70,19 @@
<version>${assertj.version}</version> <version>${assertj.version}</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<!-- Micrometer core dependency -->
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-core</artifactId>
<version>${micrometer.version}</version>
</dependency>
<!-- Micrometer Prometheus registry -->
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
<version>${micrometer.version}</version>
</dependency>
</dependencies> </dependencies>
</dependencyManagement> </dependencyManagement>
......
...@@ -87,6 +87,14 @@ ...@@ -87,6 +87,14 @@
<groupId>org.projectlombok</groupId> <groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId> <artifactId>lombok</artifactId>
</dependency> </dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-core</artifactId>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
</dependency>
<!-- Webjars --> <!-- Webjars -->
<dependency> <dependency>
......
...@@ -77,6 +77,14 @@ ...@@ -77,6 +77,14 @@
<groupId>org.projectlombok</groupId> <groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId> <artifactId>lombok</artifactId>
</dependency> </dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-core</artifactId>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
</dependency>
<!-- Testing --> <!-- Testing -->
<dependency> <dependency>
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
*/ */
package org.springframework.samples.petclinic.customers.web; package org.springframework.samples.petclinic.customers.web;
import io.micrometer.core.instrument.MeterRegistry;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
...@@ -40,6 +41,7 @@ import java.util.Optional; ...@@ -40,6 +41,7 @@ import java.util.Optional;
class OwnerResource { class OwnerResource {
private final OwnerRepository ownerRepository; private final OwnerRepository ownerRepository;
private final MeterRegistry registry;
/** /**
* Create Owner * Create Owner
...@@ -47,6 +49,7 @@ class OwnerResource { ...@@ -47,6 +49,7 @@ class OwnerResource {
@PostMapping @PostMapping
@ResponseStatus(HttpStatus.CREATED) @ResponseStatus(HttpStatus.CREATED)
public void createOwner(@Valid @RequestBody Owner owner) { public void createOwner(@Valid @RequestBody Owner owner) {
registry.counter("create.owner").increment();
ownerRepository.save(owner); ownerRepository.save(owner);
} }
...@@ -81,6 +84,7 @@ class OwnerResource { ...@@ -81,6 +84,7 @@ class OwnerResource {
ownerModel.setAddress(ownerRequest.getAddress()); ownerModel.setAddress(ownerRequest.getAddress());
ownerModel.setTelephone(ownerRequest.getTelephone()); ownerModel.setTelephone(ownerRequest.getTelephone());
log.info("Saving owner {}", ownerModel); log.info("Saving owner {}", ownerModel);
registry.counter("update.owner").increment();
return ownerRepository.save(ownerModel); return ownerRepository.save(ownerModel);
} }
} }
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
*/ */
package org.springframework.samples.petclinic.customers.web; package org.springframework.samples.petclinic.customers.web;
import io.micrometer.core.instrument.MeterRegistry;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
...@@ -36,8 +37,9 @@ import java.util.Optional; ...@@ -36,8 +37,9 @@ import java.util.Optional;
class PetResource { class PetResource {
private final PetRepository petRepository; private final PetRepository petRepository;
private final OwnerRepository ownerRepository; private final OwnerRepository ownerRepository;
private final MeterRegistry registry;
@GetMapping("/petTypes") @GetMapping("/petTypes")
public List<PetType> getPetTypes() { public List<PetType> getPetTypes() {
...@@ -55,6 +57,7 @@ class PetResource { ...@@ -55,6 +57,7 @@ class PetResource {
Owner owner = optionalOwner.orElseThrow(() -> new ResourceNotFoundException("Owner "+ownerId+" not found")); Owner owner = optionalOwner.orElseThrow(() -> new ResourceNotFoundException("Owner "+ownerId+" not found"));
owner.addPet(pet); owner.addPet(pet);
registry.counter("create.pet").increment();
save(pet, petRequest); save(pet, petRequest);
} }
...@@ -63,6 +66,7 @@ class PetResource { ...@@ -63,6 +66,7 @@ class PetResource {
public void processUpdateForm(@RequestBody PetRequest petRequest) { public void processUpdateForm(@RequestBody PetRequest petRequest) {
int petId = petRequest.getId(); int petId = petRequest.getId();
Pet pet = findPetById(petId); Pet pet = findPetById(petId);
registry.counter("update.pet").increment();
save(pet, petRequest); save(pet, petRequest);
} }
......
server.port=0
logging.level.org.springframework=INFO
package org.springframework.samples.petclinic.customers.web; package org.springframework.samples.petclinic.customers.web;
import java.util.Optional; import java.util.Optional;
import io.micrometer.core.instrument.MeterRegistry;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
...@@ -40,6 +42,9 @@ class PetResourceTest { ...@@ -40,6 +42,9 @@ class PetResourceTest {
@MockBean @MockBean
OwnerRepository ownerRepository; OwnerRepository ownerRepository;
@MockBean
MeterRegistry registry;
@Test @Test
void shouldGetAPetInJSonFormat() throws Exception { void shouldGetAPetInJSonFormat() throws Exception {
......
...@@ -93,6 +93,14 @@ ...@@ -93,6 +93,14 @@
<artifactId>mysql-connector-java</artifactId> <artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope> <scope>runtime</scope>
</dependency> </dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-core</artifactId>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
</dependency>
<!-- Testing --> <!-- Testing -->
<dependency> <dependency>
......
server.port=0
spring.profiles.active=production spring.profiles.active=production
spring.cache.cache-names=vets spring.cache.cache-names=vets
...@@ -76,6 +76,14 @@ ...@@ -76,6 +76,14 @@
<artifactId>mysql-connector-java</artifactId> <artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope> <scope>runtime</scope>
</dependency> </dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-core</artifactId>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
</dependency>
<!-- Testing --> <!-- Testing -->
<dependency> <dependency>
......
...@@ -17,6 +17,8 @@ package org.springframework.samples.petclinic.visits.web; ...@@ -17,6 +17,8 @@ package org.springframework.samples.petclinic.visits.web;
import java.util.List; import java.util.List;
import javax.validation.Valid; import javax.validation.Valid;
import io.micrometer.core.instrument.MeterRegistry;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.Value; import lombok.Value;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
...@@ -44,6 +46,7 @@ import org.springframework.web.bind.annotation.RestController; ...@@ -44,6 +46,7 @@ import org.springframework.web.bind.annotation.RestController;
class VisitResource { class VisitResource {
private final VisitRepository visitRepository; private final VisitRepository visitRepository;
private final MeterRegistry registry;
@PostMapping("owners/*/pets/{petId}/visits") @PostMapping("owners/*/pets/{petId}/visits")
@ResponseStatus(HttpStatus.NO_CONTENT) @ResponseStatus(HttpStatus.NO_CONTENT)
...@@ -53,6 +56,7 @@ class VisitResource { ...@@ -53,6 +56,7 @@ class VisitResource {
visit.setPetId(petId); visit.setPetId(petId);
log.info("Saving visit {}", visit); log.info("Saving visit {}", visit);
registry.counter("create.visit").increment();
visitRepository.save(visit); visitRepository.save(visit);
} }
......
server.port=0
package org.springframework.samples.petclinic.visits.web; package org.springframework.samples.petclinic.visits.web;
import io.micrometer.core.instrument.MeterRegistry;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
...@@ -29,6 +30,9 @@ class VisitResourceTest { ...@@ -29,6 +30,9 @@ class VisitResourceTest {
@MockBean @MockBean
VisitRepository visitRepository; VisitRepository visitRepository;
@MockBean
MeterRegistry registry;
@Test @Test
void shouldFetchVisits() throws Exception { void shouldFetchVisits() throws Exception {
given(visitRepository.findByPetIdIn(asList(111, 222))) given(visitRepository.findByPetIdIn(asList(111, 222)))
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment