class Civo::PerRequestLogger

Constants

INFLUXDB_PRECISION
INFLUXDB_RETENTION
STATS_RESOLUTION

Public Class Methods

new(app, taggers = nil) click to toggle source
# File lib/civo/logger/middleware.rb, line 16
def initialize(app, taggers = nil)
  self.class.expires_in ||= 24.hours.to_i
  @app          = app
  @taggers      = taggers || []
  if ENV["INFLUX_LOGGER_HOSTNAME"]
    Rails.logger = ActionController::Base.logger = ActiveRecord::Base.logger = self
    $stdout.sync = true
    options = {host: ENV["INFLUX_LOGGER_HOSTNAME"], port: ENV["INFLUX_LOGGER_PORT"], password: ENV["INFLUX_LOGGER_PASSWORD"], username: ENV["INFLUX_LOGGER_USERNAME"], open_timeout: 1, read_timeout: 1, timeout: 1, time_precision: "ms", retry: false}
    @influxdb = InfluxDB::Client.new ENV["INFLUX_LOGGER_DATABASE"], options
  else
    @influxdb = nil
  end
rescue InfluxDB::Error
  @influxdb = nil
end

Public Instance Methods

app_name() click to toggle source
# File lib/civo/logger/middleware.rb, line 38
def app_name
  ENV["APP_NAME"] || "unknown-app"
end
call(env) click to toggle source
# File lib/civo/logger/middleware.rb, line 32
def call(env)
  request = ActionDispatch::Request.new(env)

  call_app(request, env)
end
debug(message = "") { || ... } click to toggle source
# File lib/civo/logger/middleware.rb, line 42
def debug(message = "")
  message = yield if block_given?
  return if message.blank?
  @lines << message if debug? && @recording
end
debug?() click to toggle source
# File lib/civo/logger/middleware.rb, line 48
def debug?
  %i{debug}.include?(level)
end
end_worker() click to toggle source
# File lib/civo/logger/middleware.rb, line 113
def end_worker
  @log = @lines.join("\n")

  puts @log
  if @influxdb.nil?
    return
  end

  @end = Time.now.to_f * 1000

  data = {
    values:    { log: @log, log_size: @log.length, ms_taken: (@end-@start).to_i },
    tags:      { job_name: @name, app: app_name, run_id: SecureRandom.uuid },
    timestamp: (Time.now.to_f * 1000.0).to_i
  }

  @influxdb.write_point("workers", data, INFLUXDB_PRECISION)# , INFLUXDB_RETENTION)
rescue InfluxDB::Error => e
  puts "ERROR! InfluxDB error #{e.message}"
ensure
  @recording = false
end
error(message = "") { || ... } click to toggle source
# File lib/civo/logger/middleware.rb, line 78
def error(message = "")
  message = yield if block_given?
  return if message.blank?
  @lines << message if error? && @recording
end
error?() click to toggle source
# File lib/civo/logger/middleware.rb, line 84
def error?
  %i{debug info warn error}.include?(level)
end
fatal(message = "") { || ... } click to toggle source
# File lib/civo/logger/middleware.rb, line 88
def fatal(message = "")
  message = yield if block_given?
  return if message.blank?
  @lines << message if fatal? && @recording
end
fatal?() click to toggle source
# File lib/civo/logger/middleware.rb, line 94
def fatal?
  %i{debug info warn error fatal}.include?(level)
end
formatter() click to toggle source
# File lib/civo/logger/middleware.rb, line 102
def formatter
  ActiveSupport::Logger::SimpleFormatter
end
info(message = "") { || ... } click to toggle source
# File lib/civo/logger/middleware.rb, line 52
def info(message = "")
  message = yield if block_given?
  return if message.blank?

  matches = message.match(/Completed (\d+) .*? in (\d+)ms/)
  if matches
    @status = matches[1]
    @time_taken = matches[2]
  end
  @lines << message if info? && @recording
end
info?() click to toggle source
# File lib/civo/logger/middleware.rb, line 64
def info?
  %i{debug info}.include?(level)
end
level() click to toggle source
# File lib/civo/logger/middleware.rb, line 98
def level
  Rails.configuration.log_level
end
silence(*args) { |self| ... } click to toggle source
# File lib/civo/logger/middleware.rb, line 136
def silence(*args)
  yield self
end
start_worker(name) click to toggle source
# File lib/civo/logger/middleware.rb, line 106
def start_worker(name)
  @name = name
  @lines = []
  @start = Time.now.to_f * 1000
  @recording = true
end
warn(message = "") { || ... } click to toggle source
# File lib/civo/logger/middleware.rb, line 68
def warn(message = "")
  message = yield if block_given?
  return if message.blank?
  @lines << message if warn? && @recording
end
warn?() click to toggle source
# File lib/civo/logger/middleware.rb, line 74
def warn?
  %i{debug info warn}.include?(level)
end

Private Instance Methods

call_app(request, env) click to toggle source
# File lib/civo/logger/middleware.rb, line 142
def call_app(request, env) # :doc:
  if ENV["INFLUX_LOGGER_HOSTNAME"].blank?
    @app.call(env)
  elsif send_request?(request)
    puts "In send request"
    @lines = []
    @recording = true
    @status = nil
    @time_taken = nil
    @url = request.fullpath
    Rails.logger = ActionController::Base.logger = ActiveRecord::Base.logger = self
    instrumenter = ActiveSupport::Notifications.instrumenter
    instrumenter.start "request.action_dispatch", request: request
    logger.info { started_request_message(request) }
    status, headers, response = @app.call(env)
    @status = status.to_s
    finish(request, response)
    [status, headers, response]
  else
    Rails.logger = ActionController::Base.logger = ActiveRecord::Base.logger = self
    instrumenter = ActiveSupport::Notifications.instrumenter
    instrumenter.start "request.action_dispatch", request: request
    logger.info { started_request_message(request) }
    @app.call(env)
  end
rescue Exception => e
  finish(request, [e.message])
  raise
ensure
  ActiveSupport::LogSubscriber.flush_all!
end
compute_tags(request) click to toggle source
# File lib/civo/logger/middleware.rb, line 183
def compute_tags(request) # :doc:
  @taggers.collect do |tag|
    case tag
    when Proc
      tag.call(request)
    when Symbol
      request.send(tag)
    else
      tag
    end
  end
end
finish(request, body) click to toggle source
# File lib/civo/logger/middleware.rb, line 196
def finish(request, body)
  instrumenter = ActiveSupport::Notifications.instrumenter
  instrumenter.finish "request.action_dispatch", request: request
  @log = @lines.join("\n")

  unless body.is_a?(String)
    body = body.to_a rescue [body.body]
  end

  if body.respond_to?(:each)
    @output = []
    body.each do |line|
      @output << line
    end
    @output = @output.join("\n")
  else
    @output = body.to_s
  end

  puts @log
  if @influxdb.nil?
    return
  end

  @log ||= "None found"
  @output ||= "None found"
  @status ||= "-"

  data = {
    values:    { log: @log[0, 65535], output: @output, output_length: @output.length, status: @status, ms_taken: @time_taken.to_i},
    tags:      { url: request.fullpath, method: request.request_method, app: app_name },
    timestamp: (Time.now.to_f * 1000.0).to_i
  }
  data[:values][:email] = request.headers["X-CivoCom-User-Email"] if request.headers["X-CivoCom-User-Email"].present?
  data[:values][:civocom_request_path] = request.headers["X-CivoCom-Request-Path"] if request.headers["X-CivoCom-Request-Path"].present?
  data[:tags][:civocom_request_id] = request.headers["X-CivoCom-RequestID"] if request.headers["X-CivoCom-RequestID"].present?
  data[:tags][:request_id] = request.uuid if request.uuid.present?

  @influxdb.write_point("requests", data, INFLUXDB_PRECISION)# , INFLUXDB_RETENTION)

  if Rails.env.development? || Rails.env.test?
    File.open("#{Rails.root}/log/#{Rails.env}.log", "a") do |f|
      f << @log
    end
  end

rescue InfluxDB::Error => e
  puts "ERROR! InfluxDB error #{e.message}"
ensure
  @recording = false
end
logger() click to toggle source
# File lib/civo/logger/middleware.rb, line 265
def logger
  self
end
send_request?(request) click to toggle source
# File lib/civo/logger/middleware.rb, line 248
def send_request?(request)
  puts request.fullpath
  if request.fullpath["/resque"]
    return false
  elsif request.fullpath["/civostatsd"]
    return false
  elsif request.fullpath["/assets"]
    puts "Returning false"
    return false
  elsif request.fullpath["/ping"]
    return false
  end

  puts "Returning true"
  true
end
started_request_message(request) click to toggle source

Started GET “/session/new” for 127.0.0.1 at 2012-09-26 14:51:42 -0700

# File lib/civo/logger/middleware.rb, line 175
def started_request_message(request) # :doc:
  'Started %s "%s" for %s at %s' % [
    request.request_method,
    request.filtered_path,
    request.ip,
    Time.now.to_default_s ]
end