-
Notifications
You must be signed in to change notification settings - Fork 24
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Specify sampling rate for actors #56
Changes from all commits
051f993
1daf60a
033265f
055e1ff
5725041
9e41f11
c69bd86
1e1beba
339ead2
308ce0a
b3e773c
212ee39
8f94297
ecb0372
bf25ec2
db67ef9
cac807a
b39a5b2
66bd57a
4a35919
c950bf2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -15,7 +15,7 @@ | |
*/ | ||
package org.eigengo.monitor.agent.akka | ||
|
||
import com.typesafe.config.Config | ||
import com.typesafe.config.{ConfigObject, Config} | ||
import org.eigengo.monitor.agent.akka.ActorFilter._ | ||
import org.eigengo.monitor.agent.akka.ActorFilter.NamedActorSystem | ||
import org.eigengo.monitor.agent.akka.ActorFilter.SameType | ||
|
@@ -27,8 +27,10 @@ import org.eigengo.monitor.agent.akka.ActorFilter.SameType | |
* @param includeSystemAgents include the system agents in the monitoring? | ||
* @param incuded the filter that matches the included actors | ||
* @param excluded the filter that matches the excluded actors | ||
* @param sampling defines the sampling rate for any actors where we don't want to log every message received | ||
*/ | ||
case class AkkaAgentConfiguration(includeRoutees: Boolean, includeSystemAgents: Boolean, incuded: ActorFilter, excluded: ActorFilter) | ||
case class AkkaAgentConfiguration(includeRoutees: Boolean, includeSystemAgents: Boolean, incuded: ActorFilter, | ||
excluded: ActorFilter, sampling: SamplingRates) | ||
|
||
/** | ||
* Companion for AkkaAgentConfiguration that provides a method to turn a ``Config`` into | ||
|
@@ -50,7 +52,9 @@ object AkkaAgentConfiguration { | |
val includeRoutees = if (config.hasPath("includeRoutees")) config.getBoolean("includeRoutees") else false | ||
val included = if (config.hasPath("included")) config.getStringList("included").map(parseFilter).toList else Nil | ||
val excluded = if (config.hasPath("excluded")) config.getStringList("included").map(parseFilter).toList else Nil | ||
AkkaAgentConfiguration(includeRoutees, false, AnyAcceptActorFilter(included, true), AnyAcceptActorFilter(excluded, false)) | ||
val sampling = if (config.hasPath("sampling")) config.getObjectList("sampling").flatMap(parseSampling).toList else Nil | ||
AkkaAgentConfiguration(includeRoutees, false, AnyAcceptActorFilter(included, true), | ||
AnyAcceptActorFilter(excluded, false), SamplingRates(sampling)) | ||
} | ||
|
||
private def parseActorSystemFilter(actorSystemName: String): ActorSystemNameFilter = | ||
|
@@ -67,6 +71,14 @@ object AkkaAgentConfiguration { | |
case ActorTypePattern(name, clazz) => ActorTypeFilter(parseActorSystemFilter(name), SameType(clazz)) | ||
} | ||
|
||
private def parseSampling(samplingObject: ConfigObject): Iterable[SamplingRate] = { | ||
import scala.collection.JavaConversions._ | ||
(samplingObject.get("rate").unwrapped(), samplingObject.get("for").unwrapped()) match { | ||
case (rate: Number, filters: java.util.List[String @unchecked]) => | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nice! I didn't know about that |
||
filters.map(filter => SamplingRate(parseFilter(filter), rate.intValue())) | ||
} | ||
} | ||
|
||
} | ||
|
||
/** | ||
|
@@ -83,5 +95,24 @@ object AkkaAgentConfigurationJapi { | |
|
||
} | ||
|
||
//TODO: complete me | ||
//case class SamplingRate(included: ActorFilter, sampleEvery: Int) | ||
/** | ||
* Represents a sampling rate provided by a conf object | ||
* | ||
* @param included the filter over the actors | ||
* @param sampleEvery how often to sample (e.g. every 5 messages) | ||
*/ | ||
case class SamplingRate(included: ActorFilter, sampleEvery: Int) | ||
|
||
/** | ||
* A wrapper for holding multiple sampling rates | ||
*/ | ||
case class SamplingRates(samplingRates: List[SamplingRate]) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If we have this as just a container, you can make it There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Finally! A legitimate use for it! Good call |
||
/** | ||
* Gets the sampling rate for a particular actor | ||
* | ||
* @param pathAndClass an object representing the actor's path and (optionally) its class name | ||
* @return the rate as an integer | ||
*/ | ||
def getRate(pathAndClass: PathAndClass): Int = | ||
samplingRates.find(_.included.accept(pathAndClass)).map(_.sampleEvery).getOrElse(1) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
|
||
{ | ||
sampling: [ | ||
{ | ||
rate: 5 | ||
for: [ "akka:*.org.eigengo.monitor.agent.akka.SimpleActor" ] | ||
}, | ||
{ | ||
rate: 15 | ||
for: [ "akka:*.org.eigengo.monitor.agent.akka.WithUnhandledActor" ] | ||
}, | ||
{ | ||
rate: 4 | ||
for: [ "akka://default/user/*" ] | ||
} | ||
] | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
/* | ||
* Copyright (c) 2013 original 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.eigengo.monitor.agent.akka | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Don't forget to add license comment. |
||
|
||
import org.eigengo.monitor.{TestCounter, TestCounterInterface} | ||
import org.eigengo.monitor.agent.akka.Aspects._ | ||
import akka.testkit.TestActorRef | ||
|
||
class ActorSamplingSpec extends ActorCellMonitoringAspectSpec(Some("sample.conf")){ | ||
|
||
"Actor sampling" should { | ||
val a = TestActorRef[SimpleActor]("a") | ||
val b = TestActorRef[WithUnhandledActor]("b") | ||
val c = TestActorRef[NullTestingActor1]("c") | ||
val d = TestActorRef[NullTestingActor2]("d") | ||
|
||
"Sample concrete path" in { | ||
TestCounterInterface.clear() | ||
(0 until 1000) foreach {_ => a ! 1} | ||
|
||
Thread.sleep(500) // wait for the messages | ||
|
||
// we expect to see (1000/5)*5 messages to actor a | ||
val counter = TestCounterInterface.foldlByAspect(deliveredInteger)(TestCounter.plus) | ||
|
||
counter(0).value mustEqual 1000 | ||
counter(0).tags must contain(a.path.toString) | ||
counter.size === 200 | ||
|
||
|
||
TestCounterInterface.clear() | ||
(0 until 1000) foreach {_ => b ! 1} | ||
Thread.sleep(500) // wait for the messages | ||
|
||
// we expect to see (1000/15 ~=67)*15 = 1005 messages to actor b (we round up, since logging the first message) | ||
val counter2 = TestCounterInterface.foldlByAspect(deliveredInteger)(TestCounter.plus) | ||
|
||
counter2(0).value mustEqual 1005 | ||
counter2(0).tags must contain(b.path.toString) | ||
counter2.size === 67 | ||
} | ||
|
||
"Sample wildcard path" in { | ||
|
||
TestCounterInterface.clear() | ||
(0 until 497) foreach {_ => c ! 1} // if we weren't incrementing the counters separately for each actor, then we'd | ||
(0 until 501) foreach {_ => d ! 1} // expect 998 messages, and thus 250*4 = 1000 messages logged. But we are -- so | ||
// we expect 125*4 = 500 for actor c, and 126*4 = 504 for actor d | ||
Thread.sleep(500) // wait for the messages | ||
|
||
// we expect to see (500/4)*4*2 messages to actor c and d | ||
val counter3 = TestCounterInterface.foldlByAspect(deliveredInteger)(TestCounter.plus) | ||
|
||
counter3(0).value mustEqual 1004 | ||
counter3(0).tags must contain(d.path.toString) | ||
counter3(125).tags must contain(d.path.toString) | ||
counter3(126).tags must contain(c.path.toString) | ||
counter3.size === 251 | ||
|
||
} | ||
} | ||
|
||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're missing
@param
forsampling
.