# Streams of Data Part I
## Logging Basics


# We don't need anything complex here.
# We will use the logger in the stdlib.
# Rails.logger works fine here as well.
# Using Rails.logger is prefered as you won't muck up
# the screen when running tests.
require 'logger'
module Log
  extend self

  def puts(msg)
    # Forget about log FILES that are on spinning disks
    # Think of this logger as an outlet for streams of data.
    @@logger ||= Logger.new(STDOUT)
    # There are different kinds of levels. We will use info.
    @@logger.info(msg)
  end

end

# Ask the operating system to not buffer our output
# and to flush immediately
$stdout.sync = true

# Here is some business logic.
class Invoice
  # log line ratio 1/4
  def initialize(user)
    log("begin init params=#{user}")
    @id = rand(42)
    @user = user
    @status = "processing"
  end

  # log line ratio 3/8
  # Our logs tell a story about how are method is behaving.
  def status
    # Anchor this message for quick searches.
    # The "#" char is arbitrary but important.
    # Think of this as a "real-time" code comment.
    log("#invoice_check_status")
    # Quickly dump important peices of state.
    # This will help us debug invocations long after
    # they were invoked.
    log("invoice=#{@id} status=#{@status}")
    if @status == "processing"
      # We are about to do something interesting. Let's log it :)
      # Again, notice that our anchored message tells a story.
      log("invoice=#{@id} #invoice_finalize")
      @status = "finalize"
    else
      @status
    end
  end

  def log(msg)
    # Don't be afraid to provide a mechanism
    # to disable logging.
    if ENV["VERBOSE"]
      Log.puts("user=#{@user} #{msg}")
    end
  end

end


MongoDb = {}
# More or less....

run Proc.new {|env|
  # Define a log method wherever you want
  # to customize the context. Often different
  # modules of code will want to have a definition of logging.

  # In our invoice model, we inserted the user=id into all messages.
  def log(msg)
    Log.puts(msg)
  end

  user_id = env["REMOTE_ADDR"]
  if invoice = MongoDb[user_id]
    # Now we are telling a story about how
    # we interact with our robust document store.
    log("user=#{user_id} #database_hit")
  else
    # Whoops!
    log("user=#{user_id} #database_miss")
    invoice = MongoDb[user_id] = Invoice.new(user_id)
  end

  [
    200,
    {'Content-Type' => 'text/plain'},
    [invoice.status]
  ]
}


# Streams of data on Heorku + Papertrail