使用 InfluxDB 监控 Ruby on Rails
作者:社区 / 产品
2022年06月08日
导航至
本文由 Aniket Bhattacharyea 撰写,最初发表于 The New Stack。向下滚动查看作者简介和照片。
像 InfluxDB 这样的时序数据库是专门用于处理 时序数据的数据库,时序数据是按时间索引的数据。与传统数据库不同, 时序数据库 针对数据的读取和写入进行了优化,而对更新或删除数据的性能考虑较少。
由于时序数据的时间依赖性,时序数据库非常适合应用程序监控。如果您有 Ruby on Rails 应用程序,监控应用程序的性能以确保其平稳运行至关重要。
使用时序数据库,您可以存储来自应用程序的指标,例如已处理的请求数、消耗的内存量以及生成响应所花费的时间。在本文中,您将学习如何使用 InfluxDB 监控 Ruby on Rails 应用程序。
如果您想克隆项目并在自己的编辑器中跟随操作,这是 GitHub 仓库的链接。
先决条件
要学习本教程,您需要以下内容
- 您的计算机上已安装并设置 Docker。您需要 Docker 来运行 InfluxDB 服务器。或者,如果您不想在计算机上安装任何东西,可以使用 InfluxDB Cloud 获取免费运行的 InfluxDB 实例。
- 您的计算机上已安装最新版本的 Ruby on Rails。您可以运行 rails -v 来检查 Rails 是否正确安装。
设置 InfluxDB
在本文中,您将使用 Docker 运行本地 InfluxDB 实例。首先,使用以下命令启动 InfluxDB 容器
docker run --name influxdb -d -p 8086:8086 influxdb:2.1.1
在浏览器中访问 http://localhost:8086
以访问 InfluxDB 欢迎界面。您需要提供用户名和密码,并创建一个新的组织和存储桶。
单击“稍后配置”以访问仪表板。
在左侧边栏中,您将看到一个名为“数据”的菜单项。单击它并选择“API 令牌”选项卡。在那里,您会找到 InfluxDB 创建的默认令牌。将此令牌保存在安全的地方,以便您稍后在本教程中再次访问它。
设置 Rails 应用程序
接下来,您需要使用 rails new
命令创建一个新的 Rails 应用程序
rails new influxdb-demo
然后移动到 influxdb-demo
目录
cd influxdb-demo
请注意,此应用程序使用 SQLite 数据库,因为这仅用于演示目的,但您也可以使用 PostgreSQL 或 MySQL。
接下来,您需要使用 rails db:create
命令创建数据库
rails db:create
由于您将在应用程序中检测数据库交互,因此您需要一些与数据库交互的东西。您可以使用 Rails 的 scaffold 功能快速生成功能齐全的 CRUD API,而无需编写任何代码
rails g scaffold post title:text body:text
这将生成一个 Post
模型,其中包含 title
和 body
属性以及必要的 CRUD 端点。
通过运行 rails db:migrate
迁移数据库。
InfluxDB 有一个 influxdb-rails gem,可以自动检测 Rails 应用程序,但在撰写本文时,它不支持 InfluxDB 2.0,因此您将改用 influxdb-client gem。打开 Gemfile
并添加以下行
gem "influxdb-client", "~> 2.3.0"
然后通过运行 bundle install 安装 gem。
设置检测
您可能想知道,“我究竟该如何从 Rails 应用程序收集指标?” 幸运的是,像 Rails 中的其他一切一样,检测也是内置的。Active Support Instrumentation API 为您提供了无数的 Action Controller、Active Storage、Action Mailer、Active Record、Action View 和其他您可以订阅的事件。它还使您能够检测自定义事件。
要订阅事件,您需要使用 ActiveSupport::Notifications.subscribe
和一个在事件触发时调用的代码块。该代码块接收事件的名称、开始和结束时间、触发事件的检测器的唯一 ID 以及包含取决于事件的不同信息的有效负载。例如,以下代码订阅 process_action.action_controller
事件,该事件将在 Rails 应用程序处理请求时触发
ActiveSupport::Notifications.subscribe "process_action.action_controller" do |name, started, finished, unique_id, data|
Rails.logger.info "#{name} Received! (started: #{started}, finished: #{finished})"
end
在本文中,您将订阅以下事件,但您可以根据需要添加任意数量的事件
process_action.action_controller
:在处理请求时触发render_template.action_view
:在渲染模板时触发sql.active_record
:在执行 SQL 查询时触发instantiation.active_record
:在一个或多个 Active Record 对象被实例化时触发
创建一个新的 config/initializers/influxdb.rb
文件,您最终将在其中添加逻辑。
现在,您需要通过实现以下代码来实例化 InfluxDB 客户端
client = InfluxDB2::Client.new(
'http://localhost:8086',
'YOUR_TOKEN',
bucket: 'YOUR_BUCKET',
org: 'YOUR_ORGANIZATION',
precision: InfluxDB2::WritePrecision::NANOSECOND,
use_ssl: false
)
write_api = client.create_write_api
将 YOUR_TOKEN
替换为您从 InfluxDB 获取的令牌,将 YOUR_BUCKET
替换为存储桶名称,并将 YOUR_ORGANIZATION
替换为组织名称。如果您使用的是云帐户,您还需要将 localhost URL 替换为您的云区域 URL。
现在,我们需要订阅第一个事件。以下代码设置订阅
ActiveSupport::Notifications.subscribe "process_action.action_controller" do |name, started, finished, unique_id, data|
# Send data to influxdb
end
在代码块内,您需要设置要发送到 InfluxDB 的数据点。您可以使用 四种数据格式。在这里,您将使用哈希
ActiveSupport::Notifications.subscribe "process_action.action_controller" do |name, started, finished, unique_id, data|
hash = {
name: "process_action.action_controller",
tags: {
method: "#{data[:controller]}##{data[:action]}",
format: data[:format],
http_method: data[:method],
status: data[:status],
exception: data[:exception]&.first
},
fields: {
time_in_controller: (finished - started) * 1000,
time_in_view: (data[:view_runtime] || 0).ceil,
time_in_db: (data[:db_runtime] || 0).ceil,
},
time: started
}
write_api.write(data: hash)
end
在上面的代码中,name
键表示测量的名称,该名称设置为事件的名称。tags
键设置 标签。
在代码中,使用了五个标签
- 调用的 Ruby 方法。这将是处理请求的控制器类的方法。
- 请求的格式 (html/json/xml)。
- 请求的 HTTP 方法 (GET, POST, PUT 等)。
- 响应的 HTTP 状态代码。
- 发生的异常 (如果有)。
fields
键保存测量的 字段,并使用以下三个字段
- 处理请求所花费的总时间 (以毫秒为单位)。
- 渲染视图所花费的总时间 (以毫秒为单位)。
- 查询数据库所花费的总时间 (以毫秒为单位)。
最后,time
键用于设置数据的时间戳。此键的值是事件触发的时间。
数据点设置完成后,write_api.write
用于将数据写入 InfluxDB。
第二个订阅是针对 render_template.action_view
事件
ActiveSupport::Notifications.subscribe "render_template.action_view" do |name, started, finished, unique_id, data|
hash = {
name: "render_template.action_view",
tags: {
identifier: data[:identifier],
layout: data[:layout],
exception: data[:exception]&.first
},
fields: {
duration: (finished - started) * 1000
},
time: started
}
write_api.write(data: hash)
end
这次唯一的区别在于 tags
和 fields
键。identifier
标签告诉渲染了哪个模板,layout
标签告诉应用了哪个布局。duration
字段表示渲染模板所花费的时间 (以毫秒为单位)。
第三个订阅是针对 sql.active_record
事件
ActiveSupport::Notifications.subscribe "sql.active_record" do |name, started, finished, unique_id, data|
hash = {
name: "sql.active_record",
tags: {
name: data[:name],
statement_name: data[:statement_name],
exception: data[:exception]&.first
},
fields: {
duration: (finished - started) * 1000
},
time: started
}
write_api.write(data: hash)
end
在这里,name
标签保存操作的名称,statement_name
标签保存 SQL 语句的名称。duration
字段计算查询执行所花费的时间 (以毫秒为单位)。
最后一个订阅是针对 instantiation.active_record
字段
ActiveSupport::Notifications.subscribe "instantiation.active_record" do |name, started, finished, unique_id, data|
hash = {
name: "instantiation.active_record",
tags: {
class_name: data[:class_name],
exception: data[:exception]&.first
},
fields: {
duration: (finished - started) * 1000,
record_count: data[:record_count]
},
time: started
}
write_api.write(data: hash)
end
class_name
标签表示实例化的 Active Record 对象的类名。duration
字段表示实例化对象所花费的时间 (以毫秒为单位),record_count
字段表示实例化了多少条记录。
设置就完成了!现在您可以开始使用应用程序生成指标。
生成指标
检测设置完成后,就可以使用应用程序生成一些指标了。通过运行 rails s
启动 Rails 服务器,并访问 http://localhost:3000/posts
。您将看到帖子索引页面
单击“新帖子
”以创建新帖子。
输入标题和正文,然后单击“创建帖子”。
单击“返回帖子
”以返回帖子列表。
单击任何帖子下的“显示此帖子
”以在单独的页面上查看帖子。
单击“编辑此帖子
”进行编辑,或单击“删除此帖子
”进行删除。
现在您可以根据需要创建、编辑和删除任意数量的帖子。完成后,返回 InfluxDB 仪表板以可视化数据。
可视化数据
在 InfluxDB 仪表板中,单击“Explore”选项卡。在这里,您将看到一个交互式查询构建器,可让您可视化您选择的数据。让我们首先可视化创建帖子花费了多少时间。
首先,在“From”选项卡中选择您的存储桶
后续选项卡将让您选择如何过滤数据。
确保在下一个选项卡中选择 _measurement
,并从列表中选择 process_action.action_controller
在以下过滤器面板中选择 method
作为键,并选择 PostController#create
作为标签
最后,在 _field
过滤器中选择三个字段
从右侧的下拉列表中选择适当的时间范围 (例如,“过去 15 分钟”),然后单击“提交”。您将看到一个带有数据的闪亮新图表
现在,让我们可视化渲染视图所花费的时间。这次,您将使用 Flux 查询数据。
单击“脚本编辑器”,这将打开一个编辑器窗口,您可以在其中编写 Flux 查询。然后粘贴以下查询
from(bucket: "influxdb-rails")
|> range(start: -20m)
|> filter(fn: (r) => r["_measurement"] == "render_template.action_view")
|> filter(fn: (r) => r["_field"] == "duration")
|> aggregateWindow(every: 30s, fn: mean)
单击“提交”,您将看到数据以图表形式显示。
继续尝试您收集的所有不同指标。
结论
InfluxDB 使收集和可视化来自 Ruby on Rails 应用程序的检测数据变得容易。使用 ActiveSupport instrumentation API,您可以从应用程序收集不同的指标并将它们存储在 InfluxDB 中。
本文仅向您展示了您可以收集的少量指标。您可以在此处找到指标的完整列表。如果没有内置指标适合您的需求,您也可以创建自己的。一切皆有可能!
关于作者
Aniket 是一名数学硕士研究生,对计算机和软件充满热情。他喜欢探索与编码相关的各个领域,并使用 Ruby on Rails 和 Vue.JS 作为 Web 开发人员工作。