From e1e7853255131f26702229735e37e160c38f2d08 Mon Sep 17 00:00:00 2001 From: Ivan Topolnjak Date: Sat, 20 May 2017 14:06:03 +0200 Subject: implement entity filters --- .../test/scala/kamon/metric/EntityFilterSpec.scala | 69 +++++++++++++++++++++ .../scala/kamon/metric/GlobPathFilterSpec.scala | 71 ++++++++++++++++++++++ .../scala/kamon/metric/RecorderRegistrySpec.scala | 43 +++++++++++++ .../scala/kamon/metric/RegexPathFilterSpec.scala | 60 ++++++++++++++++++ .../metric/instrument/InstrumentFactorySpec.scala | 36 +++++------ .../kamon/testkit/DefaultInstrumentFactory.scala | 2 +- 6 files changed, 263 insertions(+), 18 deletions(-) create mode 100644 kamon-core/src/test/scala/kamon/metric/EntityFilterSpec.scala create mode 100644 kamon-core/src/test/scala/kamon/metric/GlobPathFilterSpec.scala create mode 100644 kamon-core/src/test/scala/kamon/metric/RecorderRegistrySpec.scala create mode 100644 kamon-core/src/test/scala/kamon/metric/RegexPathFilterSpec.scala (limited to 'kamon-core/src/test/scala/kamon') diff --git a/kamon-core/src/test/scala/kamon/metric/EntityFilterSpec.scala b/kamon-core/src/test/scala/kamon/metric/EntityFilterSpec.scala new file mode 100644 index 00000000..15dfc5ff --- /dev/null +++ b/kamon-core/src/test/scala/kamon/metric/EntityFilterSpec.scala @@ -0,0 +1,69 @@ +package kamon +package metric + +import com.typesafe.config.ConfigFactory +import org.scalatest.{Matchers, WordSpec} + + +class EntityFilterSpec extends WordSpec with Matchers { + val testConfig = ConfigFactory.parseString( + """ + |kamon.metric.filters { + | accept-unmatched = false + | + | some-category { + | includes = ["**"] + | excludes = ["not-me"] + | } + | + | only-includes { + | includes = ["only-me"] + | } + | + | only-excludes { + | excludes = ["not-me"] + | } + | + | specific-rules { + | includes = ["glob:/user/**", "regex:test-[0-5]"] + | } + |} + """.stripMargin + ) + + "the entity filters" should { + "use the accept-unmatched setting when there is no configuration for a given category" in { + val acceptUnmatched = EntityFilter.fromConfig(ConfigFactory.parseString("kamon.metric.filters.accept-unmatched=true")) + val rejectUnmatched = EntityFilter.fromConfig(ConfigFactory.parseString("kamon.metric.filters.accept-unmatched=false")) + + acceptUnmatched.accept(Entity("a", "b", Map.empty)) shouldBe true + rejectUnmatched.accept(Entity("a", "b", Map.empty)) shouldBe false + } + + "accept entities that are matched by any include and none exclude filters" in { + val entityFilter = EntityFilter.fromConfig(testConfig) + + entityFilter.accept(Entity("anything", "anything", Map.empty)) shouldBe false + entityFilter.accept(Entity("anything", "some-category", Map.empty)) shouldBe true + entityFilter.accept(Entity("not-me", "some-category", Map.empty)) shouldBe false + } + + "allow configuring includes only or excludes only for any category" in { + val entityFilter = EntityFilter.fromConfig(testConfig) + + entityFilter.accept(Entity("only-me", "only-includes", Map.empty)) shouldBe true + entityFilter.accept(Entity("anything", "only-includes", Map.empty)) shouldBe false + entityFilter.accept(Entity("any-other", "only-excludes", Map.empty)) shouldBe false + entityFilter.accept(Entity("not-me", "only-excludes", Map.empty)) shouldBe false + } + + "allow to explicitly decide whether patterns are treated as Glob or Regex" in { + val entityFilter = EntityFilter.fromConfig(testConfig) + + entityFilter.accept(Entity("/user/accepted", "specific-rules", Map.empty)) shouldBe true + entityFilter.accept(Entity("/other/rejected/", "specific-rules", Map.empty)) shouldBe false + entityFilter.accept(Entity("test-5", "specific-rules", Map.empty)) shouldBe true + entityFilter.accept(Entity("test-6", "specific-rules", Map.empty)) shouldBe false + } + } +} \ No newline at end of file diff --git a/kamon-core/src/test/scala/kamon/metric/GlobPathFilterSpec.scala b/kamon-core/src/test/scala/kamon/metric/GlobPathFilterSpec.scala new file mode 100644 index 00000000..50938e12 --- /dev/null +++ b/kamon-core/src/test/scala/kamon/metric/GlobPathFilterSpec.scala @@ -0,0 +1,71 @@ +/* + * ========================================================================================= + * Copyright © 2013-2014 the kamon project + * + * 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 kamon +package metric + +import org.scalatest.{Matchers, WordSpecLike} + +class GlobPathFilterSpec extends WordSpecLike with Matchers { + "The GlobPathFilter" should { + + "match a single expression" in { + val filter = new GlobPathFilter("/user/actor") + + filter.accept("/user/actor") shouldBe true + filter.accept("/user/actor/something") shouldBe false + filter.accept("/user/actor/somethingElse") shouldBe false + } + + "match all expressions in the same level" in { + val filter = new GlobPathFilter("/user/*") + + filter.accept("/user/actor") shouldBe true + filter.accept("/user/otherActor") shouldBe true + filter.accept("/user/something/actor") shouldBe false + filter.accept("/user/something/otherActor") shouldBe false + } + + "match any expressions when using double star alone (**)" in { + val filter = new GlobPathFilter("**") + + filter.accept("GET: /ping") shouldBe true + filter.accept("GET: /ping/pong") shouldBe true + filter.accept("this-doesn't_look good but-passes") shouldBe true + } + + "match all expressions and cross the path boundaries when using double star suffix (**)" in { + val filter = new GlobPathFilter("/user/actor-**") + + filter.accept("/user/actor-") shouldBe true + filter.accept("/user/actor-one") shouldBe true + filter.accept("/user/actor-one/other") shouldBe true + filter.accept("/user/something/actor") shouldBe false + filter.accept("/user/something/otherActor") shouldBe false + } + + "match exactly one character when using question mark (?)" in { + val filter = new GlobPathFilter("/user/actor-?") + + filter.accept("/user/actor-1") shouldBe true + filter.accept("/user/actor-2") shouldBe true + filter.accept("/user/actor-3") shouldBe true + filter.accept("/user/actor-one") shouldBe false + filter.accept("/user/actor-two") shouldBe false + filter.accept("/user/actor-tree") shouldBe false + } + } +} diff --git a/kamon-core/src/test/scala/kamon/metric/RecorderRegistrySpec.scala b/kamon-core/src/test/scala/kamon/metric/RecorderRegistrySpec.scala new file mode 100644 index 00000000..28402d7c --- /dev/null +++ b/kamon-core/src/test/scala/kamon/metric/RecorderRegistrySpec.scala @@ -0,0 +1,43 @@ +package kamon.metric + +import com.typesafe.config.ConfigFactory +import org.scalatest.{Matchers, WordSpec} + +class RecorderRegistrySpec extends WordSpec with Matchers { + private val testConfig = ConfigFactory.parseString( + """ + |kamon.metric.filters { + | accept-unmatched = false + | + | my-category { + | includes = ["**"] + | excludes = ["excluded"] + | } + |} + """.stripMargin + ) + private val recorderRegistry = new RecorderRegistryImpl(testConfig.withFallback(ConfigFactory.load())) + + + "the RecorderRegistry" should { + "create entity recorders as requested and always return the same instance for a given entity" in { + val myFirstEntityRecorder = recorderRegistry.getRecorder(Entity("my-entity", "my-category", Map.empty)) + val mySecondEntityRecorder = recorderRegistry.getRecorder(Entity("my-entity", "my-category", Map.empty)) + mySecondEntityRecorder shouldBe theSameInstanceAs(myFirstEntityRecorder) + } + + "properly advice regarding entity filtering read from configuration" in { + recorderRegistry.shouldTrack(Entity("my-entity", "my-category", Map.empty)) shouldBe true + recorderRegistry.shouldTrack(Entity("other-eny", "my-category", Map.empty)) shouldBe true + recorderRegistry.shouldTrack(Entity("excluded", "my-category", Map.empty)) shouldBe false + } + + "allow removing entities" in { + val myFirstEntityRecorder = recorderRegistry.getRecorder(Entity("my-entity", "my-category", Map.empty)) + recorderRegistry.removeRecorder(Entity("my-entity", "my-category", Map.empty)) + + val mySecondEntityRecorder = recorderRegistry.getRecorder(Entity("my-entity", "my-category", Map.empty)) + mySecondEntityRecorder shouldNot be theSameInstanceAs(myFirstEntityRecorder) + } + } +} diff --git a/kamon-core/src/test/scala/kamon/metric/RegexPathFilterSpec.scala b/kamon-core/src/test/scala/kamon/metric/RegexPathFilterSpec.scala new file mode 100644 index 00000000..40fb6039 --- /dev/null +++ b/kamon-core/src/test/scala/kamon/metric/RegexPathFilterSpec.scala @@ -0,0 +1,60 @@ +/* + * ========================================================================================= + * Copyright © 2013-2015 the kamon project + * + * 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 kamon +package metric + +import org.scalatest.{Matchers, WordSpecLike} + +class RegexPathFilterSpec extends WordSpecLike with Matchers { + "The RegexPathFilter" should { + + "match a single expression" in { + val filter = new RegexNameFilter("/user/actor") + + filter.accept("/user/actor") shouldBe true + + filter.accept("/user/actor/something") shouldBe false + filter.accept("/user/actor/somethingElse") shouldBe false + } + + "match arbitray expressions ending with wildcard" in { + val filter = new RegexNameFilter("/user/.*") + + filter.accept("/user/actor") shouldBe true + filter.accept("/user/otherActor") shouldBe true + filter.accept("/user/something/actor") shouldBe true + filter.accept("/user/something/otherActor") shouldBe true + + filter.accept("/otheruser/actor") shouldBe false + filter.accept("/otheruser/otherActor") shouldBe false + filter.accept("/otheruser/something/actor") shouldBe false + filter.accept("/otheruser/something/otherActor") shouldBe false + } + + "match numbers" in { + val filter = new RegexNameFilter("/user/actor-\\d") + + filter.accept("/user/actor-1") shouldBe true + filter.accept("/user/actor-2") shouldBe true + filter.accept("/user/actor-3") shouldBe true + + filter.accept("/user/actor-one") shouldBe false + filter.accept("/user/actor-two") shouldBe false + filter.accept("/user/actor-tree") shouldBe false + } + } +} diff --git a/kamon-core/src/test/scala/kamon/metric/instrument/InstrumentFactorySpec.scala b/kamon-core/src/test/scala/kamon/metric/instrument/InstrumentFactorySpec.scala index 5bf16d4c..eda838d5 100644 --- a/kamon-core/src/test/scala/kamon/metric/instrument/InstrumentFactorySpec.scala +++ b/kamon-core/src/test/scala/kamon/metric/instrument/InstrumentFactorySpec.scala @@ -11,23 +11,25 @@ class InstrumentFactorySpec extends WordSpec with Matchers{ val customEntity = Entity("test", "custom-category", Map.empty) val baseConfiguration = ConfigFactory.parseString( """ - |default-settings { - | histogram { - | lowest-discernible-value = 100 - | highest-trackable-value = 5000 - | significant-value-digits = 2 - | } + |kamon.metric.instrument-factory { + | default-settings { + | histogram { + | lowest-discernible-value = 100 + | highest-trackable-value = 5000 + | significant-value-digits = 2 + | } | - | min-max-counter { - | lowest-discernible-value = 200 - | highest-trackable-value = 6000 - | significant-value-digits = 3 - | sample-interval = 647 millis + | min-max-counter { + | lowest-discernible-value = 200 + | highest-trackable-value = 6000 + | significant-value-digits = 3 + | sample-interval = 647 millis + | } | } - |} | - |custom-settings { + | custom-settings { | + | } |} """.stripMargin ) @@ -35,7 +37,7 @@ class InstrumentFactorySpec extends WordSpec with Matchers{ "the metrics InstrumentFactory" should { "create instruments using the default configuration settings" in { - val factory = InstrumentFactory(baseConfiguration) + val factory = InstrumentFactory.fromConfig(baseConfiguration) val histogram = factory.buildHistogram(testEntity, "my-histogram") val mmCounter = factory.buildMinMaxCounter(testEntity, "my-mm-counter") @@ -50,7 +52,7 @@ class InstrumentFactorySpec extends WordSpec with Matchers{ } "accept custom settings when building instruments" in { - val factory = InstrumentFactory(baseConfiguration) + val factory = InstrumentFactory.fromConfig(baseConfiguration) val histogram = factory.buildHistogram(testEntity, "my-histogram", DynamicRange.Loose) val mmCounter = factory.buildMinMaxCounter(testEntity, "my-mm-counter", DynamicRange.Fine, Duration.ofMillis(500)) @@ -63,7 +65,7 @@ class InstrumentFactorySpec extends WordSpec with Matchers{ "allow overriding any default and provided settings via the custom-settings configuration key" in { val customConfig = ConfigFactory.parseString( """ - |custom-settings { + |kamon.metric.instrument-factory.custom-settings { | custom-category { | modified-histogram { | lowest-discernible-value = 99 @@ -82,7 +84,7 @@ class InstrumentFactorySpec extends WordSpec with Matchers{ """.stripMargin ).withFallback(baseConfiguration) - val factory = InstrumentFactory(customConfig) + val factory = InstrumentFactory.fromConfig(customConfig) val defaultHistogram = factory.buildHistogram(customEntity, "default-histogram") val modifiedHistogram = factory.buildHistogram(customEntity, "modified-histogram", DynamicRange.Loose) diff --git a/kamon-core/src/test/scala/kamon/testkit/DefaultInstrumentFactory.scala b/kamon-core/src/test/scala/kamon/testkit/DefaultInstrumentFactory.scala index acec5915..6fd193d6 100644 --- a/kamon-core/src/test/scala/kamon/testkit/DefaultInstrumentFactory.scala +++ b/kamon-core/src/test/scala/kamon/testkit/DefaultInstrumentFactory.scala @@ -6,7 +6,7 @@ import kamon.metric.instrument.InstrumentFactory trait DefaultInstrumentFactory { val defaultEntity = Entity("default-entity", "default-category", Map.empty) - val instrumentFactory = InstrumentFactory(ConfigFactory.load().getConfig("kamon.metric.instrument-factory")) + val instrumentFactory = InstrumentFactory.fromConfig(ConfigFactory.load()) def buildCounter(name: String) = instrumentFactory.buildCounter(defaultEntity, name) -- cgit v1.2.3