Giter VIP home page Giter VIP logo

spring-boot-admin's Introduction

Spring Boot Admin by codecentric

Apache License 2 Build Status codecov Maven Central Gitter

This community project provides an admin interface for Spring Boot ® web applications that expose actuator endpoints.

Monitoring Python applications is available using Pyctuator.

Compatibility Matrix

In the Spring Boot Admin Server App, the Spring Boot Admin's version matches the major and minor versions of Spring Boot.

Spring Boot Version Spring Boot Admin
2.6 2.6.Y
2.7 2.7.Y
3.0 3.0.Y
3.1 3.1.Y
3.2 3.2.Y

Nevertheless, it is possible to monitor any version of a Spring Boot service independently of the underlying Spring Boot version in the service. Hence, it is possible to run Spring Boot Admin Server version 2.6 and monitor a service that is running on Spring Boot 2.3 using Spring Boot Admin Client version 2.3.

Getting Started

A quick guide to get started can be found in our docs.

There are introductory talks available on YouTube:

Cloud Native Spring Boot® Admin by Johannes Edmeier @ Spring I/O 2019
Cloud Native Spring Boot® Admin by Johannes Edmeier @ Spring I/O 2019

Monitoring Spring Boot® Applications with Spring Boot Admin @ Spring I/O 2018
Monitoring Spring Boot® Applications with Spring Boot Admin @ Spring I/O 2018

Spring Boot® Admin - Monitoring and Configuring Spring Boot Applications at Runtime
Spring Boot® Admin - Monitoring and Configuring Spring Boot Applications at Runtime

Getting Help

Having trouble with codecentric's Spring Boot Admin? We’d like to help!

Reference Guide

Translated versions

The following reference guides have been translated by users of Spring Boot Admin and are not part of the official bundle. The maintainers of Spring Boot Admin will not update and maintain the guides mentioned below.

Version 2.6.6 (Chinese translated by @qq253498229)

Trademarks and licenses

The source code of codecentric's Spring Boot Admin is licensed under Apache License 2.0

Spring, Spring Boot and Spring Cloud are trademarks of Pivotal Software, Inc. in the U.S. and other countries.

Snapshot builds

You can access snapshot builds from the github snapshot repository by adding the following to your repositories:

<repository>
	<id>sba-snapshot</id>
	<name>Spring Boot Admin Snapshots</name>
	<url>https://maven.pkg.github.com/codecentric/spring-boot-admin</url>
	<snapshots>
		<enabled>true</enabled>
	</snapshots>
	<releases>
		<enabled>false</enabled>
	</releases>
</repository>

Contributing

See CONTRIBUTING.md file.

spring-boot-admin's People

Contributors

andreasfritz avatar antechrestos avatar asibross avatar aweigold avatar binarywang avatar britter avatar ccoltx avatar denschu avatar dependabot[bot] avatar dickerpulli avatar erikpetzold avatar fuud avatar hzpz avatar izeye avatar jonashackt avatar joshiste avatar lasylv avatar mmoayyed avatar renovate-bot avatar renovate[bot] avatar riggs333 avatar semeiser avatar soe78 avatar srempfer avatar stekoe avatar steve-oakey avatar sullis avatar tetsushiawano avatar thomaszub avatar ulischulte avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

spring-boot-admin's Issues

Can't open UI

Hi.

I tried to use spring-boot-admin. So i downloaded the sources and compiled the spring-boot-admin-sample project with intellij 14.

In the logs i can see that an application was registered, the rest api is working, but i can't open the ui. Acutally i don't know how to open it. Which url should i open to see UI?

Could you please provide a documentation for this?

Thank you

Custom healthchecks

Hi!

It would be great if dashboard will show custom healthchecks, not only "application and diskspace"

Registering client with HTTPS url results in Connection refused when polling the client

Following problem occured when using spring-boot-admin on Heroku. The spring.boot.admin.url in the client project can be HTTPS but the spring.boot.admin.client.url which is used to poll the client for new metrics cannot be HTTPS and must be changed to HTTP.

You get the following error in the logs of the admin app when the client project has spring.boot.admin.client.url set to an HTTPS URL:

2015-04-25T12:42:24.722489+00:00 heroku[router]: at=info method=GET path="/api/applications/0b17d4a9/health" host=vast-tundra-2451.herokuapp.com request_id=3417a253-28ca-43dd-b2d8-43d939ebd57f fwd="62.235.160.238" dyno=web.1 connect=10ms service=14ms status=200 bytes=423
2015-04-25T12:42:24.576719+00:00 app[web.1]: 2015-04-25 12:42:24.576  WARN 3 --- [io-18891-exec-3] o.s.c.n.z.filters.post.SendErrorFilter   : Error during filtering
2015-04-25T12:42:24.576725+00:00 app[web.1]: 
2015-04-25T12:42:24.576727+00:00 app[web.1]: java.net.ConnectException: Connection refused
2015-04-25T12:42:24.576729+00:00 app[web.1]:    at java.net.PlainSocketImpl.socketConnect(Native Method)
2015-04-25T12:42:24.576731+00:00 app[web.1]:    at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:345)
2015-04-25T12:42:24.576732+00:00 app[web.1]:    at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206)
2015-04-25T12:42:24.576734+00:00 app[web.1]:    at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188)
2015-04-25T12:42:24.576736+00:00 app[web.1]:    at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
2015-04-25T12:42:24.576737+00:00 app[web.1]:    at java.net.Socket.connect(Socket.java:589)
2015-04-25T12:42:24.576739+00:00 app[web.1]:    at sun.security.ssl.SSLSocketImpl.connect(SSLSocketImpl.java:656)
2015-04-25T12:42:24.576740+00:00 app[web.1]:    at org.apache.http.conn.ssl.SSLSocketFactory.connectSocket(SSLSocketFactory.java:524)
2015-04-25T12:42:24.576742+00:00 app[web.1]:    at org.apache.http.conn.ssl.SSLSocketFactory.connectSocket(SSLSocketFactory.java:403)
2015-04-25T12:42:24.576743+00:00 app[web.1]:    at org.apache.http.conn.ssl.SSLSocketFactory.connectSocket(SSLSocketFactory.java:472)
2015-04-25T12:42:24.576745+00:00 app[web.1]:    at org.apache.http.conn.scheme.SchemeSocketFactoryAdaptor.connectSocket(SchemeSocketFactoryAdaptor.java:65)
2015-04-25T12:42:24.576747+00:00 app[web.1]:    at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:177)
2015-04-25T12:42:24.576750+00:00 app[web.1]:    at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:144)
2015-04-25T12:42:24.576751+00:00 app[web.1]:    at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:131)
2015-04-25T12:42:24.576752+00:00 app[web.1]:    at org.apache.http.impl.client.DefaultRequestDirector.tryConnect(DefaultRequestDirector.java:611)
2015-04-25T12:42:24.576754+00:00 app[web.1]:    at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:446)
2015-04-25T12:42:24.576755+00:00 app[web.1]:    at org.apache.http.impl.client.AbstractHttpClient.doExecute(AbstractHttpClient.java:863)
2015-04-25T12:42:24.576757+00:00 app[web.1]:    at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:115)
2015-04-25T12:42:24.576758+00:00 app[web.1]:    at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:57)
2015-04-25T12:42:24.576760+00:00 app[web.1]:    at org.springframework.cloud.netflix.zuul.filters.route.SimpleHostRoutingFilter.forwardRequest(SimpleHostRoutingFilter.java:254)
2015-04-25T12:42:24.576762+00:00 app[web.1]:    at org.springframework.cloud.netflix.zuul.filters.route.SimpleHostRoutingFilter.forward(SimpleHostRoutingFilter.java:217)
2015-04-25T12:42:24.576763+00:00 app[web.1]:    at org.springframework.cloud.netflix.zuul.filters.route.SimpleHostRoutingFilter.run(SimpleHostRoutingFilter.java:175)
2015-04-25T12:42:24.576765+00:00 app[web.1]:    at com.netflix.zuul.ZuulFilter.runFilter(ZuulFilter.java:112)
2015-04-25T12:42:24.576766+00:00 app[web.1]:    at com.netflix.zuul.FilterProcessor.processZuulFilter(FilterProcessor.java:197)
2015-04-25T12:42:24.576768+00:00 app[web.1]:    at com.netflix.zuul.FilterProcessor.runFilters(FilterProcessor.java:161)
2015-04-25T12:42:24.576769+00:00 app[web.1]:    at com.netflix.zuul.FilterProcessor.route(FilterProcessor.java:120)
2015-04-25T12:42:24.576771+00:00 app[web.1]:    at com.netflix.zuul.ZuulRunner.route(ZuulRunner.java:84)
2015-04-25T12:42:24.576772+00:00 app[web.1]:    at com.netflix.zuul.http.ZuulServlet.route(ZuulServlet.java:111)
2015-04-25T12:42:24.576773+00:00 app[web.1]:    at com.netflix.zuul.http.ZuulServlet.service(ZuulServlet.java:77)
2015-04-25T12:42:24.576775+00:00 app[web.1]:    at org.springframework.web.servlet.mvc.ServletWrappingController.handleRequestInternal(ServletWrappingController.java:158)
2015-04-25T12:42:24.576777+00:00 app[web.1]:    at org.springframework.cloud.netflix.zuul.web.ZuulController.handleRequestInternal(ZuulController.java:43)
2015-04-25T12:42:24.576779+00:00 app[web.1]:    at org.springframework.web.servlet.mvc.AbstractController.handleRequest(AbstractController.java:146)
2015-04-25T12:42:24.576780+00:00 app[web.1]:    at org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter.handle(SimpleControllerHandlerAdapter.java:50)
2015-04-25T12:42:24.576781+00:00 app[web.1]:    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:943)
2015-04-25T12:42:24.576783+00:00 app[web.1]:    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:877)
2015-04-25T12:42:24.576784+00:00 app[web.1]:    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:966)
2015-04-25T12:42:24.576785+00:00 app[web.1]:    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:857)
2015-04-25T12:42:24.576787+00:00 app[web.1]:    at javax.servlet.http.HttpServlet.service(HttpServlet.java:618)
2015-04-25T12:42:24.576788+00:00 app[web.1]:    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:842)
2015-04-25T12:42:24.576789+00:00 app[web.1]:    at javax.servlet.http.HttpServlet.service(HttpServlet.java:725)
2015-04-25T12:42:24.576791+00:00 app[web.1]:    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:291)
2015-04-25T12:42:24.576792+00:00 app[web.1]:    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
2015-04-25T12:42:24.576793+00:00 app[web.1]:    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
2015-04-25T12:42:24.576795+00:00 app[web.1]:    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
2015-04-25T12:42:24.576803+00:00 app[web.1]:    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
2015-04-25T12:42:24.576805+00:00 app[web.1]:    at org.springframework.boot.actuate.autoconfigure.EndpointWebMvcAutoConfiguration$ApplicationContextHeaderFilter.doFilterInternal(EndpointWebMvcAutoConfiguration.java:291)
2015-04-25T12:42:24.576806+00:00 app[web.1]:    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
2015-04-25T12:42:24.576807+00:00 app[web.1]:    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
2015-04-25T12:42:24.576809+00:00 app[web.1]:    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
2015-04-25T12:42:24.576810+00:00 app[web.1]:    at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:77)
2015-04-25T12:42:24.576811+00:00 app[web.1]:    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
2015-04-25T12:42:24.576813+00:00 app[web.1]:    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
2015-04-25T12:42:24.576814+00:00 app[web.1]:    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
2015-04-25T12:42:24.576816+00:00 app[web.1]:    at org.springframework.boot.actuate.trace.WebRequestTraceFilter.doFilterInternal(WebRequestTraceFilter.java:102)
2015-04-25T12:42:24.576817+00:00 app[web.1]:    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
2015-04-25T12:42:24.576818+00:00 app[web.1]:    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
2015-04-25T12:42:24.576820+00:00 app[web.1]:    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
2015-04-25T12:42:24.576821+00:00 app[web.1]:    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:88)
2015-04-25T12:42:24.576822+00:00 app[web.1]:    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
2015-04-25T12:42:24.576824+00:00 app[web.1]:    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
2015-04-25T12:42:24.576825+00:00 app[web.1]:    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
2015-04-25T12:42:24.576827+00:00 app[web.1]:    at org.springframework.boot.actuate.autoconfigure.MetricFilterAutoConfiguration$MetricsFilter.doFilterInternal(MetricFilterAutoConfiguration.java:90)
2015-04-25T12:42:24.576828+00:00 app[web.1]:    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
2015-04-25T12:42:24.576830+00:00 app[web.1]:    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
2015-04-25T12:42:24.576831+00:00 app[web.1]:    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
2015-04-25T12:42:24.576832+00:00 app[web.1]:    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:219)
2015-04-25T12:42:24.576834+00:00 app[web.1]:    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106)
2015-04-25T12:42:24.576835+00:00 app[web.1]:    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:501)
2015-04-25T12:42:24.576837+00:00 app[web.1]:    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:142)
2015-04-25T12:42:24.576838+00:00 app[web.1]:    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
2015-04-25T12:42:24.576840+00:00 app[web.1]:    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)
2015-04-25T12:42:24.576841+00:00 app[web.1]:    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:516)
2015-04-25T12:42:24.576842+00:00 app[web.1]:    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1086)
2015-04-25T12:42:24.576844+00:00 app[web.1]:    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:659)
2015-04-25T12:42:24.576845+00:00 app[web.1]:    at org.apache.coyote.http11.Http11NioProtocol$Http11ConnectionHandler.process(Http11NioProtocol.java:223)
2015-04-25T12:42:24.576846+00:00 app[web.1]:    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1558)
2015-04-25T12:42:24.576848+00:00 app[web.1]:    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1515)
2015-04-25T12:42:24.576849+00:00 app[web.1]:    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
2015-04-25T12:42:24.576851+00:00 app[web.1]:    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
2015-04-25T12:42:24.576852+00:00 app[web.1]:    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
2015-04-25T12:42:24.576854+00:00 app[web.1]:    at java.lang.Thread.run(Thread.java:745)

Hostname of clients

I couldn't find anywhere that easily shows the hostname of the client.

Is this something that you are planning to implement?
Or is it too specific of a use case that I should just make such a change on my own fork for my own customizations?

I feel like it would be useful enough to have even on the main page with the Application, Version, and Status. Presumably, in any sizable application, there are going to be multiple servers including possibly multiple instances of the same application. I would like to use the Spring Boot Admin to keep track of all running instances across multiple servers.

Pie chart not rendered

Hey,

After successfully connecting my spring boot apps the pie chart on the metrics screen are not rendered.
Please see attached screenshot.

metrics

BTW,
Great job!!

Thanks,
Hanan

Health-Check for non-Boot applications

Hello all, I really like this concept, and I've successfully registered my spring boot-based REST service. Instead of using Spring MVC to serve views, I'm only providing a REST service and then I have an AngularJS web app (just static assets) using it. Due to this, the service and the web app are deployed separately.

What I'd love to be able to do is have a simple health check on whether or not hitting the web app returns a 200 OK status, and to show the status on the admin console. I can imagine a simple form that allows you to register a URL and an expected HTTP status code, along with how often to ping the URL.

I realize that this app is focused on monitoring spring-boot apps, but I don't think that what I'm doing is uncommon, and adding this health check would let me use the admin console to monitor my whole application until it grows to the point that I'd want to do something more heavy-weight.

Some ideas for enhancements

Hello,

I would like to contribute to spring-boot-admin in the future.
I have the following enhancement-ideas and we plan to implement them:

  • Health Checking: spring-boot-admin-server runs health checks regularly against a Spring Boot Actuator endpoint which is provided by the client-application during registration. If a client-application is down, the application is removed from the list.
  • Distributed-Cache: We include hazelcast as a JCace-Provider.
  • Service Discovery: spring-boot-admin-server can be deployed on multiple host and the state (registered applications) is replicated via hazelcast and can be used by client-applications to find services for client-side load balancing.
  • Spring Security: Add Spring Security to secure the spring-boot-admin-server endpoints (OAuth2, Basic Auth)

It could be a bootiful alternative to Netflix Eureka or HashiCorps Consul.

Kind regards,

Robert Winkler

Application name versus info.id

By the check() method in SpringBootAdminRegistratorTask (client-side), the spring.application.name property is required, but it is not what is actually used to register the application. The property info.id is what is used. Even though it would be able to register and monitor the app without problems, it will fail at this assertion if the spring.application.name property is not set.

Is the spring.application.name property meant to be required and if so, why is it not used?
Otherwise, is it simply meant to be the info.id property that is checked and required here?

Issues with connection pools in Zuul

Has anyone experienced any issues with connection pools with Zuul and Spring Boot Admin?

Had the following error in Zuul - Requied a reboot of the Zuul instance to get Spring Boot Admin back. Happened after running for a few days.

Opened a issue in Spring Cloud as well. spring-cloud/spring-cloud-netflix#262

2015-03-18 04:34:03.737  WARN 966 --- [http-nio-80-exec-9] o.s.c.n.z.filters.post.SendErrorFilter   : Error during filtering

com.netflix.zuul.exception.ZuulException: Forwarding error
    at org.springframework.cloud.netflix.zuul.filters.route.RibbonRoutingFilter.forward(RibbonRoutingFilter.java:146)
    at org.springframework.cloud.netflix.zuul.filters.route.RibbonRoutingFilter.run(RibbonRoutingFilter.java:110)
    at com.netflix.zuul.ZuulFilter.runFilter(ZuulFilter.java:112)
    at com.netflix.zuul.FilterProcessor.processZuulFilter(FilterProcessor.java:197)
    at com.netflix.zuul.FilterProcessor.runFilters(FilterProcessor.java:161)
    at com.netflix.zuul.FilterProcessor.route(FilterProcessor.java:120)
    at com.netflix.zuul.ZuulRunner.route(ZuulRunner.java:84)
    at com.netflix.zuul.http.ZuulServlet.route(ZuulServlet.java:111)
    at com.netflix.zuul.http.ZuulServlet.service(ZuulServlet.java:77)
    at org.springframework.web.servlet.mvc.ServletWrappingController.handleRequestInternal(ServletWrappingController.java:158)
    at org.springframework.cloud.netflix.zuul.web.ZuulController.handleRequestInternal(ZuulController.java:43)
    at org.springframework.web.servlet.mvc.AbstractController.handleRequest(AbstractController.java:146)
    at org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter.handle(SimpleControllerHandlerAdapter.java:50)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:943)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:877)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:966)
    at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:868)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:644)
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:842)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:725)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:291)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.springframework.boot.actuate.autoconfigure.EndpointWebMvcAutoConfiguration$ApplicationContextHeaderFilter.doFilterInternal(EndpointWebMvcAutoConfiguration.java:291)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at de.codecentric.boot.admin.web.EndpointCorsFilter.doFilterInternal(EndpointCorsFilter.java:63)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:77)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.springframework.boot.actuate.trace.WebRequestTraceFilter.doFilterInternal(WebRequestTraceFilter.java:102)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:88)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.springframework.boot.actuate.autoconfigure.MetricFilterAutoConfiguration$MetricsFilter.doFilterInternal(MetricFilterAutoConfiguration.java:90)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:219)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:501)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:142)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:516)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1086)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:659)
    at org.apache.coyote.http11.Http11NioProtocol$Http11ConnectionHandler.process(Http11NioProtocol.java:223)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1558)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1515)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Thread.java:745)
Caused by: com.netflix.hystrix.exception.HystrixRuntimeException: boot-adminRibbonCommand failed and no fallback available.
    at com.netflix.hystrix.AbstractCommand$20.call(AbstractCommand.java:816)
    at com.netflix.hystrix.AbstractCommand$20.call(AbstractCommand.java:798)
    at rx.internal.operators.OperatorOnErrorResumeNextViaFunction$1.onError(OperatorOnErrorResumeNextViaFunction.java:77)
    at rx.internal.operators.OperatorDoOnEach$1.onError(OperatorDoOnEach.java:70)
    at rx.internal.operators.OperatorDoOnEach$1.onError(OperatorDoOnEach.java:70)
    at rx.Observable$ThrowObservable$1.call(Observable.java:9058)
    at rx.Observable$ThrowObservable$1.call(Observable.java:9048)
    at rx.Observable.unsafeSubscribe(Observable.java:7304)
    at rx.internal.operators.OperatorOnErrorResumeNextViaFunction$1.onError(OperatorOnErrorResumeNextViaFunction.java:78)
    at rx.internal.operators.OperatorMap$1.onError(OperatorMap.java:49)
    at com.netflix.hystrix.HystrixCommand$2.call(HystrixCommand.java:318)
    at com.netflix.hystrix.HystrixCommand$2.call(HystrixCommand.java:310)
    at rx.Observable$1.call(Observable.java:145)
    at rx.Observable$1.call(Observable.java:137)
    at rx.Observable$1.call(Observable.java:145)
    at rx.Observable$1.call(Observable.java:137)
    at rx.Observable$1.call(Observable.java:145)
    at rx.Observable$1.call(Observable.java:137)
    at rx.Observable$1.call(Observable.java:145)
    at rx.Observable$1.call(Observable.java:137)
    at rx.Observable$1.call(Observable.java:145)
    at rx.Observable$1.call(Observable.java:137)
    at rx.Observable$1.call(Observable.java:145)
    at rx.Observable$1.call(Observable.java:137)
    at rx.Observable$1.call(Observable.java:145)
    at rx.Observable$1.call(Observable.java:137)
    at rx.Observable.unsafeSubscribe(Observable.java:7304)
    at rx.internal.operators.OperatorOnErrorResumeNextViaFunction$1.onError(OperatorOnErrorResumeNextViaFunction.java:78)
    at rx.internal.operators.OperatorDoOnEach$1.onError(OperatorDoOnEach.java:70)
    at rx.internal.operators.OperatorMap$1.onError(OperatorMap.java:49)
    at com.netflix.hystrix.AbstractCommand$HystrixObservableTimeoutOperator$3.onError(AbstractCommand.java:995)
    at rx.internal.operators.OperatorDoOnEach$1.onError(OperatorDoOnEach.java:70)
    at rx.internal.operators.OperatorDoOnEach$1.onError(OperatorDoOnEach.java:70)
    at rx.Observable$ThrowObservable$1.call(Observable.java:9058)
    at rx.Observable$ThrowObservable$1.call(Observable.java:9048)
    at rx.Observable.unsafeSubscribe(Observable.java:7304)
    at rx.internal.operators.OperatorOnErrorResumeNextViaFunction$1.onError(OperatorOnErrorResumeNextViaFunction.java:78)
    at rx.internal.operators.OperatorMap$1.onError(OperatorMap.java:49)
    at com.netflix.hystrix.HystrixCommand$1.call(HystrixCommand.java:301)
    at com.netflix.hystrix.HystrixCommand$1.call(HystrixCommand.java:293)
    at rx.Observable$1.call(Observable.java:145)
    at rx.Observable$1.call(Observable.java:137)
    at rx.Observable$1.call(Observable.java:145)
    at rx.Observable$1.call(Observable.java:137)
    at rx.Observable$1.call(Observable.java:145)
    at rx.Observable$1.call(Observable.java:137)
    at rx.Observable$1.call(Observable.java:145)
    at rx.Observable$1.call(Observable.java:137)
    at rx.Observable$1.call(Observable.java:145)
    at rx.Observable$1.call(Observable.java:137)
    at rx.Observable$1.call(Observable.java:145)
    at rx.Observable$1.call(Observable.java:137)
    at rx.Observable$1.call(Observable.java:145)
    at rx.Observable$1.call(Observable.java:137)
    at rx.Observable$1.call(Observable.java:145)
    at rx.Observable$1.call(Observable.java:137)
    at rx.Observable$1.call(Observable.java:145)
    at rx.Observable$1.call(Observable.java:137)
    at rx.Observable$1.call(Observable.java:145)
    at rx.Observable$1.call(Observable.java:137)
    at rx.Observable$1.call(Observable.java:145)
    at rx.Observable$1.call(Observable.java:137)
    at rx.Observable$1.call(Observable.java:145)
    at rx.Observable$1.call(Observable.java:137)
    at rx.Observable.unsafeSubscribe(Observable.java:7304)
    at com.netflix.hystrix.AbstractCommand$1.call(AbstractCommand.java:388)
    at com.netflix.hystrix.AbstractCommand$1.call(AbstractCommand.java:368)
    at rx.Observable$1.call(Observable.java:145)
    at rx.Observable$1.call(Observable.java:137)
    at rx.Observable$1.call(Observable.java:145)
    at rx.Observable$1.call(Observable.java:137)
    at rx.Observable.unsafeSubscribe(Observable.java:7304)
    at com.netflix.hystrix.AbstractCommand$ObservableCommand$1.call(AbstractCommand.java:1097)
    at com.netflix.hystrix.AbstractCommand$ObservableCommand$1.call(AbstractCommand.java:1093)
    at rx.Observable$1.call(Observable.java:145)
    at rx.Observable$1.call(Observable.java:137)
    at rx.Observable.subscribe(Observable.java:7393)
    at rx.internal.operators.BlockingOperatorToFuture.toFuture(BlockingOperatorToFuture.java:57)
    at rx.observables.BlockingObservable.toFuture(BlockingObservable.java:409)
    at com.netflix.hystrix.HystrixCommand.queue(HystrixCommand.java:385)
    at com.netflix.hystrix.HystrixCommand.execute(HystrixCommand.java:339)
    at org.springframework.cloud.netflix.zuul.filters.route.RibbonRoutingFilter.forward(RibbonRoutingFilter.java:130)
    ... 64 common frames omitted
Caused by: com.netflix.client.ClientException: null
    at com.netflix.client.AbstractLoadBalancerAwareClient.executeWithLoadBalancer(AbstractLoadBalancerAwareClient.java:123)
    at com.netflix.client.AbstractLoadBalancerAwareClient.executeWithLoadBalancer(AbstractLoadBalancerAwareClient.java:81)
    at org.springframework.cloud.netflix.zuul.filters.route.RibbonCommand.forward(RibbonCommand.java:129)
    at org.springframework.cloud.netflix.zuul.filters.route.RibbonCommand.run(RibbonCommand.java:103)
    at org.springframework.cloud.netflix.zuul.filters.route.RibbonCommand.run(RibbonCommand.java:48)
    at com.netflix.hystrix.HystrixCommand$1.call(HystrixCommand.java:298)
    ... 107 common frames omitted
Caused by: org.apache.http.conn.ConnectionPoolTimeoutException: Timeout waiting for connection from pool
    at org.apache.http.impl.conn.tsccm.ConnPoolByRoute.getEntryBlocking(ConnPoolByRoute.java:412)
    at com.netflix.http4.NamedConnectionPool.getEntryBlocking(NamedConnectionPool.java:141)
    at org.apache.http.impl.conn.tsccm.ConnPoolByRoute$1.getPoolEntry(ConnPoolByRoute.java:298)
    at org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager$1.getConnection(ThreadSafeClientConnManager.java:238)
    at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:423)
    at org.apache.http.impl.client.AbstractHttpClient.doExecute(AbstractHttpClient.java:863)
    at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:115)
    at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:57)
    at com.sun.jersey.client.apache4.ApacheHttpClient4Handler.handle(ApacheHttpClient4Handler.java:170)
    at com.sun.jersey.api.client.Client.handle(Client.java:648)
    at com.sun.jersey.api.client.WebResource.handle(WebResource.java:680)
    at com.sun.jersey.api.client.WebResource.access$200(WebResource.java:74)
    at com.sun.jersey.api.client.WebResource$Builder.post(WebResource.java:568)
    at com.netflix.niws.client.http.RestClient.execute(RestClient.java:621)
    at com.netflix.niws.client.http.RestClient.execute(RestClient.java:527)
    at com.netflix.niws.client.http.RestClient.execute(RestClient.java:92)
    at com.netflix.client.AbstractLoadBalancerAwareClient$1.call(AbstractLoadBalancerAwareClient.java:109)
    at com.netflix.loadbalancer.reactive.LoadBalancerCommand$3$1.call(LoadBalancerCommand.java:303)
    at com.netflix.loadbalancer.reactive.LoadBalancerCommand$3$1.call(LoadBalancerCommand.java:287)
    at rx.internal.operators.OperatorMap$1.onNext(OperatorMap.java:55)
    at rx.internal.util.ScalarSynchronousObservable$1.call(ScalarSynchronousObservable.java:41)
    at rx.internal.util.ScalarSynchronousObservable$1.call(ScalarSynchronousObservable.java:30)
    at rx.Observable$1.call(Observable.java:145)
    at rx.Observable$1.call(Observable.java:137)
    at rx.Observable$1.call(Observable.java:145)
    at rx.Observable$1.call(Observable.java:137)
    at rx.Observable.unsafeSubscribe(Observable.java:7304)
    at rx.internal.operators.OperatorConcat$ConcatSubscriber.subscribeNext(OperatorConcat.java:163)
    at rx.internal.operators.OperatorConcat$ConcatSubscriber.onNext(OperatorConcat.java:128)
    at rx.internal.operators.OperatorConcat$ConcatSubscriber.onNext(OperatorConcat.java:65)
    at rx.internal.operators.OperatorMap$1.onNext(OperatorMap.java:55)
    at com.netflix.loadbalancer.reactive.LoadBalancerCommand$1.call(LoadBalancerCommand.java:185)
    at com.netflix.loadbalancer.reactive.LoadBalancerCommand$1.call(LoadBalancerCommand.java:180)
    at rx.Observable$1.call(Observable.java:145)
    at rx.Observable$1.call(Observable.java:137)
    at rx.Observable$1.call(Observable.java:145)
    at rx.Observable$1.call(Observable.java:137)
    at rx.Observable.unsafeSubscribe(Observable.java:7304)
    at rx.internal.operators.OperatorRetryWithPredicate$SourceSubscriber$1.call(OperatorRetryWithPredicate.java:112)
    at rx.schedulers.TrampolineScheduler$InnerCurrentThreadScheduler.enqueue(TrampolineScheduler.java:81)
    at rx.schedulers.TrampolineScheduler$InnerCurrentThreadScheduler.schedule(TrampolineScheduler.java:59)
    at rx.internal.operators.OperatorRetryWithPredicate$SourceSubscriber.onNext(OperatorRetryWithPredicate.java:77)
    at rx.internal.operators.OperatorRetryWithPredicate$SourceSubscriber.onNext(OperatorRetryWithPredicate.java:45)
    at rx.internal.util.ScalarSynchronousObservable$1.call(ScalarSynchronousObservable.java:41)
    at rx.internal.util.ScalarSynchronousObservable$1.call(ScalarSynchronousObservable.java:30)
    at rx.Observable$1.call(Observable.java:145)
    at rx.Observable$1.call(Observable.java:137)
    at rx.Observable$1.call(Observable.java:145)
    at rx.Observable$1.call(Observable.java:137)
    at rx.Observable$1.call(Observable.java:145)
    at rx.Observable$1.call(Observable.java:137)
    at rx.Observable.subscribe(Observable.java:7393)
    at rx.observables.BlockingObservable.blockForSingle(BlockingObservable.java:441)
    at rx.observables.BlockingObservable.single(BlockingObservable.java:340)
    at com.netflix.client.AbstractLoadBalancerAwareClient.executeWithLoadBalancer(AbstractLoadBalancerAwareClient.java:102)
    ... 112 common frames omitted

Support for secured client actuator endpoints

Hello,

First of all, great job.
Are there any plans for supporting secured client actuator endpoints? Sadly without this feature whole application is unusable in production env. At least basic auth should be supported.
In #12 was some proposition for sending username/password in register request, but i'm not happy with this solution because it assigns to client knowledge of this data.
My proposition, for starters, is to allow user provide username and password used in requests to all nodes.

Regards
Mariusz

Seeing errors in logs - com.netflix.zuul.http.HttpServletRequestWrapper

We have implemented version 1.2.0 and seeing errors continually within the log files. The errors seem to be directly related to the reverse proxy calls. The errors appear with every reverse proxy call.

The setup is using the Spring Boot Admin Client 1.1.2. We do not want to use the discovery feature. That being said all logs are sent to Redis so ideally nothing about logs is handled within Spring Boot Admin.

    "message": "Content-Length is neither greater than zero or -1. = 0",
    "@timestamp": "2015-05-07T08:05:46.720Z",
    "logger": "com.netflix.zuul.http.HttpServletRequestWrapper",
    "level": "WARN",
    "thread": "http-nio-9000-exec-2",
    "location": {
      "class": "com.netflix.zuul.http.HttpServletRequestWrapper",
      "method": "parseRequest",
      "file": "HttpServletRequestWrapper.java",
      "line": "204"

This is the code within Zuul that is sending the error. Zuul-core

    private void parseRequest() throws IOException {
        if (parameters != null)
            return; //already parsed

        HashMap<String, List<String>> mapA = new HashMap<String, List<String>>();
        List<String> list;

        Map<String, List<String>> query = HTTPRequestUtils.getInstance().getQueryParams();
        if (query != null) {
            for (String key : query.keySet()) {
                list = query.get(key);
                mapA.put(key, list);
            }
        }

        LOG.debug("Path = " + req.getPathInfo());
        LOG.debug("Transfer-Encoding = " + String.valueOf(req.getHeader(ZuulHeaders.TRANSFER_ENCODING)));
        LOG.debug("Content-Encoding = " + String.valueOf(req.getHeader(ZuulHeaders.CONTENT_ENCODING)));

        LOG.debug("Content-Length header = " + req.getContentLength());
        if (req.getContentLength() > 0) {

            // Read the request body inputstream into a byte array.
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            IOUtils.copy(req.getInputStream(), baos);
            contentData = baos.toByteArray();

            try {
                LOG.debug("Length of contentData byte array = " + contentData.length);
                if (req.getContentLength() != contentData.length) {
                    LOG.warn("Content-length different from byte array length! cl=" + req.getContentLength() + ", array=" + contentData.length);
                }
            } catch(Exception e) {
                LOG.error("Error checking if request body gzipped!", e);
            }

            String enc = req.getCharacterEncoding();

            if (enc == null)
                enc = "UTF-8";
            String s = new String(contentData, enc), name, value;
            StringTokenizer st = new StringTokenizer(s, "&");
            int i;

            boolean decode = req.getContentType() != null && req.getContentType().equalsIgnoreCase("application/x-www-form-urlencoded");
            while (st.hasMoreTokens()) {
                s = st.nextToken();
                i = s.indexOf("=");
                if (i > 0 && s.length() > i + 1) {
                    name = s.substring(0, i);
                    value = s.substring(i + 1);
                    if (decode) {
                        try {
                            name = URLDecoder.decode(name, "UTF-8");
                        } catch (Exception e) {
                        }
                        try {
                            value = URLDecoder.decode(value, "UTF-8");
                        } catch (Exception e) {
                        }
                    }
                    list = mapA.get(name);
                    if (list == null) {
                        list = new LinkedList<String>();
                        mapA.put(name, list);
                    }
                    list.add(value);
                }
            }

        } else if (req.getContentLength() == -1) {
            final String transferEncoding = req.getHeader(ZuulHeaders.TRANSFER_ENCODING);
            if (transferEncoding != null && transferEncoding.equals(ZuulHeaders.CHUNKED)) {
                RequestContext.getCurrentContext().setChunkedRequestBody();
                LOG.debug("Set flag that request body is chunked.");
            }
        } else {
            LOG.warn("Content-Length is neither greater than zero or -1. = " + req.getContentLength());
        }

        HashMap<String, String[]> map = new HashMap<String, String[]>(mapA.size() * 2);
        for (String key : mapA.keySet()) {
            list = mapA.get(key);
            map.put(key, list.toArray(new String[list.size()]));
        }

        parameters = map;

    }

spring.application.name or info.id for SpringBootAdminRegistratorTask

    @PostConstruct
    public void check() {
//...
        Assert.notNull(env.getProperty("spring.application.name"), "The id of the application is mandatory");
    }

    @Override
    public void run() {
        try {
            String id = env.getProperty("info.id");

So, should i set both spring.application.name and info.id in application.properties?

To me, line 58 of SpringBootAdminRegistratorTask.java (in 1.0.5) should be the following:

            String id = env.getProperty("spring.application.name");

Webpage title

I really think the app looks slick and is very smooth, while still giving all the information in a logical way. Very great work. That being said, I hate to nit-pick, but the webpage title being blank bothers me a bit. How about adding something simple like 'Spring Boot Admin'?

Timer metrics support

Hi!

Could you please support timer metrics? i.e.:

"timer.someTimer" : 33,
"timer.someTimer.count" : 26,
"timer.someTimer.fifteenMinuteRate" : 0.20585190244272,
"timer.someTimer.fiveMinuteRate" : 0.213187349928478,
"timer.someTimer.meanRate" : 0.248698908802215,
"timer.someTimer.oneMinuteRate" : 0.187558528524916,
"timer.someTimer.snapshot.75thPercentile" : 45,
"timer.someTimer.snapshot.95thPercentile" : 60,
"timer.someTimer.snapshot.98thPercentile" : 61,
"timer.someTimer.snapshot.999thPercentile" : 61,
"timer.someTimer.snapshot.99thPercentile" : 61,
"timer.someTimer.snapshot.max" : 61,
"timer.someTimer.snapshot.mean" : 37,
"timer.someTimer.snapshot.median" : 34,
"timer.someTimer.snapshot.min" : 25,
"timer.someTimer.snapshot.stdDev" : 10,

Actuator endpoints of client apps have to be public reachable?

I was wondering if the actuator endpoints of my monitored client apps have to be reachable by the respective browser which is accessing SpringBootAdminServer UI.

I am currently running an application which consists of 4 (including SpringBootAdminServer) Spring Boot applications. Everything works as expected in my local vagrant based setup.
However in my staging environment (which is identically configured to prod environment) we're using some Nginx HTTPS reverse proxies in front of our Spring Boot applications which are only exposing required endpoints to the public internet. So the Spring Boot Admin Server is able to access for example the /logfile endpoint of it's client applications. I was assuming that the Spring Boot Admin Server is also acting as some kind of proxy between the users browser and the monitored client apps but that is (at least in my setup) not the case.

Is this from an architectural approach intended?

Message tracking

Hi,
thanks for your work!!

Could you improve it adding incoming and outgoing rest messages? Something like spring remote shell do with /trace but adding the xml/json message bodies that pass through an endpoint.

How can I customize spring-boot-admin in order to do that?

Problem with context path

I'm using this variable 'server.contextPath:/rio' in my applications.properties, but when the application starts, had problems
Did not find handler method for [/api/applications], and the applications fails to registry.

i tried to change this property

spring.boot.admin.contextPath=rio/api/applications

but the problem its the same, I can registry but now

Did not find handler method for [/rio/api/applications],

Where is admin UI url

Do not find in docs how to access to this admin ui form browser. Ok, a can get info by /metrics and others api, but can't find admin ui url.
For example: i want to access to admin by //localhost:8080/boot/admin

Registration of client failed when adding jackson-xml dependency

Hello

We have endpoint which server either json or xml content
To do that we include this dependency (as explain into spring-boot documentation)

        <dependency>
            <groupId>com.fasterxml.jackson.dataformat</groupId>
            <artifactId>jackson-dataformat-xml</artifactId>
        </dependency>

Then when a client try to register itself into an admin-server, I've got this error (cliente side)

015-04-16 12:19:45.495  WARN 6345 --- [pool-1-thread-1] d.c.b.a.s.SpringBootAdminRegistrator     : Failed to register application as [id=null, url=http://locahost:8191, name=unicorn-margin] at spring-boot-admin (http://locahost:8185/api/applications): 415 Unsupported Media Type

There is no error on Admin server Side

Christophe

Documentation needs to explain that client app needs info.id set, client needs to validate its presence

When a client tries to register with the server, the server code will throw an exception is info.id is not passed over in the client Application instance.

There should be validation in the client code to check whether or not info.id is set, and log if it isn't, rather than the server side code just failing and throwing a 500 back to the client.

The documentation needs to be updated to say that into.id must be set in the client application.properties/yaml

Long Application descriptions break layout

In the "details" view longer descriptions (2nd column) are not breaking correctly. A CSS change (class ng-binding) with word-break:break-word can fix that.

best regards,
Jens

update admin-server version

Currently https://blog.codecentric.de/en/2014/09/spring-boot-admin-first-official-release/ points to 1.0.2 version of spring-boot-admin-server.

spring-boot-admin-server, as of version 1.0.2, has transitive dependency problem when used from gradle.

Gradle resolves transitive angularjs dependency to 1.2.16-2 (latest to date) :

    +--- org.webjars:bootstrap:2.3.2
    |    \--- org.webjars:jquery:1.9.0 -> 1.11.0
    +--- org.webjars:jquery:1.11.0
    +--- org.webjars:angularjs:1.2.12 -> 1.2.16-2
    +--- org.webjars:angular-ui-router:0.2.10-1
    |    \--- org.webjars:angularjs:1.2.16-2
    +--- org.webjars:angularjs-nvd3-directives:0.0.7-1
    |    +--- org.webjars:angularjs:1.2.14 -> 1.2.16-2
    |    +--- org.webjars:d3js:3.4.1
    |    \--- org.webjars:nvd3:1.1.15-beta
    |         \--- org.webjars:d3js:2.10.3 -> 3.4.1

But source code points to 1.12

<script src="/webjars/angularjs/1.2.12/angular.min.js"></script>
    <script src="/webjars/angularjs/1.2.12/angular-resource.min.js"></script>
    <script src="/webjars/angularjs/1.2.12/angular-route.min.js"></script>

Moreover, 1.0.6 version referenced here https://github.com/codecentric/spring-boot-admin is not (yet) available at https://repo1.maven.org/maven2/de/codecentric/spring-boot-admin-server/

Should i use some different repository, not mavenCentral() ?

Allow to disable spring-boot-admin client for tests.

If one adds the spring-boot-admin-starter-client dependency to an app one cannot run the tests without configuring the admin-server "connection" as it results in the following Exception:

2015-08-03 13:31:55.694 ERROR 4600 --- [           main] o.s.test.context.TestContextManager      : Caught exception while allowing TestExecutionListener [org.springframework.test.context.support.DependencyInjectionTestExecutionListener@91161c7] to prepare test instance [demo.AppTests@6fd02e5]

java.lang.IllegalStateException: Failed to load ApplicationContext
    at org.springframework.test.context.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:94)
    at org.springframework.test.context.DefaultTestContext.getApplicationContext(DefaultTestContext.java:72)
    at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:117)
    at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83)
    at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:212)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:200)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:259)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:261)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:219)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:83)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:68)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:163)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'spring.boot.admin.client.CONFIGURATION_PROPERTIES': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private org.springframework.boot.autoconfigure.web.ServerProperties de.codecentric.boot.admin.config.AdminClientProperties.server; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.springframework.boot.autoconfigure.web.ServerProperties] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:334)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1210)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:537)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:476)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:303)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:299)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:755)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:757)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:480)
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:686)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:320)
    at org.springframework.boot.test.SpringApplicationContextLoader.loadContext(SpringApplicationContextLoader.java:103)
    at org.springframework.test.context.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:68)
    at org.springframework.test.context.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:86)
    ... 25 common frames omitted
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private org.springframework.boot.autoconfigure.web.ServerProperties de.codecentric.boot.admin.config.AdminClientProperties.server; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.springframework.boot.autoconfigure.web.ServerProperties] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:561)
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:331)
    ... 40 common frames omitted
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.springframework.boot.autoconfigure.web.ServerProperties] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:1301)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1047)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:942)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:533)
    ... 42 common frames omitted

It would be nice to be able to disable the admin starter client for tests.
Another option would be to declare the autowired dependencies to ServerProperties in de.codecentric.boot.admin.config.AdminClientProperties optional, e.g. via:

    @Autowired(required=false)
    private ServerProperties server;

If there is another prefered way to configure the tests to not cause the above exception it would be great to have an example for that in the spring-boot-admin-samples :)

Cheers,
Thomas

Make /logfile endpoint available by default.

The /logfile endpoint is only available when using the spring-boot-admin-starter-client AND specifying the spring.boot.admin.url. It would be nice to have the /logfile endpoint available when using Spring Cloud Discovery Client.

SimpleCORSFilter not being respected

I saw the corsFilter Bean being loaded but displaying the json always failed because of a the response was not from "origin". Additionally I had to disable basic auth on my endpoints to use this.
So I would like to suggest something similar to the following:
In the service.js all of the rest calls could be proxied through admin server:

return $http.get('/api/execute?uri='+ app.url + '/dump');

Where the mapping for /api/execute is

package de.codecentric.boot.admin.controller;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import org.apache.commons.codec.binary.Base64;

@RestController
public class RestEndpointController {
    private static final Logger LOGGER = LoggerFactory.getLogger(RestEndpointController.class);
    @Value("${com.company.user:}")
    String username;

    @Value("${com.company.password:}")
    String password;

    public RestEndpointController() {
    }

    @RequestMapping(value = "/api/execute", method = RequestMethod.GET)
    public Object register(@RequestParam(value="uri",required=false) String uri) throws Exception {
        LOGGER.debug("Execute rest call {}", uri);
        HttpEntity<Application> request = new HttpEntity<Application>(getBasicAuthHeader());
        RestTemplate template = new RestTemplate();
        return template.exchange(uri,HttpMethod.GET,request,Object.class);
    }

    private HttpHeaders getBasicAuthHeader(){
        String plainCreds = user+":"+password;
        byte[] base64CredsBytes = Base64.encodeBase64(plainCreds.getBytes());

        HttpHeaders headers = new HttpHeaders();
        headers.add("Authorization", "Basic " + new String(base64CredsBytes));
        return headers;
    }
}

I believe this would remove the need for the CORS filter and allow for the basic auth I needed.

Register (and show) service- and management-url

This would probably need another definition within the spring-boot-admin-client. Maybe an info property. Basic idea is that aside from the url that exist now http://hostname/admin be able to define an entry point that could open in another window to view the service.

Typo in About

All applications has to register itself at this application.

should be

All applications have to register themselves at this application.

Time series for metrics-view

Hi

Would be nice to have a feature to monitor in real time the number of requests received by a
spring boot application over the time and a time series to show that.

What do you think guys about it?

Securing Eureka with user/password causes recurring login popup

If I secure Eureka with a user/password as so

application.yml in Eureka Server:

 security:
   user:
     password: ${eureka.password} # Don't use a default password in a real app

And if the spring-boot-admin bootstrap.yml contains:

cloud:
  config:
    uri: http://localhost:8888/diagnostics/admin/config
    failFast: true

spring.boot.admin.discovery.management.context-path: /diagnostics/admin

eureka:
  instance:
    leaseRenewalIntervalInSeconds: 10
    statusPageUrlPath: /diagnostics/admin/info
    healthCheckUrlPath: /diagnostics/admin/health
    metadataMap:
      password: password
  client:
    enabled: true
    serviceUrl:
      defaultZone: http://user:password@localhost:8761/eureka/

Then when I bring up spring-boot-admin ui, the following prompt for user/password happens over and over. When it happens, log is Finding route for path: /api/applications/xxxx/yyy where yyy are /info|configprops/ and xxx are some kind of hash.

screen shot 2015-07-23 at 10 03 04 am

Allow the UI to be served under a different context path

For testing we wanted to package the Eureka Server, the Spring Cloud Config Server and the Spring Boot Admin UI into one war file.
When adding all the necessary dependencies and the applying the annotations to the Spring Boot Application class, neither the Eureka Dashboard, nor the Admin Server Dashboard find their web ressources (CSS, JS, IMG).
It would be great if you could change the targetPath in the pom.xml of the admin server ui project to be META-INF/resources/admin/ so that the Admin UI becomes available under the /admin context path and thus does not clash with the Eureka Server Dashboard.
Setting the server.contextPath does not work as it also moves the Eureka Dashbaord to the new context path.

spring.boot.admin.client.url default value doesn't support contextPath

Hi,

Thanks for this pretty nice project.

In SpringBoot it's possible to specify management context path trough tow tokens. Here is a sample in yaml :


management:
  contextPath:

or


management:
  context-path:

spring-boot admin only uses ${management.context-path} token to complete spring.boot.admin.client.url if not specified by the client.

Can you add the support of ${management.contextPath}

Regards

Impossible to register another spring-boot application listening on another port

Hi

I'm following the documentation
My setup is this current one:

  • Run an admin server (setup server.port to 9870)
  • Run a second spring-boot application (named "Foo") (setup server.port to localhost:8080) with properties: spring.boot.admin.url=http://localhost:9870

The issue is:

  • In admin-client-ui (9870) I can see 2 applications
    • The one handled by admin-server (name "MyArtifactId") and everithin is working fine
    • Another one for my second app (name "Foo")
      • But it displays "Offline" with only one possible actions: "Remove"

I've no specific error neither in admin-server or my spring-boot app using admin-client

Any thoughts ?

Regards
Christophe

Registration logging

I just wanted to verify that the current logging of the application registration is the intended process. As it is right now, both the client and admin (for each client!) will log messages every 10 seconds (by default) when the register task runs. This seems to be excessive logging. I certainly understand logging when a new application is registered, but when an already registered application is just re-registering (I assume in case the Admin restarted or something), it fills up the logs with mostly useless messages.

I think either lowering the log level to debug or eliminating the logging during re-registration would be appropriate. What do you think?

Here are examples of what I am referring to on the admin side:
2014-11-24 21:29:42.850 INFO 4628 --- [nio-8888-exec-9] d.c.b.a.registry.ApplicationRegistry : Application [id=d7d98d57, url=http://192.168.1.11:8080, name=bar] refreshed
2014-11-24 21:29:44.437 INFO 4628 --- [nio-8888-exec-4] d.c.b.a.registry.ApplicationRegistry : Application [id=da63e593, url=http://192.168.1.11:8888, name=configserver] refreshed

And on the client side:
2014-11-24 21:31:12.877 INFO 8632 --- [pool-1-thread-1] d.c.b.a.s.SpringBootAdminRegistrator : Application registered itself as [id=d7d98d57, url=http://192.168.1.11:8080, name=bar]

JMX and logging section doesn't show up

Created a standalone spring-boot-admin-server application including spring-boot-admin-server-ui.
In my already existing spring boot application I've added spring-boot-admin-client and spring-boot-starter-actuator. Furthermore I've added following properties in my already existing application:

info.build.artifact
info.build.name
info.build.description
info.version
spring.application.name
logging.file

In my new spring-boot-admin-server application the dashboard contains one entry for my already existing app but the entry is missing the respective information in the 'version' and 'info' columns. Additionally the logfile download does not work (button is disabled). The /logfile endpoint in my already existing spring boot application works as expected.

Integration in existing projects?

I'm trying to integrate Spring Boot Admin, along with the Server UI and the Admin Client, in an existing Spring Boot project. After including the three dependencies I also added the appropriate application.properties settings (my main application runs under the root context):

spring.boot.admin.url=http://localhost:8080

In the log files I see that the application does register itself but I still can't access the Admin UI using http://localhost:8080/admin, which returns a 404.
Could this be because my main application already has a controller matching against api/**, effectively intervening with internals of Spring Boot Admin?

Now if I read the docs again and understand them correctly then the Spring Boot Admin application needs to be deployed as its own application, with the Admin Client deployed in the main application. Is it correct that I can't run it along with my main application?

Sorry for brevity, I thought I'd keep things simple here instead of posting lots of code. Please let me know if you need me to post anything in addition.

Thanks
Rias

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.