
com.netflix.spectator.jvm.JmxMeasurementConfig Maven / Gradle / Ivy
The newest version!
/*
* Copyright 2014-2019 Netflix, Inc.
*
* 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 com.netflix.spectator.jvm;
import com.netflix.spectator.api.Id;
import com.netflix.spectator.api.Registry;
import com.typesafe.config.Config;
import javax.management.ObjectName;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;
import java.util.stream.Collectors;
/**
* Config for extracting a measurment from a JMX bean.
*
*
* - name: name pattern to use, see {@link MappingExpr#substitute(String, Map)}
* - tags: tags to add on, values can use patterns,
* see {@link MappingExpr#substitute(String, Map)}
* - value: value expression, see {@link MappingExpr#eval(String, Map)}
* - counter: is the value a monotonically increasing counter value?
*
*/
final class JmxMeasurementConfig {
/** Create from a Typesafe Config object. */
static JmxMeasurementConfig from(Config config) {
String name = config.getString("name");
Map tags = config.getConfigList("tags")
.stream()
.collect(Collectors.toMap(c -> c.getString("key"), c -> c.getString("value")));
String value = config.getString("value");
boolean counter = config.hasPath("counter") && config.getBoolean("counter");
return new JmxMeasurementConfig(name, tags, value, counter);
}
private final String nameMapping;
private final Map tagMappings;
private final String valueMapping;
private final boolean counter;
private final Map previousData;
private final Map previousCount;
/** Create a new instance. */
JmxMeasurementConfig(
String nameMapping,
Map tagMappings,
String valueMapping,
boolean counter) {
this.nameMapping = nameMapping;
this.tagMappings = tagMappings;
this.valueMapping = valueMapping;
this.counter = counter;
this.previousData = new ConcurrentHashMap<>();
this.previousCount = new ConcurrentHashMap<>();
}
/**
* Fill in {@code ms} with measurements extracted from {@code data}.
*/
void measure(Registry registry, JmxData data) {
Map tags = tagMappings.entrySet().stream().collect(Collectors.toMap(
Map.Entry::getKey,
e -> MappingExpr.substitute(e.getValue(), data.getStringAttrs())
));
Id id = registry
.createId(MappingExpr.substitute(nameMapping, data.getStringAttrs()))
.withTags(tags);
Map numberAttrs = new HashMap<>(data.getNumberAttrs());
JmxData previous = previousData.put(data.getName(), data);
if (previous != null) {
previous.getNumberAttrs().forEach((key, value) -> numberAttrs.put("previous:" + key, value));
}
Double v = MappingExpr.eval(valueMapping, numberAttrs);
if (v != null && !v.isNaN()) {
if (counter) {
updateCounter(registry, id, v.longValue());
} else {
registry.gauge(id).set(v);
}
}
}
private void updateCounter(Registry registry, Id id, long v) {
AtomicLong prev = previousCount.computeIfAbsent(id, i -> new AtomicLong(Long.MIN_VALUE));
long p = prev.get();
if (prev.compareAndSet(p, v) && p != Long.MIN_VALUE) {
registry.counter(id).increment(v - p);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy