Commit 2be6b3e4 authored by Stephane Nicoll's avatar Stephane Nicoll

Flexible registration of additional PublicMetrics

This commit permits the use of several PublicMetrics instances by
default. Previously, only one PublicMetrics service could be specified
and a user configuration would remove all the defaulting.

VanillaPublicMetrics now takes a collection of PublicMetrics and
invokes them in sequence to build the final collection of metrics.
The system-related metrics have been moved to SystemPublicMetrics and
are registered by default.

Also updated the documentation to mention this feature and how it
could be fully overridden.

Fixes gh-1094
parent 99971a65
......@@ -16,6 +16,7 @@
package org.springframework.boot.actuate.autoconfigure;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
......@@ -35,6 +36,7 @@ import org.springframework.boot.actuate.endpoint.MetricsEndpoint;
import org.springframework.boot.actuate.endpoint.PublicMetrics;
import org.springframework.boot.actuate.endpoint.RequestMappingEndpoint;
import org.springframework.boot.actuate.endpoint.ShutdownEndpoint;
import org.springframework.boot.actuate.endpoint.SystemPublicMetrics;
import org.springframework.boot.actuate.endpoint.TraceEndpoint;
import org.springframework.boot.actuate.endpoint.VanillaPublicMetrics;
import org.springframework.boot.actuate.health.HealthAggregator;
......@@ -68,6 +70,7 @@ import org.springframework.web.servlet.handler.AbstractHandlerMethodMapping;
* @author Phillip Webb
* @author Greg Turnquist
* @author Christian Dupuis
* @author Stephane Nicoll
*/
@Configuration
public class EndpointAutoConfiguration {
......@@ -85,7 +88,7 @@ public class EndpointAutoConfiguration {
private MetricReader metricRepository = new InMemoryMetricRepository();
@Autowired(required = false)
private PublicMetrics metrics;
private Collection<PublicMetrics> allMetrics;
@Autowired(required = false)
private TraceRepository traceRepository = new InMemoryTraceRepository();
......@@ -126,10 +129,8 @@ public class EndpointAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public MetricsEndpoint metricsEndpoint() {
if (this.metrics == null) {
this.metrics = new VanillaPublicMetrics(this.metricRepository);
}
return new MetricsEndpoint(this.metrics);
PublicMetrics metrics = new VanillaPublicMetrics(this.metricRepository, this.allMetrics);
return new MetricsEndpoint(metrics);
}
@Bean
......@@ -178,6 +179,16 @@ public class EndpointAutoConfiguration {
return endpoint;
}
@Configuration
protected static class CorePublicMetrics {
@Bean
SystemPublicMetrics systemPublicMetrics() {
return new SystemPublicMetrics();
}
}
@Configuration
protected static class InfoPropertiesConfiguration {
......
......@@ -25,6 +25,7 @@ import org.springframework.boot.actuate.metrics.Metric;
*
* @author Dave Syer
* @see VanillaPublicMetrics
* @see SystemPublicMetrics
*/
public interface PublicMetrics {
......
/*
* Copyright 2012-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.actuate.endpoint;
import java.lang.management.ClassLoadingMXBean;
import java.lang.management.GarbageCollectorMXBean;
import java.lang.management.ManagementFactory;
import java.lang.management.MemoryUsage;
import java.lang.management.ThreadMXBean;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.List;
import org.springframework.boot.actuate.metrics.Metric;
import org.springframework.util.StringUtils;
/**
* A {@link PublicMetrics} implementation that provides various
* system-related metrics.
*
* @author Dave Syer
* @author Stephane Nicoll
* @since 1.2.0
*/
public class SystemPublicMetrics implements PublicMetrics {
private long timestamp;
public SystemPublicMetrics() {
this.timestamp = System.currentTimeMillis();
}
@Override
public Collection<Metric<?>> metrics() {
Collection<Metric<?>> result = new LinkedHashSet<Metric<?>>();
addBasicMetrics(result);
addHeapMetrics(result);
addThreadMetrics(result);
addClassLoadingMetrics(result);
addGarbageCollectionMetrics(result);
return result;
}
/**
* Add basic system metrics.
*/
protected void addBasicMetrics(Collection<Metric<?>> result) {
result.add(new Metric<Long>("mem",
Runtime.getRuntime().totalMemory() / 1024));
result.add(new Metric<Long>("mem.free", Runtime.getRuntime()
.freeMemory() / 1024));
result.add(new Metric<Integer>("processors", Runtime.getRuntime()
.availableProcessors()));
// Add JVM up time in ms
result.add(new Metric<Long>("uptime", ManagementFactory
.getRuntimeMXBean().getUptime()));
result.add(new Metric<Long>("instance.uptime", System.currentTimeMillis()
- this.timestamp));
}
/**
* Add JVM heap metrics.
*/
protected void addHeapMetrics(Collection<Metric<?>> result) {
MemoryUsage memoryUsage = ManagementFactory.getMemoryMXBean()
.getHeapMemoryUsage();
result.add(new Metric<Long>("heap.committed", memoryUsage.getCommitted() / 1024));
result.add(new Metric<Long>("heap.init", memoryUsage.getInit() / 1024));
result.add(new Metric<Long>("heap.used", memoryUsage.getUsed() / 1024));
result.add(new Metric<Long>("heap", memoryUsage.getMax() / 1024));
}
/**
* Add thread metrics.
*/
protected void addThreadMetrics(Collection<Metric<?>> result) {
ThreadMXBean threadMxBean = ManagementFactory.getThreadMXBean();
result.add(new Metric<Long>("threads.peak", (long) threadMxBean
.getPeakThreadCount()));
result.add(new Metric<Long>("threads.daemon", (long) threadMxBean
.getDaemonThreadCount()));
result.add(new Metric<Long>("threads", (long) threadMxBean.getThreadCount()));
}
/**
* Add class loading metrics.
*/
protected void addClassLoadingMetrics(Collection<Metric<?>> result) {
ClassLoadingMXBean classLoadingMxBean = ManagementFactory.getClassLoadingMXBean();
result.add(new Metric<Long>("classes", (long) classLoadingMxBean
.getLoadedClassCount()));
result.add(new Metric<Long>("classes.loaded", classLoadingMxBean
.getTotalLoadedClassCount()));
result.add(new Metric<Long>("classes.unloaded", classLoadingMxBean
.getUnloadedClassCount()));
}
/**
* Add garbage collection metrics.
*/
protected void addGarbageCollectionMetrics(Collection<Metric<?>> result) {
List<GarbageCollectorMXBean> garbageCollectorMxBeans = ManagementFactory
.getGarbageCollectorMXBeans();
for (GarbageCollectorMXBean garbageCollectorMXBean : garbageCollectorMxBeans) {
String name = beautifyGcName(garbageCollectorMXBean.getName());
result.add(new Metric<Long>("gc." + name + ".count", garbageCollectorMXBean.getCollectionCount()));
result.add(new Metric<Long>("gc." + name + ".time", garbageCollectorMXBean.getCollectionTime()));
}
}
/**
* Turn GC names like 'PS Scavenge' or 'PS MarkSweep' into something that is more
* metrics friendly.
*/
private String beautifyGcName(String name) {
return StringUtils.replace(name, " ", "_").toLowerCase();
}
}
......@@ -16,36 +16,37 @@
package org.springframework.boot.actuate.endpoint;
import java.lang.management.ClassLoadingMXBean;
import java.lang.management.GarbageCollectorMXBean;
import java.lang.management.ManagementFactory;
import java.lang.management.MemoryUsage;
import java.lang.management.ThreadMXBean;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
import org.springframework.boot.actuate.metrics.Metric;
import org.springframework.boot.actuate.metrics.reader.MetricReader;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
/**
* Default implementation of {@link PublicMetrics} that exposes all metrics from a
* {@link MetricReader} along with memory information.
* {@link MetricReader} along with a collection of configurable {@link PublicMetrics}
* instances.
*
* @author Dave Syer
* @author Christian Dupuis
* @author Stephane Nicoll
*/
public class VanillaPublicMetrics implements PublicMetrics {
private final MetricReader reader;
private long timestamp;
private final Collection<PublicMetrics> publicMetrics;
public VanillaPublicMetrics(MetricReader reader) {
public VanillaPublicMetrics(MetricReader reader, Collection<PublicMetrics> publicMetrics) {
Assert.notNull(reader, "MetricReader must not be null");
Assert.notNull(publicMetrics, "PublicMetrics must not be null");
this.reader = reader;
this.timestamp = System.currentTimeMillis();
this.publicMetrics = publicMetrics;
}
public VanillaPublicMetrics(MetricReader reader) {
this(reader, Collections.<PublicMetrics>emptyList());
}
@Override
......@@ -54,92 +55,11 @@ public class VanillaPublicMetrics implements PublicMetrics {
for (Metric<?> metric : this.reader.findAll()) {
result.add(metric);
}
addMetrics(result);
addHeapMetrics(result);
addThreadMetrics(result);
addClassLoadingMetrics(result);
addGarbageCollecitonMetrics(result);
for (PublicMetrics publicMetric : publicMetrics) {
result.addAll(publicMetric.metrics());
}
return result;
}
/**
* Add basic system metrics.
*/
protected void addMetrics(Collection<Metric<?>> result) {
result.add(new Metric<Long>("mem",
new Long(Runtime.getRuntime().totalMemory()) / 1024));
result.add(new Metric<Long>("mem.free", new Long(Runtime.getRuntime()
.freeMemory()) / 1024));
result.add(new Metric<Integer>("processors", Runtime.getRuntime()
.availableProcessors()));
// Add JVM uptime in ms
result.add(new Metric<Long>("uptime", new Long(ManagementFactory
.getRuntimeMXBean().getUptime())));
result.add(new Metric<Long>("instance.uptime", System.currentTimeMillis()
- this.timestamp));
}
/**
* Add JVM heap metrics.
*/
protected void addHeapMetrics(Collection<Metric<?>> result) {
MemoryUsage memoryUsage = ManagementFactory.getMemoryMXBean()
.getHeapMemoryUsage();
result.add(new Metric<Long>("heap.committed", memoryUsage.getCommitted() / 1024));
result.add(new Metric<Long>("heap.init", memoryUsage.getInit() / 1024));
result.add(new Metric<Long>("heap.used", memoryUsage.getUsed() / 1024));
result.add(new Metric<Long>("heap", memoryUsage.getMax() / 1024));
}
/**
* Add thread metrics.
*/
protected void addThreadMetrics(Collection<Metric<?>> result) {
ThreadMXBean threadMxBean = ManagementFactory.getThreadMXBean();
result.add(new Metric<Long>("threads.peak", new Long(threadMxBean
.getPeakThreadCount())));
result.add(new Metric<Long>("threads.daemon", new Long(threadMxBean
.getDaemonThreadCount())));
result.add(new Metric<Long>("threads", new Long(threadMxBean.getThreadCount())));
}
/**
* Add class loading metrics.
*/
protected void addClassLoadingMetrics(Collection<Metric<?>> result) {
ClassLoadingMXBean classLoadingMxBean = ManagementFactory.getClassLoadingMXBean();
result.add(new Metric<Long>("classes", new Long(classLoadingMxBean
.getLoadedClassCount())));
result.add(new Metric<Long>("classes.loaded", new Long(classLoadingMxBean
.getTotalLoadedClassCount())));
result.add(new Metric<Long>("classes.unloaded", new Long(classLoadingMxBean
.getUnloadedClassCount())));
}
/**
* Add garbage collection metrics.
*/
protected void addGarbageCollecitonMetrics(Collection<Metric<?>> result) {
List<GarbageCollectorMXBean> garbageCollectorMxBeans = ManagementFactory
.getGarbageCollectorMXBeans();
for (int i = 0; i < garbageCollectorMxBeans.size(); i++) {
GarbageCollectorMXBean garbageCollectorMXBean = garbageCollectorMxBeans
.get(i);
String name = beautifyGcName(garbageCollectorMXBean.getName());
result.add(new Metric<Long>("gc." + name + ".count", new Long(
garbageCollectorMXBean.getCollectionCount())));
result.add(new Metric<Long>("gc." + name + ".time", new Long(
garbageCollectorMXBean.getCollectionTime())));
}
}
/**
* Turn GC names like 'PS Scavenge' or 'PS MarkSweep' into something that is more
* metrics friendly.
*/
private String beautifyGcName(String name) {
return StringUtils.replace(name, " ", "_").toLowerCase();
}
}
......@@ -17,7 +17,6 @@
package org.springframework.boot.actuate.autoconfigure;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.boot.actuate.endpoint.AutoConfigurationReportEndpoint;
import org.springframework.boot.actuate.endpoint.BeansEndpoint;
......@@ -26,20 +25,28 @@ import org.springframework.boot.actuate.endpoint.EnvironmentEndpoint;
import org.springframework.boot.actuate.endpoint.HealthEndpoint;
import org.springframework.boot.actuate.endpoint.InfoEndpoint;
import org.springframework.boot.actuate.endpoint.MetricsEndpoint;
import org.springframework.boot.actuate.endpoint.PublicMetrics;
import org.springframework.boot.actuate.endpoint.RequestMappingEndpoint;
import org.springframework.boot.actuate.endpoint.ShutdownEndpoint;
import org.springframework.boot.actuate.endpoint.TraceEndpoint;
import org.springframework.boot.actuate.health.Health;
import org.springframework.boot.actuate.metrics.Metric;
import org.springframework.boot.autoconfigure.condition.ConditionEvaluationReport;
import org.springframework.boot.autoconfigure.jdbc.EmbeddedDataSourceConfiguration;
import org.springframework.boot.test.EnvironmentTestUtils;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
/**
* Tests for {@link EndpointAutoConfiguration}.
*
......@@ -47,18 +54,12 @@ import static org.junit.Assert.assertTrue;
* @author Phillip Webb
* @author Greg Turnquist
* @author Christian Dupuis
* @author Stephane Nicoll
*/
public class EndpointAutoConfigurationTests {
private AnnotationConfigApplicationContext context;
@Before
public void setup() {
this.context = new AnnotationConfigApplicationContext();
this.context.register(EndpointAutoConfiguration.class);
this.context.refresh();
}
@After
public void close() {
if (this.context != null) {
......@@ -68,6 +69,7 @@ public class EndpointAutoConfigurationTests {
@Test
public void endpoints() throws Exception {
load(EndpointAutoConfiguration.class);
assertNotNull(this.context.getBean(BeansEndpoint.class));
assertNotNull(this.context.getBean(DumpEndpoint.class));
assertNotNull(this.context.getBean(EnvironmentEndpoint.class));
......@@ -81,10 +83,8 @@ public class EndpointAutoConfigurationTests {
@Test
public void healthEndpoint() {
this.context = new AnnotationConfigApplicationContext();
this.context.register(EmbeddedDataSourceConfiguration.class,
load(EmbeddedDataSourceConfiguration.class,
EndpointAutoConfiguration.class, HealthIndicatorAutoConfiguration.class);
this.context.refresh();
HealthEndpoint bean = this.context.getBean(HealthEndpoint.class);
assertNotNull(bean);
Health result = bean.invoke();
......@@ -94,10 +94,8 @@ public class EndpointAutoConfigurationTests {
@Test
public void healthEndpointWithDefaultHealthIndicator() {
this.context = new AnnotationConfigApplicationContext();
this.context.register(EndpointAutoConfiguration.class,
load(EndpointAutoConfiguration.class,
HealthIndicatorAutoConfiguration.class);
this.context.refresh();
HealthEndpoint bean = this.context.getBean(HealthEndpoint.class);
assertNotNull(bean);
Health result = bean.invoke();
......@@ -105,11 +103,33 @@ public class EndpointAutoConfigurationTests {
}
@Test
public void autoconfigurationAuditEndpoints() {
this.context = new AnnotationConfigApplicationContext();
this.context.register(EndpointAutoConfiguration.class,
public void metricEndpointsHasSystemMetricsByDefault() {
load(EndpointAutoConfiguration.class);
MetricsEndpoint endpoint = this.context.getBean(MetricsEndpoint.class);
Map<String, Object> metrics = endpoint.invoke();
assertTrue(metrics.containsKey("mem"));
assertTrue(metrics.containsKey("heap.used"));
}
@Test
public void metricEndpointCustomPublicMetrics() {
load(CustomPublicMetricsConfig.class, EndpointAutoConfiguration.class);
MetricsEndpoint endpoint = this.context.getBean(MetricsEndpoint.class);
Map<String, Object> metrics = endpoint.invoke();
// Custom metrics
assertTrue(metrics.containsKey("foo"));
// System metrics still available
assertTrue(metrics.containsKey("mem"));
assertTrue(metrics.containsKey("heap.used"));
}
@Test
public void autoConfigurationAuditEndpoints() {
load(EndpointAutoConfiguration.class,
ConditionEvaluationReport.class);
this.context.refresh();
assertNotNull(this.context.getBean(AutoConfigurationReportEndpoint.class));
}
......@@ -136,4 +156,25 @@ public class EndpointAutoConfigurationTests {
assertNotNull(endpoint);
assertNull(endpoint.invoke().get("git"));
}
private void load(Class<?>... config) {
this.context = new AnnotationConfigApplicationContext();
this.context.register(config);
this.context.refresh();
}
@Configuration
static class CustomPublicMetricsConfig {
@Bean
PublicMetrics customPublicMetrics() {
return new PublicMetrics() {
@Override
public Collection<Metric<?>> metrics() {
return Collections.<Metric<?>>singleton(new Metric<Integer>("foo", 1));
}
};
}
}
}
/*
* Copyright 2012-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.actuate.endpoint;
import static org.junit.Assert.*;
import java.util.HashMap;
import java.util.Map;
import org.junit.Test;
import org.springframework.boot.actuate.metrics.Metric;
/**
* Tests for {@link SystemPublicMetrics}
*
* @author Stephane Nicoll
*/
public class SystemPublicMetricsTests {
@Test
public void testSystemMetrics() throws Exception {
SystemPublicMetrics publicMetrics = new SystemPublicMetrics();
Map<String, Metric<?>> results = new HashMap<String, Metric<?>>();
for (Metric<?> metric : publicMetrics.metrics()) {
results.put(metric.getName(), metric);
}
assertTrue(results.containsKey("mem"));
assertTrue(results.containsKey("mem.free"));
assertTrue(results.containsKey("processors"));
assertTrue(results.containsKey("uptime"));
assertTrue(results.containsKey("heap.committed"));
assertTrue(results.containsKey("heap.init"));
assertTrue(results.containsKey("heap.used"));
assertTrue(results.containsKey("heap"));
assertTrue(results.containsKey("threads.peak"));
assertTrue(results.containsKey("threads.daemon"));
assertTrue(results.containsKey("threads"));
assertTrue(results.containsKey("classes.loaded"));
assertTrue(results.containsKey("classes.unloaded"));
assertTrue(results.containsKey("classes"));
}
}
......@@ -16,8 +16,12 @@
package org.springframework.boot.actuate.endpoint;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.Map;
import org.junit.Test;
......@@ -25,14 +29,14 @@ import org.springframework.boot.actuate.metrics.Metric;
import org.springframework.boot.actuate.metrics.repository.InMemoryMetricRepository;
import static org.hamcrest.Matchers.equalTo;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.*;
/**
* Tests for {@link VanillaPublicMetrics}.
*
* @author Phillip Webb
* @author Christian Dupuis
* @author Stephane Nicoll
*/
public class VanillaPublicMetricsTests {
......@@ -45,36 +49,38 @@ public class VanillaPublicMetricsTests {
for (Metric<?> metric : publicMetrics.metrics()) {
results.put(metric.getName(), metric);
}
assertTrue(results.containsKey("mem"));
assertTrue(results.containsKey("mem.free"));
assertThat(results.get("a").getValue().doubleValue(), equalTo(0.5));
}
@Test
public void testSystemMetrics() throws Exception {
public void testAdditionalMetrics() throws Exception {
InMemoryMetricRepository repository = new InMemoryMetricRepository();
repository.set(new Metric<Double>("a", 0.5, new Date()));
VanillaPublicMetrics publicMetrics = new VanillaPublicMetrics(repository);
Collection<PublicMetrics> allMetrics = new ArrayList<PublicMetrics>();
allMetrics.add(new ImmutablePublicMetrics(new Metric<Number>("first", 2L)));
allMetrics.add(new ImmutablePublicMetrics(new Metric<Number>("second", 4L)));
VanillaPublicMetrics publicMetrics = new VanillaPublicMetrics(repository, allMetrics);
Map<String, Metric<?>> results = new HashMap<String, Metric<?>>();
for (Metric<?> metric : publicMetrics.metrics()) {
results.put(metric.getName(), metric);
}
assertTrue(results.containsKey("mem"));
assertTrue(results.containsKey("mem.free"));
assertTrue(results.containsKey("processors"));
assertTrue(results.containsKey("uptime"));
assertTrue(results.containsKey("first"));
assertTrue(results.containsKey("second"));
assertEquals(2, results.size());
}
assertTrue(results.containsKey("heap.committed"));
assertTrue(results.containsKey("heap.init"));
assertTrue(results.containsKey("heap.used"));
assertTrue(results.containsKey("heap"));
assertTrue(results.containsKey("threads.peak"));
assertTrue(results.containsKey("threads.daemon"));
assertTrue(results.containsKey("threads"));
private static class ImmutablePublicMetrics implements PublicMetrics {
private final Collection<Metric<?>> metrics;
assertTrue(results.containsKey("classes.loaded"));
assertTrue(results.containsKey("classes.unloaded"));
assertTrue(results.containsKey("classes"));
private ImmutablePublicMetrics(Metric<?> metrics) {
this.metrics = new LinkedHashSet<Metric<?>>();
this.metrics.addAll(Arrays.asList(metrics));
}
@Override
public Collection<Metric<?>> metrics() {
return metrics;
}
}
}
......@@ -583,8 +583,14 @@ documentation].
== Metrics
Spring Boot Actuator includes a metrics service with ``gauge'' and ``counter'' support.
A ``gauge'' records a single value; and a ``counter'' records a delta (an increment or
decrement). Metrics for all HTTP requests are automatically recorded, so if you hit the
`metrics` endpoint should should see a response similar to this:
decrement). Spring Boot Actuator also provides a
{sc-spring-boot-actuator}/endpoint/PublicMetrics.{sc-ext}[`PublicMetrics`] interface that
you can implement to expose metrics that you cannot record via one of those two mechanisms. Look
at {sc-spring-boot-actuator}/endpoint/SystemPublicMetrics.{sc-ext}[`SystemPublicMetrics`]
for an example.
Metrics for all HTTP requests are automatically recorded, so if you hit the
`metrics` endpoint you should see a response similar to this:
[source,json,indent=0]
----
......@@ -612,9 +618,10 @@ decrement). Metrics for all HTTP requests are automatically recorded, so if you
----
Here we can see basic `memory`, `heap`, `class loading`, `processor` and `thread pool`
information along with some HTTP metrics. In this instance the `root` (``/'') and `/metrics`
URLs have returned `HTTP 200` responses `20` and `3` times respectively. It also appears
that the `root` URL returned `HTTP 401` (unauthorized) `4` times.
information provided by `SystemPublicMetrics` along with some HTTP metrics. In this
instance the `root` (``/'') and `/metrics` URLs have returned `HTTP 200` responses `20`
and `3` times respectively. It also appears that the `root` URL returned `HTTP 401`
(unauthorized) `4` times.
The `gauge` shows the last response time for a request. So the last request to `root` took
`2ms` to respond and the last to `/metrics` took `3ms`.
......@@ -661,6 +668,13 @@ TIP: You can use any string as a metric name but you should follow guidelines of
store/graphing technology. Some good guidelines for Graphite are available on
http://matt.aimonetti.net/posts/2013/06/26/practical-guide-to-graphite-monitoring/[Matt Aimonetti's Blog].
[[production-ready-public-metrics]]
=== Adding your own public metrics
To add additional metrics that are computed every time the metrics endpoint is invoked,
simply register additional `PublicMetrics` implementation bean(s). By default, all such
beans are gathered by the endpoint. You can easily change that by defining your own
`MetricsEndpoint`.
[[production-ready-metric-repositories]]
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment