Files
ubicloud/routes/clover_base.rb
Enes Cakir 128b93c88b Log web exceptions with Clog
When we encounter unexpected errors in our web application, we simply
print the stack trace to stderr. This makes it challenging to
investigate the error cause, as our log service can only parse JSON
logs. Thus, we can log the exceptions with Clog, similar to how we
handle exceptions in the respirate.
2024-11-02 14:42:08 -07:00

99 lines
2.9 KiB
Ruby
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# frozen_string_literal: true
module CloverBase
def self.included(base)
base.extend(ClassMethods)
base.plugin :all_verbs
base.plugin :request_headers
logger = if ENV["RACK_ENV"] == "test"
Class.new {
def write(_)
end
}.new
else
# :nocov:
$stderr
# :nocov:
end
base.plugin :common_logger, logger
end
def current_account
return @current_account if defined?(@current_account)
@current_account = Account[rodauth.session_value]
end
# Assign some HTTP response codes to common exceptions.
def parse_error(e)
case e
when Sequel::ValidationFailed
code = 400
type = "InvalidRequest"
message = e.to_s
when CloverError
code = e.code
type = e.type
message = e.message
details = e.details
else
Clog.emit("route exception") { Util.exception_to_hash(e) }
code = 500
type = "UnexceptedError"
message = "Sorry, we couldnt process your request because of an unexpected error."
end
response.status = code
{
code: code,
type: type,
message: message,
details: details
}
end
def fetch_location_based_prices(*resource_types)
# We use 1 month = 672 hours for conversion. Number of hours
# in a month changes between 672 and 744, We are also capping
# billable hours to 672 while generating invoices. This ensures
# that users won't see higher price in their invoice compared
# to price calculator and also we charge same amount no matter
# the number of days in a given month.
BillingRate.rates.filter { resource_types.include?(_1["resource_type"]) }
.group_by { [_1["resource_type"], _1["resource_family"], _1["location"]] }
.map { |_, brs| brs.max_by { _1["active_from"] } }
.each_with_object(Hash.new { |h, k| h[k] = h.class.new(&h.default_proc) }) do |br, hash|
hash[br["location"]][br["resource_type"]][br["resource_family"]] = {
hourly: br["unit_price"].to_f * 60,
monthly: br["unit_price"].to_f * 60 * 672
}
end
end
module ClassMethods
def autoload_routes(route)
route_path = "routes/#{route}"
if Config.production?
# :nocov:
Unreloader.require(route_path)
# :nocov:
else
plugin :autoload_hash_branches
Dir["#{route_path}/**/*.rb"].each do |full_path|
parts = full_path.delete_prefix("#{route_path}/").split("/")
namespaces = parts[0...-1]
filename = parts.last
if namespaces.empty?
autoload_hash_branch(File.basename(filename, ".rb").tr("_", "-"), full_path)
else
autoload_hash_branch(:"#{namespaces.join("_")}_prefix", File.basename(filename, ".rb").tr("_", "-"), full_path)
end
end
Unreloader.autoload(route_path, delete_hook: proc { |f| hash_branch(File.basename(f, ".rb").tr("_", "-")) }) {}
end
end
end
end