Skip to content
Snippets Groups Projects
Verified Commit c998c911 authored by Alexander Olofsson's avatar Alexander Olofsson
Browse files

Initial commit

parents
No related branches found
No related tags found
No related merge requests found
Pipeline #91428 failed
Showing
with 342 additions and 0 deletions
/.bundle/
/vendor/
/.yardoc
/Gemfile.lock
/_yardoc/
/coverage/
/doc/
/pkg/
/spec/reports/
/tmp/
/public/
/*.gem
---
include:
- project: ITI/ci-pipelines
file: '/foreman-module.yaml'
---
AllCops:
NewCops: enable
Style/Documentation:
Enabled: false
Metrics/AbcSize:
Enabled: false
Metrics/CyclomaticComplexity:
Enabled: false
Metrics/PerceivedComplexity:
Enabled: false
Metrics/MethodLength:
Max: 15
# frozen_string_literal: true
source 'https://rubygems.org'
gemspec
This diff is collapsed.
# Foreman Cement
Integrates Foreman with [Sentry](https://getsentry.com/), to handle exceptions and tracing.
Based on [foreman_concrete](https://github.com/timogoebel/foreman_concrete/).
## Installation
See the [Plugins install instructions, advanced installation from gems](https://theforeman.org/plugins/#2.3AdvancedInstallationfromGems) for information on how to install this plugins.
## Contributing
Bug reports and pull requests are welcome on the LiU GitLab at https://gitlab.liu.se/ITI/foreman_uuid_boot or on GitHub at https://github.com/ananace/foreman_uuid_boot
## License
The gem is available as open source under the terms of the [GPL-3.0 License](https://opensource.org/licenses/GPL-3.0).
Rakefile 0 → 100644
#!/usr/bin/env rake
# frozen_string_literal: true
require 'bundler/gem_tasks'
require 'rake/testtask'
Rake::TestTask.new(:test) do |t|
t.libs << 'test'
t.libs << 'lib'
t.test_files = FileList['test/**/*_test.rb']
end
task default: :test
# frozen_string_literal: true
module ForemanCement
module Api
module BaseControllerExtensions
extend ActiveSupport::Concern
included do
include ForemanCement::SetSentryContext
# Prepend our view path so we can display
# the last sentry event id in the error message
before_action :prepend_cement_view_path
end
def prepend_cement_view_path
engine_root = ForemanCement::Engine.root.to_s
prepend_view_path File.join(engine_root, 'app/views')
end
end
end
end
# frozen_string_literal: true
module ForemanCement
module ApplicationControllerExtensions
extend ActiveSupport::Concern
module Overrides
def generic_exception(exception)
return sti_clean_up(exception.cause) \
if User.current&.admin? && exception.try(:cause).is_a?(ActiveRecord::SubclassNotFound)
ex_message = exception.message
Foreman::Logging.exception("[Reported to Sentry as #{Sentry.last_event_id}] #{ex_message}", exception)
render template: 'foreman_cement/500',
layout: !request.xhr?,
status: :internal_server_error,
locals: {
exception: exception,
sentry_id: Sentry.last_event_id
}
end
end
included do
prepend Overrides
include ForemanCement::SetRavenContext
end
end
end
# frozen_string_literal: true
module ForemanCement
module SetSentryContext
extend ActiveSupport::Concern
included do
before_action :set_sentry_context
end
private
def set_sentry_context
Sentry.set_user(
id: User.current&.id ,
username: User.current&.login,
email: User.current&.mail
)
Sentry.set_extras(
params: params.to_unsafe_h,
url: request.url,
request_id: request.uuid
)
end
end
end
# frozen_string_literal: true
module ForemanCement
module Extensions
module Foreman
module Exception
extend ActiveSupport::Concern
def sentry_context
{
extra: {
erf_code: code
}
}
end
end
end
end
end
# frozen_string_literal: true
module ForemanCement
module Extensions
module Foreman
module Logging
extend ActiveSupport::Concern
module Overrides
def exception(context_message, exception, **options)
super
sentry_context = {
extra: {
context_message: context_message
},
level: options[:level] || :warn,
logger: options[:logger] || 'app'
}
Sentry.capture_exception(exception, **sentry_context)
end
end
included do
prepend Overrides
end
end
end
end
end
# frozen_string_literal: true
node :message do
locals[:message]
end
node :sentry_id do
Sentry.last_event_id
end
# frozen_string_literal: true
node :message do
locals[:exception].message
end
node :sentry_id do
Sentry.last_event_id
end
<div class="container-fluid">
<div class="row">
<div class="row">
<div class="col-sm-10 col-sm-offset-1 col-md-8 col-md-offset-2 col-lg-8 col-lg-offset-2">
<div class="card-pf">
<%= alert :header => _("Oops, we're sorry but something went wrong"), :class => 'alert-danger',
:actions => link_to(_('Back'), main_app.root_path, :class => 'btn btn-default'),
:text => h(exception.message),
:close => false %>
<p id="sentry">
<%= _('This has been recorded in Sentry. If you open a support ticket within your organization, please always include the Sentry event id %s.') % sentry_id %>
</p>
<div class="pull-right">
<%= documentation_button('7.3GettingHelp') %>
</div>
<p id="message">
<%= _('If you feel this is an error with Foreman itself, please open a new issue with') %>
<%= link_to _('Foreman ticketing system'), 'http://theforeman.org/projects/foreman/issues', :rel => 'external' %>,
<%= _('You would probably need to attach the') %>
<%= link_to_function(_('Full trace'), "$('#backtrace').toggle()") %>
<%= _(", relevant log entries, and it is highly recommended to also attach the foreman-debug output.") %>
</p>
<div id="backtrace" class="alert alert-block alert-danger base in fade hide">
<em><%= exception.class %></em><br>
<strong><%= exception.message %></strong><br>
<%= exception.backtrace.join("<br>").html_safe %>
</div>
</div>
</div>
</div>
</div>
</div>
# frozen_string_literal: true
require_relative 'lib/foreman_cement/version'
Gem::Specification.new do |spec|
spec.name = 'foreman_cement'
spec.version = ForemanCement::VERSION
spec.authors = ['Alexander Olofsson']
spec.email = ['alexander.olofsson@liu.se']
spec.summary = 'Send encountered exceptions and tracing to sentry.'
spec.description = spec.summary
spec.homepage = 'https://github.com/ananace/foreman_cement'
spec.license = 'GPL-3.0'
spec.files = Dir['{app,lib}/**/*'] + %w[LICENSE.txt Rakefile README.md]
spec.metadata['rubygems_mfa_required'] = 'true'
spec.add_runtime_dependency 'sentry-rails', '~> 5.8'
spec.add_runtime_dependency 'sentry-ruby', '~> 5.8'
spec.add_runtime_dependency 'sentry-sidekiq', '~> 5.8'
spec.add_development_dependency 'rubocop'
spec.add_development_dependency 'rubocop-minitest'
spec.add_development_dependency 'rubocop-performance'
spec.add_development_dependency 'rubocop-rails'
end
# frozen_string_literal: true
require 'foreman_cement/engine'
module ForemanCement
end
# frozen_string_literal: true
require 'sentry-ruby'
require 'sentry-rails'
require 'sentry-sidekiq'
Sentry.init do |config|
config.logger = Foreman::Logging.logger('foreman_cement')
config.dsn = SETTINGS['sentry_dsn']
config.release = SETTINGS[:version].version
config.breadcrumbs_logger = %i[active_support_logger http_logger]
if SETTINGS['sentry_trace']
config.traces_sample_rate = if SETTINGS['sentry_trace'].is_a?(Hash)
SETTINGS.dig('sentry_trace', 'rate') || 0.2
else
0.2
end
end
filter = ActiveSupport::ParameterFilter.new(Rails.application.config.filter_parameters)
config.before_send = lambda do |event, _hint|
filter.filter(event.to_hash)
end
end
# frozen_string_literal: true
module ForemanCement
class Engine < ::Rails::Engine
engine_name 'foreman_cement'
config.autoload_paths += Dir["#{config.root}/app/lib"]
config.autoload_paths += Dir["#{config.root}/app/controllers/concerns"]
initializer 'foreman_cement.register_plugin', before: :finisher_hook do |_app|
Foreman::Plugin.register :foreman_cement do
requires_foreman '>= 3.0'
end
end
initializer 'foreman_cement.configure_sentry', after: :load_environment_config do
require 'foreman_cement/configure_sentry' if SETTINGS['sentry_dsn']
end
# Include concerns in this config.to_prepare block
config.to_prepare do
::Foreman::Exception.include ForemanCement::Extensions::Foreman::Exception
::Foreman::LoggingImpl.include ForemanCement::Extensions::Foreman::Logging
::ApplicationController.include ForemanCement::ApplicationControllerExtensions
::Api::BaseController.include ForemanCement::Api::BaseControllerExtensions
rescue StandardError => e
Sentry.capture_exception(e)
Rails.logger.warn "ForemanCement: skipping engine hook (#{e})"
end
end
end
# frozen_string_literal: true
module ForemanCement
VERSION = '0.1.0'
end
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment