Lots of updates
This commit is contained in:
@@ -77,4 +77,6 @@ Rails.application.configure do
|
||||
# config.generators.apply_rubocop_autocorrect_after_generate!
|
||||
config.active_job.queue_adapter = :solid_queue
|
||||
config.solid_queue.connects_to = { database: { writing: :queue } }
|
||||
# Don't store finished jobs - we don't need job history, saves DB space
|
||||
config.solid_queue.preserve_finished_jobs = false
|
||||
end
|
||||
|
||||
@@ -52,6 +52,8 @@ Rails.application.configure do
|
||||
# Replace the default in-process and non-durable queuing backend for Active Job.
|
||||
config.active_job.queue_adapter = :solid_queue
|
||||
config.solid_queue.connects_to = { database: { writing: :queue } }
|
||||
# Don't store finished jobs - we don't need job history, saves DB space
|
||||
config.solid_queue.preserve_finished_jobs = false
|
||||
|
||||
# Ignore bad email addresses and do not raise email delivery errors.
|
||||
# Set this to true and configure the email server for immediate delivery to raise delivery errors.
|
||||
|
||||
@@ -5,3 +5,7 @@ pin "@hotwired/turbo-rails", to: "turbo.min.js"
|
||||
pin "@hotwired/stimulus", to: "stimulus.min.js"
|
||||
pin "@hotwired/stimulus-loading", to: "stimulus-loading.js"
|
||||
pin_all_from "app/javascript/controllers", under: "controllers"
|
||||
|
||||
# Tom Select for enhanced multi-select
|
||||
pin "tom-select", to: "https://cdn.jsdelivr.net/npm/tom-select@2.3.1/dist/js/tom-select.complete.min.js"
|
||||
pin "tom-select-css", to: "https://cdn.jsdelivr.net/npm/tom-select@2.3.1/dist/css/tom-select.css"
|
||||
|
||||
156
config/initializers/sentry.rb
Normal file
156
config/initializers/sentry.rb
Normal file
@@ -0,0 +1,156 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
# Sentry configuration for error tracking and performance monitoring
|
||||
# Only initializes if SENTRY_DSN is configured
|
||||
|
||||
return unless ENV['SENTRY_DSN'].present?
|
||||
|
||||
require 'sentry-rails'
|
||||
|
||||
Sentry.init do |config|
|
||||
config.dsn = ENV['SENTRY_DSN']
|
||||
|
||||
# Configure sampling for production (lower in production, higher in staging)
|
||||
config.traces_sample_rate = case Rails.env
|
||||
when 'production' then ENV.fetch('SENTRY_TRACES_SAMPLE_RATE', '0.05').to_f
|
||||
when 'staging' then ENV.fetch('SENTRY_TRACES_SAMPLE_RATE', '0.2').to_f
|
||||
else ENV.fetch('SENTRY_TRACES_SAMPLE_RATE', '0.1').to_f
|
||||
end
|
||||
|
||||
# Enable breadcrumbs for better debugging
|
||||
config.breadcrumbs_logger = [:active_support_logger, :http_logger]
|
||||
|
||||
# Send PII data (like IPs) to Sentry for debugging (disable in production if needed)
|
||||
config.send_default_pii = ENV.fetch('SENTRY_SEND_PII', 'false') == 'true'
|
||||
|
||||
# Set environment
|
||||
config.environment = Rails.env
|
||||
|
||||
# Configure release info from Docker tag or Git
|
||||
if ENV['GIT_COMMIT_SHA']
|
||||
config.release = ENV['GIT_COMMIT_SHA'][0..7]
|
||||
elsif ENV['APP_VERSION']
|
||||
config.release = ENV['APP_VERSION']
|
||||
end
|
||||
|
||||
# Set server name for multi-instance environments
|
||||
config.server_name = ENV.fetch('SERVER_NAME', 'baffle-agent')
|
||||
|
||||
# Filter out certain errors to reduce noise and add tags
|
||||
config.before_send = lambda do |event, hint|
|
||||
# Filter out 404 errors and other expected HTTP errors
|
||||
if event.contexts.dig(:response, :status_code) == 404
|
||||
nil
|
||||
# Filter out validation errors in development
|
||||
elsif Rails.env.development? && event.exception&.message&.include?("Validation failed")
|
||||
nil
|
||||
# Filter out specific noisy exceptions
|
||||
elsif %w[ActionController::RoutingError
|
||||
ActionController::InvalidAuthenticityToken
|
||||
ActionController::UnknownFormat
|
||||
ActionDispatch::Http::Parameters::ParseError].include?(event.exception&.class&.name)
|
||||
nil
|
||||
else
|
||||
# Add tags for better filtering in Sentry
|
||||
event.tags.merge!({
|
||||
ruby_version: RUBY_VERSION,
|
||||
rails_version: Rails.version,
|
||||
environment: Rails.env
|
||||
})
|
||||
event
|
||||
end
|
||||
end
|
||||
|
||||
# Configure exception class exclusion
|
||||
config.excluded_exceptions += [
|
||||
'ActionController::RoutingError',
|
||||
'ActionController::InvalidAuthenticityToken',
|
||||
'CGI::Session::CookieStore::TamperedWithCookie',
|
||||
'ActionController::UnknownFormat',
|
||||
'ActionDispatch::Http::Parameters::ParseError',
|
||||
'Mongoid::Errors::DocumentNotFound'
|
||||
]
|
||||
end
|
||||
|
||||
# SolidQueue monitoring will be automatically handled by sentry-solid_queue gem
|
||||
|
||||
# Add correlation ID to Sentry context
|
||||
ActiveSupport::Notifications.subscribe('action_controller.process_action') do |name, start, finish, id, payload|
|
||||
controller = payload[:controller]
|
||||
action = payload[:action]
|
||||
request_id = payload[:request]&.request_id
|
||||
|
||||
if controller && action && request_id
|
||||
Sentry.set_context(:request, {
|
||||
correlation_id: request_id,
|
||||
controller: controller.controller_name,
|
||||
action: action.action_name,
|
||||
ip: request&.remote_ip
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
# Add ActiveJob context to all job transactions
|
||||
ActiveSupport::Notifications.subscribe('perform.active_job') do |name, start, finish, id, payload|
|
||||
job = payload[:job]
|
||||
|
||||
Sentry.configure_scope do |scope|
|
||||
scope.set_tag(:job_class, job.class.name)
|
||||
scope.set_tag(:job_queue, job.queue_name)
|
||||
scope.set_tag(:job_id, job.job_id)
|
||||
|
||||
scope.set_context(:job, {
|
||||
job_id: job.job_id,
|
||||
job_class: job.class.name,
|
||||
queue_name: job.queue_name,
|
||||
arguments: job.arguments.to_s,
|
||||
enqueued_at: job.enqueued_at,
|
||||
executions: job.executions
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
# Monitor SolidQueue job failures
|
||||
ActiveSupport::Notifications.subscribe('solid_queue.error') do |name, start, finish, id, payload|
|
||||
job = payload[:job]
|
||||
error = payload[:error]
|
||||
|
||||
Sentry.with_scope do |scope|
|
||||
scope.set_tag(:job_class, job.class_name)
|
||||
scope.set_tag(:job_queue, job.queue_name)
|
||||
scope.set_context(:job, {
|
||||
job_id: job.active_job_id,
|
||||
arguments: job.arguments.to_s,
|
||||
queue_name: job.queue_name,
|
||||
created_at: job.created_at
|
||||
})
|
||||
scope.set_context(:error, {
|
||||
error_class: error.class.name,
|
||||
error_message: error.message
|
||||
})
|
||||
|
||||
Sentry.capture_exception(error)
|
||||
end
|
||||
end
|
||||
|
||||
# Set user context when available
|
||||
if defined?(Current) && Current.user
|
||||
Sentry.set_user(id: Current.user.id, email: Current.user.email)
|
||||
end
|
||||
|
||||
# Add application-specific context
|
||||
app_version = begin
|
||||
File.read(Rails.root.join('VERSION')).strip
|
||||
rescue
|
||||
ENV['APP_VERSION'] || ENV['GIT_COMMIT_SHA']&.[](0..7) || 'unknown'
|
||||
end
|
||||
|
||||
Sentry.set_context('application', {
|
||||
name: 'BaffleHub',
|
||||
version: app_version,
|
||||
environment: Rails.env,
|
||||
database: ActiveRecord::Base.connection.adapter_name,
|
||||
queue_adapter: Rails.application.config.active_job.queue_adapter
|
||||
})
|
||||
|
||||
Rails.logger.info "Sentry configured for environment: #{Rails.env}"
|
||||
@@ -9,7 +9,11 @@
|
||||
# priority: 2
|
||||
# schedule: at 5am every day
|
||||
|
||||
production:
|
||||
clear_solid_queue_finished_jobs:
|
||||
command: "SolidQueue::Job.clear_finished_in_batches(sleep_between_batches: 0.3)"
|
||||
schedule: every hour at minute 12
|
||||
# No recurring tasks configured yet
|
||||
# (previously had clear_solid_queue_finished_jobs, but now preserve_finished_jobs: false in queue.yml)
|
||||
|
||||
# Clean up failed jobs older than 1 day
|
||||
cleanup_failed_jobs:
|
||||
command: "SolidQueue::FailedExecution.where('created_at < ?', 1.day.ago).delete_all"
|
||||
queue: background
|
||||
schedule: every 6 hours
|
||||
|
||||
@@ -11,6 +11,13 @@ Rails.application.routes.draw do
|
||||
# Admin user management (admin only)
|
||||
resources :users, only: [:index, :show, :edit, :update]
|
||||
|
||||
# Settings management (admin only)
|
||||
resources :settings, only: [:index] do
|
||||
collection do
|
||||
patch :update
|
||||
end
|
||||
end
|
||||
|
||||
# DSN management (admin only)
|
||||
resources :dsns do
|
||||
member do
|
||||
@@ -44,7 +51,7 @@ Rails.application.routes.draw do
|
||||
root "analytics#index"
|
||||
|
||||
# Event management
|
||||
resources :events, only: [:index]
|
||||
resources :events, only: [:index, :show]
|
||||
|
||||
# Network range management
|
||||
resources :network_ranges, only: [:index, :show, :new, :create, :edit, :update, :destroy] do
|
||||
@@ -79,4 +86,11 @@ Rails.application.routes.draw do
|
||||
post :create_country
|
||||
end
|
||||
end
|
||||
|
||||
# GeoLite2 data import management (admin only)
|
||||
resources :data_imports, only: [:index, :new, :create, :show, :destroy] do
|
||||
member do
|
||||
get :progress
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -4,7 +4,7 @@ test:
|
||||
|
||||
local:
|
||||
service: Disk
|
||||
root: <%= Rails.root.join("storage") %>
|
||||
root: <%= Rails.root.join("storage", "uploads") %>
|
||||
|
||||
# Use bin/rails credentials:edit to set the AWS secrets (as aws:access_key_id|secret_access_key)
|
||||
# amazon:
|
||||
|
||||
13
config/tailwind.config.js
Normal file
13
config/tailwind.config.js
Normal file
@@ -0,0 +1,13 @@
|
||||
/** @type {import('tailwindcss').Config} */
|
||||
module.exports = {
|
||||
content: [
|
||||
'./app/helpers/**/*.rb',
|
||||
'./app/javascript/**/*.js',
|
||||
'./app/views/**/*.erb',
|
||||
'./app/views/**/*.html.erb'
|
||||
],
|
||||
theme: {
|
||||
extend: {},
|
||||
},
|
||||
plugins: [],
|
||||
}
|
||||
Reference in New Issue
Block a user