• We need to change the actuator endpoints to be on a different port number (To serve the Kubernetes probes)
  • We also need the logs from the Actuator to go to stdout
  • Changing the value of management.server.port: 8404 causes an exception as the server configures the new port to stream logs to /dev/management_stdout when it should be /dev/stdout (already configured for the server, as shown in the Question section below)

SpringBoot Setup

buildscript {
    repositories {
        mavenCentral()

        // For src/gradle/tests.gradle
        maven {
            url "https://plugins.gradle.org/m2/"
        }
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:2.3.5.RELEASE")
    }
}

dependencies {
    implementation('org.springframework.boot:spring-boot-starter-actuator')
}

Changing SpringBoot Actuator

  • Changed the port number as follows in application.yaml
management:
  endpoints:
    web:
      exposure:
        include: "*"
  server:
    port: 8404

Error shown during bootstrap

  • The default logger is trying to write to /dev/management_stdout
2020-11-15T17:23:41 ERROR [app=parking-plus-service,prf=default][tid=,sid=,sxp=][cid=] 77926 --- 
  [  restartedMain] o.apache.catalina.valves.AccessLogValve  : 
        Failed to open access log file [/dev/management_stdout]

java.io.FileNotFoundException: /dev/management_stdout (Operation not permitted)
    at java.base/java.io.FileOutputStream.open0(Native Method)
    at java.base/java.io.FileOutputStream.open(FileOutputStream.java:291)
    at java.base/java.io.FileOutputStream.<init>(FileOutputStream.java:234)
    at org.apache.catalina.valves.AccessLogValve.open(AccessLogValve.java:651)
    at org.apache.catalina.valves.AccessLogValve.startInternal(AccessLogValve.java:685)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
    at org.apache.catalina.core.StandardPipeline.startInternal(StandardPipeline.java:176)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
    at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:933)
    at org.apache.catalina.core.StandardEngine.startInternal(StandardEngine.java:262)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
    at org.apache.catalina.core.StandardService.startInternal(StandardService.java:421)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
    at org.apache.catalina.core.StandardServer.startInternal(StandardServer.java:930)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
    at org.apache.catalina.startup.Tomcat.start(Tomcat.java:486)
    at org.springframework.boot.web.embedded.tomcat.TomcatWebServer.initialize(TomcatWebServer.java:123)
    at org.springframework.boot.web.embedded.tomcat.TomcatWebServer.<init>(TomcatWebServer.java:104)
    at org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory.getTomcatWebServer(TomcatServletWebServerFactory.java:440)
    at org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory.getWebServer(TomcatServletWebServerFactory.java:193)
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.createWebServer(ServletWebServerApplicationContext.java:178)
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.onRefresh(ServletWebServerApplicationContext.java:158)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:545)
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:143)
    at org.springframework.boot.actuate.autoconfigure.web.server.ManagementContextAutoConfiguration$DifferentManagementContextConfiguration.onApplicationEvent(ManagementContextAutoConfiguration.java:142)
    at org.springframework.boot.actuate.autoconfigure.web.server.ManagementContextAutoConfiguration$DifferentManagementContextConfiguration.onApplicationEvent(ManagementContextAutoConfiguration.java:114)
    at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:172)
    at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:165)
    at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:139)
    at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:404)
    at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:361)
    at org.springframework.boot.web.servlet.context.WebServerStartStopLifecycle.start(WebServerStartStopLifecycle.java:46)
    at org.springframework.context.support.DefaultLifecycleProcessor.doStart(DefaultLifecycleProcessor.java:182)
    at org.springframework.context.support.DefaultLifecycleProcessor.access$200(DefaultLifecycleProcessor.java:53)
    at org.springframework.context.support.DefaultLifecycleProcessor$LifecycleGroup.start(DefaultLifecycleProcessor.java:360)
    at org.springframework.context.support.DefaultLifecycleProcessor.startBeans(DefaultLifecycleProcessor.java:158)
    at org.springframework.context.support.DefaultLifecycleProcessor.onRefresh(DefaultLifecycleProcessor.java:122)
    at org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:895)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:554)
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:143)
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:758)
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:750)
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:405)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:315)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1237)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1226)
    at cash.super_.platform.service.ParkingPlusApplication.main(ParkingPlusApplication.java:12)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:564)
    at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49)

Question

  • Which property sets the file name prefix stdout just like on the server settings shown below?
  • Maybe the management embedded tomcat is taking the value of directory and using the prefix as management_stdout as the value of the file?
server:
  #port: 8080 default
  tomcat:
    accesslog:
      enabled: true
      directory: /dev
      prefix: stdout
      buffered: false
      suffix:
      file-date-format:

Comment From: wilkinsona

When you configure a separate management port, you end up with two embedded Tomcat instances. There's one instance for your application and one for the actuator. When accessing logging is enabled, to avoid the two Tomcat instances writing their access logs to the same location, the management server prefixes its location with management_.

https://github.com/spring-projects/spring-boot/issues/14948 is tracking making this management-specific prefix customisable. It also suggests a workaround that you could use in the interim.

Comment From: marcellodesales

@wilkinsona Thanks a lot for clarifying it!!!