Updates to redis repositories
* Ensure prefix ends with period * Allow prefix and key index to be set separately
This commit is contained in:
@@ -22,8 +22,6 @@ import javax.servlet.Filter;
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.Servlet;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
@@ -39,7 +37,7 @@ import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.util.StopWatch;
|
||||
import org.springframework.web.filter.GenericFilterBean;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
import org.springframework.web.util.UrlPathHelper;
|
||||
|
||||
/**
|
||||
@@ -72,23 +70,20 @@ public class MetricFilterAutoConfiguration {
|
||||
* Filter that counts requests and measures processing times.
|
||||
*/
|
||||
@Order(Ordered.HIGHEST_PRECEDENCE)
|
||||
private final class MetricsFilter extends GenericFilterBean {
|
||||
private final class MetricsFilter extends OncePerRequestFilter {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.web.filter.OncePerRequestFilter#doFilterInternal(javax.
|
||||
* servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse,
|
||||
* javax.servlet.FilterChain)
|
||||
*/
|
||||
@Override
|
||||
public void doFilter(ServletRequest request, ServletResponse response,
|
||||
FilterChain chain) throws IOException, ServletException {
|
||||
if ((request instanceof HttpServletRequest)
|
||||
&& (response instanceof HttpServletResponse)) {
|
||||
doFilter((HttpServletRequest) request, (HttpServletResponse) response,
|
||||
chain);
|
||||
}
|
||||
else {
|
||||
chain.doFilter(request, response);
|
||||
}
|
||||
}
|
||||
|
||||
public void doFilter(HttpServletRequest request, HttpServletResponse response,
|
||||
FilterChain chain) throws IOException, ServletException {
|
||||
protected void doFilterInternal(HttpServletRequest request,
|
||||
HttpServletResponse response, FilterChain chain) throws ServletException,
|
||||
IOException {
|
||||
UrlPathHelper helper = new UrlPathHelper();
|
||||
String suffix = helper.getPathWithinApplication(request);
|
||||
StopWatch stopWatch = new StopWatch();
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright 2012-2013 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.metrics.reader;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.boot.actuate.metrics.Metric;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
*/
|
||||
public class CompositeMetricReader implements MetricReader {
|
||||
|
||||
private List<MetricReader> delegates = Collections.emptyList();
|
||||
|
||||
public void setDelegates(Collection<MetricReader> delegates) {
|
||||
this.delegates = new ArrayList<MetricReader>(delegates);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Metric<?> findOne(String metricName) {
|
||||
for (MetricReader delegate : this.delegates) {
|
||||
Metric<?> value = delegate.findOne(metricName);
|
||||
if (value != null) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<Metric<?>> findAll() {
|
||||
List<Metric<?>> values = new ArrayList<Metric<?>>((int) count());
|
||||
for (MetricReader delegate : this.delegates) {
|
||||
Iterable<Metric<?>> all = delegate.findAll();
|
||||
for (Metric<?> value : all) {
|
||||
values.add(value);
|
||||
}
|
||||
}
|
||||
return values;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long count() {
|
||||
long count = 0;
|
||||
for (MetricReader delegate : this.delegates) {
|
||||
count += delegate.count();
|
||||
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -45,9 +45,9 @@ public class RedisMetricRepository implements MetricRepository {
|
||||
|
||||
private String prefix = DEFAULT_METRICS_PREFIX;
|
||||
|
||||
private String keys = this.prefix + "keys";
|
||||
private String key = "keys." + DEFAULT_METRICS_PREFIX;
|
||||
|
||||
private final BoundZSetOperations<String, String> zSetOperations;
|
||||
private BoundZSetOperations<String, String> zSetOperations;
|
||||
|
||||
private final RedisOperations<String, String> redisOperations;
|
||||
|
||||
@@ -59,7 +59,7 @@ public class RedisMetricRepository implements MetricRepository {
|
||||
RedisTemplate<String, Long> longRedisTemplate = RedisUtils.createRedisTemplate(
|
||||
redisConnectionFactory, Long.class);
|
||||
this.longOperations = longRedisTemplate.opsForValue();
|
||||
this.zSetOperations = this.redisOperations.boundZSetOps(this.keys);
|
||||
this.zSetOperations = this.redisOperations.boundZSetOps(this.key);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -68,20 +68,30 @@ public class RedisMetricRepository implements MetricRepository {
|
||||
* @param prefix the prefix to set for all metrics keys
|
||||
*/
|
||||
public void setPrefix(String prefix) {
|
||||
if (!prefix.endsWith(".")) {
|
||||
prefix = prefix + ".";
|
||||
}
|
||||
this.prefix = prefix;
|
||||
this.keys = this.prefix + "keys";
|
||||
}
|
||||
|
||||
/**
|
||||
* The redis key to use to store the index of other keys. The redis store will hold a
|
||||
* zset under this key. Defaults to "keys.spring.metrics". REad operations, especially
|
||||
* {@link #findAll()} and {@link #count()}, will be much more efficient if the key is
|
||||
* unique to the {@link #setPrefix(String) prefix} of this repository.
|
||||
*
|
||||
* @param key the key to set
|
||||
*/
|
||||
public void setKey(String key) {
|
||||
this.key = key;
|
||||
this.zSetOperations = this.redisOperations.boundZSetOps(this.key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Metric<?> findOne(String metricName) {
|
||||
String redisKey = keyFor(metricName);
|
||||
String raw = this.redisOperations.opsForValue().get(redisKey);
|
||||
if (raw != null) {
|
||||
return deserialize(redisKey, raw);
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
return deserialize(redisKey, raw);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -94,7 +104,10 @@ public class RedisMetricRepository implements MetricRepository {
|
||||
List<Metric<?>> result = new ArrayList<Metric<?>>(keys.size());
|
||||
List<String> values = this.redisOperations.opsForValue().multiGet(keys);
|
||||
for (String v : values) {
|
||||
result.add(deserialize(keysIt.next(), v));
|
||||
Metric<?> value = deserialize(keysIt.next(), v);
|
||||
if (value != null) {
|
||||
result.add(value);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
||||
@@ -131,6 +144,9 @@ public class RedisMetricRepository implements MetricRepository {
|
||||
}
|
||||
|
||||
private Metric<?> deserialize(String redisKey, String v) {
|
||||
if (redisKey == null || v == null || !redisKey.startsWith(this.prefix)) {
|
||||
return null;
|
||||
}
|
||||
String[] vals = v.split("@");
|
||||
Double value = Double.valueOf(vals[0]);
|
||||
Date timestamp = vals.length > 1 ? new Date(Long.valueOf(vals[1])) : new Date();
|
||||
@@ -146,8 +162,6 @@ public class RedisMetricRepository implements MetricRepository {
|
||||
}
|
||||
|
||||
private String nameFor(String redisKey) {
|
||||
Assert.state(redisKey != null && redisKey.startsWith(this.prefix),
|
||||
"Invalid key does not start with prefix: " + redisKey);
|
||||
return redisKey.substring(this.prefix.length());
|
||||
}
|
||||
|
||||
|
||||
@@ -37,20 +37,23 @@ public class RedisMetricRepositoryTests {
|
||||
@Rule
|
||||
public RedisServer redis = RedisServer.running();
|
||||
private RedisMetricRepository repository;
|
||||
private String prefix;
|
||||
|
||||
@Before
|
||||
public void init() {
|
||||
this.repository = new RedisMetricRepository(this.redis.getResource());
|
||||
this.prefix = "spring.test." + System.currentTimeMillis();
|
||||
this.repository.setPrefix(this.prefix);
|
||||
}
|
||||
|
||||
@After
|
||||
public void clear() {
|
||||
assertNotNull(new StringRedisTemplate(this.redis.getResource()).opsForValue()
|
||||
.get("spring.metrics.foo"));
|
||||
.get(this.prefix + ".foo"));
|
||||
this.repository.reset("foo");
|
||||
this.repository.reset("bar");
|
||||
assertNull(new StringRedisTemplate(this.redis.getResource()).opsForValue().get(
|
||||
"spring.metrics.foo"));
|
||||
this.prefix + ".foo"));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -25,7 +25,6 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.redis.connection.PoolConfig;
|
||||
@@ -112,8 +111,13 @@ public class RedisAutoConfiguration {
|
||||
}
|
||||
}
|
||||
|
||||
@Bean(name = "org.springframework.autoconfigure.redis.RedisProperties")
|
||||
@ConditionalOnMissingBean
|
||||
public RedisProperties redisProperties() {
|
||||
return new RedisProperties();
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableConfigurationProperties(RedisProperties.class)
|
||||
protected static class RedisConfiguration {
|
||||
|
||||
@Autowired
|
||||
|
||||
Reference in New Issue
Block a user