指标#

Mars 拥有统一的指标 API 和三个不同的后端。

统一指标 API#

Mars 指标 API 位于 mars/metrics/api.py,并且有四种指标类型:

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

  • Gauge 是一个单一的数值。

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

  • Histogram 是一种统计方法,用于记录窗口数据的平均值。

我们可以如下使用这些类型:

# 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,并且标签的键必须与 tag_keys 一致。

三种不同的后端#

Mars 指标支持三种不同的后端:

  • console 用于调试,它只是打印值。

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

  • ray 是一个度量后端,它仅在 ray 引擎上运行。

控制台#

默认度量后端是 console。当日志级别为 debug 时,它只是记录该值。

普罗米修斯#

首先,我们应该下载Prometheus。有关详细信息,请参阅 Prometheus 入门指南

其次,我们可以通过配置Prometheus后端来新建一个Mars会话,如下所示:

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 任务:

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

Ray#

我们可以在创建Ray集群或新建会话时配置 metrics.backend

指标命名规范#

我们为指标提出以下命名规范:

命名空间.[组件].指标名称[_单位]

  • namespace 可以是 mars

  • component 可以是 supervisorworkerband 等,可以省略。

  • units 是当记录时间时可能是秒的度量单位,或者在度量类型为 Counter 时为 _count,如果度量类型为 Gauge 则为 _number,如果没有合适的单位。