Metrics#

Mars 有一个统一的 metrics API 和三个不同的后端。

统一的 Metrics API#

Mars metrics API 在 mars/metrics/api.py,有四种 metric 类型:

  • Counter 是一种累积类型的数据,代表一个单调递增的数字。

  • Gauge 是一个单一的数值。

  • Meter 是一组事件发生的速率。 我们可以将其用作 qps 或 tps。

  • Histogram 是一种统计类型,它记录窗口数据的平均值。

我们可以如下使用这几种 metrics:

# Four metrics have a unified parameter list:
# 1. Declarative method: Metrics.counter(name: str, description: str = "", tag_keys: Optional[Tuple[str]] = None)
# 2. Record method: record(value=1, tags: Optional[Dict[str, str]] = None)

c1 = Metrics.counter('counter1', 'A counter')
c1.record(1)

c2 = Metrics.counter('counter2', 'A counter', ('service', 'tenant'))
c2.record(1, {'service': 'mars', 'tenant': 'test'})

g1 = Metrics.gauge('gauge1')
g1.record(1)

g2 = Metrics.gauge('gauge2', 'A gauge', ('service', 'tenant'))
g2.record(1, {'service': 'mars', 'tenant': 'test'})

m1 = Metrics.meter('meter1')
m1.record(1)

m2 = Metrics.meter('meter1', 'A meter', ('service', 'tenant'))
m2.record(1, {'service': 'mars', 'tenant': 'test'})

h1 = Metrics.histogram('histogram1')
h1.record(1)

h2 = Metrics.histogram('histogram1', 'A histogram', ('service', 'tenant')))
h2.record(1, {'service': 'mars', 'tenant': 'test'})

注意:如果声明了 tag_keys,调用 record 方法时必须指定 tags 参数,并且 tags 的 keys 必须跟 tag_keys 保持一致。

三种不同的后端#

Mars metrics 支持3种不同的后端:

  • console 是用来调试的,只打印出 metric 值。

  • prometheus 一个开源系统监控和报警工具包。

  • ray 是一种运行在 ray 引擎上的 metric 后端。

Console#

默认的 metric 后端是 console. 它只是在日志级别为 debug 时打印出 metric 的值。

Prometheus#

首先,我们需要下载 Prometheus。具体的可以参考 Prometheus Getting Started.

其次,我们可以如下配置 Prometheus 后端来启动一个 Mars session:

In [1]: import mars

In [2]: session = mars.new_session(
   ...:     n_worker=1,
   ...:     n_cpu=2,
   ...:     web=True,
   ...:     config={"metrics.backend": "prometheus"}
   ...: )
Finished startup prometheus http server and port is 15768
Finished startup prometheus http server and port is 44303
Finished startup prometheus http server and port is 63391
Finished startup prometheus http server and port is 13722
Web service started at http://0.0.0.0:15518

第三,我们要配置 Prometheus,更多的配置可以参考 Prometheus Configuration.

scrape_configs:
  - job_name: 'mars'

    scrape_interval: 5s

    static_configs:
      - targets: ['localhost:15768', 'localhost:44303', 'localhost:63391', 'localhost:13722']

接着,启动 Prometheus:

$ prometheus --config.file=promconfig.yaml
level=info ts=2022-06-07T13:05:01.484Z caller=main.go:296 msg="no time or size retention was set so using the default time retention" duration=15d
level=info ts=2022-06-07T13:05:01.484Z caller=main.go:332 msg="Starting Prometheus" version="(version=2.13.1, branch=non-git, revision=non-git)"
level=info ts=2022-06-07T13:05:01.484Z caller=main.go:333 build_context="(go=go1.13.1, user=brew@Mojave.local, date=20191018-01:13:04)"
level=info ts=2022-06-07T13:05:01.485Z caller=main.go:334 host_details=(darwin)
level=info ts=2022-06-07T13:05:01.485Z caller=main.go:335 fd_limits="(soft=256, hard=unlimited)"
level=info ts=2022-06-07T13:05:01.485Z caller=main.go:336 vm_limits="(soft=unlimited, hard=unlimited)"
level=info ts=2022-06-07T13:05:01.487Z caller=main.go:657 msg="Starting TSDB ..."
level=info ts=2022-06-07T13:05:01.488Z caller=web.go:450 component=web msg="Start listening for connections" address=0.0.0.0:9090
level=info ts=2022-06-07T13:05:01.494Z caller=head.go:514 component=tsdb msg="replaying WAL, this may take awhile"
level=info ts=2022-06-07T13:05:01.495Z caller=head.go:562 component=tsdb msg="WAL segment loaded" segment=0 maxSegment=1
level=info ts=2022-06-07T13:05:01.495Z caller=head.go:562 component=tsdb msg="WAL segment loaded" segment=1 maxSegment=1
level=info ts=2022-06-07T13:05:01.497Z caller=main.go:672 fs_type=1a
level=info ts=2022-06-07T13:05:01.497Z caller=main.go:673 msg="TSDB started"
level=info ts=2022-06-07T13:05:01.497Z caller=main.go:743 msg="Loading configuration file" filename=promconfig_mars.yaml
level=info ts=2022-06-07T13:05:01.501Z caller=main.go:771 msg="Completed loading of configuration file" filename=promconfig_mars.yaml
level=info ts=2022-06-07T13:05:01.501Z caller=main.go:626 msg="Server is ready to receive web requests."

第四,执行一个 Mars task:

In [3]: import numpy as np

In [4]: import mars.dataframe as md

In [5]: df1 = md.DataFrame(np.random.randint(0, 3, size=(10, 4)),
   ...:                    columns=list('ABCD'), chunk_size=5)
   ...: df2 = md.DataFrame(np.random.randint(0, 3, size=(10, 4)),
   ...:                    columns=list('ABCD'), chunk_size=5)
   ...:
   ...: r = md.merge(df1, df2, on='A').execute()

最后,我们可以在 Prometheus 的网页端 http://localhost:9090 查看 metrics。

Ray#

我们可以在创建 Ray cluster 时或新建 session 时配置 metrics.backend

Metrics 命名约定#

我们提出一种如下的 metrics 命名约定:

namespace.[component].metric_name[_units]

  • namespace 可以是 mars

  • component 可以是 supervisorworkerband 等等,也可以省略这个参数。

  • units 是 metric 的单位,当记录的是时间时,可以用 seconds,当没有合适的单位时,Counter 类型的 metric 可以用 _countGauge 类型的 metric 可以用 _number