Expose metrics from spring application to prometheus without using spring-boot actuator - spring

I have been trying to collect micrometer metrics in a non springboot application and expose them to prometheus.I have added the following dependency and the test method for the same.I would like to know how to proceed and expose the collected metrics to prometheus from my non spring boot application(traditional spring application).
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
<version>1.2.0</version>
</dependency>
public string testmetrics(){
private PrometheusMeterRegistry registry = new PrometheusMeterRegistry(PrometheusConfig.DEFAULT);
registry.counter("ws metric collection","tktdoc metrics");
String metricsInfo = registry.scrape();
return metricsInfo;
}

You practically have to expose an HTTP endpoint and configure Prometheus with it; the HTTP endpoint will supply the data for the scrapes.
An example showing how to add the HTTP endpoint by starting up an HTTP Server (your application may already be using one) is here.

Related

How to get access to the Spring-boot actuator JSON payload

I m working on a customized health check for an API. Where I m using :
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
<version>2.5.5</version>
</dependency>
and implementing the HealthIndicator interface.
I m wondering if there is a way to get access to the payload returned by /actuator/health ?
so I can desterilize it, and base on the values on the object (payload), I will build the implementation for the heath() method from HealthIndicator Interface.
I have tried to use:
- HealthEndpoint but it needs an implementation for HealtContributorRegistary , not sure how to do that.
- SystemHealth (im getting the error : class Cannot be accessed from outside package).
any help is very welcomed.
Thank you.
I was able to get access to all my API components status by
#Autowired HealthContributor[] healthContributors;
in a service.
I have followed this answer : Direct access to Spring Boot Actuator Health beans/data?

Spring cloud bus with AWS Kinesis stream #refreshscope

I read everywhere #RefreshScope for cloud bus applications work with RabbitMQ and Kafka. But in my case, I am using AWS Parameter store. I want all my client instances to be refreshed automatically without rebuilding servers on AWS Console.
I created AWS Eventbridge from Paramstore to notify Kinesis Stream but I am not able to figure out how can it notify all my client nodes instead of load balancer refresh to only one node(instance).
Thank you for responding in advance.
I've never worked with AWS Eventbridge / Kinesis, however:
#RefreshScope is something that belongs to spring cloud and not not AWS.
More precisely, beans defined with this scope will be re-loaded by spring without reloading the whole application context "dynamically" when configuration changes in spring boot cloud configuration service. Usually this means that you don't have to restart the application.
Now, spring boot microservice should be deployed with actuator that exposes refresh endpoint. Calling this endpoint manually will cause all the #RefreshScope beans to reload.
Here is the source code of the RefreshEndpoint:
#Endpoint(id = "refresh")
public class RefreshEndpoint {
private ContextRefresher contextRefresher;
public RefreshEndpoint(ContextRefresher contextRefresher) {
this.contextRefresher = contextRefresher;
}
#WriteOperation
public Collection<String> refresh() {
Set<String> keys = this.contextRefresher.refresh();
return keys;
}
}
As you see, its merely invokes contextRefresher.refresh(), ContextRefresher is a bean that you can inject in your custom code that will listen to the changes coming from AWS Parameter store (it should somehow invoke it directly or maybe send some message that you could consume or something).
If you're using spring-cloud-bus (disclaimer, I've never worked with it) it exposes the bus-refresh endpoint as well (pretty similar mechanism to what I've described), read spring-cloud-bus documentation for more details.
Thank you Team for sharing info.
Here is what I did to make it work. Added these two libraries to my project
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-stream-binder-kinesis</artifactId>
<version>1.1.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-bus</artifactId>
</dependency>
And added these two entries into bootstrap.properties
cloud.aws.region.static=us-east-1
cloud.aws.stack.auto = false
And refreshing using this endpoint (/bus-refresh)

How to consume spring cloud config server Jdbc backend configs from Spring cloud Client server?

I went through lots of tutorials regarding this but could not get this done.
Here is my table structure for this.
Application Profile Label prop_key value
masking dev latest test-property message
I have a cloud config server which should integrate with JDBC backend. Here is my application.properties in config server
server.port=8082
spring.application.name=masking
management.endpoints.web.exposure.include=*
spring.datasource.url=jdbc:postgresql://localhost:8000/finos?currentSchema=xlabs
spring.datasource.username=mufgdev
spring.datasource.password=XXX
spring.profiles.active=XXX
spring.cloud.config.server.jdbc.sql=SELECT prop_key,value from xlabs.properties where application=? and profile=? and label=?
spring.cloud.config.server.jdbc.order=1
With this configs if I enter http://localhost:8082/masking/dev/latest response will show the results as I want.
I want to consume properties in client side with the following configs in bootstrap.properties
spring.application.name=masking
spring.cloud.config.uri=http://localhost:8082
spring.cloud.config.label=latest
spring.cloud.config.profile=dev
And in my client side
#RestController
#RefreshScope
public class TestController {
#Value("${test-property}")
private String aConf;
#GetMapping("/message")
String message() {
String name =aConf ;
return name;
}
}
This gives java.lang.IllegalArgumentException: Could not resolve placeholder 'test-property' in value "${test-property}"
Can anyone comment on this?
Thanks.
This issue comes with the latest Spring boot release, All the above code segments steps all okay, But by default Spring has disabled bootstrap. So you have to enable them by adding
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>
No need add for older versions of the Spring boot projects.

Issue in consuming Restful webserive using apache camel reslet framework

I have a Camel Project which runs in 8080 port to consume external restful web service which is a SpringBoot project which runs in port 8082, toproduce employee information based on the end point call. Here I'm trying to consume ResetFul webservice using Apache Camel Restlet. While consuming the webservice every alternative call is failing.
Restlet operation failed invoking http://localhost:8082/employeeController/getEmployeeDetails/12?wsdl with statusCode: 400 /n responseBody:<html><body><h1>400 Bad request</h1>Your browser sent an invalid request.</body></html>
This is the error i'm getting on every alternative call.
Restlet code to consume which is written inside Camel Context.
<to id="getEmployeeDetails" pattern="InOut" uri="restlet:http://localhost:8082/employeeManager/getEmployeeDetails/{employeeId}?restletMethod=GET"/>
SpringBoot code which produces webservice,
#Controller
#RequestMapping(value="employeeController")
public class EmployeeController{
#RequestMapping(value="/getEmployeeDetails/{employeeId}", method=RequestMethod.GET,produces=MediaType.APPLICATION_XML_VALUE)
#ResponseBody
public String getEmployeeDetails(#PathVariable("employeeId") int employeeId) {
//getting the employee information from DB
}
}
The Camel Resetlet dependency added in pom.xml is
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-restlet</artifactId>
<version>2.24.1</version>
</dependency>>
Do i need add any other maven dependency in order to work for every endpoint call? Could you please help me here.
The easiest way to consume Restlet Resources is to use the Restlet HTTP Client:
<dependency>
<groupId>org.restlet.jse</groupId>
<artifactId>org.restlet</artifactId>
<version>2.4.0</version>
</dependency>
<dependency>
<groupId>org.restlet.jse</groupId>
<artifactId>org.restlet.ext.httpclient</artifactId>
<version>2.4.0</version>
</dependency>
With a code similar to this:
Component c = new Component();
Client client = c.getClients().add(Protocol.HTTP);
client.getContext().getParameters().add ( "socketTimeout", "1000" );
Response resp = client.handle(new Request(Method.GET, "https://swapi.co/api/people/1/"));
System.out.println("Output: " + resp.getEntity().getText());

How to change the endpoint of prometheus metrics

I am trying to expose some metrics from a spring-boot service to prometheus.
Unfortunately, both spring-boot actuator and the prometheus simple-client expose their metrics through the /metrics endpoint.
How can the endpoint of the simple-client be changed?
Thanks
You might want to have a look at the Prometheus Java Simpleclient Spring Boot Metric it exposes prometheus metrics at the /prometheus endpoint.
Github Project: https://github.com/prometheus/client_java/tree/master/simpleclient_spring_boot
Maven Artifact: https://mvnrepository.com/artifact/io.prometheus/simpleclient_spring_boot
On your pom.xml:
<dependency>
<groupId>io.prometheus</groupId>
<artifactId>simpleclient_spring_boot</artifactId>
<version>0.0.17</version>
</dependency>
In your springboot configuration class:
#Configuration
public class Configuration {
#Bean
public ServletRegistrationBean servletRegistrationBean() {
DefaultExports.initialize();
return new ServletRegistrationBean(new MetricsServlet(), "/prometheus");
}
#Bean
public SpringBootMetricsCollector springBootMetricsCollector(Collection<PublicMetrics> publicMetrics) {
SpringBootMetricsCollector springBootMetricsCollector = new SpringBootMetricsCollector(
publicMetrics);
springBootMetricsCollector.register();
return springBootMetricsCollector;
}
You can change spring-boot actuator's endponit and leave /metrics to Prometheus.
Add following configurations to your application.properties:
endpoints.metrics.id=springmetrics
endpoints.metrics.sensitive=false
endpoints.metrics.enabled=true
and you'll have a new endpoint /springmetics for spring actuator and /metrics for Prometheus.
For the java client you specify the endpoint when setting up the servlet, see https://github.com/RobustPerception/java_examples/blob/master/java_simple/src/main/java/io/robustperception/java_examples/JavaSimple.java#L39 for example. You can change the endpoint to whatever you like.
Have you tried to set up these properties in your application.properties file:
management.endpoints.web.path-mapping.prometheus=
management.endpoints.web.base-path=

Resources