Rails日志实现探索(2)

日志功能实现

Rails中对日志的处理采用的是“消息-订阅”机制,各部分组件和功能如下:

日志消息的发送:ActiveSupport::Notifications

  • instrument: 通知所有的 subscribers

扩展:可在通知前先执行一个代码块;

ActiveSupport::Notifications.instrument('render', extra: :information) do
  render text: 'Foo'
end
  • ActiveSupport::Notifications::Instrumenter: 下发通知的组织

  • ActiveSupport::Notifications::Fanout: 下发通知的执行人

工作流程

安排下发通知的人

# 1、每个事件分配一个执行人员(员工)
ActiveSupport::Notifications.notifier = ActiveSupport::Notifications::Fanout.new

# 2、不能瞎指派员工,指派的员工须得有这个能力
if notifier.listening?(name)
  instrumenter.instrument(name, payload) { yield payload if block_given? }
end

# 3、通过员工的上级领导(cto)分配工作
def instrumenter
  InstrumentationRegistry.instance.instrumenter_for(notifier)
end

具体工作

1、Instrumenter安排工作

# Send a start notification with +name+ and +payload+.
def start(name, payload)
  @notifier.start name, @id, payload
end

# Send a finish notification with +name+ and +payload+.
def finish(name, payload)
  @notifier.finish name, @id, payload
end

2、Fanout 接受任务开始干活

def start(name, id, payload)
  listeners_for(name).each { |s| s.start(name, id, payload) }
end

def finish(name, id, payload)
  listeners_for(name).each { |s| s.finish(name, id, payload) }
end

def publish(name, *args)
  listeners_for(name).each { |s| s.publish(name, *args) }

  # s 为`ActiveSupport::Notifications::Fanout::Subscribers::Evented`实例
end

干活的人多了个publish方法,反馈任务(员工需要汇报工作)

3、ActiveSupport::Notifications::Fanout::Subscribers::Evented 具体的任务

def publish(name, *args)
  if @can_publish
    @delegate.publish name, *args
  end
end

def start(name, id, payload)
  @delegate.start name, id, payload
end

def finish(name, id, payload)
  @delegate.finish name, id, payload
end

delegate 这个又是谁呢?

答案揭晓

其实这个员工他也不干活,他将工作外包出去了!!!