Spring Boot Actuator PoolingHttpClientConnectionManager Metrics - spring-boot

We are using Spring Boot 2 with Actuator and Prometheus to display a Grafana dashboard. I would like to add Apache Http Client PoolingHttpClientConnectionManager metrics to report on connection pool stats. I see that this was added to micrometer-core:1.3.0 (https://github.com/micrometer-metrics/micrometer/pull/1223). However I do not see any related metrics in /actuator/metrics or /actuator/prometheus endpoints. I have tried updating dependency in pom.xml:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.6.RELEASE</version>
<relativePath/>
<!-- lookup parent from repository -->
</parent>
...
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-core</artifactId>
<version>1.4.2</version>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
<version>1.4.2</version>
</dependency>
application.yml
# Spring Actuator Configuration
management:
endpoint:
health:
show-details: always
endpoints:
web:
exposure:
include: "*"
metrics:
enable:
all: true
/actuator/metrics
{
"names": [
"jvm.buffer.memory.used",
"jvm.threads.states",
"tomcat.servlet.error",
"process.uptime",
"jvm.memory.used",
"system.load.average.1m",
"tomcat.servlet.request.max",
"tomcat.cache.hit",
"tomcat.global.request.max",
"tomcat.global.error",
"tomcat.cache.access",
"logback.events",
"jvm.memory.committed",
"tomcat.sessions.active.current",
"jvm.buffer.total.capacity",
"jvm.gc.pause",
"jvm.memory.max",
"system.cpu.usage",
"jvm.threads.live",
"jvm.classes.unloaded",
"tomcat.global.sent",
"jvm.classes.loaded",
"jvm.threads.peak",
"tomcat.threads.config.max",
"tomcat.sessions.rejected",
"tomcat.sessions.alive.max",
"jvm.gc.memory.promoted",
"jvm.buffer.count",
"jvm.gc.memory.allocated",
"tomcat.global.received",
"tomcat.sessions.expired",
"tomcat.sessions.created",
"jvm.gc.max.data.size",
"system.cpu.count",
"tomcat.threads.busy",
"process.start.time",
"jvm.threads.daemon",
"process.files.max",
"tomcat.threads.current",
"tomcat.sessions.active.max",
"tomcat.global.request",
"process.files.open",
"jvm.gc.live.data.size",
"tomcat.servlet.request",
"process.cpu.usage"
]
}
Are supporting changes needed in spring actuator or am I missing something for configuration? Any help or advice is appreciated.

This code is copy from github issue
Apache HTTP client instrumentation
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager();
HttpClient httpClient = HttpClientBuilder.create().setConnectionManager(connectionManager).build();
new PoolingHttpClientConnectionManagerMetricsBinder(connectionManager, "my-pool").bindTo(registry);

io.micrometer.core.instrument.binder.httpcomponents #Incubating(since = "1.4.0")
public class MicrometerHttpClientInterceptor
extends Object
Provides HttpRequestInterceptor and HttpResponseInterceptor for configuring with an org.apache.http.nio.client.HttpAsyncClient. Usage example:
MicrometerHttpClientInterceptor interceptor = new MicrometerHttpClientInterceptor(registry,
request -> request.getRequestLine().getUri(),
Tags.empty(),
true);
CloseableHttpAsyncClient httpAsyncClient = HttpAsyncClients.custom()
.addInterceptorFirst(interceptor.getRequestInterceptor())
.addInterceptorLast(interceptor.getResponseInterceptor())
.build();
Since:
1.4.0

Related

How to enable all SpringBoot actuator endpoints?

SpringBoot v2.5.1
I would like to have all actuator endpoints (described in documentation) available.
Following the docs, have added actuator starter dependency and a property, but most of the endpoints are not available (HTTP 404).
The only available endpoint is GET /actuator/health, but it shows useless info: {"status": "UP"}
Added property management.endpoints.enabled-by-default=true.
Added dependency:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
Result of GET /actuator
{
"_links": {
"self": {
"href": "http://localhost:9999/actuator",
"templated": false
},
"health-path": {
"href": "http://localhost:9999/actuator/health/{*path}",
"templated": true
},
"health": {
"href": "http://localhost:9999/actuator/health",
"templated": false
}
}
}
What is the minimal set up to enable actuator endpoints?
Add micrometer-core and micrometer-registry-prometheus dependencies in your pom.xml file:
<!-- Spring boot actuator to expose metrics endpoint -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- Micormeter core dependecy -->
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-core</artifactId>
</dependency>
<!-- Micrometer Prometheus registry -->
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
</dependency>
Add below properties in your application.properties file:
#Metrics related configurations
management.endpoint.metrics.enabled = true
management.endpoints.web.exposure.include = *
management.endpoint.prometheus.enabled = true
management.metrics.export.prometheus.enabled = true
If you need to expose everything over HTTP then you need to set management.endpoints.web.exposure.include as shown in above example. In your code this property is missing. Please refer spring docs if you wish to expose specific endpoints. I have also added dependencies in above examples which are required to expose prometheus related endpoints.

How to get http_ metrics from Spring-Boot Api

I have list of metrics from Spring Boot Api but it doesn't contains http_* metrics
my pom.xml contains
<prometheus.version>0.1.0</prometheus.version>
....
<dependency>
<groupId>io.prometheus</groupId>
<artifactId>simpleclient_hotspot</artifactId>
<version>${prometheus.version}</version>
</dependency>
<dependency>
<groupId>io.prometheus</groupId>
<artifactId>simpleclient_servlet</artifactId>
<version>${prometheus.version}</version>
</dependency>
<dependency>
<groupId>io.prometheus</groupId>
<artifactId>simpleclient</artifactId>
<version>${prometheus.version}</version>
</dependency>
I made DefaultExports.initialize() and set bean
#Bean
SpringBootMetricsCollector springBootMetricsCollector(Collection<PublicMetrics> publicMetrics) {
SpringBootMetricsCollector springBootMetricsCollector = new SpringBootMetricsCollector(publicMetrics);
springBootMetricsCollector.register();
return springBootMetricsCollector;
}
then i get list of metrics from spring boot api but it does not contain htpp_ * metrics
like http_request_duration_microseconds
how can i get it?

consul first bootstrap with spring cloud config

Iam using spring-cloud-config for centralized configuration and consul for service discovery. Like eureka first bootstrap - does spring support consul first bootstrap i.e on booting up a client service - I should look up the config server through consul. The otherway round works perfectly fine i.e - in config client bootstrap.properties - I provide the spring.cloud.config.uri=http://localhost:8888 which located the config server and pulls config from it. And in the config repository for my client application - I provide the consul config like :
spring.cloud.consul.host=localhost ,
spring.cloud.consul.port=8500
However, when i try to use consul first bootstrap I am unable to read the properties from config server.
Client Application (for consul first bootstrap):
pom.xml
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-parent</artifactId>
<!-- <version>Brixton.BUILD-SNAPSHOT</version> -->
<version>Brixton.M5</version>
<relativePath />
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-consul-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-all</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zuul</artifactId>
</dependency>
</dependencies>
bootstrap.properties:
spring.application.name=demo
spring.cloud.config.failFast=true
spring.cloud.config.retry.maxAttempts=20
spring.cloud.config.retry.initialInterval=3000
spring.cloud.consul.host=localhost
spring.cloud.consul.port=8500
DemoApplication.java
#EnableDiscoveryClient
#EnableZuulProxy
#SpringBootApplication
public class DemoSleuthApplication {
public static void main(String[] args) {
SpringApplication.run(DemoSleuthApplication.class, args);
}
}
#RefreshScope
#RestController
class RestAPIController
{
#Value(value = "${server.port}")
String port;
#Value(value = "${message}")
String message;
#RequestMapping("/message")
public String welcome(){
String s = this.restTemplate.getForObject("http://localhost:"+this.port+"/message", String.class);
return this.message + s;
}
}
In the consul K/V store
folder structure config/demo
Key/Value : spring.cloud.config.uri=http://localhost:8888
Config server git repo: not adding the config server code for brevity
demo.properties
server.port=9080
message=test
Ideally when I implement the concept of consul first bootstrap - I am thinking consul should be started and the client should identify itself using the #EnableDiscoveryClient annotation and in the consul properties - find config server url , and fetch the config properties from the server configurations. But in my case, service is being discovered and registered in consul but i am not able to read properties from config server git repo.
It was done here. It is available in SNAPSHOTS and in RC2 which will come hopefully next week.
Giving my sample code here for benefit of others. I had to do a lot of tinkering with the properties file to get to this.
As answered by #spencergibb it is available in SNAPSHOT only for now.
This time i did not use any key value properties in consul.
config server code:
pom.xml:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-all</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-consul-discovery</artifactId>
</dependency>
application.yml
spring:
profiles:
active: native
cloud:
config:
server:
native:
search-locations: file://${HOME}/properties
consul:
port: 8500
host: localhost
enabled: true
discovery:
enabled: true
register: true
service-name: server --registers in consul as server instead of config-server
hostname: localhost
server:
port: 8888
bootstrap.yml ::
spring:
application:
name: config-server
COnfigServerApplication.java
#EnableDiscoveryClient
#EnableConfigServer
#SpringBootApplication
public class SpringConfigServerApplication {
public static void main(String[] args) {
SpringApplication.run(SpringConfigServerApplication.class, args);
}
}
Client microservice: demo
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-parent</artifactId>
<version>Brixton.BUILD-SNAPSHOT</version>
<!-- <version>Brixton.M5</version> -->
<relativePath />
</parent>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-all</artifactId>
</dependency>
bootstrap.properties
spring.application.name=demo-spring-cloud-sleuth
spring.cloud.config.failFast=true
spring.cloud.config.retry.maxAttempts=20
spring.cloud.config.retry.initialInterval=3000
spring.cloud.config.enabled=true
spring.cloud.config.discovery.enabled=true
spring.cloud.config.discovery.serviceId=config-server
spring.cloud.consul.discovery.hostName=localhost
spring.cloud.consul.discovery.register=true -- unless this is there, the service fails to register in consul.
git uri property file for client:
server.port=9082
message=message local
foo1=bar

How to exclude Hystrix Metrics from the Actuator /metrics endpoint?

I have a spring-boot-app with Actuator and Hystrix enabled.
Spring-Boot-Version: 1.3.1.RELEASE
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>
When I add #HystrixCommandto some methods, the /metrics Endpoint shows all the metrics from hystrix:
gauge.hystrix.HystrixCommand.RestEndpoints.TestController.test.errorPercentage: 0,
gauge.hystrix.HystrixThreadPool.RestEndpoints.rollingMaxActiveThreads: 1,
...
Question:
How can I exclude the hystrix-metrics completely from the /metricsendpoint?
Update 1
I tried to exclude the ServoMetrics and SpectatorMetrics with these approaches:
1)
#EnableAutoConfiguration(exclude={ServoMetricsAutoConfiguration.class,
SpectatorMetricsAutoConfiguration.class} )
2)
#SpringBootApplication(exclude={ServoMetricServices.class, SpectatorMetricServices.class})
But both did not achieved the desired effect.
This issue was created and fixed. In snapshots you can now set the following:
hystrix.metrics.enabled=false.
If you don't want any other metrics, better solution would be to create your own MetricsRegistry. This way, any other future code changes (adding more jars with more in built metrics) would not affect.
#Configuration
public class MetricsConfiguration {
private MetricRegistry metricRegistry;
MetricsConfiguration() {
//avoid other metrics already registered
metricRegistry = new MetricRegistry();
}
}
Note: Creating a #Bean of type MetricRegistry would not help, as Spring autoconfigure will use this Bean object instead of MetricsRegistry object from MetricsDropwizardAutoConfiguration.java

Micro-services: Zuul & consul in Spring cloud application

I'm trying to create a Spring cloud microservice application using Zuul and Consul.
I have 2 components in my project:
api-gateway microservice using Zuul
Hello world microservice (a simple hello world Rest Webservice)
Here is the code of The api-gateway:
#SpringBootApplication
#EnableZuulProxy
#EnableDiscoveryClient
public class ZuulApplication {
public static void main(String[] args) {
SpringApplication.run(ZuulApplication.class, args);
}
}
The pom.xml
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-parent</artifactId>
<version>Brixton.M3</version>
</parent>
<properties>
<java.version>1.8</java.version>
<spring.cloud.consul.version>1.0.0.M4</spring.cloud.consul.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-commons</artifactId>
</dependency>
<dependency>
<!-- Setup Spring Boot -->
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<!-- Setup Spring MVC & REST, use Embedded Tomcat -->
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency>
<dependency>
<!-- Spring Cloud starter -->
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zuul</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-all</artifactId>
<version>${spring.cloud.consul.version}</version>
</dependency>
</dependencies>
application.yml
zuul:
routes:
hello1:
path: /hello1/**
serviceId: microservice-example
logging:
level:
org.springframework: INFO
com.netflix: DEBUG
bootstrap.yml
spring:
application:
name: edge-server
cloud:
consul:
config:
enabled: true
host: localhost
port: 8500
Here is the code of hello microservice:
#SpringBootApplication
#EnableConfigServer
#EnableDiscoveryClient
#RestController
public class Application {
#RequestMapping(value="/hello1",method = RequestMethod.GET)
public String hello() {
System.out.print("hello1");
return "Hello1";
}
public static void main(String[] args) {
new SpringApplicationBuilder(Application.class).web(true).run(args);
}
}
bootstrap.yml:
spring:
application:
name: microservice-example
profiles:
active: native
cloud:
consul:
config:
enabled: true
host: localhost
port: 8500
But, when I start the api-gateway I got the following exception:
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.cloud.netflix.zuul.filters.RouteLocator]: Factory method 'routeLocator' threw exception; nested exception is java.lang.IllegalStateException: Unable to locate service in consul agent: edge-server
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:189) ~[spring-beans-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:588) ~[spring-beans-4.2.3.RELEASE.jar:4.2.3.RELEASE]
... 69 common frames omitted
Caused by: java.lang.IllegalStateException: Unable to locate service in consul agent: edge-server
at org.springframework.cloud.consul.discovery.ConsulDiscoveryClient.getLocalServiceInstance(ConsulDiscoveryClient.java:66) ~[spring-cloud-consul-discovery-1.0.0.M4.jar:1.0.0.M4]
This issue is fixed in Brixton.M3 (1.0.0.M5). As mentioned above this was an issue with spring-cloud-consul. The new version is working fine

Resources