Skip to content

Instantly share code, notes, and snippets.

@motine
Last active April 22, 2021 16:45
Show Gist options
  • Star 9 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save motine/cd6f1a77b4ca510f9aafadacf4f5c433 to your computer and use it in GitHub Desktop.
Save motine/cd6f1a77b4ca510f9aafadacf4f5c433 to your computer and use it in GitHub Desktop.
Simple Rails Monitoring
# services/monitoring/cleanup_service.rb
class Monitoring::CleanupService
def self.run
Monitoring::Measurement.where("recorded_at < ?", 3.months.ago).delete_all
end
end
# let this service run nightly
# models/monitoring/job.rb
class Monitoring::Job < Monitoring::Measurement
# value shows how long the job took in seconds
end
# config/initializers/monitoring.rb
class MonitoringPlugin < Delayed::Plugin
callbacks do |lifecycle|
lifecycle.around(:perform) do |worker, job, &block|
return if job.nil? || block.nil?
duration = Benchmark.realtime do
block.call(worker)
end
Monitoring::Job.create!(
recorded_at: Time.current,
subject: job.name,
value: duration,
details: {})
rescue => e
# notify exception
end
end
end
Delayed::Worker.plugins << MonitoringPlugin
# example data
# | id | type | recorded_at | subject | value | details |
# |----|-----------------|---------------------|---------------|-------|---------|
# | 1 | Monitoring::Job | 2021-03-15 11:44:00 | SomeJob#run | 0.017 | {} |
# | 2 | Monitoring::Job | 2021-03-15 11:44:00 | OtherJob.send | 1.074 | {} |
# models/monitoring/mail.rb
class Monitoring::Mail < Monitoring::Measurement
store_accessor :details, :to
# value shows how long the sending took in seconds
end
# config/initializers/monitoring.rb
ActiveSupport::Notifications.subscribe 'deliver.action_mailer' do |name, started, finished, unique_id, data|
Monitoring::Mail.create!(recorded_at: started, subject: "#{data[:mailer]}", value: finished - started, to: data[:to])
rescue => e
# notify exception
end
# example data:
# | id | type | recorded_at | subject | value | details |
# |----|------------------|---------------------|---------|-------|-------------------------------------|
# | 1 | Monitoring::Mail | 2021-03-13 11:38:00 | | 0.06 | {"to": ["development@example.net"]} |
# | 2 | Monitoring::Mail | 2021-03-13 11:38:00 | | 0.05 | {"to": ["development@example.net"]} |
# | 3 | Monitoring::Mail | 2021-03-13 11:38:00 | | 0.05 | {"to": ["development@example.net"]} |
# value shows how big the table is in MB
class Monitoring::TableSize < Monitoring::Measurement
store_accessor :details, :index_size, :data_size
end
# services/monitoring/table_size_recorder_service.rb
class Monitoring::TableSizeRecorderService
def self.run
query = 'SELECT relname AS table_name, pg_total_relation_size(relid) AS total_size, pg_indexes_size(relid) AS index_size, pg_relation_size(relid) AS data_size FROM pg_catalog.pg_statio_user_tables'
ActiveRecord::Base.connection.execute(query).each do |row|
Monitoring::TableSize.create!(
recorded_at: Time.current,
subject: row['table_name'],
value: row['total_size'] / 1_048_576.0, # mb
index_size: row['index_size'] / 1_048_576.0,
data_size: row['data_size'] / 1_048_576.0
)
end
end
end
# let this service run nightly
# example data:
# | id | type | recorded_at | subject | value | details |
# |----|-----------------------|---------------------|----------|--------|--------------------------------------------|
# | 1 | Monitoring::TableSize | 2021-03-15 11:47:00 | users | 0.59 | {"data_size": 0.414, "index_size": 0.15} |
# | 2 | Monitoring::TableSize | 2021-03-15 11:47:00 | articles | 14.48 | {"data_size": 9.703, "index_size": 4.75} |
# | 3 | Monitoring::TableSize | 2021-03-15 11:47:00 | sausages | 190.85 | {"data_size": 150.296, "index_size": 40.5} |
@ogirginc
Copy link

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment