spring-boot-admin-docs/src/site/docs/03-client/30-metadata.md
Metadata allows you to attach custom information to your application registration, which can be used for filtering, grouping, and providing additional context in the Spring Boot Admin UI.
The MetadataContributor interface enables you to programmatically add metadata to your application registration:
@FunctionalInterface
public interface MetadataContributor {
Map<String, String> getMetadata();
}
Automatically adds the application startup timestamp:
public class StartupDateMetadataContributor implements MetadataContributor {
private final OffsetDateTime timestamp = OffsetDateTime.now();
@Override
public Map<String, String> getMetadata() {
return singletonMap("startup",
timestamp.format(DateTimeFormatter.ISO_DATE_TIME));
}
}
This metadata is automatically included and helps the Admin Server detect application restarts.
For Cloud Foundry deployments, adds CF-specific metadata:
public class CloudFoundryMetadataContributor implements MetadataContributor {
@Override
public Map<String, String> getMetadata() {
Map<String, String> metadata = new HashMap<>();
metadata.put("applicationId", vcapApplication.getApplicationId());
metadata.put("instanceId", vcapApplication.getInstanceId());
// Additional CF metadata
return metadata;
}
}
Automatically activated when running on Cloud Foundry.
Combines multiple metadata contributors:
public class CompositeMetadataContributor implements MetadataContributor {
private final List<MetadataContributor> delegates;
public CompositeMetadataContributor(List<MetadataContributor> delegates) {
this.delegates = delegates;
}
@Override
public Map<String, String> getMetadata() {
Map<String, String> metadata = new LinkedHashMap<>();
delegates.forEach(delegate -> metadata.putAll(delegate.getMetadata()));
return metadata;
}
}
Spring Boot Admin automatically creates a composite contributor from all MetadataContributor beans.
Add static metadata through properties:
spring:
boot:
admin:
client:
instance:
metadata:
team: platform-team
environment: production
region: us-east-1
version: 1.0.0
support-email: [email protected]
Use property placeholders to inject environment-specific values:
spring:
boot:
admin:
client:
instance:
metadata:
environment: ${APP_ENV:development}
version: ${APP_VERSION:unknown}
hostname: ${HOSTNAME:localhost}
pod-name: ${POD_NAME:}
namespace: ${NAMESPACE:default}
Create custom metadata contributors for dynamic or computed metadata:
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.Map;
@Component
public class CustomMetadataContributor implements MetadataContributor {
private final Environment environment;
private final BuildProperties buildProperties;
public CustomMetadataContributor(Environment environment,
@Autowired(required = false) BuildProperties buildProperties) {
this.environment = environment;
this.buildProperties = buildProperties;
}
@Override
public Map<String, String> getMetadata() {
Map<String, String> metadata = new HashMap<>();
// Add build information
if (buildProperties != null) {
metadata.put("build.version", buildProperties.getVersion());
metadata.put("build.time", buildProperties.getTime().toString());
metadata.put("build.artifact", buildProperties.getArtifact());
}
// Add environment information
metadata.put("spring.profiles", String.join(",",
environment.getActiveProfiles()));
// Add JVM information
metadata.put("java.version", System.getProperty("java.version"));
metadata.put("java.vendor", System.getProperty("java.vendor"));
// Add custom business metadata
metadata.put("feature-flags",
environment.getProperty("app.feature-flags", ""));
return metadata;
}
}
@Component
@ConditionalOnProperty(name = "kubernetes.enabled", havingValue = "true")
public class KubernetesMetadataContributor implements MetadataContributor {
@Override
public Map<String, String> getMetadata() {
Map<String, String> metadata = new HashMap<>();
// Read from environment variables set by Kubernetes
metadata.put("k8s.pod", System.getenv("HOSTNAME"));
metadata.put("k8s.namespace", System.getenv("POD_NAMESPACE"));
metadata.put("k8s.node", System.getenv("NODE_NAME"));
metadata.put("k8s.service-account",
System.getenv("SERVICE_ACCOUNT"));
// Add labels as metadata
String labels = System.getenv("POD_LABELS");
if (labels != null) {
metadata.put("k8s.labels", labels);
}
return metadata;
}
}
Tags are a special type of metadata used for visual markers in the Admin UI. They appear as colored badges in the application list and instance views.
spring:
boot:
admin:
client:
instance:
metadata:
tags:
environment: production
region: us-west-2
tier: backend
info:
tags:
environment: production
region: us-west-2
tier: backend
Tags appear as colored badges:
Create tags dynamically based on runtime conditions:
@Component
public class DynamicTagMetadataContributor implements MetadataContributor {
private final Environment environment;
public DynamicTagMetadataContributor(Environment environment) {
this.environment = environment;
}
@Override
public Map<String, String> getMetadata() {
Map<String, String> metadata = new HashMap<>();
// Environment tag
String env = environment.getProperty("spring.profiles.active", "default");
metadata.put("tags.environment", env);
// Deployment type
if (isKubernetes()) {
metadata.put("tags.platform", "kubernetes");
} else if (isCloudFoundry()) {
metadata.put("tags.platform", "cloud-foundry");
} else {
metadata.put("tags.platform", "standalone");
}
// Health-based tag
metadata.put("tags.monitoring", "enabled");
return metadata;
}
private boolean isKubernetes() {
return System.getenv("KUBERNETES_SERVICE_HOST") != null;
}
private boolean isCloudFoundry() {
return System.getenv("VCAP_APPLICATION") != null;
}
}
Pass credentials for actuator endpoint access:
spring:
boot:
admin:
client:
instance:
metadata:
user.name: ${spring.security.user.name}
user.password: ${spring.security.user.password}
:::warning Credentials in metadata are masked in the Admin UI but transmitted over the network. Always use HTTPS when transmitting sensitive data. :::
eureka:
instance:
metadata-map:
startup: ${random.int} # Trigger update on restart
user.name: ${spring.security.user.name}
user.password: ${spring.security.user.password}
tags.environment: ${APP_ENV}
spring:
cloud:
consul:
discovery:
metadata:
user-name: ${spring.security.user.name} # Note: use dashes, not dots
user-password: ${spring.security.user.password}
environment: production
:::warning
Consul does not allow dots (.) in metadata keys. Use dashes (-) instead.
:::
spring:
boot:
admin:
client:
instance:
metadata:
group: Legacy Squad
squad: backend-team
cost-center: CC-1234
The Admin UI can use the group metadata for visual grouping.
spring:
boot:
admin:
client:
instance:
metadata:
management.context-path: /actuator
service-url: https://my-app.example.com
service-path: /api
spring:
boot:
admin:
client:
instance:
metadata:
hide-url: true # Hide service URL in UI
Metadata is available through the instance object:
@Component
public class MetadataProcessor {
public void processInstance(Instance instance) {
Map<String, String> metadata = instance.getRegistration().getMetadata();
String environment = metadata.get("tags.environment");
String team = metadata.get("team");
String version = metadata.get("version");
// Process metadata
log.info("Instance {} - Environment: {}, Team: {}, Version: {}",
instance.getRegistration().getName(),
environment, team, version);
}
}
tags.environment, k8s.namespace)/actuator/info for build and git informationThe Admin Server masks certain metadata keys by default:
passwordsecretkeytokencredentialsThese values are hidden in the UI but still transmitted to the server.
Always use HTTPS when transmitting sensitive metadata:
spring:
boot:
admin:
client:
url: https://admin-server.example.com # Use HTTPS