Commit 8bb578ad by Spencer Gibb

update ServerMetricCollector to include instance and statistic tags if present.

fixes gh-348
parent 3bb1562b
/*
* Copyright 2013-2015 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.cloud.netflix.servo;
import com.netflix.servo.Metric;
import com.netflix.servo.annotations.DataSourceType;
import com.netflix.servo.monitor.MonitorConfig;
import com.netflix.servo.tag.Tag;
import com.netflix.servo.tag.TagList;
/**
* @author Spencer Gibb
*/
public class DefaultServoMetricNaming implements ServoMetricNaming {
private static final String JMX_DOMAIN_KEY = "JmxDomain";
public static final String SERVO = "servo.";
@Override
public String getName(Metric metric) {
MonitorConfig config = metric.getConfig();
TagList tags = config.getTags();
Tag domainTag = tags.getTag(JMX_DOMAIN_KEY);
String name;
if (domainTag != null) { // jmx metric
name = handleJmxMetric(config, tags);
}
else {
name = handleMetric(config, tags);
}
return name.toLowerCase();
}
private String handleMetric(MonitorConfig config, TagList tags) {
String type = cleanValue(tags.getTag(DataSourceType.KEY), false);
String instanceName = cleanValue(tags.getTag("instance"), false);
String name = cleanupIllegalCharacters(config.getName(), false);
String statistic = cleanValue(tags.getTag("statistic"), false);
StringBuilder nameBuilder = new StringBuilder();
if (type != null) {
nameBuilder.append(type).append(".");
}
nameBuilder.append(SERVO);
if (instanceName != null) {
nameBuilder.append(instanceName).append(".");
}
if (name != null) {
nameBuilder.append(name).append(".");
}
if (statistic != null) {
nameBuilder.append(statistic).append(".");
}
// remove trailing "."
nameBuilder.deleteCharAt(nameBuilder.lastIndexOf("."));
return nameBuilder.toString();
}
private String handleJmxMetric(MonitorConfig config, TagList tags) {
String domain = cleanValue(tags.getTag(JMX_DOMAIN_KEY), true);
String type = cleanValue(tags.getTag("Jmx.type"), false);
String instanceName = cleanValue(tags.getTag("Jmx.instance"), false);
String name = cleanValue(tags.getTag("Jmx.name"), false);
String fieldName = cleanupIllegalCharacters(config.getName(), false);
StringBuilder nameBuilder = new StringBuilder();
nameBuilder.append(domain).append(".");
if (type != null) {
nameBuilder.append(type).append(".");
}
nameBuilder.append(SERVO);
if (instanceName != null) {
nameBuilder.append(instanceName).append(".");
}
if (name != null) {
nameBuilder.append(name).append(".");
}
if (fieldName != null) {
nameBuilder.append(fieldName).append(".");
}
// remove trailing "."
nameBuilder.deleteCharAt(nameBuilder.lastIndexOf("."));
return nameBuilder.toString();
}
private String cleanValue(Tag tag, boolean allowPeriodsInName) {
if (tag == null) {
return null;
}
return cleanupIllegalCharacters(tag.getValue(), allowPeriodsInName);
}
private String cleanupIllegalCharacters(String s, boolean allowPeriodsInName) {
if (!allowPeriodsInName) {
s = s.replace(".", "_");
}
return s.replace(" ", "_");
}
}
......@@ -17,19 +17,15 @@
package org.springframework.cloud.netflix.servo;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;
import lombok.extern.apachecommons.CommonsLog;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.boot.actuate.metrics.Metric;
import org.springframework.boot.actuate.metrics.reader.MetricReader;
import org.springframework.boot.actuate.metrics.writer.MetricWriter;
import com.netflix.servo.monitor.MonitorConfig;
import com.netflix.servo.publish.BaseMetricObserver;
import com.netflix.servo.publish.BasicMetricFilter;
import com.netflix.servo.publish.MetricObserver;
import com.netflix.servo.publish.MonitorRegistryMetricPoller;
......@@ -46,9 +42,9 @@ import com.netflix.servo.publish.PollScheduler;
@CommonsLog
public class ServoMetricCollector implements DisposableBean {
public ServoMetricCollector(MetricWriter metrics) {
List<MetricObserver> observers = new ArrayList<MetricObserver>();
observers.add(new ServoMetricObserver(metrics));
public ServoMetricCollector(MetricWriter metrics, ServoMetricNaming naming) {
List<MetricObserver> observers = new ArrayList<>();
observers.add(new ServoMetricObserver(metrics, naming));
PollRunnable task = new PollRunnable(new MonitorRegistryMetricPoller(),
BasicMetricFilter.MATCH_ALL, true, observers);
......@@ -80,35 +76,4 @@ public class ServoMetricCollector implements DisposableBean {
}
}
/**
* {@link MetricObserver} to convert Servo metrics into Spring Boot {@link Metric}
* instances.
*/
private static final class ServoMetricObserver extends BaseMetricObserver {
private final MetricWriter metrics;
public ServoMetricObserver(MetricWriter metrics) {
super("spring-boot");
this.metrics = metrics;
}
@Override
public void updateImpl(List<com.netflix.servo.Metric> servoMetrics) {
for (com.netflix.servo.Metric servoMetric : servoMetrics) {
MonitorConfig config = servoMetric.getConfig();
String type = config.getTags().getValue("type");
String key = new StringBuilder(type).append(".servo.")
.append(config.getName()).toString().toLowerCase();
if (servoMetric.hasNumberValue()) {
this.metrics.set(new Metric<Number>(key,
servoMetric.getNumberValue(), new Date(servoMetric
.getTimestamp())));
}
}
}
}
}
/*
* Copyright 2013-2015 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.cloud.netflix.servo;
import com.netflix.servo.Metric;
/**
* @author Spencer Gibb
*/
public interface ServoMetricNaming {
String getName(Metric metric);
}
/*
* Copyright 2013-2015 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.cloud.netflix.servo;
import com.netflix.servo.Metric;
import com.netflix.servo.publish.BaseMetricObserver;
import org.springframework.boot.actuate.metrics.writer.MetricWriter;
import java.util.Date;
import java.util.List;
/**
* {@link com.netflix.servo.publish.MetricObserver} to convert Servo metrics into Spring Boot {@link org.springframework.boot.actuate.metrics.Metric}
* instances.
*/
final class ServoMetricObserver extends BaseMetricObserver {
private final MetricWriter metrics;
private final ServoMetricNaming naming;
public ServoMetricObserver(MetricWriter metrics, ServoMetricNaming naming) {
super("spring-boot");
this.metrics = metrics;
this.naming = naming;
}
@Override
public void updateImpl(List<Metric> servoMetrics) {
for (Metric servoMetric : servoMetrics) {
String key = naming.getName(servoMetric);
if (servoMetric.hasNumberValue()) {
this.metrics.set(new org.springframework.boot.actuate.metrics.Metric<>(key,
servoMetric.getNumberValue(), new Date(servoMetric
.getTimestamp())));
}
}
}
}
......@@ -45,8 +45,15 @@ public class ServoMetricsAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public ServoMetricCollector servoMetricCollector(MetricWriter metrics) {
return new ServoMetricCollector(metrics);
public ServoMetricNaming servoMetricNaming() {
return new DefaultServoMetricNaming();
}
@Bean
@ConditionalOnMissingBean
public ServoMetricCollector servoMetricCollector(MetricWriter metrics,
ServoMetricNaming naming) {
return new ServoMetricCollector(metrics, naming);
}
}
/*
* Copyright 2013-2015 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.cloud.netflix.servo;
import static org.junit.Assert.*;
import static org.hamcrest.Matchers.*;
import com.netflix.servo.annotations.DataSourceType;
import com.netflix.servo.monitor.MonitorConfig;
import org.junit.Test;
import com.netflix.servo.Metric;
/**
* @author Spencer Gibb
*/
public class DefaultServerMetricNamingTests {
private DefaultServoMetricNaming naming = new DefaultServoMetricNaming();
@Test
public void vanillaServoMetricWorks() {
MonitorConfig config = MonitorConfig.builder("testMetric") .build();
String name = naming.getName(new Metric(config, System.currentTimeMillis(), 0));
assertThat(name, is(equalTo("servo.testmetric")));
}
@Test
public void typeTagWorks() {
MonitorConfig config = MonitorConfig.builder("testMetric")
.withTag(DataSourceType.KEY, DataSourceType.COUNTER.getValue())
.build();
String name = naming.getName(new Metric(config, System.currentTimeMillis(), 0));
assertThat(name, is(equalTo("counter.servo.testmetric")));
}
@Test
public void instanceTagWorks() {
MonitorConfig config = MonitorConfig.builder("testMetric")
.withTag("instance", "instance0")
.build();
String name = naming.getName(new Metric(config, System.currentTimeMillis(), 0));
assertThat(name, is(equalTo("servo.instance0.testmetric")));
}
@Test
public void statisticTagWorks() {
MonitorConfig config = MonitorConfig.builder("testMetric")
.withTag("statistic", "min")
.build();
String name = naming.getName(new Metric(config, System.currentTimeMillis(), 0));
assertThat(name, is(equalTo("servo.testmetric.min")));
}
@Test
public void allTagsWork() {
MonitorConfig config = MonitorConfig.builder("testMetric")
.withTag(DataSourceType.KEY, DataSourceType.COUNTER.getValue())
.withTag("instance", "instance0")
.withTag("statistic", "min")
.build();
String name = naming.getName(new Metric(config, System.currentTimeMillis(), 0));
assertThat(name, is(equalTo("counter.servo.instance0.testmetric.min")));
}
}
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