Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/dev' into task/rc-2.0.1
Browse files Browse the repository at this point in the history
  • Loading branch information
jonrandahl committed Dec 20, 2024
2 parents 290a5d3 + c0b595f commit c635736
Show file tree
Hide file tree
Showing 9 changed files with 68 additions and 74 deletions.
19 changes: 18 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,22 @@ This app allows the user to explore HMLR price-paid open linked data.

## Changelog

## 2.0.1 - 2024-12

- (Jon) Updated the error template path to use `Rails.public_path` as well as
contain the `html` extension to ensure the correct template is rendered
- (Jon) Improves error metrics reporting to ensure that logging always happens
with the appropriate severity depending on the exception status while reducing
the types of errors that can trigger a an error metric and therefore a
notification in slack
[GH-149](https://github.com/epimorphics/hmlr-linked-data/issues/149)
- (Jon) Added catch for missing `SENTRY_API_KEY` env var to `entrypoint.sh` for
docker build
- (Jon) Updated target status level to trigger internal error metrics to 500
status codes only in the `search_controller`
- (Jon) Added `message`, `status`, and `type` arguments to be logged by the
`json_rails_logger` gem for respective error responses in the `search_controller`

## 2.0.0 - 2024-11

- (Bogdan) Updated all gems by regenerating `Gemfile.lock`
Expand All @@ -13,7 +29,8 @@ This app allows the user to explore HMLR price-paid open linked data.

## 1.8.0 - 2024-10

- (Dan) Updates ruby version to 2.7.8 and alpine version to 3.16 [GH-253](https://github.com/epimorphics/ppd-explorer/issues/253)
- (Dan) Updates ruby version to 2.7.8 and alpine version to 3.16
[GH-253](https://github.com/epimorphics/ppd-explorer/issues/253)

## 1.7.11 - 2024-10

Expand Down
4 changes: 2 additions & 2 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -428,10 +428,10 @@ GEM
faraday_middleware (~> 1.2.0)
json (~> 2.6.1)
yajl-ruby (~> 1.4.1)
json_rails_logger (1.0.3)
json_rails_logger (2.0.1)
json
lograge
railties
railties (~> 7.0)
lr_common_styles (2.1.3)
bootstrap-sass
font-awesome-rails
Expand Down
33 changes: 26 additions & 7 deletions app/controllers/application_controller.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# frozen_string_literal: true

# :nodoc:
class ApplicationController < ActionController::Base
class ApplicationController < ActionController::Base # rubocop:disable Metrics/ClassLength
# Prevent CSRF attacks by raising an exception.
# For APIs, you may want to use :null_session instead.

Expand Down Expand Up @@ -36,11 +36,6 @@ def log_request_result
# or attempt to render a generic error page if no specific error page exists
unless Rails.application.config.consider_all_requests_local
rescue_from StandardError do |e|
# Instrument ActiveSupport::Notifications for internal errors but only for non-404 errors:
unless e.is_a?(ActionController::RoutingError) || e.is_a?(ActionView::MissingTemplate)
ActiveSupport::Notifications.instrument('internal_error.application', exception: e)
end

# Trigger the appropriate error handling method based on the exception
case e.class
when ActionController::RoutingError, ActionView::MissingTemplate
Expand All @@ -61,6 +56,8 @@ def handle_internal_error(exception)
render_error(400)
else
Rails.logger.warn "No explicit error page for exception #{exception} - #{exception.class}"
# Instrument ActiveSupport::Notifications for internal server errors only:
instrument_internal_error(exception)
render_error(500)
end
end
Expand Down Expand Up @@ -93,7 +90,7 @@ def render_error(status)

def render_html_error_page(status)
render(layout: true,
file: Rails.root.join('public', 'landing', status.to_s),
file: Rails.public_path + "landing/#{status}.html",
status: status)
end

Expand Down Expand Up @@ -129,4 +126,26 @@ def detailed_request_log(duration)
end
end
# rubocop:enable Metrics/AbcSize, Metrics/MethodLength

# Notify subscriber(s) of an internal error event with the payload of the
# exception once done
# @param [exc] exp the exception that caused the error
# @return [ActiveSupport::Notifications::Event] provides an object-oriented
# interface to the event
def instrument_internal_error(exc) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
err = {
message: exc&.message || exc,
status: exc&.status || Rack::Utils::SYMBOL_TO_STATUS_CODE[exc]
}
err[:type] = exc.class&.name if exc&.class
err[:cause] = exc&.cause if exc&.cause
err[:backtrace] = exc&.backtrace if exc&.backtrace && Rails.env.development?
# Log the exception to the Rails logger with the appropriate severity
Rails.logger.send(err[:status] < 500 ? :warn : :error, JSON.generate(err))
# Return unless the status code is 500 or greater to ensure subscribers are NOT notified
return unless err[:status] >= 500

# Instrument the internal error event to notify subscribers of the error
ActiveSupport::Notifications.instrument('internal_error.application', exception: err)
end
end
16 changes: 13 additions & 3 deletions app/controllers/search_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -56,13 +56,24 @@ def render_error_page(err, message, status, template = 'ppd/error')
# link the error to the actual request id otherwise generate one for this error
uuid = Thread.current[:request_id] || SecureRandom.uuid

status_code = Rack::Utils::SYMBOL_TO_STATUS_CODE[status]

@message = message

# log the error with as much detail as possible in development to aid in resolving the issue
@message = "#{Rack::Utils::SYMBOL_TO_STATUS_CODE[status]} ~ #{err.class.name} error: #{message}" if Rails.env.development?
@message = "#{status_code} ~ #{err.class.name} error: #{message}" if Rails.env.development?

# Keep it simple silly in production!
log_error(Rack::Utils::SYMBOL_TO_STATUS_CODE[status], message)
log_error(status_code, message)

# Trigger metric on internal errors
if status_code >= 500
instrument_internal_error({
message: message,
status: status_code,
type: err.class.name
})
end

@error_message =
[
Expand All @@ -85,5 +96,4 @@ def log_error(status, message)
Rails.logger.info(message)
end
end

end
2 changes: 1 addition & 1 deletion app/lib/version.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
module Version
MAJOR = 2
MINOR = 0
PATCH = 0
PATCH = 1
SUFFIX = nil
VERSION = "#{MAJOR}.#{MINOR}.#{PATCH}#{SUFFIX && ".#{SUFFIX}"}"
end
4 changes: 2 additions & 2 deletions app/subscribers/application_prometheus_subscriber.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ class ApplicationPrometheusSubscriber < ActiveSupport::Subscriber
attach_to :application

def internal_error(event)
message = event.payload[:exception]
error = event.payload[:exception]
Prometheus::Client.registry
.get(:internal_application_error)
.increment(labels: { message: message.to_s })
.increment(labels: { result: 'failure', message: "#{error[:type]}: #{error[:message]}", status: error[:status].to_i }) # rubocop:disable Layout/LineLength
end
end
6 changes: 3 additions & 3 deletions config/initializers/prometheus.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
prometheus.counter(
:internal_application_error,
docstring: 'Unexpected events and internal error count, labelled by message',
labels: [:message]
labels: %i[message result status]
)

# Prometheus gauges
Expand All @@ -50,5 +50,5 @@
)

# Middleware instrumentation
# This fixes the 0 memory bug by notifying Action Dispatch subscribers on Prometheus initialise
ActiveSupport::Notifications.instrument('process_middleware.action_dispatch')
# This fixes the 0 memory bug by notifying Action Dispatch subscribers on Prometheus initialise
ActiveSupport::Notifications.instrument('process_middleware.action_dispatch')
55 changes: 0 additions & 55 deletions config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,59 +8,4 @@
resource :ppd_data

get '*unmatched_route', to: 'application#render_404'

# The priority is based upon order of creation: first created -> highest priority.
# See how all your routes lay out with "rake routes".

# You can have the root of your site routed with "root"
# root 'welcome#index'

# Example of regular route:
# get 'products/:id' => 'catalog#view'

# Example of named route that can be invoked with purchase_url(id: product.id)
# get 'products/:id/purchase' => 'catalog#purchase', as: :purchase

# Example resource route (maps HTTP verbs to controller actions automatically):
# resources :products

# Example resource route with options:
# resources :products do
# member do
# get 'short'
# post 'toggle'
# end
#
# collection do
# get 'sold'
# end
# end

# Example resource route with sub-resources:
# resources :products do
# resources :comments, :sales
# resource :seller
# end

# Example resource route with more complex sub-resources:
# resources :products do
# resources :comments
# resources :sales do
# get 'recent', on: :collection
# end
# end

# Example resource route with concerns:
# concern :toggleable do
# post 'toggle'
# end
# resources :posts, concerns: :toggleable
# resources :photos, concerns: :toggleable

# Example resource route within a namespace:
# namespace :admin do
# # Directs /admin/products/* to Admin::ProductsController
# # (app/controllers/admin/products_controller.rb)
# resources :products
# end
end
3 changes: 3 additions & 0 deletions entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ mkdir -pm 1777 ./tmp
# Set the environment
[ -z "$RAILS_ENV" ] && RAILS_ENV=production

# Check for SENTRY_API_KEY variable and report if missing
[ -z "$SENTRY_API_KEY" ] && echo "{\"ts\":\"$(date -u +%FT%T.%3NZ)\",\"level\":\"ERROR\",\"message\":\"SENTRY_API_KEY is required\"}"

# Check for API Service URL variable and log it
[ -n "$API_SERVICE_URL" ] && echo "{\"ts\":\"$(date -u +%FT%T.%3NZ)\",\"level\":\"INFO\",\"message\":\"API_SERVICE_URL=${API_SERVICE_URL}\"}"

Expand Down

0 comments on commit c635736

Please sign in to comment.