Spring Boot 2.2.2 - Prometheus not working in Actuator - spring-boot

I've upgraded my Spring Boot application to the latest 2.2.2 Boot version. Since then, I only have a metrics endpoint but no Prometheus.
My build.gradle.kts file has org.springframework.boot:spring-boot-starter-actuator as dependency, I also added io.micrometer:micrometer-registry-prometheus as the reference suggests (Prometheus endpoint).
My application.yml looks like the following:
management:
server:
port: 9000
endpoints:
web:
exposure:
include: health, shutdown, prometheus
endpoint:
shutdown:
enabled: true
Can someone guide me to the right direction?
Edit: It was working in Spring Boot 2.2.0. This is the link to download an identical project: link
Edit 2: I can verify that it works with 2.2.1 as well.

I followed your setup, I created a project from this project loaded Spring Boot 2.2.2.RELEASE, I added the following dependency for Prometheus
implementation("io.micrometer:micrometer-registry-prometheus")
Also I added the following configuration in application.yml
management:
server:
port: 9000
endpoints:
web:
exposure:
include: health, shutdown, prometheus
endpoint:
shutdown:
enabled: true
When the application starts you will see the following info which shows you that 3 endpoints are exposed (health, shutdown and prometheus).
2020-01-05 23:48:19.489 INFO 7700 --- [ main] o.s.b.a.e.web.EndpointLinksResolver : Exposing 3 endpoint(s) beneath base path '/actuator'
And used Postman for method GET this endpoint http://localhost:9000/actuator/prometheus and it works well. I created a repository by following these steps here So please let me know what error is displayed, or what happens when you don't get the expected result so that I can help and edit this answer.

Add below maven dependency for prometheus
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
<scope>runtime</scope>
</dependency>
In application.yml, add the below configuration
management:
endpoints:
web:
exposure:
include: "*"
endpoint:
health:
show-components: always
show-details: always
probes:
enabled: true
Now you could see the below message when you restart the server
Exposing 15 endpoint(s) beneath base path '/actuator'
Access the prometheus url: http://localhost:8080/actuator/prometheus

Related

spring boot 3 profile property values getting overridden in boostrap.yaml

Recently trying to upgrade to Spring Boot 3, but facing property issue.
My bootstrap yml looks like below,
When I run with profile dev, the configserver url is always getting connected to qa, basically whichever is declared last.
This is working fine in 2.7.X version of spring, but not in spring boot 3
spring:
application:
name: appname
profiles:
active: ${spring.profiles.active}
include:
- global-defaults
group:
dev:
- config-server-dev
- cloud-config-dev
qa:
- config-server-qa
- cloud-config-qa
---
spring:
config:
activate:
on-profile: config-server-dev
cloud:
config:
enabled: true
uri: http://urltoconfigserverdev
label: master
---
spring:
config:
activate:
on-profile: config-server-qa
cloud:
config:
enabled: true
uri: http://urltoconfigserverqa
label: master
---
But the same is working fine if add the property migration pom dependency. which is not suggested for higher environments.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-properties-migrator</artifactId>
<scope>runtime</scope>
</dependency>
If adding the properties migrator fixes the problem, it's likely that your configuration file is using a configuration property name that's been removed after deprecation. I'm not seeing anything specific to Spring Boot in the changelog, maybe this is due to a change in spring cloud config? The properties migrator should print WARN logs during startup, looking at those should tell you what needs fixing.

Microservices not registering on all Eureka Instances

Spring Boot version: 2.1.6.RELEASE
Spring Cloud Version: Greenwich.SR1
Objective is to set up two instances of Eureka Servers in a cluster and have all microservices registered to both, in order to achieve HA. Currently I am testing this on my local machine running Ubuntu 18.04.
So as mentioned in the official docs, I have set up the peer to peer awareness of Eureka Instances. On bringing both the Eureka Server Instances up, on the dashboard of Instance-1(Port 8080) under available replicas showing Instance-2 name and on dashboard of Instance-2(Port 8081) it is showing Instance-1 name. So far so good.
I have deployed them on external tomcat server as war and not running them as jar. War name is "eureka-naming-server". So my access URL becomes: http://localhost:8080/eureka-naming-server/eureka and http://localhost:8081/eureka-naming-server/eureka.
I have set up a load balancer using Apache 2 and mod_jk. So instead of accessing them using their individual URLs i.e. http://localhost:8080/eureka-naming-server/eureka, http://localhost:8081/eureka-naming-server/eureka, I can access them using Apache URL as http://localhost:80/eureka-naming-server/eureka and I can see load-balancing happening properly.
Now the issue is that once I give Eureka URL as http://localhost:80/eureka-naming-server/eureka in the microservice, it registers only on one instance depending on which Eureka instance the load-balancer has redirected the request. But even though peer to peer awareness is setup, microservice is not getting registered on the other eureka instance.
In Eureak servers, I'm using the below dependency:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
Eureka-1 props:
spring:
application:
name: eureka-naming-server
jmx:
default-domain: eureka-naming-server
eureka:
client:
service-url:
defaultZone: http://eureka-server-2:8081/eureka-naming-server/eureka
#register-with-eureka: false
#fetch-registry: false
instance:
hostname: eureka-server-1
Eureka-2 props:
spring:
application:
name: eureka-naming-server
jmx:
default-domain: eureka-naming-server
eureka:
client:
service-url:
defaultZone: http://eureka-server-1:8080/eureka-naming-server/eureka
#register-with-eureka: false
#fetch-registry: false
instance:
hostname: eureka-server-2
In microservices, I'm using below dependencies:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
Microservice props:
eureka:
instance:
metadata-map:
configPath: /config
client:
service-url:
defaultZone: http://localhost/eureka-naming-server/eureka
In the machine's /etc/hosts file I have set it up as:
127.0.0.1 eureka-server-1
127.0.0.1 eureka-server-2
The eureka instance on which it is getting registered I can see the below in the logs:
WARN 13748 --- [nio-8009-exec-3] Registered instance CONFIG-SERVER/192.168.1.16:config-server:8888 with status UP (replication=false)
The other Eureka instance where it is not registered, when it receives the heart-beat because of the load-balancer, shows this in the logs:
WARN 13748 --- [nio-8009-exec-3] c.n.e.registry.AbstractInstanceRegistry : DS: Registry: lease doesn't exist, registering resource: CONFIG-SERVER - 192.168.1.16:config-server:8888
2019-12-26 19:00:34.995 WARN 13748 --- [nio-8009-exec-3] c.n.eureka.resources.InstanceResource : Not Found (Renew): CONFIG-SERVER - 192.168.1.16:config-server:8888
Eureka-1 Dashboard
Eureka-2 Dashboard
I have already tried suggestions mentioned here and here. But nothing seems to work.
So what could I be missing here?
Issue:
spring:
application:
name: eureka-naming-server
You put the same name for an application so it's displayed like this.
you need to change it to,
Eureka-1 props:
spring:
application:
name: eureka-naming-server-1
Eureka-2 props:
spring:
application:
name: eureka-naming-server-2
It may also be worth checking your security configuration for your eureka servers. If you do have spring boot security enabled, you will need to be sure that you include the corresponding username/password in the defaultZone portion of your config.
i.e. in your eureka server 1 config: eureka.client.serviceUrl.defaultZone=http://:#eureka-server-2:8761/eureka
(and visa versa for your eureka server 2 config)
I only mention this because I had left out my own username/password values in that config value and it was not registering my microservices on all my eureka instances. After make this change, it worked as I was expecting.

Unable to read property values using config-client app from PCF config server service

In my PCF logs config-client app gives
"ConfigServicePropertySourceLocator : Could not locate PropertySource:
401 Unauthorized"
I have gitlab repository to provide properties files in PCF config server.
If I check Config Server -> manage -> it gives "
Config server is online"
Where am I missing the configuration?
bootstrap.yml config-client-app
spring:
application:
name: <config-client-name>
cloud:
config:
enabled: true
name: <config-server-instance-name>
uri: <uri details from view credential modal>
# username: <tried different permutations to get it working>
# password: <tried different permutations to get it working>
management:
security:
enabled: false
manifest.yml config-client-app
applications:
- name: <app-name>
host: <app-name>
memory: 1024M
instances: 1
path: /target/<app-name>-0.0.1-SNAPSHOT.jar
buildpack: java_buildpack_offline
services:
- <pcf config server instance name>
env:
SPRING_PROFILES_ACTIVE: dev
I have done lots of work around to get some result but no luck, sample app works fine.
I have tried my own config-server and config client app with github repository and it worked.
But in PCF I am totally stuck please help.
Doesn't a look anything wrong in your configuration. if you are seeing Config server is online in PCF that means config service is intialized properly and ready for use.
But let's try with the sample app which is working fine for you.
Add following information in you build.gradle if you are using gradle build(or add in pom.xml accordingly.)
SCS(Spring Cloud services) (mentioned versions are compatible with springBootVersion = '2.0.6.RELEASE' Check for comparability if you are using a different version of spring-boot.)
imports {
mavenBom "io.pivotal.spring.cloud:spring-cloud-services-dependencies:2.0.1.RELEASE"
mavenBom "org.springframework.cloud:spring-cloud-dependencies:Finchley.RELEASE"
}
include config-client dependency
compile("io.pivotal.spring.cloud:spring-cloud-services-starter-config-client")
Now let's move to bootstrap.yml:
only following information is enough to pick the properties
spring:
application:
name: <config-client-name>
No change required in application.yml if you are using the same active profile while pushing to PCF.
#Avhi - your answer helped me.
My mistake was I was using wrong dependency, and I was adding unnecessary info. in bootstrap.yml
spring:
application:
name: <config-client-name>
cloud:
config:
enabled: true
name: <config-server-instance-name>
uri: <uri details from view credential modal>
# username: <tried different permutations to get it working>
# password: <tried different permutations to get it working>
management:
security:
enabled: false
name: <config-server-instance-name> we should configure the property file name that we are going to point from client application, I was providing config-server instance name.
Note: I have learnt that we can specify multiple properties files separated by comma.
uri: <uri details from view credential modal>
# username: <tried different permutations to get it working>
# password: <tried different permutations to get it working>
The above three properties were useless and I wasted most of my time because of this.
We need not have these values set unless we want to bind config-server service in our localhost:8080 app.
There's no harm in providing service name in our manifest.yml and as it is not the part of application, it won't create any trouble. BTW we can use CLI or PCF App Manager web console to create and bind service to our app.
After setting up all, we can expect spring security web page to enter username & password (that obviously we don't know). if spring security is configured then fine or we can disable while testing.
I did two things to disable and activate all endpoints of actuator (as I am using spring-boot 2.x)
added dependencies as below:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-rsa</artifactId>
<!-- <version>1.0.5.RELEASE</version> -->
</dependency>
and created SecurityConfiguration to disable security explicitly
#Configuration
#EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter{
#Override
protected void configure(HttpSecurity http) throws Exception{
http.csrf().disable();
http.authorizeRequests().antMatchers("/").permitAll();
}
}
To make all the actuators endpoints accessible I have done the following:
management:
endpoints:
web:
exposure:
include: "*"

spring boot admin Cannot get information from client

Been Trying to setup Boot admin server. Connection to a client instance fails
on IOException - An established connection was aborted by the software in your host machine even though all relevant endpoints are reachable (and spring security is not in the classpath)
On server start I'm getting:
Couldn't retrieve status for Instance(id=91e01a92b3bf, version=0, registration=Registration(name=test, managementUrl=https://client-url:8080/actuator, healthUrl=https://client-url:8080/actuator/health, serviceUrl=https://client-url:8080/, source=discovery), registered=true, statusInfo=StatusInfo(status=UNKNOWN, details={}), statusTimestamp=2018-10-24T13:57:58.816657Z, info=Info(values={}), endpoints=Endpoints(endpoints={health=Endpoint(id=health, url=https://client-url:8080/actuator/health)}), buildVersion=null, tags=Tags(values={}))
Admin pom.xml
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-commons</artifactId>
<version>2.0.1.RELEASE</version>
</dependency>
Admin application.yml per admin docs
spring:
cloud:
discovery:
client:
simple:
instances:
test:
- uri: https://client-url:8080
metadata:
management.context-path: /actuator
Client application.yml
management:
endpoints:
web:
exposure:
include: "*"
endpoint:
health:
show-details: always
metrics:
enabled: true
Admin server logs are full with org.apache.coyote.CloseNowException: Connection [74], Stream [21], This stream is not writable errors
Running the admin/client in debug mode will give more detailed logs in terms what exact url server is trying to hit and does the client getting any request from server or not. I came across similar situation and it was because there was difference of version between Spring Boot Admin and Client application.
Confirm that healthUrl=https://client-url:8080/actuator/health giving 200 OK response.
if not then you may want to change the below client property :
spring.boot.admin.client.api-path=/actuator
then check again that its giving 200 OK response.

Spring Boot + Spring Cloud Config - How to add more profiles from the Git external configuration

I have this configuration in a spring boot application:
spring:
application:
name: my-app
profiles:
active: ${ENVIRONMENT}
cloud:
config:
uri: http://localhost:8888
My config server reads the following files:
my-app-dev.yaml
prop: dev property
my-app-pro.yaml
prop: pro property.
I launch the spring boot app setting -DENVIRONMENT=dev, loading correctly the dev external Git properties.
When I inject the Environment in let's say a controller and do env.getActiveProfiles() I get "dev" as expected.
I would like to add more profiles from the git configuration. For instance:
my-app-dev.yaml
prop: dev property
spring:
active:
profiles: dev,business1
my-app-pro.yaml
prop: dev property
spring:
active:
profiles: pro,business2
So that env.getActiveProfiles() returns ["dev","business1"]. However what it returns is the initial "dev".
How could this be done?
UPDATE:
As suggested by Dave Syer I tried using spring.profiles.include in the Git files but the new profiles aren't added to the Environment:
my-app-dev.yaml
prop: dev property
spring:
profiles:
include: business1
my-app-pro.yaml
prop: dev property
spring:
profiles:
include: business2
environment.getActiveProfiles() ---> "dev"
Update your spring-boot to 1.5.4.
I tested the same case on my Mac, I found that spring with different version behaves different.
When I'm using Spring Boot 1.3.8.RELEASE with Spring Cloud Brixton.SR7, I got the [dev] profile as active profile(also with Spring Boot 1.4.5.RELEASE)
When I'm using Spring Boot 1.5.4.RELEASE with Spring Cloud Dalston.SR1, I got the
[business1, dev] profile as active profile
So I believe it is a bug in Spring Boot 1.3.x and 1.4.x

Resources