railswatch 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +485 -0
- data/Rakefile +37 -0
- data/app/assets/config/railswatch_manifest.js +0 -0
- data/app/assets/images/activity.svg +13 -0
- data/app/assets/images/bot.svg +1 -0
- data/app/assets/images/close.svg +13 -0
- data/app/assets/images/details.svg +3 -0
- data/app/assets/images/download.svg +3 -0
- data/app/assets/images/export.svg +13 -0
- data/app/assets/images/external.svg +1 -0
- data/app/assets/images/git.svg +1 -0
- data/app/assets/images/github.svg +1 -0
- data/app/assets/images/home.svg +16 -0
- data/app/assets/images/import.svg +13 -0
- data/app/assets/images/menu.svg +16 -0
- data/app/assets/images/moon.svg +3 -0
- data/app/assets/images/stat.svg +1 -0
- data/app/assets/images/sun.svg +4 -0
- data/app/assets/images/user.svg +1 -0
- data/app/controllers/railswatch/base_controller.rb +35 -0
- data/app/controllers/railswatch/concerns/csv_exportable.rb +31 -0
- data/app/controllers/railswatch/railswatch_controller.rb +183 -0
- data/app/engine_assets/javascripts/apex_ext.js +30 -0
- data/app/engine_assets/javascripts/application.js +9 -0
- data/app/engine_assets/javascripts/autoupdate.js +79 -0
- data/app/engine_assets/javascripts/charts.js +279 -0
- data/app/engine_assets/javascripts/navbar.js +11 -0
- data/app/engine_assets/javascripts/panel.js +43 -0
- data/app/engine_assets/javascripts/table.js +12 -0
- data/app/engine_assets/javascripts/theme.js +43 -0
- data/app/engine_assets/stylesheets/panel.css +111 -0
- data/app/engine_assets/stylesheets/responsive.css +102 -0
- data/app/engine_assets/stylesheets/style.css +960 -0
- data/app/helpers/railswatch/railswatch_helper.rb +338 -0
- data/app/views/railswatch/_panel.html.erb +15 -0
- data/app/views/railswatch/layouts/railswatch.html.erb +81 -0
- data/app/views/railswatch/railswatch/_card.html.erb +7 -0
- data/app/views/railswatch/railswatch/_chart.html.erb +13 -0
- data/app/views/railswatch/railswatch/_crashes_table_content.html.erb +62 -0
- data/app/views/railswatch/railswatch/_custom_events_table_content.html.erb +27 -0
- data/app/views/railswatch/railswatch/_delayed_job_table_content.html.erb +52 -0
- data/app/views/railswatch/railswatch/_export.html.erb +4 -0
- data/app/views/railswatch/railswatch/_grape_requests_table_content.html.erb +31 -0
- data/app/views/railswatch/railswatch/_overview.html.erb +124 -0
- data/app/views/railswatch/railswatch/_rake_tasks_table_content.html.erb +25 -0
- data/app/views/railswatch/railswatch/_recent_requests_table_content.html.erb +28 -0
- data/app/views/railswatch/railswatch/_recent_row.html.erb +41 -0
- data/app/views/railswatch/railswatch/_requests_table_content.html.erb +51 -0
- data/app/views/railswatch/railswatch/_sidekiq_jobs_table_content.html.erb +50 -0
- data/app/views/railswatch/railswatch/_summary.html.erb +50 -0
- data/app/views/railswatch/railswatch/_table.html.erb +30 -0
- data/app/views/railswatch/railswatch/_trace.html.erb +78 -0
- data/app/views/railswatch/railswatch/crashes.html.erb +2 -0
- data/app/views/railswatch/railswatch/custom.html.erb +6 -0
- data/app/views/railswatch/railswatch/delayed_job.html.erb +6 -0
- data/app/views/railswatch/railswatch/grape.html.erb +6 -0
- data/app/views/railswatch/railswatch/index.html.erb +9 -0
- data/app/views/railswatch/railswatch/rake.html.erb +6 -0
- data/app/views/railswatch/railswatch/recent.html.erb +2 -0
- data/app/views/railswatch/railswatch/requests.html.erb +2 -0
- data/app/views/railswatch/railswatch/resources.html.erb +28 -0
- data/app/views/railswatch/railswatch/sidekiq.html.erb +6 -0
- data/app/views/railswatch/railswatch/slow.html.erb +2 -0
- data/app/views/railswatch/railswatch/summary.js.erb +3 -0
- data/app/views/railswatch/railswatch/trace.js.erb +9 -0
- data/app/views/railswatch/shared/_header.html.erb +39 -0
- data/app/views/railswatch/shared/_page_header.html.erb +23 -0
- data/config/routes.rb +27 -0
- data/lib/generators/railswatch/install/USAGE +19 -0
- data/lib/generators/railswatch/install/install_generator.rb +46 -0
- data/lib/generators/railswatch/install/templates/create_railswatch_tables.rb +140 -0
- data/lib/generators/railswatch/install/templates/initializer.rb +87 -0
- data/lib/railswatch/data_source.rb +106 -0
- data/lib/railswatch/engine.rb +103 -0
- data/lib/railswatch/events/record.rb +63 -0
- data/lib/railswatch/extensions/trace.rb +14 -0
- data/lib/railswatch/extensions/trace_db.rb +21 -0
- data/lib/railswatch/gems/custom_ext.rb +38 -0
- data/lib/railswatch/gems/delayed_job_ext.rb +70 -0
- data/lib/railswatch/gems/grape_ext.rb +64 -0
- data/lib/railswatch/gems/rake_ext.rb +69 -0
- data/lib/railswatch/gems/sidekiq_ext.rb +55 -0
- data/lib/railswatch/instrument/metrics_collector.rb +70 -0
- data/lib/railswatch/interface.rb +9 -0
- data/lib/railswatch/models/application_record.rb +31 -0
- data/lib/railswatch/models/base_record.rb +59 -0
- data/lib/railswatch/models/collection.rb +37 -0
- data/lib/railswatch/models/custom_record.rb +32 -0
- data/lib/railswatch/models/delayed_job_record.rb +39 -0
- data/lib/railswatch/models/event_record.rb +11 -0
- data/lib/railswatch/models/grape_record.rb +61 -0
- data/lib/railswatch/models/rake_record.rb +33 -0
- data/lib/railswatch/models/request_record.rb +105 -0
- data/lib/railswatch/models/resource_record.rb +33 -0
- data/lib/railswatch/models/sidekiq_record.rb +41 -0
- data/lib/railswatch/models/trace_record.rb +21 -0
- data/lib/railswatch/pruner.rb +47 -0
- data/lib/railswatch/rails/middleware.rb +117 -0
- data/lib/railswatch/rails/query_builder.rb +20 -0
- data/lib/railswatch/reports/annotations_report.rb +13 -0
- data/lib/railswatch/reports/base_report.rb +48 -0
- data/lib/railswatch/reports/breakdown_report.rb +11 -0
- data/lib/railswatch/reports/crash_report.rb +11 -0
- data/lib/railswatch/reports/overview_report.rb +88 -0
- data/lib/railswatch/reports/percentile_report.rb +16 -0
- data/lib/railswatch/reports/recent_requests_report.rb +21 -0
- data/lib/railswatch/reports/requests_report.rb +75 -0
- data/lib/railswatch/reports/resources_report.rb +42 -0
- data/lib/railswatch/reports/response_time_report.rb +27 -0
- data/lib/railswatch/reports/slow_requests_report.rb +21 -0
- data/lib/railswatch/reports/throughput_report.rb +16 -0
- data/lib/railswatch/reports/trace_report.rb +17 -0
- data/lib/railswatch/system_monitor/resources_monitor.rb +88 -0
- data/lib/railswatch/thread/current_request.rb +37 -0
- data/lib/railswatch/utils.rb +58 -0
- data/lib/railswatch/version.rb +7 -0
- data/lib/railswatch/widgets/base.rb +17 -0
- data/lib/railswatch/widgets/card.rb +19 -0
- data/lib/railswatch/widgets/chart.rb +33 -0
- data/lib/railswatch/widgets/crashes_table.rb +27 -0
- data/lib/railswatch/widgets/custom_events_table.rb +48 -0
- data/lib/railswatch/widgets/delayed_job_table.rb +31 -0
- data/lib/railswatch/widgets/grape_requests_table.rb +31 -0
- data/lib/railswatch/widgets/percentile_card.rb +23 -0
- data/lib/railswatch/widgets/rake_tasks_table.rb +31 -0
- data/lib/railswatch/widgets/recent_requests_table.rb +35 -0
- data/lib/railswatch/widgets/requests_table.rb +27 -0
- data/lib/railswatch/widgets/resource_chart.rb +116 -0
- data/lib/railswatch/widgets/response_time_chart.rb +29 -0
- data/lib/railswatch/widgets/sidekiq_jobs_table.rb +31 -0
- data/lib/railswatch/widgets/slow_requests_table.rb +33 -0
- data/lib/railswatch/widgets/table.rb +43 -0
- data/lib/railswatch/widgets/throughput_chart.rb +29 -0
- data/lib/railswatch.rb +184 -0
- data/lib/tasks/railswatch.rake +9 -0
- metadata +445 -0
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Railswatch
|
|
4
|
+
module Widgets
|
|
5
|
+
class ResourceChart < Chart
|
|
6
|
+
attr_reader :server, :key, :type
|
|
7
|
+
|
|
8
|
+
def initialize(server, key:, type:, **)
|
|
9
|
+
super(nil)
|
|
10
|
+
@server = server
|
|
11
|
+
@key = key
|
|
12
|
+
@type = type
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def id
|
|
16
|
+
[key, 'report', server.key.parameterize].join('_')
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def data
|
|
20
|
+
all_data = server.report.extract_signal { |event| signal(event) }
|
|
21
|
+
all_data[server.key]
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def signal(event)
|
|
25
|
+
format(event[key])
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def format(measurement)
|
|
29
|
+
measurement
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
class CPULoad < ResourceChart
|
|
34
|
+
def initialize(server)
|
|
35
|
+
super(
|
|
36
|
+
server,
|
|
37
|
+
key: :cpu,
|
|
38
|
+
type: 'Percentage',
|
|
39
|
+
subtitle: 'CPU',
|
|
40
|
+
description: 'CPU load average (1 min), average per 1 minute',
|
|
41
|
+
legend: 'CPU',
|
|
42
|
+
)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def format(measurement)
|
|
46
|
+
measurement['one_min'].to_f.round(2)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def measure
|
|
50
|
+
load_averages = Sys::CPU.load_avg
|
|
51
|
+
{
|
|
52
|
+
one_min: load_averages[0],
|
|
53
|
+
five_min: load_averages[1],
|
|
54
|
+
fifteen_min: load_averages[2]
|
|
55
|
+
}
|
|
56
|
+
rescue StandardError => e
|
|
57
|
+
::Rails.logger.error "Error fetching CPU usage: #{e.message}"
|
|
58
|
+
{ one_min: 0.0, five_min: 0.0, fifteen_min: 0.0 }
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
class MemoryUsage < ResourceChart
|
|
63
|
+
def initialize(server)
|
|
64
|
+
super(
|
|
65
|
+
server,
|
|
66
|
+
key: :memory,
|
|
67
|
+
type: 'Usage',
|
|
68
|
+
subtitle: 'Memory',
|
|
69
|
+
description: 'App memory usage',
|
|
70
|
+
legend: 'Usage',
|
|
71
|
+
)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def format(measurement)
|
|
75
|
+
measurement.to_f.round(2)
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def measure
|
|
79
|
+
GetProcessMem.new.bytes
|
|
80
|
+
rescue StandardError => e
|
|
81
|
+
::Rails.logger.error "Error fetching memory usage: #{e.message}"
|
|
82
|
+
0
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
class DiskUsage < ResourceChart
|
|
87
|
+
def initialize(server)
|
|
88
|
+
super(
|
|
89
|
+
server,
|
|
90
|
+
key: :disk,
|
|
91
|
+
type: 'Usage',
|
|
92
|
+
subtitle: 'Storage',
|
|
93
|
+
description: 'Available storage size (local disk size)',
|
|
94
|
+
legend: 'Usage',
|
|
95
|
+
)
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def format(measurement)
|
|
99
|
+
measurement['available'].to_f.round(2)
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def measure
|
|
103
|
+
path = '/'
|
|
104
|
+
stat = Sys::Filesystem.stat(path)
|
|
105
|
+
{
|
|
106
|
+
available: stat.blocks_available * stat.block_size,
|
|
107
|
+
total: stat.blocks * stat.block_size,
|
|
108
|
+
used: (stat.blocks - stat.blocks_available) * stat.block_size
|
|
109
|
+
}
|
|
110
|
+
rescue StandardError => e
|
|
111
|
+
::Rails.logger.error "Error fetching disk space: #{e.message}"
|
|
112
|
+
{ available: 0, total: 0, used: 0 }
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Railswatch
|
|
4
|
+
module Widgets
|
|
5
|
+
class ResponseTimeChart < Chart
|
|
6
|
+
def initialize(
|
|
7
|
+
datasource,
|
|
8
|
+
subtitle: 'Average Response Time Report',
|
|
9
|
+
description: 'All requests (site visitors, search engines, bots, etc)',
|
|
10
|
+
legend: 'Response Time',
|
|
11
|
+
units: nil
|
|
12
|
+
)
|
|
13
|
+
super
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def id
|
|
17
|
+
'response_time_report_chart'
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def type
|
|
21
|
+
'RT'
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def data
|
|
25
|
+
Reports::ResponseTimeReport.new(datasource.db).data
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Railswatch
|
|
4
|
+
module Widgets
|
|
5
|
+
class SidekiqJobsTable < Table
|
|
6
|
+
def subtitle
|
|
7
|
+
"Recent Jobs (last #{Railswatch.recent_requests_time_window / 60} minutes)"
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def data
|
|
11
|
+
@data ||= Railswatch::Reports::RecentRequestsReport.new(datasource.db).data
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def empty_message
|
|
15
|
+
'Nothing to show here. Try to make a few requests in the main app.'
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def show_export?
|
|
19
|
+
false
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def table_classes
|
|
23
|
+
'table is-fullwidth is-hoverable is-narrow'
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def content_partial_path
|
|
27
|
+
'railswatch/railswatch/sidekiq_jobs_table_content'
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Railswatch
|
|
4
|
+
module Widgets
|
|
5
|
+
class SlowRequestsTable < Table
|
|
6
|
+
def subtitle
|
|
7
|
+
window_minutes = Railswatch.slow_requests_time_window / 60
|
|
8
|
+
threshold = Railswatch.slow_requests_threshold
|
|
9
|
+
"Slow Requests (last #{window_minutes} minutes + slower than #{threshold}ms)"
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def data
|
|
13
|
+
@data ||= Railswatch::Reports::SlowRequestsReport.new(datasource.db).data
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def empty_message
|
|
17
|
+
'Nothing to show here. Try to make a few requests in the main app.'
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def table_id
|
|
21
|
+
'recent'
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def table_classes
|
|
25
|
+
'table is-fullwidth is-hoverable is-narrow'
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def content_partial_path
|
|
29
|
+
'railswatch/railswatch/recent_requests_table_content'
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Railswatch
|
|
4
|
+
module Widgets
|
|
5
|
+
class Table < Base
|
|
6
|
+
def subtitle
|
|
7
|
+
raise NotImplementedError
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def data
|
|
11
|
+
raise NotImplementedError
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def empty_message
|
|
15
|
+
'No data to display.'
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def show_export?
|
|
19
|
+
true
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def auto_update_interval
|
|
23
|
+
nil
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def table_id
|
|
27
|
+
nil
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def table_classes
|
|
31
|
+
'table is-fullwidth is-hoverable'
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def content_partial_path
|
|
35
|
+
raise NotImplementedError, 'Subclasses must define content_partial_path'
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def to_partial_path
|
|
39
|
+
'railswatch/railswatch/table'
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Railswatch
|
|
4
|
+
module Widgets
|
|
5
|
+
class ThroughputChart < Chart
|
|
6
|
+
def initialize(
|
|
7
|
+
datasource,
|
|
8
|
+
subtitle: 'Throughput Report',
|
|
9
|
+
description: 'All requests (site visitors, search engines, bots, etc)',
|
|
10
|
+
legend: 'RPM',
|
|
11
|
+
units: 'rpm'
|
|
12
|
+
)
|
|
13
|
+
super
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def id
|
|
17
|
+
'throughput_report_chart'
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def type
|
|
21
|
+
'TIR'
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def data
|
|
25
|
+
Reports::ThroughputReport.new(datasource.db).data
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
data/lib/railswatch.rb
ADDED
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'active_record'
|
|
4
|
+
require 'browser'
|
|
5
|
+
require 'active_support/core_ext/integer'
|
|
6
|
+
require_relative 'railswatch/version'
|
|
7
|
+
require_relative 'railswatch/rails/query_builder'
|
|
8
|
+
require_relative 'railswatch/rails/middleware'
|
|
9
|
+
require_relative 'railswatch/models/application_record'
|
|
10
|
+
require_relative 'railswatch/models/base_record'
|
|
11
|
+
require_relative 'railswatch/models/request_record'
|
|
12
|
+
require_relative 'railswatch/models/sidekiq_record'
|
|
13
|
+
require_relative 'railswatch/models/delayed_job_record'
|
|
14
|
+
require_relative 'railswatch/models/grape_record'
|
|
15
|
+
require_relative 'railswatch/models/trace_record'
|
|
16
|
+
require_relative 'railswatch/models/rake_record'
|
|
17
|
+
require_relative 'railswatch/models/resource_record'
|
|
18
|
+
require_relative 'railswatch/models/custom_record'
|
|
19
|
+
require_relative 'railswatch/models/event_record'
|
|
20
|
+
require_relative 'railswatch/data_source'
|
|
21
|
+
require_relative 'railswatch/utils'
|
|
22
|
+
require_relative 'railswatch/reports/base_report'
|
|
23
|
+
require_relative 'railswatch/reports/requests_report'
|
|
24
|
+
require_relative 'railswatch/reports/crash_report'
|
|
25
|
+
require_relative 'railswatch/reports/response_time_report'
|
|
26
|
+
require_relative 'railswatch/reports/throughput_report'
|
|
27
|
+
require_relative 'railswatch/reports/recent_requests_report'
|
|
28
|
+
require_relative 'railswatch/reports/slow_requests_report'
|
|
29
|
+
require_relative 'railswatch/reports/breakdown_report'
|
|
30
|
+
require_relative 'railswatch/reports/trace_report'
|
|
31
|
+
require_relative 'railswatch/reports/percentile_report'
|
|
32
|
+
require_relative 'railswatch/reports/resources_report'
|
|
33
|
+
require_relative 'railswatch/reports/annotations_report'
|
|
34
|
+
require_relative 'railswatch/reports/overview_report'
|
|
35
|
+
require_relative 'railswatch/events/record'
|
|
36
|
+
require_relative 'railswatch/widgets/base'
|
|
37
|
+
require_relative 'railswatch/widgets/chart'
|
|
38
|
+
require_relative 'railswatch/widgets/card'
|
|
39
|
+
require_relative 'railswatch/widgets/table'
|
|
40
|
+
require_relative 'railswatch/widgets/throughput_chart'
|
|
41
|
+
require_relative 'railswatch/widgets/response_time_chart'
|
|
42
|
+
require_relative 'railswatch/widgets/percentile_card'
|
|
43
|
+
require_relative 'railswatch/widgets/resource_chart'
|
|
44
|
+
require_relative 'railswatch/widgets/requests_table'
|
|
45
|
+
require_relative 'railswatch/widgets/recent_requests_table'
|
|
46
|
+
require_relative 'railswatch/widgets/crashes_table'
|
|
47
|
+
require_relative 'railswatch/widgets/slow_requests_table'
|
|
48
|
+
require_relative 'railswatch/widgets/sidekiq_jobs_table'
|
|
49
|
+
require_relative 'railswatch/widgets/delayed_job_table'
|
|
50
|
+
require_relative 'railswatch/widgets/custom_events_table'
|
|
51
|
+
require_relative 'railswatch/widgets/grape_requests_table'
|
|
52
|
+
require_relative 'railswatch/widgets/rake_tasks_table'
|
|
53
|
+
require_relative 'railswatch/extensions/trace'
|
|
54
|
+
require_relative 'railswatch/extensions/trace_db'
|
|
55
|
+
require_relative 'railswatch/thread/current_request'
|
|
56
|
+
require_relative 'railswatch/interface'
|
|
57
|
+
require_relative 'railswatch/pruner'
|
|
58
|
+
require 'isolate_assets'
|
|
59
|
+
|
|
60
|
+
module Railswatch
|
|
61
|
+
extend Railswatch::Interface
|
|
62
|
+
|
|
63
|
+
FORMAT = '%Y%m%dT%H%M'
|
|
64
|
+
|
|
65
|
+
@duration = 4.hours
|
|
66
|
+
@recent_requests_time_window = 60.minutes
|
|
67
|
+
@recent_requests_limit = nil
|
|
68
|
+
@slow_requests_time_window = 4.hours
|
|
69
|
+
@slow_requests_limit = 500
|
|
70
|
+
@slow_requests_threshold = 500
|
|
71
|
+
@database_connection_name = nil
|
|
72
|
+
@debug = false
|
|
73
|
+
@enabled = true
|
|
74
|
+
@mount_at = '/railswatch'
|
|
75
|
+
@http_basic_authentication_enabled = false
|
|
76
|
+
@http_basic_authentication_user_name = 'railswatch'
|
|
77
|
+
@http_basic_authentication_password = 'password12'
|
|
78
|
+
@verify_access_proc = proc { |_controller| true }
|
|
79
|
+
@ignored_endpoints = Set.new([])
|
|
80
|
+
@ignored_paths = Set.new([])
|
|
81
|
+
@skip = false
|
|
82
|
+
@home_link = '/'
|
|
83
|
+
@skipable_rake_tasks = []
|
|
84
|
+
@custom_data_proc = nil
|
|
85
|
+
@current_user_proc = nil
|
|
86
|
+
@include_rake_tasks = false
|
|
87
|
+
@include_custom_events = true
|
|
88
|
+
@ignore_trace_headers = ['datetimei']
|
|
89
|
+
@url_options = nil
|
|
90
|
+
@system_monitor_duration = 24.hours
|
|
91
|
+
@retention = {
|
|
92
|
+
requests: @duration,
|
|
93
|
+
sidekiq: @duration,
|
|
94
|
+
delayed_job: @duration,
|
|
95
|
+
grape: @duration,
|
|
96
|
+
rake: @duration,
|
|
97
|
+
custom: @duration,
|
|
98
|
+
resources: @system_monitor_duration,
|
|
99
|
+
traces: @recent_requests_time_window,
|
|
100
|
+
events: nil
|
|
101
|
+
}
|
|
102
|
+
@system_monitors = %w[
|
|
103
|
+
CPULoad
|
|
104
|
+
MemoryUsage
|
|
105
|
+
DiskUsage
|
|
106
|
+
]
|
|
107
|
+
@dashboard_charts = [
|
|
108
|
+
%w[P50Card P95Card P99Card],
|
|
109
|
+
'ThroughputChart',
|
|
110
|
+
'ResponseTimeChart'
|
|
111
|
+
]
|
|
112
|
+
@_resource_monitor = nil
|
|
113
|
+
@_running_mode = nil
|
|
114
|
+
@_resource_monitor_enabled = false
|
|
115
|
+
|
|
116
|
+
class << self
|
|
117
|
+
attr_accessor :duration,
|
|
118
|
+
:recent_requests_time_window,
|
|
119
|
+
:recent_requests_limit,
|
|
120
|
+
:slow_requests_time_window,
|
|
121
|
+
:slow_requests_limit,
|
|
122
|
+
:slow_requests_threshold,
|
|
123
|
+
:database_connection_name,
|
|
124
|
+
:debug,
|
|
125
|
+
:enabled,
|
|
126
|
+
:mount_at,
|
|
127
|
+
:http_basic_authentication_enabled,
|
|
128
|
+
:http_basic_authentication_user_name,
|
|
129
|
+
:http_basic_authentication_password,
|
|
130
|
+
:verify_access_proc,
|
|
131
|
+
:skip,
|
|
132
|
+
:home_link,
|
|
133
|
+
:skipable_rake_tasks,
|
|
134
|
+
:custom_data_proc,
|
|
135
|
+
:current_user_proc,
|
|
136
|
+
:include_rake_tasks,
|
|
137
|
+
:include_custom_events,
|
|
138
|
+
:ignore_trace_headers,
|
|
139
|
+
:url_options,
|
|
140
|
+
:system_monitor_duration,
|
|
141
|
+
:retention,
|
|
142
|
+
:system_monitors,
|
|
143
|
+
:dashboard_charts,
|
|
144
|
+
:_resource_monitor,
|
|
145
|
+
:_running_mode,
|
|
146
|
+
:_resource_monitor_enabled
|
|
147
|
+
|
|
148
|
+
attr_reader :ignored_endpoints, :ignored_paths
|
|
149
|
+
|
|
150
|
+
def ignored_endpoints=(endpoints)
|
|
151
|
+
@ignored_endpoints = Set.new(endpoints)
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
def ignored_paths=(paths)
|
|
155
|
+
@ignored_paths = Set.new(paths)
|
|
156
|
+
end
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
def self.setup
|
|
160
|
+
yield(self)
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
def self.prune!
|
|
164
|
+
Railswatch::Pruner.call
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
def self.measure(...)
|
|
168
|
+
Railswatch::Gems::CustomExtension.measure(...)
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
def self.log(message)
|
|
172
|
+
return unless Railswatch.debug
|
|
173
|
+
|
|
174
|
+
if ::Rails.logger
|
|
175
|
+
::Rails.logger.debug(message)
|
|
176
|
+
else
|
|
177
|
+
puts(message)
|
|
178
|
+
end
|
|
179
|
+
end
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
require 'railswatch/engine'
|
|
183
|
+
|
|
184
|
+
require_relative 'railswatch/gems/custom_ext'
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
namespace :railswatch do
|
|
4
|
+
desc 'Prune old railswatch records based on configured retention'
|
|
5
|
+
task prune: :environment do
|
|
6
|
+
results = Railswatch.prune!
|
|
7
|
+
puts results.map { |type, count| "#{type}: #{count}" }.join("\n")
|
|
8
|
+
end
|
|
9
|
+
end
|