NIFI-12483 Streamlined JMX Metrics Filtering Parameters

- Added bean name filter processing and added test cases

Signed-off-by: Pierre Villard <pierre.villard.fr@gmail.com>

This closes #8134.
This commit is contained in:
exceptionfactory 2023-12-06 14:30:41 -06:00 committed by Pierre Villard
parent 17a331b9e1
commit 5c1b0a1140
No known key found for this signature in database
GPG Key ID: F92A93B30C07C6D5
2 changed files with 48 additions and 9 deletions

View File

@ -20,40 +20,68 @@ import org.apache.nifi.web.api.dto.JmxMetricsResultDTO;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.Collections;
import java.util.Set;
import java.util.function.Predicate;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException; import java.util.regex.PatternSyntaxException;
import java.util.stream.Collectors; import java.util.stream.Collectors;
public class JmxMetricsFilter { public class JmxMetricsFilter {
private static final Logger LOGGER = LoggerFactory.getLogger(JmxMetricsFilter.class); private static final Logger LOGGER = LoggerFactory.getLogger(JmxMetricsFilter.class);
private final static String MATCH_NOTHING = "~^"; private static final String MATCH_NOTHING = "~^";
private final static String MATCH_ALL = ""; private static final String NAME_SEPARATOR = "\\|";
private static final String REPLACE_CHARACTERS = "[\\^$.*()]";
private static final String EMPTY = "";
private final Pattern allowedNameFilter; private final Pattern allowedNameFilter;
private final Pattern beanNameFilter; private final Set<String> beanNameFilters;
public JmxMetricsFilter(final String allowedNameFilter, final String beanNameFilter) { public JmxMetricsFilter(final String allowedNameFilter, final String beanNameFilter) {
this.allowedNameFilter = createPattern(allowedNameFilter, MATCH_NOTHING); this.allowedNameFilter = createPattern(allowedNameFilter);
this.beanNameFilter = createPattern(beanNameFilter, MATCH_ALL); this.beanNameFilters = createBeanNameFilters(beanNameFilter);
} }
private Pattern createPattern(final String filter, final String defaultValue) { private Pattern createPattern(final String filter) {
try { try {
if (filter == null || filter.isEmpty()) { if (filter == null || filter.isEmpty()) {
return Pattern.compile(defaultValue); return Pattern.compile(MATCH_NOTHING);
} else { } else {
return Pattern.compile(filter); return Pattern.compile(filter);
} }
} catch (PatternSyntaxException e) { } catch (PatternSyntaxException e) {
LOGGER.warn("Invalid JMX MBean filter pattern ignored [{}]", filter); LOGGER.warn("Invalid JMX MBean filter pattern ignored [{}]", filter);
return Pattern.compile(defaultValue); return Pattern.compile(MATCH_NOTHING);
}
}
private Set<String> createBeanNameFilters(final String filter) {
if (filter == null || filter.isEmpty()) {
return Collections.emptySet();
} else {
return Arrays.stream(
filter.split(NAME_SEPARATOR)).map(
name -> name.replaceAll(REPLACE_CHARACTERS, EMPTY)
)
.filter(Predicate.not(String::isBlank))
.collect(Collectors.toSet());
} }
} }
public Collection<JmxMetricsResultDTO> filter(final Collection<JmxMetricsResultDTO> results) { public Collection<JmxMetricsResultDTO> filter(final Collection<JmxMetricsResultDTO> results) {
return results.stream() return results.stream()
.filter(result -> allowedNameFilter.asPredicate().test(result.getBeanName())) .filter(result -> allowedNameFilter.asPredicate().test(result.getBeanName()))
.filter(result -> beanNameFilter.asPredicate().test(result.getBeanName())) .filter(result -> {
final boolean included;
if (beanNameFilters.isEmpty()) {
included = true;
} else {
final String beanName = result.getBeanName();
included = beanNameFilters.stream().anyMatch(beanName::contains);
}
return included;
})
.collect(Collectors.toList()); .collect(Collectors.toList());
} }
} }

View File

@ -35,6 +35,7 @@ class JmxMetricsFilterTest {
private static final String INVALID_REGEX = "("; private static final String INVALID_REGEX = "(";
private static final String TEST_BEAN_NAME_ONE = "testBean1"; private static final String TEST_BEAN_NAME_ONE = "testBean1";
private static final String TEST_BEAN_NAME_TWO = "testBean2"; private static final String TEST_BEAN_NAME_TWO = "testBean2";
private static final String BEGIN_END_PATTERN = "^test.*$";
private static final JmxMetricsResultDTO RESULT_ONE = new JmxMetricsResultDTO(TEST_BEAN_NAME_ONE, null, null); private static final JmxMetricsResultDTO RESULT_ONE = new JmxMetricsResultDTO(TEST_BEAN_NAME_ONE, null, null);
private static final JmxMetricsResultDTO RESULT_TWO = new JmxMetricsResultDTO(TEST_BEAN_NAME_TWO, null, null); private static final JmxMetricsResultDTO RESULT_TWO = new JmxMetricsResultDTO(TEST_BEAN_NAME_TWO, null, null);
private static List<JmxMetricsResultDTO> results; private static List<JmxMetricsResultDTO> results;
@ -56,6 +57,16 @@ class JmxMetricsFilterTest {
assertTrue(actual.containsAll(results)); assertTrue(actual.containsAll(results));
} }
@Test
public void testBeginEndPatternMatches() {
final JmxMetricsFilter metricsFilter = new JmxMetricsFilter(ALLOW_ALL_PATTERN, BEGIN_END_PATTERN);
final Collection<JmxMetricsResultDTO> actual = metricsFilter.filter(results);
assertEquals(actual.size(), 2);
assertTrue(actual.containsAll(results));
}
@Test @Test
public void testAllowedNameFiltersRemovesMBeanFromResult() { public void testAllowedNameFiltersRemovesMBeanFromResult() {
final JmxMetricsFilter metricsFilter = new JmxMetricsFilter(TEST_BEAN_NAME_ONE, EMPTY_STRING_PATTERN); final JmxMetricsFilter metricsFilter = new JmxMetricsFilter(TEST_BEAN_NAME_ONE, EMPTY_STRING_PATTERN);