1 监测程序简介
Active Support 提供的监测 API 允许开发者提供钩子,供其他开发者订阅。在 Rails 框架中,有很多。通过这个 API,开发者可以选择在应用或其他 Ruby 代码中发生特定事件时接收通知。
例如,Active Record 中有一个钩子,在每次使用 SQL 查询数据库时调用。开发者可以订阅这个钩子,记录特定操作执行的查询次数。还有一个钩子在控制器的动作执行前后调用,记录动作的执行时间。
在应用中甚至还可以自己创建事件,然后订阅。
2 Rails 框架中的钩子
Ruby on Rails 框架为很多常见的事件提供了钩子。下面详述。
3 Action Controller
3.1 write_fragment.action_controller
{
key: 'posts/1-dashboard-view'
}
|
3.2 read_fragment.action_controller
{
key: 'posts/1-dashboard-view'
}
|
3.3 expire_fragment.action_controller
{
key: 'posts/1-dashboard-view'
}
|
3.4 exist_fragment?.action_controller
{
key: 'posts/1-dashboard-view'
}
|
3.5 write_page.action_controller
3.6 expire_page.action_controller
3.7 start_processing.action_controller
键 |
值 |
:controller |
控制器名 |
:action |
动作名 |
:params |
请求参数散列,不过滤 |
:headers |
请求首部 |
:format |
html、js、json、xml 等 |
:method |
HTTP 请求方法 |
:path |
请求路径 |
{
controller: "PostsController" ,
action: "new" ,
params: { "action" => "new" , "controller" => "posts" },
headers:
format: :html ,
method: "GET" ,
path: "/posts/new"
}
|
3.8 process_action.action_controller
键 |
值 |
:controller |
控制器名 |
:action |
动作名 |
:params |
请求参数散列,不过滤 |
:headers |
请求首部 |
:format |
html、js、json、xml 等 |
:method |
HTTP 请求方法 |
:path |
请求路径 |
:status |
HTTP 状态码 |
:view_runtime |
花在视图上的时间量(ms) |
:db_runtime |
执行数据库查询的时间量(ms) |
{
controller: "PostsController" ,
action: "index" ,
params: { "action" => "index" , "controller" => "posts" },
headers:
format: :html ,
method: "GET" ,
path: "/posts" ,
status: 200 ,
view_runtime: 46 . 848 ,
db_runtime: 0 . 157
}
|
3.9 send_file.action_controller
3.10 send_data.action_controller
ActionController
在载荷(payload)中没有任何特定的信息。所有选项都传到载荷中。
3.11 redirect_to.action_controller
键 |
值 |
:status |
HTTP 响应码 |
:location |
重定向的 URL |
{
status: 302 ,
location: "http://localhost:3000/posts/new"
}
|
3.12 halted_callback.action_controller
{
filter: ":halting_filter"
}
|
4 Action View
4.1 render_template.action_view
键 |
值 |
:identifier |
模板的完整路径 |
:layout |
使用的布局 |
{
identifier: "/Users/adam/projects/notifications/app/views/posts/index.html.erb" ,
layout: "layouts/application"
}
|
4.2 render-partial-action-view
{
identifier: "/Users/adam/projects/notifications/app/views/posts/_form.html.erb"
}
|
4.3 render_collection.action_view
键 |
值 |
:identifier |
模板的完整路径 |
:count |
集合的大小 |
:cache_hits |
从缓存中获取的局部视图数量 |
仅当渲染集合时设定了 cached: true
选项,才有 :cache_hits
键。
{
identifier: "/Users/adam/projects/notifications/app/views/posts/_post.html.erb" ,
count: 3 ,
cache_hits: 0
}
|
5 Active Record
5.1 sql.active_record
键 |
值 |
:sql |
SQL 语句 |
:name |
操作的名称 |
:connection_id |
self.object_id |
:binds |
绑定的参数 |
{
sql: "SELECT \"posts\".* FROM \"posts\" " ,
name: "Post Load" ,
connection_id: 70307250813140 ,
binds: []
}
|
5.2 instantiation.active_record
键 |
值 |
:record_count |
实例化记录的数量 |
:class_name |
记录所属的类 |
{
record_count: 1 ,
class_name: "User"
}
|
6 Action Mailer
6.1 receive.action_mailer
键 |
值 |
:mailer |
邮件程序类的名称 |
:message_id |
邮件的 ID,由 Mail gem 生成 |
:subject |
邮件的主题 |
:to |
邮件的收件地址 |
:from |
邮件的发件地址 |
:bcc |
邮件的密送地址 |
:cc |
邮件的抄送地址 |
:date |
发送邮件的日期 |
:mail |
邮件的编码形式 |
{
mailer: "Notification" ,
message_id: "4f5b5491f1774_181b23fc3d4434d38138e5@mba.local.mail" ,
subject: "Rails Guides" ,
to: [ "users@rails.com" , "ddh@rails.com" ],
from: [ "me@rails.com" ],
date: Sat, 10 Mar 2012 14 : 18 : 09 + 0100 ,
mail: "..."
}
|
6.2 deliver.action_mailer
键 |
值 |
:mailer |
邮件程序类的名称 |
:message_id |
邮件的 ID,由 Mail gem 生成 |
:subject |
邮件的主题 |
:to |
邮件的收件地址 |
:from |
邮件的发件地址 |
:bcc |
邮件的密送地址 |
:cc |
邮件的抄送地址 |
:date |
发送邮件的日期 |
:mail |
邮件的编码形式 |
{
mailer: "Notification" ,
message_id: "4f5b5491f1774_181b23fc3d4434d38138e5@mba.local.mail" ,
subject: "Rails Guides" ,
to: [ "users@rails.com" , "ddh@rails.com" ],
from: [ "me@rails.com" ],
date: Sat, 10 Mar 2012 14 : 18 : 09 + 0100 ,
mail: "..."
}
|
7 Active Support
7.1 cache_read.active_support
键 |
值 |
:key |
存储器中使用的键 |
:hit |
是否读取了缓存 |
:super_operation |
如果使用 #fetch 读取了,添加 :fetch |
7.2 cache_generate.active_support
仅当使用块调用 #fetch
时使用这个事件。
写入存储器时,传给 fetch
的选项会合并到载荷中。
{
key: 'name-of-complicated-computation'
}
|
7.3 cache_fetch_hit.active_support
仅当使用块调用 #fetch
时使用这个事件。
{
key: 'name-of-complicated-computation'
}
|
7.4 cache_write.active_support
{
key: 'name-of-complicated-computation'
}
|
7.5 cache_delete.active_support
{
key: 'name-of-complicated-computation'
}
|
7.6 cache_exist?.active_support
{
key: 'name-of-complicated-computation'
}
|
8 Active Job
8.1 enqueue_at.active_job
键 |
值 |
:adapter |
处理作业的 QueueAdapter 对象 |
:job |
作业对象 |
8.2 enqueue.active_job
键 |
值 |
:adapter |
处理作业的 QueueAdapter 对象 |
:job |
作业对象 |
键 |
值 |
:adapter |
处理作业的 QueueAdapter 对象 |
:job |
作业对象 |
键 |
值 |
:adapter |
处理作业的 QueueAdapter 对象 |
:job |
作业对象 |
9 Railties
9.1 load_config_initializer.railties
键 |
值 |
:initializer |
从 config/initializers 中加载的初始化脚本的路径 |
10 Rails
10.1 deprecation.rails
键 |
值 |
:message |
弃用提醒 |
:callstack |
弃用的位置 |
11 订阅事件
订阅事件是件简单的事,在 ActiveSupport::Notifications.subscribe
的块中监听通知即可。
这个块接收下述参数:
事件的名称
开始时间
结束时间
事件的唯一 ID
载荷(参见前述各节)
ActiveSupport::Notifications.subscribe "process_action.action_controller" do |name, started, finished, unique_id, data|
Rails.logger.info "#{name} Received!"
end
|
每次都定义这些块参数很麻烦,我们可以使用 ActiveSupport::Notifications::Event
创建块参数,如下:
ActiveSupport::Notifications.subscribe "process_action.action_controller" do |*args|
event = ActiveSupport::Notifications::Event. new *args
event.name
event.duration
event.payload
Rails.logger.info "#{event} Received!"
end
|
多数时候,我们只关注数据本身。下面是只获取数据的简洁方式:
ActiveSupport::Notifications.subscribe "process_action.action_controller" do |*args|
data = args.extract_options!
data
end
|
此外,还可以订阅匹配正则表达式的事件。这样可以一次订阅多个事件。下面是订阅 ActionController
中所有事件的方式:
ActiveSupport::Notifications.subscribe /action_controller/ do |*args|
end
|
12 自定义事件
自己添加事件也很简单,繁重的工作都由 ActiveSupport::Notifications
代劳,我们只需调用 instrument
,并传入 name
、payload
和一个块。通知在块返回后发送。ActiveSupport
会生成起始时间和唯一的 ID。传给 instrument
调用的所有数据都会放入载荷中。
下面举个例子:
ActiveSupport::Notifications.instrument "my.custom.event" , this: :data do
end
|
然后可以使用下述代码监听这个事件:
ActiveSupport::Notifications.subscribe "my.custom.event" do |name, started, finished, unique_id, data|
puts data.inspect
end
|
自己定义事件时,应该遵守 Rails 的约定。事件名称的格式是 event.library
。如果应用发送推文,应该把事件命名为 tweet.twitter
。
反馈
我们鼓励您帮助提高本指南的质量。
如果看到如何错字或错误,请反馈给我们。
您可以阅读我们的文档贡献指南。
您还可能会发现内容不完整或不是最新版本。
请添加缺失文档到 master 分支。请先确认 Edge Guides 是否已经修复。
关于用语约定,请查看Ruby on Rails 指南指导。
无论什么原因,如果你发现了问题但无法修补它,请创建 issue。
最后,欢迎到 rubyonrails-docs 邮件列表参与任何有关 Ruby on Rails 文档的讨论。
中文翻译反馈
贡献:https://github.com/ruby-china/guides。