Rails 中度量指标入门

导航到

如果你像我一样,你对度量指标领域是新手。你听到它的诱惑,想要了解更多,但不知道从何开始。每次你开始教程时,你都会被教程中使用的词汇分散注意力(也许这只是一部分是我)。这可能是一个陡峭的学习曲线。

<figcaption> 有朝一日我会成为巫师</figcaption>

Rails 中的度量指标

我决定从我知道的技能开始,尝试添加少量度量工具,看看我能从简单的 Rails 应用中学到什么。Rails 是一个好的选择,原因有两个:(1)我知道如何编写 Ruby 并使用 Rails,因此我可以专注于度量,(2)Rails 经常没有被衡量,因为我们使用强大的测试套件和其他工具来告诉我们正在发生什么。

我像弗兰肯斯坦一样,复活了一个旧应用,拼凑在一起直到它醒来。它没有样式,删除操作似乎有问题,它是测量的完美候选人。欢迎来到 Blogger(你可以在我的 Github 上找到源代码)。

<figcaption> 看啊!</figcaption>

我们想了解这个应用什么?一般来说,我们想知道它是否以意外的方式进行失败,它处理了多少请求,以及是否像弗兰肯斯坦一样,表现得非常糟糕,进行了一场狂欢,只提供 404。请求数据可能不是最复杂的指标,但其价值是直接的;对于 Blogger 来说,至少我们期望它存在并提供 200 状态码,所以这是一个好的起点。

市面上有很多工具可以收集指标,每个工具都有适合它的用例。知道从哪里开始是最困难的部分,所以我听取了朋友的建议,观看了 Coda Hale 的演讲 “度量,无处不在”。他出色地解释了仪表的价值(总结来说,我们测量事物,因为它们帮助我们形成一个准确的心理地图,了解它们的成本)。这确实帮助我克服了我在尝试跨越的词汇/知识差距。

Coda 的演讲引导我到 John Ewart 的 Ruby 度量库ruby-metrics,它是基于 Coda 的度量库metrics(为清晰的命名加分)。Ruby-metrics 有一个很好的 README,所以它是初学者的完美候选人。

<figcaption> 我在吸收知识</figcaption>

在我的 Gemfile 中添加了 'ruby-metrics' 并进行捆绑后,这是我在 Rails 应用程序中添加的内容。

config.middleware.use(
  Metrics::Integration::Rack::Middleware, :agent => Metrics::Agent.new, :show => '/stats'
)

就这么多。这个 Rack 中间件位于 application.rb 中,并创建了一个名为 ‘/stats’ 的端点,该端点提供 JSON 有效载荷。通过 ruby-metrics 获取指标有多种方式,但 ‘/stats’ 路径在 Rails 场景中很熟悉,也容易理解。

{
  "_requests": {
    "count": 6,
    "rates": {
      "one_minute_rate": 0.062685889170148,
      "five_minute_rate": 0.013168198374952,
      "fifteen_minute_rate": 0.0044259829392568,
      "unit": "seconds"
    },
    "durations": {
      "min": 7.6055526733398e-5,
      "max": 0.38426399230957,
      "mean": 0.070876717567444,
      "percentiles": {
        "0.25": 0.0034220218658447,
        "0.5": 0.010805130004883,
        "0.75": 0.016463041305542,
        "0.95": 0.29253399372101,
        "0.97": 0.32922599315643,
        "0.98": 0.34757199287415,
        "0.99": 0.36591799259186
      },
      "unit": "seconds"
    }
  },
  "_uncaught_exceptions": 0,
  "_status_1xx": 0,
  "_status_2xx": 4,
  "_status_3xx": 0,
  "_status_4xx": 2,
  "_status_5xx": 0
}

看看所有这些数字!

然后是 JSON

突然有了数据!我甚至知道一些数据的含义。虽然我们可以解析这些数据并理解这些指标,但可视化不更容易快速了解重要细节吗?一切是否正常?Frankenstein 是否正在攻击村民?

为了了解情况,我们需要一些帮助。同样,有很多工具可用。如果我能在我的博客应用程序中填充来自《星球大战》宇宙的随机行星,任何事情都可能发生,梦想也会成真。我的观点是,如果你有一个喜欢的可视化工具,请使用它。对于这个示例,我将使用 Chronograf,因为它易于设置,我也喜欢制作它的人。

这也是我再次滑回学习曲线的过程。我所知道的是:我在 ‘/stats’ 端点有一个 JSON 有效载荷,并想使用 Chronograf 来查看这些数据。

我的思考过程

如果您正在跟随,并且您之前尚未安装 TICK Stack,这里有一个快速、5分钟的指南来 开始

配置 Telegraf

正如互联网和我的一些同事很快告诉我的那样,上图中的魔法森林的一部分是 Telegraf,它仅用于收集数据,而另一部分是 Chronograf 可以连接到的数据库。为了在 Chronograf 中查看我的统计信息,我们需要设置一个管道。幸运的是,Telegraf 是由插件驱动的,有两种类型的插件听起来完全合适:输入和输出。其中一个输入非常突出:httpjson。砰——那是这一端。我是通过 Telegraf 的 入门指南找到了我的 telegraf 配置文件。它取决于您的操作系统,但在 MacOS 上,它位于 /usr/local/etc/telegraf.conf。您可以使用 Telegraf 生成一个示例配置文件,但过多的信息可能会让人感到不知所措(至少对我来说是这样的)。

[[inputs.httpjson]]
## Name for the service being polled. Will be appended to the name of the
## measurement e.g. "httpjson_webserver_stats".
##
## Deprecated (1.3.0): Use name_override, name_suffix, name_prefix instead.
name = "webserver_stats"

名称保留为默认值,但如果我以后决定使用多个输入插件,我会更改它。此外,这里有一个关于弃用的说明,我一直想注意,但尝试使用除名称之外的其他东西总是会导致崩溃。我想跟进这个问题,因为我不想保留弃用的代码(当我弄清楚时会更新 Blogger)。

## URL of each server in the service's cluster
servers = [
"https://127.0.0.1:3000/stats"
]

我用 Blogger 的统计信息的位置替换了样板地址。

## Set response_timeout (default 5 seconds)
response_timeout = "5s"

文档建议减少响应超时可能不是一个好主意。我同意他们的看法。

## HTTP method to use: GET or POST (case-sensitive)
method = "GET"

这默认为 GET,这对 Blogger 来说很完美。我有一个想法,如果需要授权才能访问端点,这可能会如何改变。目前,我脆弱但本地的端点应该可以工作。

在这个步骤上我又遇到了一堵墙。我可能已经连接了我的输入插件。但是我不敢肯定——我也不知道怎么才能确定。在花了很多时间寻找深入Telegraf查看发生了什么的方法(我相信这是可能的,而且可能并不那么复杂)之后,我决定跳到输出插件。如果我能够将Telegraf连接到数据库,我就可以检查管道是否工作正常。

对于我的数据库,我几乎选择了Postgres,因为我以前使用过它,很熟悉。然而,当我想到关系数据库的结构时,我觉得它不太合适。我不想为了存储博客统计数据而做很多工作,所以我需要一种更灵活的格式。另一个因素是,我的博客统计数据似乎随着时间的推移比单独的数据更有价值。一次失败对我来说没问题——但失败模式就令人沮丧,可能没有人会在我那令人沮丧的博客应用上写博客。

我选择了InfluxDB;作为时序数据库,它可以按时间段分组数据点,并且不需要预定义的模式。再次提到,我查阅了InfluxDB输出插件的README来设置配置文件。与我的早期努力相反,输入和输出插件可以放在同一个文件中。

[[outputs.influxdb]]
## The full HTTP or UDP URL for your InfluxDB instance.
##
## Multiple urls can be specified as part of the same cluster,
## this means that only ONE of the urls will be written to each interval.
# urls = ["udp://127.0.0.1:8089"] # UDP endpoint example
urls = ["http://127.0.0.1:8086"] # required

InfluxDB的默认端口是8086,这是我们希望数据最终到达的地方。

## The target database for metrics (telegraf will create it if not exists).
database = "metrics" # required

就像往常一样,我可以给它起任何我想要的名称,这很诱人,但如果我称之为gravy_train,我会期望它满是酱汁,而不是指标。

## Write timeout (for the InfluxDB client), formatted as a string.
## If not provided, will default to 5s. 0s means no timeout (not recommended).
timeout = "5s"

说实话,我会在某个时候将其更改为零以看看会发生什么。但今天不是那天。

可视化我的指标

这时,我汗流浃背,又饿又渴,我需要这个系统能够工作。是时候运行博客和Telegraf了。请记住,您的配置文件路径是相对的。

rails s
telegraf --config telegraf.conf

我在博客上点击了几下,满怀希望地看着它成功或失败。我检查了'/stats'端点。数字都在那里。

<figcaption> 不要呕吐,不要呕吐</figcaption>

检查统计数据是否通过管道的最佳方法是使用Influx CLI。

$influx

您应该看到确认信息,表明您已连接到InfluxDB。

>SHOW DATABASES

希望您至少能看到_internal和metrics(或您的数据库名称)。

>USE metrics

这是我们告诉InfluxDB我们想要查询哪个数据库的方法。

>SHOW measurements

如果星星都排成一行(也就是管道),我们应该会看到这里列出了httpjson数据。

现在统计数据已经进入数据库(好开心啊!),我可以在Chronograf中看到好消息。我进入Chronograf的仪表板选项卡,创建了一个新的仪表板,并从列表中选择了我的数据库。这是一张我制作的过去五分钟每分钟总请求数量的图表。

<figcaption> 选择仪表板选项卡。</figcaption>

<figcaption> 选择创建新仪表板,然后添加图表。</figcaption>

<figcaption> 选择添加查询。选择您的数据库、测量和字段。</figcaption>

<figcaption> 我将requests_count函数改为计数而不是平均值,以便我可以看到每个请求。点击绿色的勾号!</figcaption>

<figcaption> 我将时间窗口改为了最后五分钟。真是太美了。</figcaption>

我没哭,是你哭了。

一场舞会和几包Skittles之后,我从成功查看我的统计数据的高潮中平静下来。在探索过程中,我的解决方案感觉很好,但也有一些问题。一个问题就是它只在本地上运行,而对于这样一个应用程序来说,生产才是关键。坦白说,有很多工具可以查看网站流量。我想知道我的应用程序表现得好不好——这个工具做不到这一点。然而,这些都是我经过与ruby-metrics和Telegraf的探索阶段后才能得出的结论。

我还想知道更多:当博客数量增加,请求更加频繁时,数据库会如何表现?如果将其移入容器或虚拟环境,Blogger会怎样?我应该监控容器还是应用程序?或者两者都要?我开始看到指标如何从整体上提高我的应用程序,甚至作为开发者的我。

目前,我将平滑Blogger的瑕疵——可能添加一些CSS。我要将其移入生产,确保我的管道能承受得住。然后我将再次尝试破坏整个系统——并测量其失败和成功。