Остановите ActiveSupport :: TaggedLogging от вмешательства в структурированные журналы - PullRequest
0 голосов
/ 15 октября 2019

ActiveSupport::TaggedLogging работает путем добавления ActiveSupport::TaggedLogging::Formatter в цепочку наследования текущего средства форматирования через Object#extend.

К сожалению, ActiveSupport::TaggedLogging::Formatter#call предполагает, что аргумент msg всегда является строкой, что приводит к мусорукогда он добавляет теги к хешу (например, с помощью Lograge и Ougai ). И некоторые стандартные библиотеки, такие как Webpacker , настаивают на введении TaggedLogging.

Я предложил метод метапрограммирования ниже, чтобы предотвратить переопределение ActiveSupport::TaggedLogging::Formatter#call реализации суперкласса (в этомдело от Ougai):

class MyBunyanFormatter < Ougai::Formatters::Bunyan
  def extend(mod)
    return super unless mod.method_defined?(:call)

    call_original = self.method(:call)            # 1. preserve original
    super(mod)                                    # 2. overridden here
    define_singleton_method(:call, call_original) # 3. de-overridden here
  end
end

Но это неуклюже и нелогично, и я не в восторге от этого.

Другая альтернатива, , по крайней мере, в случае с Webpacker , кажется, для написания собственного регистратора, который реализует tagged():

class MyLogger < Ougai::Logger
  def tagged(*tags)
    # do something with tags
    yield self
  end
end

Это, по крайней мере, не связано с метапрограммированием махинаций, но мне интересно, могу ли я рассчитывать на другие библиотеки, кроме Webpacker? впрыскивать TaggedLogging в любом случае.

Конечно, я не первый, у кого возникла эта проблема, так как люди начали пытаться делать структурированную регистрацию из приложений Rails. Какое правильное решение?

1 Ответ

0 голосов
/ 15 октября 2019

Решение, приведенное в Документах Ougai , состоит в том, чтобы обезопасить TaggedLogging, чтобы устранить это поведение.

module ActiveSupport::TaggedLogging::Formatter
  def call(severity, time, progname, data)
    data = { msg: data.to_s } unless data.is_a?(Hash)
    tags = current_tags
    data[:tags] = tags if tags.present?
    _call(severity, time, progname, data)
  end
end

Обратите внимание, что _call работает, только если для Ougai-basedFormatters.

...