/* * Copyright 2016 Google, 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.controllers.filter; import com.netflix.spectator.controllers.model.TestId; import com.netflix.spectator.controllers.model.TestMeter; import com.netflix.spectator.api.BasicTag; import com.netflix.spectator.api.Clock; import com.netflix.spectator.api.Id; import com.netflix.spectator.api.Measurement; import com.netflix.spectator.api.Meter; import com.netflix.spectator.api.Tag; import java.io.IOException; import java.util.Arrays; import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.regex.Pattern; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @RunWith(JUnit4.class) public class PrototypeMeasurementFilterTest { private long millis = 12345L; Clock clock = new Clock() { public long wallTime() { return millis; } public long monotonicTime() { return millis; } }; PrototypeMeasurementFilterSpecification spec; PrototypeMeasurementFilterSpecification.ValueFilterSpecification valueSpecAxBy; PrototypeMeasurementFilterSpecification.ValueFilterSpecification valueSpecAyBx; PrototypeMeasurementFilterSpecification.ValueFilterSpecification valueSpecAzBy; PrototypeMeasurementFilterSpecification.MeterFilterSpecification meterSpecA; PrototypeMeasurementFilterSpecification.MeterFilterSpecification meterSpecB; PrototypeMeasurementFilterSpecification.MeterFilterSpecification meterSpecC; PrototypeMeasurementFilterSpecification.MeterFilterSpecification meterSpecD; @Before public void setup() { List<PrototypeMeasurementFilterSpecification.TagFilterSpecification> tagsAxBy = Arrays.asList( new PrototypeMeasurementFilterSpecification.TagFilterSpecification("tagA", "X"), new PrototypeMeasurementFilterSpecification.TagFilterSpecification("tagB", "Y")); List<PrototypeMeasurementFilterSpecification.TagFilterSpecification> tagsAyBx = Arrays.asList( new PrototypeMeasurementFilterSpecification.TagFilterSpecification("tagA", "Y"), new PrototypeMeasurementFilterSpecification.TagFilterSpecification("tagB", "X")); List<PrototypeMeasurementFilterSpecification.TagFilterSpecification> tagsAzBy = Arrays.asList( new PrototypeMeasurementFilterSpecification.TagFilterSpecification("tagA", "Z"), new PrototypeMeasurementFilterSpecification.TagFilterSpecification("tagB", "Y")); valueSpecAxBy = new PrototypeMeasurementFilterSpecification.ValueFilterSpecification(); valueSpecAxBy.getTags().addAll(tagsAxBy); valueSpecAyBx = new PrototypeMeasurementFilterSpecification.ValueFilterSpecification(); valueSpecAyBx.getTags().addAll(tagsAyBx); valueSpecAzBy = new PrototypeMeasurementFilterSpecification.ValueFilterSpecification(); valueSpecAzBy.getTags().addAll(tagsAzBy); meterSpecA = new PrototypeMeasurementFilterSpecification.MeterFilterSpecification( Collections.singletonList(valueSpecAxBy)); meterSpecB = new PrototypeMeasurementFilterSpecification.MeterFilterSpecification( Collections.singletonList(valueSpecAyBx)); meterSpecC = new PrototypeMeasurementFilterSpecification.MeterFilterSpecification( Collections.singletonList(valueSpecAzBy)); meterSpecD = new PrototypeMeasurementFilterSpecification.MeterFilterSpecification( Arrays.asList(valueSpecAxBy, valueSpecAyBx)); } @Test public void testPatternFromSpec() { List<PrototypeMeasurementFilter.TagFilterPattern> tagPatterns = Arrays.asList( new PrototypeMeasurementFilter.TagFilterPattern(Pattern.compile("tagA"), Pattern.compile("X")), new PrototypeMeasurementFilter.TagFilterPattern(Pattern.compile("tagB"), Pattern.compile("Y"))); PrototypeMeasurementFilter.MeterFilterPattern meterPattern = new PrototypeMeasurementFilter.MeterFilterPattern("meterA", meterSpecA); Assert.assertEquals(meterPattern.getValues().size(), 1); Assert.assertEquals(meterPattern.getValues().get(0).getTags(), tagPatterns); } @Test public void testMetricToPatterns() { PrototypeMeasurementFilterSpecification spec = new PrototypeMeasurementFilterSpecification(); spec.getInclude().put("meterA", meterSpecA); spec.getInclude().put(".+B", meterSpecB); spec.getInclude().put(".+C.*", meterSpecC); PrototypeMeasurementFilter filter = new PrototypeMeasurementFilter(spec); PrototypeMeasurementFilter.MeterFilterPattern meterPatternA = new PrototypeMeasurementFilter.MeterFilterPattern("meterA", meterSpecA); PrototypeMeasurementFilter.MeterFilterPattern meterPatternC = new PrototypeMeasurementFilter.MeterFilterPattern(".+C.*", meterSpecC); final List<PrototypeMeasurementFilter.ValueFilterPattern> emptyList = new ArrayList<PrototypeMeasurementFilter.ValueFilterPattern>(); Assert.assertEquals( filter.metricToPatterns("meterA"), new PrototypeMeasurementFilter.IncludeExcludePatterns( meterPatternA.getValues(), emptyList)); Assert.assertEquals( filter.metricToPatterns("meterBextra"), new PrototypeMeasurementFilter.IncludeExcludePatterns( emptyList, emptyList)); Assert.assertEquals( filter.metricToPatterns("meterCthing"), new PrototypeMeasurementFilter.IncludeExcludePatterns( meterPatternC.getValues(), emptyList)); } @Test public void testMetricToPatternsWithMultipleMeters() { PrototypeMeasurementFilterSpecification spec = new PrototypeMeasurementFilterSpecification(); spec.getInclude().put("meterA", meterSpecA); spec.getInclude().put("meter.+", meterSpecB); PrototypeMeasurementFilter filter = new PrototypeMeasurementFilter(spec); PrototypeMeasurementFilter.MeterFilterPattern meterPatternA = new PrototypeMeasurementFilter.MeterFilterPattern("ignored", meterSpecA); PrototypeMeasurementFilter.MeterFilterPattern meterPatternB = new PrototypeMeasurementFilter.MeterFilterPattern("ignored", meterSpecB); final List<PrototypeMeasurementFilter.ValueFilterPattern> emptyList = new ArrayList<PrototypeMeasurementFilter.ValueFilterPattern>(); Assert.assertEquals( filter.metricToPatterns("meterB"), new PrototypeMeasurementFilter.IncludeExcludePatterns( meterPatternB.getValues(), emptyList)); List<PrototypeMeasurementFilter.ValueFilterPattern> expect = new ArrayList<PrototypeMeasurementFilter.ValueFilterPattern>(); expect.addAll(meterPatternA.getValues()); expect.addAll(meterPatternB.getValues()); PrototypeMeasurementFilter.IncludeExcludePatterns patterns = filter.metricToPatterns("meterA"); Assert.assertEquals(new HashSet<PrototypeMeasurementFilter.ValueFilterPattern>(expect), new HashSet<PrototypeMeasurementFilter.ValueFilterPattern>(patterns.getInclude())); } @Test public void keepAnyTag() { PrototypeMeasurementFilter.TagFilterPattern pattern = new PrototypeMeasurementFilter.TagFilterPattern( new PrototypeMeasurementFilterSpecification.TagFilterSpecification("", "")); Tag tagA = new BasicTag("some_name_value", "some_value_string"); Assert.assertTrue(pattern.test(tagA)); } @Test public void keepTagOk() { PrototypeMeasurementFilter.TagFilterPattern pattern = new PrototypeMeasurementFilter.TagFilterPattern( Pattern.compile(".+_name_.+"), Pattern.compile(".+_value_.+")); Tag tagA = new BasicTag("some_name_value", "some_value_string"); Assert.assertTrue(pattern.test(tagA)); } @Test public void keepTagNotOk() { PrototypeMeasurementFilter.TagFilterPattern pattern = new PrototypeMeasurementFilter.TagFilterPattern( Pattern.compile(".+_name_.+"), Pattern.compile(".+_value_.+")); Tag tagOnlyNameOk = new BasicTag("some_name_value", "some_string"); Tag tagOnlyValueOk = new BasicTag("some_value", "some_value_string"); Tag tagNeitherOk = new BasicTag("some_value", "some_string"); Assert.assertFalse(pattern.test(tagOnlyNameOk)); Assert.assertFalse(pattern.test(tagOnlyValueOk)); Assert.assertFalse(pattern.test(tagNeitherOk)); } @Test public void valueTagsOk() { PrototypeMeasurementFilter.ValueFilterPattern pattern = new PrototypeMeasurementFilter.ValueFilterPattern(valueSpecAxBy); List<Tag> tagsAxBy = Arrays.asList(new BasicTag("tagA", "X"), new BasicTag("tagB", "Y")); List<Tag> tagsByAx = Arrays.asList(tagsAxBy.get(1), tagsAxBy.get(0)); Assert.assertTrue(pattern.test(tagsAxBy)); Assert.assertTrue(pattern.test(tagsByAx)); } @Test public void extraValueTagsOk() { PrototypeMeasurementFilter.ValueFilterPattern pattern = new PrototypeMeasurementFilter.ValueFilterPattern(valueSpecAxBy); List<Tag> tagsAxBy = Arrays.asList(new BasicTag("tagX", "X"), new BasicTag("tagA", "X"), new BasicTag("tagC", "C"), new BasicTag("tagB", "Y")); List<Tag> tagsByAx = Arrays.asList(tagsAxBy.get(3), tagsAxBy.get(2), tagsAxBy.get(1), tagsAxBy.get(0)); Assert.assertTrue(pattern.test(tagsAxBy)); Assert.assertTrue(pattern.test(tagsByAx)); } @Test public void valueTagsMissing() { PrototypeMeasurementFilter.ValueFilterPattern pattern = new PrototypeMeasurementFilter.ValueFilterPattern(valueSpecAxBy); List<Tag> tagsAx = Collections.singletonList(new BasicTag("tagA", "X")); List<Tag> tagsAxZy = Arrays.asList(new BasicTag("tagA", "X"), new BasicTag("tagZ","Y")); List<Tag> tagsAyBy = Arrays.asList(new BasicTag("tagA", "Y"), new BasicTag("tagB", "Y")); Assert.assertFalse(pattern.test(tagsAx)); Assert.assertFalse(pattern.test(tagsAxZy)); Assert.assertFalse(pattern.test(tagsAyBy)); } @Test public void meterOk() { PrototypeMeasurementFilterSpecification.MeterFilterSpecification meterSpec = new PrototypeMeasurementFilterSpecification.MeterFilterSpecification( Arrays.asList(valueSpecAyBx, valueSpecAzBy)); PrototypeMeasurementFilterSpecification spec = new PrototypeMeasurementFilterSpecification(); spec.getInclude().put("counter.+", meterSpec); PrototypeMeasurementFilter filter = new PrototypeMeasurementFilter(spec); Id idAYX = new TestId("counterA").withTag("tagA", "Y").withTag("tagB", "X"); Id idBZY = new TestId("counterB").withTag("tagA", "Z").withTag("tagB", "Y"); Assert.assertTrue(filter.test(new Measurement(idAYX, 1, 1))); Assert.assertTrue(filter.test(new Measurement(idBZY, 2, 2))); } @Test public void metersExcluded() { PrototypeMeasurementFilterSpecification spec = new PrototypeMeasurementFilterSpecification(); spec.getInclude().put( "counter.+", new PrototypeMeasurementFilterSpecification.MeterFilterSpecification()); spec.getExclude().put( "counterC", new PrototypeMeasurementFilterSpecification.MeterFilterSpecification()); PrototypeMeasurementFilter filter = new PrototypeMeasurementFilter(spec); Id idAYX = new TestId("counterA").withTag("tagA", "Y").withTag("tagB", "X"); Id idCYX = new TestId("counterC").withTag("tagA", "Y").withTag("tagB", "X"); Assert.assertTrue(filter.test(new Measurement(idAYX, 1, 1))); Assert.assertFalse(filter.test(new Measurement(idCYX, 2, 2))); } @Test public void meterNotOkBecauseNotIncluded() { PrototypeMeasurementFilterSpecification.MeterFilterSpecification meterSpec = new PrototypeMeasurementFilterSpecification.MeterFilterSpecification( Arrays.asList(valueSpecAyBx, valueSpecAzBy)); PrototypeMeasurementFilterSpecification spec = new PrototypeMeasurementFilterSpecification(); spec.getInclude().put("counter.+", meterSpec); PrototypeMeasurementFilter filter = new PrototypeMeasurementFilter(spec); Id idAXX = new TestId("counterA").withTag("tagA", "X").withTag("tagB", "X"); Id idBZX = new TestId("counterB").withTag("tagA", "Z").withTag("tagB", "X"); Assert.assertFalse(filter.test(new Measurement(idAXX, 1, 1))); Assert.assertFalse(filter.test(new Measurement(idBZX, 2, 2))); } @Test public void loadFromJson() throws IOException { String path = getClass().getResource("/test_measurement_filter.json").getFile(); PrototypeMeasurementFilterSpecification spec = PrototypeMeasurementFilterSpecification.loadFromPath(path);; PrototypeMeasurementFilterSpecification specA = new PrototypeMeasurementFilterSpecification();; specA.getInclude().put("meterA", meterSpecA); specA.getInclude().put("meterD", meterSpecD); specA.getInclude().put( "empty", new PrototypeMeasurementFilterSpecification.MeterFilterSpecification( new ArrayList())); List<PrototypeMeasurementFilterSpecification.TagFilterSpecification> tagsX = Arrays.asList( new PrototypeMeasurementFilterSpecification.TagFilterSpecification("tagA", "X"), new PrototypeMeasurementFilterSpecification.TagFilterSpecification("tagX", ".*")); PrototypeMeasurementFilterSpecification.ValueFilterSpecification valueSpecX = new PrototypeMeasurementFilterSpecification.ValueFilterSpecification(); valueSpecX.getTags().addAll(tagsX); specA.getExclude().put( ".+", new PrototypeMeasurementFilterSpecification.MeterFilterSpecification( Collections.singletonList(valueSpecX))); Assert.assertEquals(spec, specA); } }