Spring Boot Actuator 사용해서 애플리케이션 모니터링하기

노영삼·2020년 9월 13일
0

Spring Boot Actuator

  • Actuator also integrates with external application monitoring systems like Prometheus, Graphite, DataDog, Influx, Wavefront, New Relic and many more.
  • Actuator uses Micrometer, an application metrics facade to integrate with these external application monitoring systems. This makes it super easy to plug-in any application monitoring system with very little configuration.

의존성 추가하기

<dependencies>
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-actuator</artifactId>
	</dependency>
</dependencies>
dependencies {
	compile("org.springframework.boot:spring-boot-starter-actuator")
}

어플리케이션 모니터링 하기

  • /health

    • 어플리케이션에 대한 기본적인 정보를 제공한다.
    • Status가 UP 인 경우 어플리케이션이 건강하다는 뜻이다
    • DOWN 인경우 디비와 연결 문제가 있거나 디스크 공간이 부족하거나 등등의 문제가 있다는 것이다.
  • /metrics

    • JVM memory 사용률
    • CPU usage
  • /loggers

    • 어플리케이션의 로그를 보여준다
    • 로그 설정을 바꿔 런타임에 로그 레벨을 바꿀 수 있다.
  • http://localhost:8080/actuator

    • ![Spring Boot default exposed Actuator endpoints](/Users/yeongsamno/Library/Mobile Documents/com~apple~CloudDocs/image/spring-boot-default-exposed-actuator-endpoints.png)
  • ![image-20200903125059041](/Users/yeongsamno/Library/Mobile Documents/com~apple~CloudDocs/image/image-20200903125059041.png)


Endpoints 활성화(비활성화)하기

기본적으로 모든 endpoint은 활성화 되어 있다. (shutdown 빼고) properties파일을 통해 endpoint를 활성화하고 비활성화 할 수 있다.

  • management.endpoint.<id>.enabled = true
management.endpoint.shutdown.enabled=true //false

Endpoints 공개하기

HTTP상에서 healthinfo 만 공개되어 있다.

  • Http 상에서 endpoint 공개하기
management.endpoints.web.exposure.include=health,info 
management.endpoints.web.exposure.exclude=health,info

endpoints

/health endpoint

  • 세부 정보 표시하기

    • management.endpoint.health.show-details=always
    • // http://localhost:8080/actuator/health
      
      {
        "status": "UP",
        "details": {
          "diskSpace": {
            "status": "UP",
            "details": {
              "total": 1000240963584,
              "free": 890297954304,
              "threshold": 10485760
            }
          },
          "db": {
            "status": "UP",
            "details": {
              "database": "MySQL",
              "hello": 1
            }
          }
        }
      }

커스텀 helth indicator 만들기

HealthIndicator 를 구현하거나 AbstractHealthIndicator 를 상속받아 커스텀한 인디케이터를 만들 수 있다.

package com.example.actuatordemo.health;

import org.springframework.boot.actuate.health.AbstractHealthIndicator;
import org.springframework.boot.actuate.health.Health;
import org.springframework.stereotype.Component;

@Component
public class CustomHealthIndicator extends AbstractHealthIndicator {

    @Override
    protected void doHealthCheck(Health.Builder builder) throws Exception {
        // Use the builder to build the health status details that should be reported.
        // If you throw an exception, the status will be DOWN with the exception message.
        
        builder.up()
                .withDetail("app", "Alive and Kicking")
                .withDetail("error", "Nothing! I'm good.");
    }
}

/metrics endpoint

  • http://localhost:8080/actuator/metrics/{MetricName}

    • http://localhost:8080/actuator/metrics/system.cpu.usage

    • {
         "name":"system.cpu.usage",
         "measurements":[
            {
               "statistic":"VALUE",
               "value":0.11774479321066383
            }
         ],
         "availableTags":[
      
         ]
      }

/loggers endpoint

  • http://localhost:8080/actuator/loggers

    • 설정된 로거들의 목록을 보여준다
  • http://localhost:8080/actuator/loggers/{name}

    • 해당 로거의 세부 사항을 보여준다

    • // http://localhost:8080/actuator/loggers/root
      
      {
        "configuredLevel": "INFO",
        "effectiveLevel": "INFO"
      }
  • 런타임에 로그 레벨 변경하기

    • ![image-20200903142515791](/Users/yeongsamno/Library/Mobile Documents/com~apple~CloudDocs/image/image-20200903142515791.png)

    • 다음과 같이 POST로 요청을 보내면 아래와 같이 로그 레벨이 변경된다.

    • // http://localhost:8080/actuator/loggers/root
      
      {
        "configuredLevel": "DEBUG",
        "effectiveLevel": "DEBUG"
      }

/info endpoint

info 엔드포인트는 어플리케이션의 정보를 보여준다. 빌드 정보는 META-INF/build-info.properties 에서 가져오고 , 깃 정보는 git.properties 에서 가져온다 또한 info 로 시작하는 모든 property도 보여준다 아래는 예시이다.

# INFO ENDPOINT CONFIGURATION
info.app.name=@project.name@
info.app.description=@project.description@
info.app.version=@project.version@
info.app.encoding=@project.build.sourceEncoding@
info.app.java.version=@java.version@
// http://localhost:8080/actuator/info

{
  "app": {
    "name": "@project.name@",
    "description": "@project.description@",
    "version": "@project.version@",
    "encoding": "@project.build.sourceEncoding@",
    "java": {
      "version": "@java.version@"
    }
  }
}

스프링 스큐리티와 함께 쓰기

endpoints에는 민감한 정보가 있기에 보호되어야한다.

import org.springframework.boot.actuate.autoconfigure.security.servlet.EndpointRequest;
import org.springframework.boot.actuate.context.ShutdownEndpoint;
import org.springframework.boot.autoconfigure.security.servlet.PathRequest;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

@Configuration
public class ActuatorSecurityConfig extends WebSecurityConfigurerAdapter {

    /*
        This spring security configuration does the following

        1. Restrict access to the Shutdown endpoint to the ACTUATOR_ADMIN role.
        2. Allow access to all other actuator endpoints.
        3. Allow access to static resources.
        4. Allow access to the home page (/).
        5. All other requests need to be authenticated.
        5. Enable http basic authentication to make the configuration complete.
           You are free to use any other form of authentication.
     */

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .authorizeRequests()
                    .requestMatchers(EndpointRequest.to(ShutdownEndpoint.class))
                        .hasRole("ACTUATOR_ADMIN")
                    .requestMatchers(EndpointRequest.toAnyEndpoint())
                        .permitAll()
                    .requestMatchers(PathRequest.toStaticResources().atCommonLocations())
                        .permitAll()
                    .antMatchers("/")
                        .permitAll()
                    .antMatchers("/**")
                        .authenticated()
                .and()
                .httpBasic();
    }
}

Spring Boot Actuator with Prometheus and Grafana

Prometheus

  • A data scraper that pulls metrics data over HTTP periodically at a configured interval.
  • A time-series database to store all the metrics data.
  • A simple user interface where you can visualize, query, and monitor all the metrics.

Grafana

Elasticsearch, Prometheus, Graphite, InfluxDB 등에서 데이터를 가져와 시각화하여 보여준다.

의존성 추가

<!-- Micrometer Prometheus registry  -->
<dependency>
	<groupId>io.micrometer</groupId>
	<artifactId>micrometer-registry-prometheus</artifactId>
</dependency>

/prometheus Endpoint

Prometheus 다운 받고 실행하기

  1. Prometheus 다운로드
$ docker pull prom/prometheus
$ docker image ls
REPOSITORY                                   TAG                 IMAGE ID            CREATED             SIZE
prom/prometheus                              latest              b82ef1f3aa07        5 days ago          119MB
  1. Prometheus config 설정하기
# 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).

# Load rules once and periodically evaluate them according to the global 'evaluation_interval'.
rule_files:
  # - "first_rules.yml"
  # - "second_rules.yml"

# A scrape configuration containing exactly one endpoint to scrape:
# Here it's Prometheus itself.
scrape_configs:
  # The job name is added as a label `job=<job_name>` to any timeseries scraped from this config.
  - job_name: 'prometheus'
    # metrics_path defaults to '/metrics'
    # scheme defaults to 'http'.
    static_configs:
    - targets: ['127.0.0.1:9090']

  - job_name: 'spring-actuator'
    metrics_path: '/actuator/prometheus'
    scrape_interval: 5s
    static_configs:
    - targets: ['HOST_IP:8080']

Please make sure to replace the HOST_IP with the IP address of the machine where your Spring Boot application is running. Note that, localhost won’t work here because we’ll be connecting to the HOST machine from the docker container. You must specify the network IP address.

  1. Docker로 Prometheus실행하기
$ docker run -d --name=prometheus -p 9090:9090 -v <PATH_TO_prometheus.yml_FILE>:/etc/prometheus/prometheus.yml prom/prometheus --config.file=/etc/prometheus/prometheus.yml

$ docker run -d --name=prometheus -p 9090:9090 -v /Users/yeongsamno/Desktop/com/soma/recorder/backend/sprint1/src/main/resources/
prometheus.yml:/etc/prometheus/prometheus.yml prom/prometheus --config.file=/etc/prometheus/prometheus.yml

Please make sure to replace the <PATH_TO_prometheus.yml_FILE> with the PATH where you have stored the Prometheus configuration file.

$ docker container ls
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                    NAMES
e036eb20b8ad        prom/prometheus     "/bin/prometheus --c…"   4 minutes ago       Up 4 minutes        0.0.0.0:9090->9090/tcp   prometheus
  1. Prometheus dashboard로 메트릭 시각화 하기

    [http://localhost:9090](http://localhost:9090/) 으로 Prometheus dashboard 접근

Grafana 설치하고 실행하기

$ docker run -d --name=grafana -p 3000:3000 grafana/grafana 
$ docker container ls
CONTAINER ID        IMAGE               COMMAND                  CREATED                  STATUS              PORTS                    NAMES
cf9196b30d0d        grafana/grafana     "/run.sh"                Less than a second ago   Up 5 seconds        0.0.0.0:3000->3000/tcp   grafana
e036eb20b8ad        prom/prometheus     "/bin/prometheus --c…"   16 minutes ago           Up 16 minutes       0.0.0.0:9090->9090/tcp   prometheus

That’s it! You can now navigate to http://localhost:3000 and log in to Grafana with the default username admin and password admin.

Grafana 설정하기

  1. 데이터 소스에 Prometheus 추가하기

    • ![image-20200903162339234](/Users/yeongsamno/Library/Mobile Documents/com~apple~CloudDocs/image/image-20200903162339234.png)
    • ![image-20200903162401322](/Users/yeongsamno/Library/Application Support/typora-user-images/image-20200903162401322.png)
  2. 새로운 대시보드 만들기

  3. 쿼리 에디터에 Prometheus Query expression 추가하기

profile
개발자가 되고싶다.

0개의 댓글