![control panel](../img/control-panel.png)
Micronaut Control Panel
The Micronaut Control Panel module provides a web UI that allows you to view and manage the state of your Micronaut application, typically in a development environment.
Version:
1 Introduction
The Micronaut Control Panel module provides a web UI that allows you to view and manage the state of your Micronaut application, typically in a development environment.
![control panel](../img/control-panel.png)
2 Release History
For this project, you can find a list of releases (with release notes) here:
3 Quick Start
To get started, add the UI module as a runtime dependency:
developmentOnly("io.micronaut.controlpanel:micronaut-control-panel-ui")
<dependency>
<groupId>io.micronaut.controlpanel</groupId>
<artifactId>micronaut-control-panel-ui</artifactId>
<scope>provided</scope>
</dependency>
Then, add the control panel modules that you want. For example, if you already have the
io.micronaut:micronaut-management
module, you can add the micronaut-control-panel-management
module:
developmentOnly("io.micronaut.controlpanel:micronaut-control-panel-management")
<dependency>
<groupId>io.micronaut.controlpanel</groupId>
<artifactId>micronaut-control-panel-management</artifactId>
<scope>provided</scope>
</dependency>
By default, the Control Panel is only enabled in the dev
or test
environments. You can change this and other settings
in your configuration file:
Property | Type | Description |
---|---|---|
|
boolean |
Enables/disables the control panel module. Default value: "true". |
|
java.util.Set |
Configures the environments where the control panel module is enabled. By default, it is only enabled in the "dev" and "test" environments. |
|
java.lang.String |
Configures the path where the control panel can be accessed. Default value: "/control-panel". |
Therefore, make sure you activate the appropriate environments when running locally, for example, using default environments:
# For Maven:
MICRONAUT_ENVIRONMENTS=dev ./mvnw mn:run
# For Gradle:
MICRONAUT_ENVIRONMENTS=dev ./gradlew run
Once the application is running, you can access the control panel at http://localhost:8080/control-panel.
4 Available Control Panels
All Control Panels are configurable with the following properties:
Property | Type | Description |
---|---|---|
|
boolean |
Enables/disables this control panel. Default value: true. |
|
int |
Sets the order of this control panel, since they will be displayed sorted by order. |
|
java.lang.String |
The title is displayed in the header of the card UI element. |
|
java.lang.String |
Icon class of the card UI element. |
|
java.lang.String |
The unique name of the control panel. Can be used in URLs. |
For example, to disable the routes control panel, set the property
micronaut.control-panel.panels.routes.enabled
to false
.
Beyond displaying the available panels, the control panel also allows to perform 2 additional actions, provided that the corresponding endpoints are enabled and non-sensitive:
-
Refresh: refreshing the application will cause all
@Refreshable
beans in the context to be destroyed and re-instantiated upon further requests. This requires the Refresh Endpoint to be enabled and non-sensitive. -
Stop: will shut down the application. This requires the Stop Endpoint to be enabled and non-sensitive.
Micronaut Endpoints require having the io.micronanut:micronaut-management dependency on the classpath.
|
4.1 Built-in
The following control panels are available by default with the UI module:
-
routes
: displays information about the available HTTP routes.
4.2 Management
To add the management panels, include the following dependency:
developmentOnly("io.micronaut.controlpanel:micronaut-control-panel-management")
<dependency>
<groupId>io.micronaut.controlpanel</groupId>
<artifactId>micronaut-control-panel-management</artifactId>
<scope>provided</scope>
</dependency>
Note that you also need the Management module:
runtimeOnly("io.micronaut.:micronaut-management")
<dependency>
<groupId>io.micronaut.</groupId>
<artifactId>micronaut-management</artifactId>
<scope>runtime</scope>
</dependency>
The following panels are available:
-
health
: Application Health -
env
: Environment Properties -
beans
: Bean Definitions -
loggers
: Logging Configuration
Application Heath
This panel displays the health information of your application, and relies on the Health Endpoint to display its information. Note that, by default, the health endpoint only displays the details to authenticated users. To be able to see the details in the control panel, you need to configure the health endpoint to expose the details to unauthenticated users:
Make sure this is done in an environment-specific configuration file, for example, application-dev.yml .
|
endpoints.health.details-visible=ANONYMOUS
endpoints:
health:
details-visible: ANONYMOUS
[endpoints]
[endpoints.health]
details-visible="ANONYMOUS"
endpoints {
health {
detailsVisible = "ANONYMOUS"
}
}
{
endpoints {
health {
details-visible = "ANONYMOUS"
}
}
}
{
"endpoints": {
"health": {
"details-visible": "ANONYMOUS"
}
}
}
Environment Properties
This panel displays all the configuration properties resolved, and relies on the Environment Endpoint to display all the properties. This endpoint is disabled and sensitive (requires authentication to display the information) by default, so you need to configure it to be enabled and accessible to anonymous users in the environments where the control panel is enabled:
Make sure this is done in an environment-specific configuration file, for example, application-dev.yml .
|
endpoints.env.enabled=true
endpoints.env.sensitive=false
endpoints:
env:
enabled: true
sensitive: false
[endpoints]
[endpoints.env]
enabled=true
sensitive=false
endpoints {
env {
enabled = true
sensitive = false
}
}
{
endpoints {
env {
enabled = true
sensitive = false
}
}
}
{
"endpoints": {
"env": {
"enabled": true,
"sensitive": false
}
}
}
Also, by default, all the values will be masked. If you want to see the actual configuration values in the control panel,
you need to provide an implementation of the
EnvironmentEndpointFilter
interface and register it as a bean. For example:
@Singleton
@Requires(env = Environment.DEVELOPMENT)
public class AllPlainEnvironmentEndpointFilter implements EnvironmentEndpointFilter {
@Override
public void specifyFiltering(@NonNull EnvironmentFilterSpecification specification) {
specification.legacyMasking();
}
}
This will show all values apart from those that contain the words password
, credential
, certificate
, key
,
secret
or token
anywhere in their name.
Bean Definitions
This panel displays all the beans, and their relationships, grouped by packages. It relies on the Beans Endpoint to display all the bean definitions. This endpoint is sensitive by default, so if you want to see the bean definitions in the control panel, you need to configure the endpoint to be accessible to anonymous users in the environments where the control panel is enabled:
Make sure this is done in an environment-specific configuration file, for example, application-dev.yml .
|
endpoints.beans.sensitive=false
endpoints:
beans:
sensitive: false
[endpoints]
[endpoints.beans]
sensitive=false
endpoints {
beans {
sensitive = false
}
}
{
endpoints {
beans {
sensitive = false
}
}
}
{
"endpoints": {
"beans": {
"sensitive": false
}
}
}
Logging Configuration
This panel allows you to view and re-configure the logging levels without restarting the application. It relies on the Loggers Endpoint to display and update the logging levels. This endpoint is disabled by default, so if you want to manage the logging configuration in the control panel, you need to enable the endpoint. Also, by default, the endpoint is read-only, so you need to configure it to be writable:
Make sure this is done in an environment-specific configuration file, for example, application-dev.yml .
|
endpoints.loggers.enabled=true
endpoints.loggers.write-sensitive=false
endpoints:
loggers:
enabled: true
write-sensitive: false
[endpoints]
[endpoints.loggers]
enabled=true
write-sensitive=false
endpoints {
loggers {
enabled = true
writeSensitive = false
}
}
{
endpoints {
loggers {
enabled = true
write-sensitive = false
}
}
}
{
"endpoints": {
"loggers": {
"enabled": true,
"write-sensitive": false
}
}
}
5 Creating Custom Control Panels
You can add your own control panels to the Control Panel UI. Creating custom panels requires the following:
-
An implementation of the ControlPanel interface.
-
Some configuration values.
-
The views.
The Control Panel UI uses the open-source AdminLTE template, including Bootstrap and Font Awesome.
The categories are used to group the control panels in the UI. Categories are rendered as left side menu items. There is
a default category called Dashboard
that is used for all control panels that don’t specify a category.
Control Panel Implementation
The easiest way to implement a custom panel is to extend from AbstractControlPanel. For example:
@Singleton
public class MyApplicationControlPanel extends AbstractControlPanel<String> { // (1)
private static final String NAME = "my-application"; // (2)
public MyApplicationControlPanel(@Named(NAME) ControlPanelConfiguration configuration) {
super(NAME, configuration); // (3)
}
@Override
public String getBody() {
return "This is an application-provided control panel. This text is coming from the body.";
}
@Override
public Category getCategory() {
return new Category(NAME, "My Application", "fa-copy"); // (4)
}
}
1 | The String type parameter indicates the object type of the body. You can use your own classes or records to return
custom data to the view. In this example, the control panel only returns a message. |
2 | Unique name for your control panel. This is used for the configuration properties prefix. In this case:
micronaut.control-panel.panels.my-application . |
3 | Call the parent constructor. You could inject any other beans in this constructor. |
4 | The category under which the control panel will be displayed, if other than the default. |
Check the ControlPanel interface to see the other methods that can be overridden, for example, to display a badge in the control panel header.
Configuration
There are some values for the UI that can be configured:
micronaut.control-panel.panels.my-application.title=My Application Control Panel
micronaut.control-panel.panels.my-application.icon=fa-plug
micronaut.control-panel.panels.my-application.order=10
micronaut:
control-panel:
panels:
my-application:
title: My Application Control Panel # (1)
icon: fa-plug # (2)
order: 10 # (3)
[micronaut]
[micronaut.control-panel]
[micronaut.control-panel.panels]
[micronaut.control-panel.panels.my-application]
title="My Application Control Panel"
icon="fa-plug"
order=10
micronaut {
controlPanel {
panels {
myApplication {
title = "My Application Control Panel"
icon = "fa-plug"
order = 10
}
}
}
}
{
micronaut {
control-panel {
panels {
my-application {
title = "My Application Control Panel"
icon = "fa-plug"
order = 10
}
}
}
}
}
{
"micronaut": {
"control-panel": {
"panels": {
"my-application": {
"title": "My Application Control Panel",
"icon": "fa-plug",
"order": 10
}
}
}
}
}
1 | Title to be displayed in the control panel headeer. |
2 | Icon class (from Font Awesome) of the control panel. |
3 | The order in which the control panel will be displayed in the UI. |
Views
For rendering the views, the Control Panel uses Micronaut Views with Handlebars.java templates.
Each control panel needs to provide 2 views: one for the control panel list, that can contain a summary of the
information to be displayed, and another one for the detailed view. The must be placed in a views/<panel-name>
directory
on the classpath, and names body.hbs
and detail.hbs
, respectively. For example, in the above example:
src/main/resources/views/my-application/body.hbs
.<p class="card-text">
This is the body of the application-provided control panel
</p>
The ControlPanel instance (MyApplicationControlPanel
in this case) is stored on the Handlebars
context, so you can implicitly access its methods and properties. For example, to access the badge:
src/main/resources/views/my-application/body.hbs
.<p class="card-text">
<strong>{{badge}}</strong> bean definitions active.
</p>
In the case of the detail view, the control panel instance is passed as an implicit controlPanel
variable. For example,
to access the body of our control panel example:
src/main/resources/views/my-application/detail.hbs
.{{ controlPanel.body }}
6 Repository
You can find the source code of this project in this repository: