Grafana+Prometheus系統監控之SpringBoot

前言

前一段時間使用SpringBoot建立了一個webhook項目,因爲近期項目中也使用了很多SpringBoot相關的項目,趁着週末,配置一下使用prometheus監控微服務Springboot。html

項目配置

引入座標

<!-- Exposition spring_boot --><dependency>
	<groupId>io.prometheus</groupId>
	<artifactId>simpleclient_spring_boot</artifactId>
	<version>0.1.0</version></dependency><!-- Hotspot JVM metrics --><dependency>
	<groupId>io.prometheus</groupId>
	<artifactId>simpleclient_hotspot</artifactId>
	<version>0.1.0</version></dependency><!-- Exposition servlet --><dependency>
	<groupId>io.prometheus</groupId>
	<artifactId>simpleclient_servlet</artifactId>
	<version>0.1.0</version></dependency>

配置Application

@SpringBootApplication@EnablePrometheusEndpoint@EnableSpringBootMetricsCollectorpublic class Application  {	private static final Logger logger = LoggerFactory.getLogger(Application.class);	public static void main(String[] args) throws InterruptedException {
		SpringApplication.run(Application.class, args);
		logger.info("項目啓動 ");
	}
}

配置MonitoringConfig

@Configurationclass MonitoringConfig {    @Bean
    SpringBootMetricsCollector springBootMetricsCollector(Collection<PublicMetrics> publicMetrics) {

        SpringBootMetricsCollector springBootMetricsCollector = new SpringBootMetricsCollector(publicMetrics);
        springBootMetricsCollector.register();        return springBootMetricsCollector;
    }    @Bean
    ServletRegistrationBean servletRegistrationBean() {
        DefaultExports.initialize();        return new ServletRegistrationBean(new MetricsServlet(), "/prometheus");
    }
}

配置Interceptor

RequestCounterInterceptor(計數):java

public class RequestCounterInterceptor extends HandlerInterceptorAdapter {    // @formatter:off
    // Note (1)
    private static final Counter requestTotal = Counter.build()
         .name("http_requests_total")
         .labelNames("method", "handler", "status")
         .help("Http Request Total").register();    // @formatter:on

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception e)
                                                                                                         throws Exception {         // Update counters
         String handlerLabel = handler.toString();         // get short form of handler method name
         if (handler instanceof HandlerMethod) {
              Method method = ((HandlerMethod) handler).getMethod();
              handlerLabel = method.getDeclaringClass().getSimpleName() + "." + method.getName();
         }         // Note (2)
         requestTotal.labels(request.getMethod(), handlerLabel, Integer.toString(response.getStatus())).inc();
    }
}

RequestTimingInterceptor(統計請求時間):web

package com.itstyle.webhook.interceptor;import java.lang.reflect.Method;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import io.prometheus.client.Summary;import org.springframework.web.method.HandlerMethod;import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;public class RequestTimingInterceptor extends HandlerInterceptorAdapter {    private static final String REQ_PARAM_TIMING = "timing";    // @formatter:off
    // Note (1)
    private static final Summary responseTimeInMs = Summary
         .build()
         .name("http_response_time_milliseconds")
         .labelNames("method", "handler", "status")
         .help("Request completed time in milliseconds")
         .register();    // @formatter:on

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {         // Note (2)
         request.setAttribute(REQ_PARAM_TIMING, System.currentTimeMillis());         return true;
    }    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)throws Exception {
         Long timingAttr = (Long) request.getAttribute(REQ_PARAM_TIMING);         long completedTime = System.currentTimeMillis() - timingAttr;
         String handlerLabel = handler.toString();         // get short form of handler method name
         if (handler instanceof HandlerMethod) {
              Method method = ((HandlerMethod) handler).getMethod();
              handlerLabel = method.getDeclaringClass().getSimpleName() + "." + method.getName();
         }       // Note (3)
       responseTimeInMs.labels(request.getMethod(), handlerLabel, 
    		                   Integer.toString(response.getStatus())).observe(completedTime);
    }
}

配置Controller

主要是爲了測試攔截器的效果spring

@RestControllerpublic class HomeController {     private static final Logger logger = LoggerFactory.getLogger(HomeController.class); 
     @RequestMapping("/endpointA")
     public void handlerA() throws InterruptedException {
          logger.info("/endpointA");
          Thread.sleep(RandomUtils.nextLong(0, 100));
     } 
     @RequestMapping("/endpointB")
     public void handlerB() throws InterruptedException {
          logger.info("/endpointB");
          Thread.sleep(RandomUtils.nextLong(0, 100));
     }
}

以上都配置完成後啓動項目便可。app

配置Prometheus

vi prometheus.ymldom

  - job_name: webhook
    metrics_path: '/prometheus'
    static_configs:
     - targets: ['localhost:8080']       labels:
         instance: webhook

保存後從新啓動Prometheus便可。ide

訪問http://ip/targets 服務State 爲up說明配置成功,查閱不少教程都說須要配置 spring.metrics.servo.enabled=false,不然在prometheus的控制檯的targets頁籤裏,會一直顯示此endpoint爲down狀態,然貌似並無配置也是ok的。wordpress

訪問http://ip/graph 測試一下效果spring-boot

配置Grafana

如圖所示:微服務

參考連接

https://blog.52itstyle.com/archives/1984/

https://blog.52itstyle.com/archives/2084/

https://raymondhlee.wordpress.com/2016/09/24/monitoring-spring-boot-applications-with-prometheus/

https://raymondhlee.wordpress.com/2016/10/03/monitoring-spring-boot-applications-with-prometheus-part-2/

相關文章
相關標籤/搜索