Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a public API for broadcasting logs #48615

Merged
merged 1 commit into from
Sep 25, 2023
Merged

Commits on Sep 25, 2023

  1. Add a public API for broadcasting logs:

    - ## Context
    
      While working on rails#44695, I
      realised that Broadcasting was still a private API, although it’s
      commonly used. Rafael mentioned that making it public would require
      some refactor because of the original implementation which was hard
      to understand and maintain.
    
      ### Changing how broadcasting works:
    
      Broadcasting in a nutshell worked by “transforming” an existing
      logger into a broadcasted one.
      The logger would then be responsible to log and format its own
      messages as well as passing the message along to other logger it
      broadcasts to.
    
      The problem with this approach was the following:
    
      - Heavy use of metaprogramming.
      - Accessing the loggers in the broadcast wasn’t possible.
        Removing a logger from the broadcast either.
      - More importantly, modifying the main logger (the one that broadcasts
        logs to the others) wasn’t possible and the main source of
        misunderstanding.
    
        ```ruby
          logger = Logger.new(STDOUT)
          stderr_logger = Logger.new(STDER))
          logger.extend(AS::Logger.broadcast(stderr_logger))
    
          logger.level = DEBUG # This modifies the level on all other loggers
          logger.formatter = … # Modified the formatter on all other loggers
        ```
    
      To keep the contract unchanged on what Rails.logger returns, the new
      BroadcastLogger class implement duck typing with all methods
      that has the vanilla Ruby Logger class.
    
      It's a simple and boring PORO that keeps an array of all the loggers
      that are part of the broadcast and iterate over whenever a log is
      sent.
      Now, users can access all loggers inside the broadcast and modify
      them on the fly. They can also remove any logger from the broadcast
      at any time.
    
      ```ruby
      # Before
    
      stdout_logger = Logger.new(STDOUT)
      stderr_logger = Logger.new(STDER)
      file_logger = Logger.new(“development.log”)
      stdout_logger.extend(AS::Logger.broadcast(stderr_logger))
      stdout_logger.extend(AS::Logger.broadcast(file_logger))
    
      # After
    
      broadcast = BroadcastLogger.new(stdout_logger, stderr_logger, file_logger)
      ```
    
      I also think that now, it should be more clear for users that the
      broadcast sole job is to pass everything to the whole loggers in
      the broadcast. So there should be no surprise that all loggers in
      the broadcast get their level modified when they call
      `broadcast.level = DEBUG` .
    
      It’s also easier to wrap your head around more complex setup such
      as broadcasting logs to another broadcast:
      `broadcast.broadcast_to(stdout_logger, other_broadcast)`
    Edouard-chin authored and rafaelfranca committed Sep 25, 2023
    Configuration menu
    Copy the full SHA
    1fbd812 View commit details
    Browse the repository at this point in the history