0

I have set up the following using this: Ruby - share logger instance among module/classes

EDIT: Based on the comments below, I updated the code but still have issues logging.

module Logging

  # in classes needing to be logged use 'include Logger'
  require 'logger'
  require 'remote_syslog_logger'
  require_relative 'env'

  class << self
    def logger

      return @logger if @logger

      if ENV['ENVIRONMENT'] == 'production' #may need to change this

        @logger ||= Logger.new($stdout)

        @logger.level = Logger::WARN
        @logger.datetime_format = "%N "

      elsif ENV['ENVIRONMENT'] == 'development'

        binding.pry

        #$logger = Logger.new(STDOUT)
        @logger = RemoteSyslogLogger.new('logs2.papertrailapp.com',39257)
        @logger.level = Logger::DEBUG
        @logger.datetime_format = "%N "

      end 

    end

    def logger=(logger)
      @logger = logger
    end
  end

  # Addition
  def self.included(base)
    class << base
      def logger
        Logging.logger
      end
    end
  end

  def logger
    Logging.logger
  end


end

How I log:

class CronCheck
  require_relative 'module_logger.rb'
  include Logging

  def self.run
    begin
      logger.debug "**** running cron_check_schedule.rb #{Time.now}  #{Time.now.to_i}****"
    rescue
  end
end

Question: How can I modify the module so that this type of logic can be defined once, and all I have to do is pass an ENV value for all the classes and methods to log in the same way?

I get an error at logger.debug: undefined method `debug' for "%N ":String

Community
  • 1
  • 1
Satchel
  • 16,414
  • 23
  • 106
  • 192

2 Answers2

0

Assuming the first snippet is the module Logging you suppose to include everywhere for logging (otherwise global var as in second snippet just works perfectly out of the box,) all you need is to initialize logger according to snippet #2:

# this is the topmost method from your snippet #1,
#    updated to use env settings for logger tuning
def logger
  # @logger ||= Logger.new($stdout)
  return @logger if @logger

  @logger = case ENV['ENVIRONMENT']
            when 'production'
              Logger.new(STDOUT).tap do |logger|
                logger.level = Logger::WARN
                logger.datetime_format = "%N "
              end
            else 
              .......
            end
end

That’s it.

Aleksei Matiushkin
  • 119,336
  • 10
  • 100
  • 160
0

Your code is almost exactly right. What you need to do, though, is set Logging.logger, not $logger:

def self.instantiate_logger
  logger = Logger.new(STDOUT)
  logger.datetime_format = "%N "

  if ENV['ENVIRONMENT'] == 'production'
    logger.level = Logger::WARN
  elsif ENV['ENVIRONMENT'] == 'development'
    logger.level = Logger::DEBUG
  end

  Logging.logger = logger
end

It's not clear from your question where this method lives, but it should be somewhere you can call it during your app's initialization.

You'll notice that I removed the code related to Pry; since that code's not directly related to logging, it should probably go somewhere else.

I would make one more improvement, though, which is to make it more declarative by putting the log levels in a hash keyed by their respective environments:

LOG_LEVELS = {
  "production" => Logger::WARN,
  "development" => Logger::DEBUG
}

def self.instantiate_logger
  Logging.logger = Logger.new(STDOUT).tap do |logger|
    logger.datetime_format = "%N "
    logger.level = LOG_LEVELS[ENV['ENVIRONMENT']] || LOG_LEVELS["development"]
  end
end
Jordan Running
  • 102,619
  • 17
  • 182
  • 182
  • Thanks. If I want to send one environnt to paper rail instead of standard out would I replace logger.new statement. Not quite sure. Let me take a swing with this. – Satchel Jan 19 '16 at 19:19
  • Where should I instantly ate it with this method? Could I have it run somewhere within your code since the module makes it available across all classes? – Satchel Jan 19 '16 at 19:20
  • Hm, still doesn't seem to work within the `self.run` method. It doesn't recognize logger. – Satchel Jan 19 '16 at 20:34
  • Can you edit your question to include the code you're using now? The code in your question at present doesn't look anything like what I've posted. – Jordan Running Jan 19 '16 at 20:36
  • I took what you wrote for instantiate_logger and got rid of that method since I wasn't sure how to or where to call it and just made it part of the Logger method. I haven't yet push your hash since the script just goes off of the environment right now. so I tried to take your logic and put it into mine....sorry, let me review again to pin down the area. – Satchel Jan 19 '16 at 20:40
  • it's sort of combinging both your response and the response of the other responder -- and getting rid of stuff that now looks confusing, so I took your answers and put it into a single method. – Satchel Jan 19 '16 at 20:40