我正在学习DropWizard Metrics library(以前的Coda Hale指标),我很困惑何时应该使用Meters
vs Timers
。根据文件:
仪表:仪表测量一组事件发生的速率
和
计时器:计时器基本上是事件类型持续时间的直方图和发生率的计量表
基于这些定义,我无法辨别这些定义之间的区别。让我感到困惑的是Timer
没有像我预期的那样被使用。对我而言,Timer
就是这样:一个计时器;它应衡量start()
和stop()
之间的时差。但似乎Timers
也会捕捉事件发生的比率,感觉就像踩着Meters
脚趾一样。
如果我能看到每个组件输出的示例,可能有助于我了解何时/何地使用其中任何一个。
答案 0 :(得分:132)
你很困惑,因为DW Metrics Timer IS ,其中包括DW Metrics Meter。
仪表专门关注速率,以Hz(每秒事件数)为单位。每个Meter会导致发布4个(?)不同的指标:
您通过在代码中的不同点记录值来使用Meter - DW Metrics会自动记下每个调用的挂起时间以及您给出的值,并使用这些来计算该值的值增加:
Meter getRequests = registry.meter("some-operation.operations")
getRequests.mark() //resets the value, e.g. sets it to 0
int numberOfOps = doSomeNumberOfOperations() //takes 10 seconds, returns 333
getRequests.mark(numberOfOps) //sets the value to number of ops.
我们预计我们的费率为33.3 Hz,因为发生了333次操作,两次调用mark()之间的时间是10秒。
计时器计算以上4个指标(将每个Timer.Context视为一个事件),并为其添加一些额外指标:
每个计时器都报告了15个总指标。
简而言之:计时器会报告很多指标,而且它们可能很难理解,但一旦你这样做,它们就是发现spikey行为的一种非常强大的方法。
事实上,只收集两点之间的时间并不是一个非常有用的指标。考虑一下:你有一个像这样的代码块:
Timer timer = registry.timer("costly-operation.service-time")
Timer.Context context = timer.time()
costlyOperation() //service time 10 ms
context.stop()
让我们假设expensiveOperation()具有恒定的成本,恒定的负载并在单个线程上运行。在1分钟的报告期内,我们应该期望这次操作6000次。显然,我们不会通过电线6000x报告实际服务时间 - 相反,我们需要一些方法来总结所有这些操作以适合我们所需的报告窗口。 DW Metrics'Timer为我们自动执行此操作,每分钟一次(我们的报告期)。 5分钟后,我们的度量标准注册表将报告:
现在,我们考虑进入一个时期,我们的操作偶尔会完全脱离轨道并长时间阻挡:
Timer timer = registry.timer("costly-operation.service-time")
Timer.Context context = timer.time()
costlyOperation() //takes 10 ms usually, but once every 1000 times spikes to 1000 ms
context.stop()
超过1分钟的收集期,我们现在看到的执行次数少于6000次,因为每1000次执行需要更长的时间。计算出大约5505.在第一分钟(总系统时间为6分钟)后,我们现在看到:
如果您将此图表显示,您会看到大多数请求(p50,p75,p99等)在10毫秒内完成,但1000个(p99)中的一个请求在1秒内完成。这也可以看作平均率略有下降(约2%),1分钟均值(近9%)大幅减少。
如果你只看时间的意思(速率或持续时间),你永远不会发现这些尖峰 - 它们会在很多成功的操作平均时被拖入背景噪音中。同样,只知道max是没有用的,因为它不会告诉你max发生的频率。这就是为什么直方图是跟踪性能的强大工具,以及为什么DW Metrics的Timer发布速率和直方图。