使用 ActiveSupport Around-Callbacks 在调用我的服务时执行代码 (tracing/logging)?
Use ActiveSupport Around-Callbacks to execute code (tracing/logging) around when my services are invoked?
在我的 app/services 目录中,我有一堆服务,每个服务都有一个初始化方法和一个不带参数的 public perform
方法。
显示结构的简单示例服务可能如下所示:
module Users
class CreateService
def initialize(name)
@name = name
end
def perform
# code to create the user
end
end
我的目标是向我的应用程序添加跟踪,这样我就可以跟踪我的每项服务何时被调用,而无需显着修改每项服务的代码。最后,我希望做到这一点,以便在我的任何服务调用其 perform()
方法时,自动生成跟踪。
我相信这应该可以使用 ActiveSupport::Callbacks,类似于 ActiveJob 让我们为我们的工作定义 around_perform 回调的方式。我试图创建一个问题,我可以将其包含在我的服务中,以检测所需的行为
module Traceable
extend ActiveSupport::Concern
include ActiveSupport::Callbacks
included do
include ActiveSupport::Callbacks
define_callbacks :perform
set_callback :perform, :around, lambda { |r, block|
puts "start the trace"
result = block.call
puts "end the trace"
}
end
end
但是,考虑到这个问题后,我想定义的回调(所有服务统一)仍然没有被调用。我怎样才能使这项工作?谢谢!
参考资料:
https://api.rubyonrails.org/classes/ActiveSupport/Callbacks/ClassMethods.html
https://api.rubyonrails.org/classes/ActiveSupport/Callbacks.html
https://edgeapi.rubyonrails.org/classes/ActiveJob/Callbacks/ClassMethods.html#method-i-around_perform(查看around_perform
class方法的源代码)
最干净的方法是使用 prepended.
看起来像这样:
module Traceable
extend ActiveSupport::Concern
prepended do
include ActiveSupport::Callbacks
define_callbacks :trace
set_callback :trace, :around do |_r, block|
puts "start the trace"
block.call
puts "end the trace"
end
end
def perform
run_callbacks :trace do
super
end
end
end
module Users
class CreateService
prepend Traceable
attr_accessor :name
def initialize(name)
@name = name
end
def perform
# code to create the user
puts "perform"
end
end
end
link 有更多详细信息。服务中的 prepend
表示 Users::CreateService.perform
将首先在 Traceable
模块中查找其定义。这允许 Traceable
将 perform
包装在回调中。
由于我们在服务中使用 prepend
而不是 include
,我们需要在 ActiveSupport::Concern
的内部调用 define_callbacks
和 set_callback
prepended
块。
如果您 prepend
服务中的 Traceable
模块,您根本不需要 callbacks
或 concerns
。 Traceable
模块可能只是这个,它会产生相同的结果:
module Traceable
def perform
puts "before"
super
puts "after"
end
end
module Users
class CreateService
prepend Traceable
...
end
end
在我的 app/services 目录中,我有一堆服务,每个服务都有一个初始化方法和一个不带参数的 public perform
方法。
显示结构的简单示例服务可能如下所示:
module Users
class CreateService
def initialize(name)
@name = name
end
def perform
# code to create the user
end
end
我的目标是向我的应用程序添加跟踪,这样我就可以跟踪我的每项服务何时被调用,而无需显着修改每项服务的代码。最后,我希望做到这一点,以便在我的任何服务调用其 perform()
方法时,自动生成跟踪。
我相信这应该可以使用 ActiveSupport::Callbacks,类似于 ActiveJob 让我们为我们的工作定义 around_perform 回调的方式。我试图创建一个问题,我可以将其包含在我的服务中,以检测所需的行为
module Traceable
extend ActiveSupport::Concern
include ActiveSupport::Callbacks
included do
include ActiveSupport::Callbacks
define_callbacks :perform
set_callback :perform, :around, lambda { |r, block|
puts "start the trace"
result = block.call
puts "end the trace"
}
end
end
但是,考虑到这个问题后,我想定义的回调(所有服务统一)仍然没有被调用。我怎样才能使这项工作?谢谢!
参考资料:
https://api.rubyonrails.org/classes/ActiveSupport/Callbacks/ClassMethods.html
https://api.rubyonrails.org/classes/ActiveSupport/Callbacks.html
https://edgeapi.rubyonrails.org/classes/ActiveJob/Callbacks/ClassMethods.html#method-i-around_perform(查看around_perform
class方法的源代码)
最干净的方法是使用 prepended.
看起来像这样:
module Traceable
extend ActiveSupport::Concern
prepended do
include ActiveSupport::Callbacks
define_callbacks :trace
set_callback :trace, :around do |_r, block|
puts "start the trace"
block.call
puts "end the trace"
end
end
def perform
run_callbacks :trace do
super
end
end
end
module Users
class CreateService
prepend Traceable
attr_accessor :name
def initialize(name)
@name = name
end
def perform
# code to create the user
puts "perform"
end
end
end
link 有更多详细信息。服务中的 prepend
表示 Users::CreateService.perform
将首先在 Traceable
模块中查找其定义。这允许 Traceable
将 perform
包装在回调中。
由于我们在服务中使用 prepend
而不是 include
,我们需要在 ActiveSupport::Concern
的内部调用 define_callbacks
和 set_callback
prepended
块。
如果您 prepend
服务中的 Traceable
模块,您根本不需要 callbacks
或 concerns
。 Traceable
模块可能只是这个,它会产生相同的结果:
module Traceable
def perform
puts "before"
super
puts "after"
end
end
module Users
class CreateService
prepend Traceable
...
end
end