erikvanoosten / metrics-scala Goto Github PK
View Code? Open in Web Editor NEWThe scala API for Dropwizard's Metrics.
License: Apache License 2.0
The scala API for Dropwizard's Metrics.
License: Apache License 2.0
Looking for a build against metrics-core 3.0.1 (scala 2.11) - the most recent stable release. 3.1.0 has some issues with graphite:
dropwizard/metrics#694
I believe that this signature:
implicit def fromBooleanCheck[A <% Boolean](checker: => A) = new HealthCheckMagnet {
...
if (checker) Result.healthy() else Result.unhealthy(unhealthyMessage)
...
}
is dangerous, as the by-name parameter probably won't always match your intention when used as part of an implicit. I think this is best illustrated with an example:
var counter = 0;
healthCheck("broken") { counter += 1; counter % 2 == 0 }
The idea here is that the block which is passed as the last argument to healthCheck
will be converted to a HealtCheckMagnet
using the implicit
above. Because the parameter checker
is by-name, you would expect the given expression to be evaluated every time it is used, i.e. every time the if (checker)
is evaluated.
Assuming that the block { counter += 1; counter % 2 == 0 }
is the expression passed to checker, you would thus expect counter % 2 == 0
to return false every other time and hence the Health Check to fail every other time.
This would work if healthCheck
's signature would be something like def healthCheck(message: String...)(checker: => Boolean) ...
.
However, with (checker: HealthCheckMagnet)
and the implicit
doing the conversion from => Boolean
to HealthCheckMagnet
, the health check fails every time.
Why this is happening is made clearer when inserting some directly visible side effect as part of the block, for instance by turning it into { println("checking!"); counter += 1; counter % 2 == 0 }
. This reveals that the block is only evaluated once, and only at the time the health check is defined. The reason for this lies in an idiosyncrasy of Scala: When the compiler encounters the block given to healthCheck
, it will not "pass" the whole block to the implicit fromBooleanCheck
. Instead it will evaluate the block up until to its last expression (counter % 2 == 0
) and, since this is a Boolean
, happily pass it to fromBooleanCheck
, fixing whatever its result was at that time (in this case false
).
A workaround would be to write the example code as follows:
healthCheck("workaround")(()=>{ counter += 1; counter % 2 == 0 }())
or
def actualCheck = { counter += 1; counter % 2 == 0 }
healthCheck("workaround")(actualCheck)
Both being somewhat non-obvious.
I believe that this is dangerous because it makes bogus health checks very easy to write by just passing a non-trivial block to healthCheck
. Furthermore, because health checks are likely to pass the first time they are performed, the error will not emerge until failure of the checked system actually occurs and the health check fails to indicate this, potentially making a detectable failure much worse down the line.
I suggest changing the signature of fromBooleanCheck
to something akin to
implicit def fromBooleanCheck[A <% Boolean](checker: () => A) =
or maybe using a new implicit
and deprecating the old one to prevent existing code from breaking (though note that code written using that old implicit may already be unwittingly broken).
That way, checker
is a function and it is obvious that it will be called for each health check, at the meager cost of having to preface each inline block with () =>
.
Hi,
how can I export the different collected metrics in json format ?
I saw that the java project has json module, but it was not clear to me how to use it.
would be great if you can share some example.
Thanks,
3.1.1_a2.3 causes this SBT error when used with a project that uses Scala 2.11.0 and akka-actor 2.3.2:
[error] Modules were resolved with conflicting cross-version suffixes in {file:/Users/ngocdt/src/xitrum/}xitrum:
[error] com.typesafe.akka:akka-actor _2.11, _2.11.0-RC4
I now have to use 3.1.1.1_a2.3.
When measuring a multithreaded class, I am getting some inconsistent results between two counters (one must be greater than the other, but that's the opposite that happens). From what I see in the code, there is no synchronization in the Metric implementation.
We should have a trait to mix in either directly, or using convenience methods such as MetricBuilder.counterSync
.
Hi there,
I had a some counters in my app, declared like so:
class Foo extends Instrumented {
val counter = metrics.counter("my-counter")
...
counter.inc(1)
and in my unit tests for Foo
, I create a new instance of Foo
before every tests, something like this:
class Fixture {
val foo = new Foo()
}
var f: Fixture = _
before { f = new Fixture }
def `test Foo 1 ` { ... }
def `testFoo 2` { ... }
Now using counters, all the tests would run fine. I switched some of these counters to gauges, and my tests fail when the class throws the exception ("metric named my-counter already exists").
It appears that there's a method
private <T extends Metric> T getOrAdd(String name, MetricBuilder<T> builder)
that calling metrics.gauge
skips, while metrics.counters
does call it (and seems to grab the existing counter?
I'm confused why I'm seeing these differences between gauges and counters (and does that mean I can't multiple instances of the same class for gauges, because they'll throw?). I wanted to check with the metrics-scala library first before I ask the dropwizard folks in case anyone has any pointers. It seems like catching exception for the gauge and then reading the gauge with that name from the registry would be an anti pattern - seems like I'm misunderstanding something.
Thanks!
I'm getting this error in my build:
[error] Modules were resolved with conflicting cross-version suffixes in main:
[error] com.typesafe.akka:akka-actor _2.11, _2.11.0-RC4
[error] com.typesafe.akka:akka-testkit _2.11.0-RC4, _2.11
akka-testkit has been released, could you make a new release?
Hi,
I want to use metrics-scala 3.0.5(metrics 3.0.2) without akka but there is no built for it. Should i exclude akka or just declare a dependency on metrics 3.0.2 with metrics-scala 3.0.4?
metrics-scala > 3.0.0 depends on akka 2.2 on the other hand Play depends on akka 2.1.0
Gauge[Integer]{
taskManager.countTasks()
}
countTasks returns a Future[Int]
Would be nice to have a Gauge that accepts futures or is this a bad idea?
It looks like datasift/dropwizard-scala project provides a metrics module for providing Scala-friendly access to dropwizard metrics. That project is listed in Dropwizard's docs while this project is listed in Dropwizard Metrics' docs.
Is there any relationship between the two packages, or are they simply different approaches to the same general concept?
As of Dropwizard 1.0.0, Dropwizard apps register their metric registry as "default" in SharedMetricRegistries. Since there's now a mechanism to discover the app's registry via SharedMetricRegistries
, this project could define a DefaultInstrumented
trait that points at the registry marked as "default", avoiding the need for users to define their own Instrumented
trait unless they want to point at a non-default registry.
Would you be open to such an enhancement?
Probably less of a bug issue than a usage thing, but I wanted to double check.
Assume I have the Instrumented trait defined and want to create a ReceiveCounterActor measure.
I assumed it should work like this (also as documented in the source):
class SomeMonitoredActor extends Actor with ReceiveCounterActor with Instrumented {
def receive = {case "ping" => sender ! "pong" }
}
However, this results in a compiler error:
missing parameter type for expanded function
The argument types of an anonymous function must be fully known. (SLS 8.5)
Expected type was: PartialFunction[Any,Unit]
def receive = {
^
Trying to fix this with override yields further errors I haven't quite had the time to follow up on and understand.
The usage pattern described in the Unit tests on the other hand works:
class SomeActor extends Actor {
def receive = {case "ping" => sender ! "pong" }
}
class SomeMonitoredActor extends ReceiveCounterActor with Instrumented
And then SomeMonitoredActor is used as the instantiated actor.
Is this the intended (or limited by the SLS) usage?
I was thinking about creating our own stackable actor implementation anyway to add multiple protocol wrappers for different functionality, so this is not a problem, more interest.
Latest changes were made 6 month ago.
We depend on this library in production.
@erikvanoosten if you don't have time for this library please assign collaborators to maintain this project.
Thanks!
I am trying to integrate the 2.12 JAR (https://mvnrepository.com/artifact/nl.grons/metrics-scala_2.12/3.5.5), building with jdk1.8 and scala 2.12.0, and I'm running into a problem NoSuchMethodError nl.grons.metrics.scala.BaseBuilder.$init$.
What version of the JDK was the library compiled with?
When I take the metrics-scala source and build it locally with JDK1.8- I have no problem.
thanks,
Just read in the docs:
"There is no scala support for JMX or other Reporters"
Just wondering what the reason is for this.
What about Metrics itself?
Just been playing with the lovely http://hawt.io/ was hoping for a JMX endpoint.
Thanks.
Hi --
I'm updating a project from Scala 2.9.2 to 2.9.3 so I could use dispatch 0.10.0 (http://notes.implicit.ly/post/47436559635/dispatch-0-10-0). If you could add that version to the mix it would be greatly appreciated :) Thank you!
-Dragos
any examples for using reporters like the ConsoleReporter or the CvsReporter ?
thanks in advance.
This is a question, not an issue, perhaps we can have them marked separately.
Our devs thought that metrics better be static, and defined them like
object Widget extends Instrumented {
private val UpdateTimer = metrics.timer("update")
...
}
class Widget {
import Widget._
private def update(): Unit = synchronized {
UpdateTimer.time { ... }
}
}
Is it worth doing, or would it strain the metrics system if we simply define each timer in the class?
https://github.com/erikvanoosten/metrics-scala/blob/master/docs/HealthCheckManual.md
JmxReporter.forRegistry doesn't seem to take a health registry.
Thanks.
Hi,
I'm using metrics-scala 3.0.3 and in the ivy xml file the akka-actor dependency is defined like this:
<dependency org="com.typesafe.akka" name="akka-actor_2.10" rev="[2.2,)" force="true" conf="compile->compile(*),master(*);runtime->runtime(*)"/>
Although I'm using Akka 2.2 in my project since today 2.3-M1 was released, and the Akka dependency is not set as provided, metrics-scala automatically pulls the latest version available.
Hi,
I believe there is a little bug in the version 3.1.0_a2.3 of your API.
Manual says you can mix in InstrumentedBuilder and CheckedBuilder traits:
trait Instrumented extends InstrumentedBuilder with CheckedBuilder {
val metricRegistry = YourApplication.metricRegistry
val healthCheckRegistry = YourApplication.healthCheckRegistry
}
However, both traits actually have a value called metricBaseName and so, the compiler returns an "inherits conflicting members" error.
I've solved this problem with an override of this val:
override lazy val metricBaseName = MetricName(getClass)
Thanks and congratulations for your API
We use Akka in our project and we create gauges inside our actor. This causes a problem when the actor dies and restarts. When it restarts we get an exception that the gauge already exists. I have the following test that shows the behaviour.
import akka.actor.SupervisorStrategy.Restart
import akka.actor._
import akka.testkit.{DefaultTimeout, ImplicitSender, TestKit}
import org.scalatest.{BeforeAndAfterAll, Matchers, WordSpecLike}
import scala.concurrent.duration._
/**
* a Test to show some TestKit examples
*/
class ActorGuageSpec
extends TestKit(ActorSystem("ActorGuageSpec"))
with DefaultTimeout with ImplicitSender with WordSpecLike with Matchers with BeforeAndAfterAll {
override def afterAll {
shutdown()
}
val supervisor = system.actorOf(Props[SupervisingActor])
supervisor ! Props[TestActor]
val actor = expectMsgType[ActorRef]
"The Actor" should {
"Be able to replace the guage when it restarts" in {
within(5.seconds) {
actor ! 'increase
expectMsg(1)
actor ! Kill
actor ! 'increase
expectMsg(1)
}
}
}
}
class SupervisingActor extends Actor {
override val supervisorStrategy =
OneForOneStrategy(maxNrOfRetries = 10, withinTimeRange = 1.second) {
case _ => Restart
}
def receive = {
case p: Props => sender ! context.actorOf(p)
}
}
class TestActor extends Actor with Instrumented {
override val supervisorStrategy =
OneForOneStrategy(maxNrOfRetries = 10, withinTimeRange = 1.second) {
case _ => Restart
}
var counter = 0
metrics.gauge("test-counter") {
counter
}
override def receive: Receive = {
case 'increase =>
counter += 1
println(counter)
sender ! counter
}
}
That produces the following log when I run it:
Testing started at 5:25 PM ...
1
[ERROR] [12/09/2015 17:25:38.993] [ActorGuageSpec-akka.actor.default-dispatcher-2] [akka://ActorGuageSpec/user/$a/$a] Kill (akka.actor.ActorKilledException)
[ERROR] [12/09/2015 17:25:38.997] [ActorGuageSpec-akka.actor.default-dispatcher-3] [akka://ActorGuageSpec/user/$a/$a] A metric named TestActor.test-counter already exists
akka.actor.PostRestartException: exception post restart (class akka.actor.ActorKilledException)
at akka.actor.dungeon.FaultHandling$$anonfun$6.apply(FaultHandling.scala:249)
at akka.actor.dungeon.FaultHandling$$anonfun$6.apply(FaultHandling.scala:247)
at akka.actor.dungeon.FaultHandling$$anonfun$handleNonFatalOrInterruptedException$1.applyOrElse(FaultHandling.scala:302)
at akka.actor.dungeon.FaultHandling$$anonfun$handleNonFatalOrInterruptedException$1.applyOrElse(FaultHandling.scala:297)
at scala.runtime.AbstractPartialFunction.apply(AbstractPartialFunction.scala:36)
at akka.actor.dungeon.FaultHandling$class.finishRecreate(FaultHandling.scala:247)
at akka.actor.dungeon.FaultHandling$class.faultRecreate(FaultHandling.scala:76)
at akka.actor.ActorCell.faultRecreate(ActorCell.scala:374)
at akka.actor.ActorCell.invokeAll$1(ActorCell.scala:464)
at akka.actor.ActorCell.systemInvoke(ActorCell.scala:483)
at akka.dispatch.Mailbox.processAllSystemMessages(Mailbox.scala:282)
at akka.dispatch.Mailbox.run(Mailbox.scala:223)
at akka.dispatch.Mailbox.exec(Mailbox.scala:234)
at scala.concurrent.forkjoin.ForkJoinTask.doExec(ForkJoinTask.java:260)
at scala.concurrent.forkjoin.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1339)
at scala.concurrent.forkjoin.ForkJoinPool.runWorker(ForkJoinPool.java:1979)
at scala.concurrent.forkjoin.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:107)
Caused by: java.lang.IllegalArgumentException: A metric named TestActor.test-counter already exists
at com.codahale.metrics.MetricRegistry.register(MetricRegistry.java:91)
at nl.grons.metrics.scala.MetricBuilder.gauge(MetricBuilder.scala:35)
at TestActor.<init>(ActorGuageSpec.scala:57)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:422)
at java.lang.Class.newInstance(Class.java:442)
at akka.util.Reflect$.instantiate(Reflect.scala:44)
at akka.actor.NoArgsReflectConstructor.produce(IndirectActorProducer.scala:105)
at akka.actor.Props.newActor(Props.scala:214)
at akka.actor.ActorCell.newActor(ActorCell.scala:562)
at akka.actor.dungeon.FaultHandling$class.finishRecreate(FaultHandling.scala:234)
... 11 more
I've tried removing guages but that says it's not supported. What kind of options do we have here?
Building further on #30, also build a version for 2.10 without Akka.
Hi,
Trying to understand how should one go about reporting to Graphite using metrics-scala & metrics-graphite module in Scala ?
Thanks.
Hey!
There is no mention of the most recent version (3.2.0) of the library in the GitHub releases page: https://github.com/erikvanoosten/metrics-scala/releases. That's for me, and I suppose not only me, the first place to look for the current version of any software component I'm using.
The latest version I see there is 3.0.3, which is confusing.
Let me start by saying thank you for bringing your effort into this enriched Scala version of Metrics library.
Just one minor thing I've stumbled upon was missing FutureMetrics
trait in pure 3.1.1
version of the library, so I have to use 3.1.1_a2.2
version. I did not expect a dependency on Akka, because Scala Future
does not depend on Akka.
Guys, what do you think? Does it make sense to move FutureMetrics
to the main source tree?
Thanks in advance!
I'm trying to send metrics to graphite, and they are not passing through. I see them in the admin servlet, and they have a $ in their names, e.g.:
"com.versal.restapi.SomeClassName$.payload"
-- is this expected and swallowable by graphite?
A+
I see something like:
name=com.foo.bar.MyActor.com.foo.bar.MyActor.receiveCounter
I suppose this is because the actor traits use the class name in the metric name, which then is appended onto the base name, which also is the class name:
trait ReceiveCounterActor extends Actor { self: InstrumentedBuilder =>
def receiveCounterName: String = MetricName(getClass).append("receiveCounter").name
lazy val counter: Counter = metrics.counter(receiveCounterName)
counter
calls metricNameFor
which is implemented as: baseName.append(name, scope).name
, and the base name comes from:
trait BaseBuilder {
/** The base name for all metrics created from this builder. */
lazy val metricBaseName = MetricName(getClass)
}
I had to explicitly add MyTimer.time[List[Result]](myFunc(someString))
generic parameter instantiation, otherwise I was getting a PartialFunction[Int,Result]
instead of List[Result]
error, where the wrapped function has a signature def myFunc(x: String): List[Result]
. Note the weird Int
getting in from the cold. Apparently PartialFunction
support needs more type inference checking/testing!
Hi,
The jar for metrics-scala_2.11-3.5.2_a2.3 is missing from JCenter repository. I'm not sure if JCenter mirrors Maven Central or do you push metrics-scala
manually there.
The pom file for the same artifact version is present, though. Previous version is unaffected.
See https://jcenter.bintray.com/nl/grons/metrics-scala_2.11/3.5.2_a2.3/
I'd like to write a bit of helper code to make it easy to add metrics to both Actors and Futures. It would be 2.10-only code, unless we pull in Akka for 2.9.x. This should be manageable according to:
http://stackoverflow.com/questions/13872226/how-to-support-multiple-scala-versions-in-a-library
WDYT?
I'm having a not found: value metrics for the metrics
builder object. I cannot find it in the source code, how I can import this one?
Hi,
I think it would be interesting to be able to reset metrics as I need this for my project.
My current solution involves creating new instances of MetricRegistry which is not a very clean solution...
Similar to #47.
Starting with Scala 2.10 you can also instrument Actors and Futures. This is described at Instrumenting Actors and Futures.
- link gives 404
Since akka 2.4 is now in RC2 would you mind doing a build against that?
Currently we do magic to create specific releases for each scala version with or without Akka support. It would be better to split out Akka support to its own sub-project that depends on the metrics-core sub-project.
Ideally the names of the releases do not change.
Anyone who feels like taking this up is welcome to do so!
I was not able to figure out how to create an histogram with a specific type of reservoir, like a window or similar.
Hdrhistogram.md
states:
in addition, you should probably override the dependency to HdrHistogram. E.g.:
libraryDependencies += "org.hdrhistogram" % "HdrHistogram" % "2.1.6"
See the README to see which version(s) you can use.
In both README
and AvailableVersions.md
there is a table with column Hdr version
but numbers put in this column seems to be versions of hdrhistogram-metrics-reservoir
not HdrHistogram itself.
It may be confusing and actually it is for me :) I've overriden HdrHistogram to 2.1.7 (which is the most recent version) but not completely sure if it's non-breaking and the sentence See the README to see which version(s) you can use
suggest that README can help me in being sure about it but it's not. I suggest either changing this sentence or extending README to contain information about "suggested" HdrHistogram version.
Also, how can I find out that HdrHistogram
2.1.7 will work with hdrhistogram-metrics-reservoir
1.1.0 - HdrHistogram does not seem to have changelog.
Actually I am not sure if this can be considered an "issue". I would rather ask first on user group forum, but AFAIK there's no user group for metrics-scala so I am asking here :)
Is it possible to change Reservoir for histograms?
I want to use SlidingTimeWindowReservoir but didn't find API to do this.
Akka 2.4.x has been released:
http://akka.io/news/2015/09/30/akka-2.4.0-released.html
BIG changes:
Migration Guide 2.3.x to 2.4.x:
http://doc.akka.io/docs/akka/2.4.1/project/migration-guide-2.3.x-2.4.x.html
2.4.x is basically binary compatible with 2.3.x, but because it's a major version, may be you should release an new version of metrics-scala for it?
I have a long running job that I want to know the lifetime distribution on processing work rather than the last 5 minutes or so. Changing the reservoir on my timer was painful. Please expose modifying the reservoir.
Best I got was
private[this] val splitTimer = {
// metricNameFor() is protected
val name = metrics.baseName.append("split.times").name
new scala.Timer(metrics.registry.register( name, new Timer(new UniformReservoir())) )
}
There is a ".package" substring in metrics name if we use scala package objects.
It would be nice to cut it too.
This is more of a question than an issue. If we call the instrumentation API inside of a web service (written in spray).
The timeFuture is written as
def timeFuture[A](future: => Future[A])(implicit context: ExecutionContext): Future[A] = { val ctx = metric.time() val f = future f.onComplete(_ => ctx.stop()) f }
I wonder what is the impact of calling "onComplete" on the threadpool utilization of Spray.
We were using inc and dec for a Counter, in 3.0.1 we got a compilation error that they are missing. Intentional?
Akka 2.3.3 has been released:
https://groups.google.com/forum/#!topic/akka-user/mEcBXRr9Kto
Users of distributed systems that rely on serialization to exchange objects (such as akka) should upgrade to Scala 2.11.1 (and akka 2.3.3) immediately. We also strongly recommend that libraries that themselves declare classes with @serialversionuid annotations release a new version and ask their Scala 2.11 users to upgrade.
I am unable to build with 2.11. This is what I got:
[warn] ::::::::::::::::::::::::::::::::::::::::::::::
[warn] :: UNRESOLVED DEPENDENCIES ::
[warn] ::::::::::::::::::::::::::::::::::::::::::::::
[warn] :: nl.grons#metrics-scala_2.11;3.0.6_a2.3: not found
[warn] ::::::::::::::::::::::::::::::::::::::::::::::
Is there a specific repository I have to add?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.