Metrics
=======
Xitrum thu thập thông tin bộ nhớ JVM heap, CPU, và tình trạng thực thi của các action từ mỗi node
trong Akka cluster của ứng dụng. Nó xuất ra các số liệu trong định dạng dữ liệu JSON. Xitrum cũng
cho phép bạn thu thập cách các dữ liệu khác.
Công cụ metrics này dựa theo thư viện `Coda Hale Metrics `_.
Thu thập thông tin
------------------
Bộ nhớ heap và CPU
~~~~~~~~~~~~~~~~~~
Bộ nhớ JVM heap và CPU sẽ được thu thập
`NodeMetrics `_
từ mỗi node của hệ thống Akka actor.
Bộ nhớ heap:
.. image:: ../img/metrics_heapmemory.png
CPU: số lượng tiến trình và tải trung bình
.. image:: ../img/metrics_cpu.png
Action metric
~~~~~~~~~~~~~
Xitrum thu thập tình trạng thực thi các action của mỗi node như một
`Histogram `_.
Bạn có thể biết chính các bao nhiêu lần action được thực thi và thời gian
thực thi của những non-async action.
.. image:: ../img/metrics_action_count.png
Thời gian thực hiện lần gần nhất của một action:
.. image:: ../img/metrics_action_time.png
Thu thập các số liệu tùy chỉnh
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Ngoài các số liệu mặc định nêu trên, bạn có thể thu thập các dữ liệu cho riêng mình.
``xitrum.Metrics`` có thể truy cập vào ``gauge``, ``counter``, ``meter``,
``timer`` và ``histogram``. Vui lòng tham khảo
`Coda Hale Metrics `_ và
`bản hiện thực Scala của nó `_
để biết cách sử dụng.
Ví dụ về timer:
::
import xitrum.{Action, Metrics}
import xitrum.annotation.GET
object MyAction {
lazy val myTimer = Metrics.timer("myTimer")
}
@GET("my/action")
class MyAction extends Action {
import MyAction._
def execute() {
myTimer.time {
// Something that you want to measure execution time
...
}
...
}
}
Xuất ra các metric
------------------
Xitrum xuất ra giá trị mới nhất của metric dưới định đạng JSON sau một chu kỳ
xác định.
Các dữ liệu thu thập được có nhiều biến động, sẽ không được lưu trữ vĩnh viễn
HeapMemory:
::
{
"TYPE" : "heapMemory",
"SYSTEM" : akka.actor.Address.system,
"HOST" : akka.actor.Address.host,
"PORT" : akka.actor.Address.port,
"HASH" : akka.actor.Address.hashCode,
"TIMESTAMP" : akka.cluster.NodeMetrics.timestamp,
"USED" : Number as byte,
"COMMITTED" : Number as byte,
"MAX" : Number as byte
}
CPU:
::
{
"TYPE" : "cpu",
"SYSTEM" : akka.actor.Address.system,
"HOST" : akka.actor.Address.host,
"PORT" : akka.actor.Address.port,
"HASH" : akka.actor.Address.hashCode,
"TIMESTAMP" : akka.cluster.NodeMetrics.timestamp
"SYSTEMLOADAVERAGE" : Number,
"CPUCOMBINED" : Number,
"PROCESSORS" : Number
}
MetricsRegistry sẽ được phân tách bởi
`metrics-json `_.
Xitrum viewer mặc định
~~~~~~~~~~~~~~~~~~~~~~
Xitrum cung cấp metric viewer mặc định tại URL ``/xitrum/metrics/viewer?api_key=``.
URL này hiển thị các đồ thị như trên. Các đồ thị được tạo bởi `D3.js `_.
URL có thể được tạ ra với:
::
import xitrum.Config
import xitrum.metrics.XitrumMetricsViewer
url[XitrumMetricsViewer]("api_key" -> Config.xitrum.metrics.get.apiKey)
Jconsole viewer
~~~~~~~~~~~~~~~
Bạn có thể xem nó với `JVM Reporter `_.
.. image:: ../img/metrics_jconsole.png
Khởi động JMX reporter:
::
import com.codahale.metrics.JmxReporter
object Boot {
def main(args: Array[String]) {
Server.start()
JmxReporter.forRegistry(xitrum.Metrics.registry).build().start()
}
}
Sau đó chạy `jconsole `_ command.
Hiển thị metiric với custom viewer
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Metric sẽ được xuất ra tại SockJS URL ``xitrum/metrics/channel`` như JSON.
``jsAddMetricsNameSpace`` là một JavaScript snippet mà Xitrum cung cấp để tạo
kết nối.
Sử dụng JSON handler của bạn và gọi ``initMetricsChannel`` với handler đó.
Ví dụ về action:
::
import xitrum.annotation.GET
import xitrum.metrics.MetricsViewer
@GET("my/metrics/viewer")
class MySubscriber extends MetricsViewer {
def execute() {
jsAddMetricsNameSpace("window")
jsAddToView("""
function onValue(json) {
console.log(json);
}
function onClose(){
console.log("channel closed");
}
window.initMetricsChannel(onValue, onClose);
""")
respondView()
}
}
Lưu metric
~~~~~~~~~~
Để tiết kiệm bộ nhớ, Xitrum không ghi nhớ các giá trị metric cũ. Nếu bạn muốn lưu metric vào
cơ sở dữ liệu hoặc tập tin nào đó, bạn cần implement vào subscriber của bạn.
Ví dụ:
::
import akka.actor.Actor
import xitrum.metrics.PublisherLookUp
class MySubscriber extends Actor with PublisherLookUp {
override def preStart() {
lookUpPublisher()
}
def receive = {
case _ =>
}
override def doWithPublisher(globalPublisher: ActorRef) = {
context.become {
// When run in multinode environment
case multinodeMetrics: Set[NodeMetrics] =>
// Save to DB or write to file.
// When run in single node environment
case nodeMetrics: NodeMetrics =>
// Save to DB or write to file.
case Publish(registryAsJson) =>
// Save to DB or write to file.
case _ =>
}
}
}