Module: Railswatch::RailswatchHelper
- Defined in:
- app/helpers/railswatch/railswatch_helper.rb
Constant Summary collapse
- NAVIGATION_ITEMS =
[ { section: :dashboard, label: 'Overview', route: :railswatch_url }, { section: :requests, label: 'Requests', route: :railswatch_requests_url }, { section: :recent, label: 'Recent', route: :railswatch_recent_url }, { section: :slow, label: 'Slow', route: :railswatch_slow_url }, { section: :crashes, label: 'Errors', route: :railswatch_crashes_url }, { section: :resources, label: 'System', route: :railswatch_resources_url, visible: -> { Railswatch._resource_monitor_enabled } }, { section: :sidekiq, label: 'Sidekiq', route: :railswatch_sidekiq_url, visible: -> { defined?(Sidekiq) } }, { section: :delayed_job, label: 'Delayed Job', route: :railswatch_delayed_job_url, visible: -> { defined?(Delayed::Job) } }, { section: :grape, label: 'Grape', route: :railswatch_grape_url, visible: -> { defined?(Grape) } }, { section: :rake, label: 'Rake', route: :railswatch_rake_url, visible: -> { Railswatch.include_rake_tasks } }, { section: :custom, label: 'Custom', route: :railswatch_custom_url, visible: -> { Railswatch.include_custom_events } } ].freeze
- PAGE_META =
{ index: { eyebrow: 'Performance', title: 'Application Command Center', description: lambda { "Live request health, latency, and throughput over the last #{human_window(Railswatch.duration)}." }, badge: 'Live' }, requests: { eyebrow: 'Analysis', title: 'Request Breakdown', description: 'Compare controllers and actions by volume, percentiles, averages, and slowest paths.' }, recent: { eyebrow: 'Realtime', title: 'Recent Requests', description: lambda { "Inspect fresh traffic sampled from the last #{human_window(Railswatch.recent_requests_time_window)}." } }, slow: { eyebrow: 'Latency', title: 'Slow Requests', description: lambda { "Focus on requests above #{Railswatch.slow_requests_threshold} ms " \ 'and inspect traces before they age out.' } }, crashes: { eyebrow: 'Reliability', title: '500 Error Timeline', description: 'Review failures, backtraces, and the request context that led to them.' }, resources: { eyebrow: 'Infrastructure', title: 'System Resources', description: lambda { 'Watch CPU, memory, and disk behavior across the last ' \ "#{human_window(Railswatch.system_monitor_duration)}." } }, sidekiq: { eyebrow: 'Async Jobs', title: 'Sidekiq Workload', description: 'Track job throughput, worker runtime, and recent executions.' }, delayed_job: { eyebrow: 'Async Jobs', title: 'Delayed Job Workload', description: 'Monitor queue throughput, execution time, and recent jobs.' }, grape: { eyebrow: 'API', title: 'Grape Endpoints', description: 'Keep an eye on API traffic volume and recent endpoint activity.' }, rake: { eyebrow: 'Automation', title: 'Rake Tasks', description: 'Surface task runtime and throughput for your scheduled or manual jobs.' }, custom: { eyebrow: 'Business Events', title: 'Custom Measurements', description: 'Explore custom event timing and throughput captured with Railswatch.measure.' }, default: { eyebrow: 'Monitoring', title: 'Railswatch', description: 'Observe the health of your Rails application.' } }.freeze
Instance Method Summary collapse
- #active?(section) ⇒ Boolean
-
#bot_icon(user_agent) ⇒ Object
rubocop:disable Metrics/MethodLength.
- #card_caption(label) ⇒ Object
- #card_tone(label) ⇒ Object
- #compact_number(value) ⇒ Object
-
#duration_alert_class(duration_str) ⇒ Object
rubocop:disable Metrics/MethodLength.
- #extract_duration(str) ⇒ Object
-
#format_datetime(event = nil) ⇒ Object
Keep this method permissive because host applications may already call ‘format_datetime` with arbitrary values in their own templates.
- #format_rm_datetime(event) ⇒ Object
- #health_tone(value) ⇒ Object
- #icon(name) ⇒ Object
- #link_to_path(event) ⇒ Object
- #ms(value, limit = 1) ⇒ Object
- #navigation_items ⇒ Object
- #page_meta(section = action_name.to_sym) ⇒ Object
- #percentage(value, precision = 1) ⇒ Object
- #report_name(hash) ⇒ Object
- #round_it(value, limit = 1) ⇒ Object
- #short_path(path, length: 55) ⇒ Object
-
#status_tag(status) ⇒ Object
rubocop:disable Metrics/MethodLength.
Instance Method Details
#active?(section) ⇒ Boolean
297 298 299 300 301 302 303 304 305 306 307 308 |
# File 'app/helpers/railswatch/railswatch_helper.rb', line 297 def active?(section) actions = { dashboard: 'index', crashes: 'crashes', requests: 'requests', resources: 'resources', recent: 'recent', slow: 'slow', sidekiq: 'sidekiq', delayed_job: 'delayed_job', grape: 'grape', rake: 'rake', custom: 'custom' } return false unless controller_name == 'railswatch' 'is-active' if action_name == actions[section] end |
#bot_icon(user_agent) ⇒ Object
rubocop:disable Metrics/MethodLength
262 263 264 265 266 267 268 269 270 271 272 273 274 275 |
# File 'app/helpers/railswatch/railswatch_helper.rb', line 262 def bot_icon(user_agent) # rubocop:disable Metrics/MethodLength return nil if user_agent.blank? browser = Browser.new(user_agent) if browser.bot? content_tag(:span, class: 'user-agent-icon', title: browser.bot&.name) do icon('bot') end else content_tag(:span, class: 'user-agent-icon user-agent-icon-user', title: 'Real User') do icon('user') end end end |
#card_caption(label) ⇒ Object
205 206 207 208 209 210 211 212 213 214 215 216 |
# File 'app/helpers/railswatch/railswatch_helper.rb', line 205 def card_caption(label) case label.to_s.downcase when 'p50' 'Median request latency' when 'p95' 'Tail latency for slower traffic' when 'p99' 'Worst-case request experience' else 'Request insight' end end |
#card_tone(label) ⇒ Object
192 193 194 195 196 197 198 199 200 201 202 203 |
# File 'app/helpers/railswatch/railswatch_helper.rb', line 192 def card_tone(label) case label.to_s.downcase when 'p50' 'healthy' when 'p95' 'warning' when 'p99' 'critical' else 'neutral' end end |
#compact_number(value) ⇒ Object
174 175 176 177 178 |
# File 'app/helpers/railswatch/railswatch_helper.rb', line 174 def compact_number(value) return '0' if value.blank? number_to_human(value, precision: 3, strip_insignificant_zeros: true) end |
#duration_alert_class(duration_str) ⇒ Object
rubocop:disable Metrics/MethodLength
142 143 144 145 146 147 148 149 150 151 152 153 154 155 |
# File 'app/helpers/railswatch/railswatch_helper.rb', line 142 def duration_alert_class(duration_str) # rubocop:disable Metrics/MethodLength if duration_str.to_s =~ /(\d+.?\d+?)/ duration = ::Regexp.last_match(1).to_f if duration >= 500 'has-background-danger has-text-white-bis' elsif duration >= 200 'has-background-warning has-text-black-ter' else 'has-background-success has-text-white-bis' end else 'has-background-light' end end |
#extract_duration(str) ⇒ Object
157 158 159 160 161 162 163 164 165 |
# File 'app/helpers/railswatch/railswatch_helper.rb', line 157 def extract_duration(str) return str[:duration].to_s if str.is_a?(Hash) && str[:duration] if str =~ /Duration: (\d+.?\d+?ms)/i ::Regexp.last_match(1) else '-' end end |
#format_datetime(event = nil) ⇒ Object
Keep this method permissive because host applications may already call ‘format_datetime` with arbitrary values in their own templates.
291 292 293 294 295 |
# File 'app/helpers/railswatch/railswatch_helper.rb', line 291 def format_datetime(event = nil, **) return event.to_s unless event.respond_to?(:in_time_zone) || event.respond_to?(:utc) format_rm_datetime(event) end |
#format_rm_datetime(event) ⇒ Object
284 285 286 287 |
# File 'app/helpers/railswatch/railswatch_helper.rb', line 284 def format_rm_datetime(event) dt = Railswatch::Reports::BaseReport.time_in_app_time_zone(event) I18n.l(dt, format: '%Y-%m-%d %H:%M:%S') end |
#health_tone(value) ⇒ Object
184 185 186 187 188 189 190 |
# File 'app/helpers/railswatch/railswatch_helper.rb', line 184 def health_tone(value) return 'neutral' if value.nil? return 'critical' if value >= 5 return 'warning' if value >= 1 'healthy' end |
#icon(name) ⇒ Object
277 278 279 280 281 282 |
# File 'app/helpers/railswatch/railswatch_helper.rb', line 277 def icon(name) @icons ||= {} # https://www.iconfinder.com/iconsets/vivid @icons[name] ||= raw File.read(File.(File.dirname(__FILE__) + "/../../assets/images/#{name}.svg")) end |
#link_to_path(event) ⇒ Object
224 225 226 227 228 229 230 |
# File 'app/helpers/railswatch/railswatch_helper.rb', line 224 def link_to_path(event) if event[:method] == 'GET' link_to(short_path(event[:path]), event[:path], target: '_blank', title: short_path(event[:path])) else short_path(event[:path]) end end |
#ms(value, limit = 1) ⇒ Object
167 168 169 170 171 172 |
# File 'app/helpers/railswatch/railswatch_helper.rb', line 167 def ms(value, limit = 1) result = round_it(value, limit) return '-' if result.nil? result && result != 0 ? "#{result} ms" : '< 0 ms' end |
#navigation_items ⇒ Object
123 124 125 126 127 128 129 |
# File 'app/helpers/railswatch/railswatch_helper.rb', line 123 def NAVIGATION_ITEMS.filter_map do |item| next unless (item) item.slice(:section, :label).merge(path: railswatch.public_send(item[:route])) end end |
#page_meta(section = action_name.to_sym) ⇒ Object
131 132 133 |
# File 'app/helpers/railswatch/railswatch_helper.rb', line 131 def (section = action_name.to_sym) (PAGE_META[section.to_sym] || PAGE_META[:default]) end |
#percentage(value, precision = 1) ⇒ Object
180 181 182 |
# File 'app/helpers/railswatch/railswatch_helper.rb', line 180 def percentage(value, precision = 1) number_to_percentage(value.to_f, precision: precision) end |
#report_name(hash) ⇒ Object
232 233 234 235 236 237 238 239 240 241 242 243 244 |
# File 'app/helpers/railswatch/railswatch_helper.rb', line 232 def report_name(hash) hash.except(:on).collect do |key, value| next if value.blank? %( <div class="control"> <span class="tags has-addons"> <span class="tag">#{key}</span> <span class="tag is-info is-light">#{value}</span> </span> </div>) end.compact.join.html_safe end |
#round_it(value, limit = 1) ⇒ Object
135 136 137 138 139 140 |
# File 'app/helpers/railswatch/railswatch_helper.rb', line 135 def round_it(value, limit = 1) return nil unless value return value if value.is_a?(Integer) value.nan? ? nil : value.round(limit) end |
#short_path(path, length: 55) ⇒ Object
218 219 220 221 222 |
# File 'app/helpers/railswatch/railswatch_helper.rb', line 218 def short_path(path, length: 55) content_tag :span, title: path do truncate(path, length: length) end end |
#status_tag(status) ⇒ Object
rubocop:disable Metrics/MethodLength
246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 |
# File 'app/helpers/railswatch/railswatch_helper.rb', line 246 def status_tag(status) # rubocop:disable Metrics/MethodLength klass = case status.to_s when /error/, /^5/ 'tag is-danger' when /^4/ 'tag is-warning' when /^3/ 'tag is-info' when /^2/, /success/ 'tag is-success' end content_tag(:span, class: klass) do status end end |