Currently spring boot actuator metrics returns metrics for various system parameters. I want to turn on some selected metrics parameters, for example; show only metrics related to memory and processor. I had several attempts to figure out solution but nothing worked for me. I see SystemPublicMetrics registers all basic system metrics and management system matrics, how can I turn on only few of them?
Required output:
{
"mem": 495055,
"mem.free": 372397,
"processors": 4
}
You can do this by disabling CacheMetricsAutoConfiguration of spring boot auto configuration at start-up by adding metrics class to exclusion list.
For instance to disable cache metrics add following at startup:
import org.springframework.boot.actuate.autoconfigure.metrics.cache.CacheMetricsAutoConfiguration;
#EnableAutoConfiguration(exclude = {CacheMetricsAutoConfiguration.class})
public class Application extends SpringBootServletInitializer {
...
...
This should help..
You will not be able to disable specific metrics. Rather, you will be able to enable/disable at endpoints only.
Following are the flags that you can add in application.properties to enable/disable specific endpoints in Spring Boot Actuator
endpoints.autoconfig.enabled=false
endpoints.beans.enabled=false
endpoints.configprops.enabled=false
endpoints.dump.enabled=false
endpoints.env.enabled=false
endpoints.health.enabled=true
endpoints.info.enabled=true
endpoints.metrics.enabled=false
endpoints.mappings.enabled=false
endpoints.shutdown.enabled=false
endpoints.trace.enabled=false
Related
I have to change my custom defined spring properties (defined via #ConfigurationProperties beans) during runtime of my Spring Boot application.
Is there any elegant way of doing this using Spring Cloud Config?
I don't want to use an external application.properties in a git repository (as the spring boot application gets shipped to customers and I dont' want to create a git repository for everyone of them).
I just want to access and change the local application.properties (the one in the classpath, located in src/main/resources) file in my Spring container or (if thats not possible) in the Spring Cloud Config Server, which I could embed into my Spring Boot app. Is that possible somehow?
BTW: The goal is to create a visual editor for the customers, so that they can change the application.properties during runtime in their spring boot app.
Spring Boot supports profile based application configuration. Just add application-<profile>.properties file. Then just when running the application select a profile depending on the environment making use of spring.profiles.active.
-Dspring.profiles.active=dev
This will run the application with application-dev.properties file (overriding the default application.properties, i.e you can just leave the common stuff in the default file and change the rest depending on the env)
On a side note, having a repo for configuration is not a must. You could just place them in the class path and give a search-location.
spring:
application:
name: config-server
profiles:
active: native
cloud:
config:
server:
native:
search-locations: classpath:configs/
It actually is possible and in the end quite easy to achieve. It just took me a whole day to get all the information together. Maybe this helps someone:
You basically just need Spring Actuator, but for a certain endpoint, you also need the spring cloud dependency. (to make Post requests to the /env endpoint of Spring Actuator)
To alter your config at runtime, just add the following to your application.properties:
management.endpoints.web.exposure.include: env,refresh
management.endpoint.env.post.enabled: true //this property is only available when spring cloud is added as dependency to your project
If you (like me) don't need the feature of an externalized config, then you also have to add the following (otherwise, your Spring app will not start and throw an error that some config is missing)
spring.cloud.config.enabled: false
Now, if you send a POST request to /actuator/env endpoint with an object in the HTTP body in the form of {"name":"...", "value":"..."} (name is the name of a config property), then your config gets changed. To check that, you can do a GET request to /actuator/env/[name_of_config_property] and see that your config property has changed. No need to restart your app.
Don't forget to secure the /actuator endpoint in your SecurityConfig if you use a custom one.
It seems to me that you neither need the #RefreshScope annotation at your config classes nor the /actuator/refresh endpoint to "apply" the config changes.
Maybe what your looking for could be achieved with Spring cloud config and spring cloud bus. It's explained here: https://cloud.spring.io/spring-cloud-config/reference/html/#_push_notifications_and_spring_cloud_bus
In summary, any change on configuration sent an event to the spring cloud bus and you can then reload app context or configuration with new properties.
Spring boot actuator metrics (/actuator/metrics) comes with many default metrics. Some of them are:
"jvm.memory.max",
"jvm.threads.states",
"process.files.max",
"jvm.gc.memory.promoted",
"tomcat.servlet.error",
"system.load.average.1m",
"jvm.memory.used",
"jvm.gc.max.data.size",
"jvm.memory.committed",
"http.server.requests",
"system.cpu.count",
"logback.events",
"tomcat.global.sent",
...
Is it possible to expose only few of them? (i.e. filtering them or better yet, telling Spring boot not to collect them at all?)
You can use management.metrics.enable.* properties to control the metrics that are enabled and bound to the meter registry. Where a metric's name is . separated, you can disable multiple metrics with a single property. For example, to disable all jvm properties you can use the following property:
management.metrics.enable.jvm=false
Where there are multiple properties that match the same metric, the most-specific wins. For example, to disable all jvm metrics other than jvm.memory.max, you can use the following properties:
management.metrics.enable.jvm=false
management.metrics.enable.jvm.memory.max=true
You can use all to match all metrics. For example, to disable all metrics other than jvm.memory metrics, you can use the following properties:
management.metrics.enable.all=false
management.metrics.enable.jvm.memory=true
I am having an issue where EC2MetaDataUtils.getItems is being invoked on application start up ( Spring boot app), we do not use EC2 and so the calls made to AWS to get Metadata always fail, the application attempts to get this data 3 times and so this is adding around 15 seconds to the start time of the application.
I have been searching high and low for solutions I found a promising solution would suggested the following #EnableAutoConfiguration(exclude = { ContextResourceLoaderAutoConfiguration.class, ContextResourceLoaderConfiguration.class, ContextInstanceDataAutoConfiguration.class })
However when I try to start up the application it complains that ContextResourceLoaderConfiguration.class cannot be excluded as it is not auto configuration; if I just exclude the other 2 the application still invokes the MetaDataUtils.
Has anyone experienced this in the past and managed to resolve it?
Thank you for your time.
Resolved with the following:
#EnableAutoConfiguration(exclude = {ContextInstanceDataAutoConfiguration.class, ContextStackAutoConfiguration.class, ContextResourceLoaderAutoConfiguration.class})
when running spring-boot-application with AWS dependencies ,
It invokes stack auto-configuration , you need to disable it ,
add following to application.yml
cloud.aws.stack.auto: false
SpringBoot application should not do any call to EC2. This mean your are using some AWS specific library/component/what ever and this library on startup do this call.
Please check your dependencies and context configuration. There are nothing about SpringBoot. There is something with your custom dependencies/components.
If you're not using EC2, you can try removing the spring-cloud-aws* libraries from your dependencies.
You can use Spring profiles to differentiate between cloud and default profiles. For cloud profile, you can use spring-cloud-aws artifact to get metadata about EC2 instance which you need EC2 read permission access from an attached IAM role whereas for default profile, you don't need to worry about cloud environment and disable the cloud configuration properties which should not cause an issue for the application startup.
I'm currently using an EnvironmentPostProcessor to add my external PropertySource, the code looks like this :
public class ExternalPropertySourceEnvironmentPostProcessor implements EnvironmentPostProcessor
{
private static final String EXTERNAL_PROPERTY_SOURCE_NAME = "ExternalPropertySource";
#Override
public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application)
{
if (environment.acceptsProfiles(Profiles.EXTERNAL_PROPERTY_SOURCE_ENABLED_PROFILE)) {
environment.getPropertySources()
.addLast(new ExternalPropertySource(EXTERNAL_PROPERTY_SOURCE_NAME, new ExternalSource()));
}
}
}
A spring.factories is also used to register this EnvironmentPostProcessor.
This code actually works if the profile is set in the vm environment variables, but if it is added in src/main/resources/application.yml, the profile doesn't seem to be injected yet in the environment and is not returned by the environment.getActiveProfiles(). I've tried using the interface Ordered with the lowest precedence, but it doesn't help.
To add a bit of context around what I'm trying to achieve, this class is in a small library that adds an external property source like a database. Then we can use it in some other spring boot applications. Something like Spring Cloud Config does.
I'd like a clean way to enable or disable this property source depending on the environment where the code runs. I don't mind using something else then profiles or even another way to inject the property source, I just want something clean that doesn't depend on several factors to work.
The main problem in my code right now is that I'm using spring boot's property sources to make my own property source configurable.
UPDATE : I used a Spring Cloud app to debug this, and was confusing the bootstrap context with the normal spring boot context. See my answer below.
Further investigation made me figure out the problem appeared only with a Spring Cloud application.
In fact the breakpoint I had in this code was triggered twice, once after the bootstrap context initialization and once after the spring boot context initialization. I was only debugging the profiles in the first occurence. At that point, only the bootstrap.yml properties are loaded and not the ones from the application.yml file. The second occurence obviously had the profiles from my application.yml file.
My code worked as expected with a vanilla Spring Boot application. As the documentation states :
The Environment has already been prepared with all the usual property
sources that Spring Boot loads by default.
I was confused by the behaviour of my app which seemed to be different from that statement, but it was Spring Cloud's bootstrap that was messing with my debugging.
Since I need a PropertySource that has the highest precedence, I need to add it in the post bootstrap initialization for Spring Cloud apps. I used an init flag on my EnvironmentPostProcessor so it doesn't get executed twice and used the bootstrap.yml on Spring Cloud apps to set the profile.
TL;DR :
With Spring Cloud, an EnvironmentPostProcessor gets called twice: once after the bootstrap init and once after the normal Spring Boot context init. If you need injected properties and are targeting the Spring Cloud's post bootstrap initialization, use the bootstrap.yml instead of application.yml.
Spring Boot has preconfigured metrics. As I know it uses http://metrics.codahale.com/ library. How can I get MetricRegistry object to add my custom metrics?
Spring boot now supports Codahale Metrics out of the box.
See http://docs.spring.io/spring-boot/docs/1.0.0.RC5/reference/htmlsingle/#production-ready-code-hale-metrics
Spring Boot Does not use Codahale Metrics (yet). The plan is to support it as an option if it is on the classpath. If you prefer to do it that way then a MetricRegistry will be in the application context and you can simply #Autowire it and use it. You can see that work in progress on a branch in my fork.
The Boot interfaces for adding metrics are GaugeService and CounterService. You inject those and use them to record measurements. When Codahale gets support then this will be the recommended entry point for that as well, so you can get started using it now and add the Codahale stuff later if you want.
There's some integration magic accomplished by http://www.ryantenney.com/metrics-spring/ that wires codahale metrics into the actuator /health endpoint.
With this dependency included,
compile 'com.ryantenney.metrics:metrics-spring:3.0.0-RC2'
you can "enableMetrics" in your application configuration
#EnableMetrics
public class ApplicationConfiguration {
...
This allows you to time each request with the #timed annotation:
#Timed
#RequestMapping(method=RequestMethod.GET)
public #ResponseBody
Foo foo() {
...
and to have your other interactions with MetricRegistry aggregate into the actuator /health endpoint.
I've put together an example application which implements this integration:
https://github.com/benschw/consul-cluster-puppet/tree/master/demo
and written a more in depth tutorial here:
http://txt.fliglio.com/2014/10/spring-boot-actuator/