dbwatcher 1.1.1 → 1.1.2
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 +4 -4
- data/README.md +24 -2
- data/app/assets/javascripts/dbwatcher/components/changes_table_hybrid.js +12 -22
- data/app/assets/javascripts/dbwatcher/components/dashboard.js +325 -0
- data/app/assets/stylesheets/dbwatcher/application.css +394 -41
- data/app/assets/stylesheets/dbwatcher/application.scss +4 -0
- data/app/assets/stylesheets/dbwatcher/components/_badges.scss +68 -23
- data/app/assets/stylesheets/dbwatcher/components/_compact_table.scss +83 -26
- data/app/assets/stylesheets/dbwatcher/components/_diagrams.scss +3 -3
- data/app/assets/stylesheets/dbwatcher/components/_navigation.scss +9 -0
- data/app/assets/stylesheets/dbwatcher/components/_tabulator.scss +248 -0
- data/app/assets/stylesheets/dbwatcher/vendor/_tabulator_overrides.scss +37 -0
- data/app/controllers/dbwatcher/api/v1/system_info_controller.rb +180 -0
- data/app/controllers/dbwatcher/dashboard/system_info_controller.rb +64 -0
- data/app/controllers/dbwatcher/dashboard_controller.rb +17 -0
- data/app/controllers/dbwatcher/sessions_controller.rb +3 -19
- data/app/helpers/dbwatcher/application_helper.rb +43 -11
- data/app/helpers/dbwatcher/diagram_helper.rb +0 -88
- data/app/views/dbwatcher/dashboard/_layout.html.erb +27 -0
- data/app/views/dbwatcher/dashboard/_overview.html.erb +188 -0
- data/app/views/dbwatcher/dashboard/_system_info.html.erb +22 -0
- data/app/views/dbwatcher/dashboard/_system_info_content.html.erb +389 -0
- data/app/views/dbwatcher/dashboard/index.html.erb +8 -177
- data/app/views/dbwatcher/sessions/_changes.html.erb +91 -0
- data/app/views/dbwatcher/sessions/_layout.html.erb +23 -0
- data/app/views/dbwatcher/sessions/index.html.erb +107 -87
- data/app/views/dbwatcher/sessions/show.html.erb +10 -4
- data/app/views/dbwatcher/tables/index.html.erb +32 -40
- data/app/views/layouts/dbwatcher/application.html.erb +100 -48
- data/config/routes.rb +23 -6
- data/lib/dbwatcher/configuration.rb +18 -1
- data/lib/dbwatcher/services/base_service.rb +2 -0
- data/lib/dbwatcher/services/system_info/database_info_collector.rb +263 -0
- data/lib/dbwatcher/services/system_info/machine_info_collector.rb +387 -0
- data/lib/dbwatcher/services/system_info/runtime_info_collector.rb +328 -0
- data/lib/dbwatcher/services/system_info/system_info_collector.rb +114 -0
- data/lib/dbwatcher/storage/concerns/error_handler.rb +6 -6
- data/lib/dbwatcher/storage/session.rb +5 -0
- data/lib/dbwatcher/storage/system_info_storage.rb +242 -0
- data/lib/dbwatcher/storage.rb +12 -0
- data/lib/dbwatcher/version.rb +1 -1
- data/lib/dbwatcher.rb +15 -1
- metadata +20 -15
- data/app/helpers/dbwatcher/component_helper.rb +0 -29
- data/app/views/dbwatcher/sessions/_changes_tab.html.erb +0 -265
- data/app/views/dbwatcher/sessions/_tab_navigation.html.erb +0 -12
- data/app/views/dbwatcher/sessions/changes.html.erb +0 -21
- data/app/views/dbwatcher/sessions/components/changes/_filters.html.erb +0 -44
- data/app/views/dbwatcher/sessions/components/changes/_table_list.html.erb +0 -96
- data/app/views/dbwatcher/sessions/diagrams.html.erb +0 -21
- data/app/views/dbwatcher/sessions/shared/_layout.html.erb +0 -8
- data/app/views/dbwatcher/sessions/shared/_navigation.html.erb +0 -35
- data/app/views/dbwatcher/sessions/shared/_session_header.html.erb +0 -25
- data/app/views/dbwatcher/sessions/summary.html.erb +0 -21
- /data/app/views/dbwatcher/sessions/{_diagrams_tab.html.erb → _diagrams.html.erb} +0 -0
- /data/app/views/dbwatcher/sessions/{_summary_tab.html.erb → _summary.html.erb} +0 -0
@@ -0,0 +1,328 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "../../logging"
|
4
|
+
|
5
|
+
module Dbwatcher
|
6
|
+
module Services
|
7
|
+
module SystemInfo
|
8
|
+
# Runtime information collector service
|
9
|
+
#
|
10
|
+
# Collects runtime-specific information including Ruby version, Rails version,
|
11
|
+
# loaded gems, environment variables, and application configuration.
|
12
|
+
#
|
13
|
+
# @example
|
14
|
+
# info = SystemInfo::RuntimeInfoCollector.call
|
15
|
+
# puts info[:ruby_version]
|
16
|
+
# puts info[:rails_version]
|
17
|
+
# puts info[:gem_count]
|
18
|
+
#
|
19
|
+
# This class is necessarily complex due to the comprehensive runtime information
|
20
|
+
# it needs to collect across different Ruby and Rails environments.
|
21
|
+
# rubocop:disable Metrics/ClassLength
|
22
|
+
class RuntimeInfoCollector
|
23
|
+
include Dbwatcher::Logging
|
24
|
+
|
25
|
+
# Class method to create instance and call
|
26
|
+
#
|
27
|
+
# @return [Hash] runtime information
|
28
|
+
def self.call
|
29
|
+
new.call
|
30
|
+
end
|
31
|
+
|
32
|
+
# Collect runtime information
|
33
|
+
#
|
34
|
+
# @return [Hash] collected runtime information
|
35
|
+
# rubocop:disable Metrics/MethodLength
|
36
|
+
def call
|
37
|
+
log_info "#{self.class.name}: Collecting runtime information"
|
38
|
+
|
39
|
+
{
|
40
|
+
ruby_version: collect_ruby_version,
|
41
|
+
ruby_engine: collect_ruby_engine,
|
42
|
+
ruby_patchlevel: collect_ruby_patchlevel,
|
43
|
+
rails_version: collect_rails_version,
|
44
|
+
rails_env: collect_rails_env,
|
45
|
+
environment: collect_environment,
|
46
|
+
pid: Process.pid,
|
47
|
+
gem_count: collect_gem_count,
|
48
|
+
loaded_gems: collect_loaded_gems,
|
49
|
+
load_path: collect_load_path_info,
|
50
|
+
environment_variables: collect_environment_variables,
|
51
|
+
application_config: collect_application_config
|
52
|
+
}
|
53
|
+
rescue StandardError => e
|
54
|
+
log_error "Runtime info collection failed: #{e.message}"
|
55
|
+
{ error: e.message }
|
56
|
+
end
|
57
|
+
# rubocop:enable Metrics/MethodLength
|
58
|
+
|
59
|
+
private
|
60
|
+
|
61
|
+
# Collect Ruby version information
|
62
|
+
#
|
63
|
+
# @return [String] Ruby version
|
64
|
+
def collect_ruby_version
|
65
|
+
RUBY_VERSION
|
66
|
+
rescue StandardError => e
|
67
|
+
log_error "Failed to get Ruby version: #{e.message}"
|
68
|
+
"unknown"
|
69
|
+
end
|
70
|
+
|
71
|
+
# Collect Ruby engine information
|
72
|
+
#
|
73
|
+
# @return [String] Ruby engine (e.g., ruby, jruby, rbx)
|
74
|
+
def collect_ruby_engine
|
75
|
+
defined?(RUBY_ENGINE) ? RUBY_ENGINE : "ruby"
|
76
|
+
rescue StandardError => e
|
77
|
+
log_error "Failed to get Ruby engine: #{e.message}"
|
78
|
+
"unknown"
|
79
|
+
end
|
80
|
+
|
81
|
+
# Collect Ruby patchlevel
|
82
|
+
#
|
83
|
+
# @return [String] Ruby patchlevel
|
84
|
+
def collect_ruby_patchlevel
|
85
|
+
RUBY_PATCHLEVEL.to_s
|
86
|
+
rescue StandardError => e
|
87
|
+
log_error "Failed to get Ruby patchlevel: #{e.message}"
|
88
|
+
"unknown"
|
89
|
+
end
|
90
|
+
|
91
|
+
# Collect Rails version if available
|
92
|
+
#
|
93
|
+
# @return [String] Rails version or nil
|
94
|
+
def collect_rails_version
|
95
|
+
return nil unless defined?(Rails)
|
96
|
+
|
97
|
+
Rails.version
|
98
|
+
rescue StandardError => e
|
99
|
+
log_error "Failed to get Rails version: #{e.message}"
|
100
|
+
nil
|
101
|
+
end
|
102
|
+
|
103
|
+
# Collect Rails environment if available
|
104
|
+
#
|
105
|
+
# @return [String] Rails environment or nil
|
106
|
+
def collect_rails_env
|
107
|
+
return nil unless defined?(Rails)
|
108
|
+
|
109
|
+
Rails.env
|
110
|
+
rescue StandardError => e
|
111
|
+
log_error "Failed to get Rails environment: #{e.message}"
|
112
|
+
nil
|
113
|
+
end
|
114
|
+
|
115
|
+
# Collect current environment
|
116
|
+
#
|
117
|
+
# @return [String] current environment
|
118
|
+
def collect_environment
|
119
|
+
ENV["RAILS_ENV"] || ENV["RACK_ENV"] || "development"
|
120
|
+
rescue StandardError => e
|
121
|
+
log_error "Failed to get environment: #{e.message}"
|
122
|
+
"unknown"
|
123
|
+
end
|
124
|
+
|
125
|
+
# Collect loaded gems count
|
126
|
+
#
|
127
|
+
# @return [Integer] number of loaded gems
|
128
|
+
def collect_gem_count
|
129
|
+
Gem.loaded_specs.size
|
130
|
+
rescue StandardError => e
|
131
|
+
log_error "Failed to get gem count: #{e.message}"
|
132
|
+
0
|
133
|
+
end
|
134
|
+
|
135
|
+
# Collect loaded gems information
|
136
|
+
#
|
137
|
+
# @return [Hash] loaded gems with versions
|
138
|
+
def collect_loaded_gems
|
139
|
+
return {} unless Dbwatcher.configuration.system_info_include_performance_metrics
|
140
|
+
|
141
|
+
gems = {}
|
142
|
+
Gem.loaded_specs.each do |name, spec|
|
143
|
+
gems[name] = spec.version.to_s
|
144
|
+
end
|
145
|
+
gems
|
146
|
+
rescue StandardError => e
|
147
|
+
log_error "Failed to get loaded gems: #{e.message}"
|
148
|
+
{}
|
149
|
+
end
|
150
|
+
|
151
|
+
# Collect load path information
|
152
|
+
#
|
153
|
+
# @return [Hash] load path statistics
|
154
|
+
def collect_load_path_info
|
155
|
+
{
|
156
|
+
size: $LOAD_PATH.size,
|
157
|
+
paths: Dbwatcher.configuration.system_info_include_performance_metrics ? $LOAD_PATH.first(10) : []
|
158
|
+
}
|
159
|
+
rescue StandardError => e
|
160
|
+
log_error "Failed to get load path info: #{e.message}"
|
161
|
+
{ size: 0, paths: [] }
|
162
|
+
end
|
163
|
+
|
164
|
+
# Collect environment variables (filtered for security)
|
165
|
+
#
|
166
|
+
# @return [Hash] filtered environment variables
|
167
|
+
# rubocop:disable Metrics/MethodLength
|
168
|
+
def collect_environment_variables
|
169
|
+
return {} unless Dbwatcher.configuration.collect_sensitive_env_vars
|
170
|
+
|
171
|
+
env_vars = {}
|
172
|
+
|
173
|
+
# Safe environment variables to include
|
174
|
+
safe_vars = %w[
|
175
|
+
RAILS_ENV
|
176
|
+
RACK_ENV
|
177
|
+
RUBY_VERSION
|
178
|
+
PATH
|
179
|
+
HOME
|
180
|
+
USER
|
181
|
+
SHELL
|
182
|
+
TERM
|
183
|
+
LANG
|
184
|
+
LC_ALL
|
185
|
+
TZ
|
186
|
+
RAILS_LOG_LEVEL
|
187
|
+
RAILS_SERVE_STATIC_FILES
|
188
|
+
RAILS_CACHE_ID
|
189
|
+
RAILS_RELATIVE_URL_ROOT
|
190
|
+
BUNDLE_GEMFILE
|
191
|
+
BUNDLE_PATH
|
192
|
+
GEM_HOME
|
193
|
+
GEM_PATH
|
194
|
+
]
|
195
|
+
|
196
|
+
safe_vars.each do |var|
|
197
|
+
env_vars[var] = ENV[var] if ENV[var]
|
198
|
+
end
|
199
|
+
|
200
|
+
env_vars
|
201
|
+
rescue StandardError => e
|
202
|
+
log_error "Failed to get environment variables: #{e.message}"
|
203
|
+
{}
|
204
|
+
end
|
205
|
+
# rubocop:enable Metrics/MethodLength
|
206
|
+
|
207
|
+
# Collect application configuration
|
208
|
+
#
|
209
|
+
# @return [Hash] application configuration
|
210
|
+
def collect_application_config
|
211
|
+
config = {}
|
212
|
+
|
213
|
+
# Collect Rails configuration if available
|
214
|
+
config[:rails] = collect_rails_config if defined?(Rails)
|
215
|
+
|
216
|
+
# Collect DBWatcher configuration
|
217
|
+
config[:dbwatcher] = collect_dbwatcher_config if defined?(Dbwatcher)
|
218
|
+
|
219
|
+
config
|
220
|
+
rescue StandardError => e
|
221
|
+
log_error "Failed to get application config: #{e.message}"
|
222
|
+
{}
|
223
|
+
end
|
224
|
+
|
225
|
+
# Collect Rails configuration if available
|
226
|
+
#
|
227
|
+
# @return [Hash] Rails configuration
|
228
|
+
# rubocop:disable Metrics/MethodLength, Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
229
|
+
def collect_rails_config
|
230
|
+
rails_config = {}
|
231
|
+
|
232
|
+
return rails_config unless defined?(Rails)
|
233
|
+
|
234
|
+
# Basic Rails configuration
|
235
|
+
rails_config[:environment] = Rails.env
|
236
|
+
rails_config[:version] = Rails.version
|
237
|
+
rails_config[:root] = Rails.root.to_s
|
238
|
+
|
239
|
+
# Rails application configuration
|
240
|
+
if Rails.application
|
241
|
+
app_config = Rails.application.config
|
242
|
+
rails_config[:app_name] = Rails.application.class.name.split("::").first
|
243
|
+
rails_config[:autoload_paths] =
|
244
|
+
app_config.respond_to?(:autoload_paths) ? app_config.autoload_paths.size : nil
|
245
|
+
rails_config[:eager_load_paths] =
|
246
|
+
app_config.respond_to?(:eager_load_paths) ? app_config.eager_load_paths.size : nil
|
247
|
+
rails_config[:eager_load] = app_config.respond_to?(:eager_load) ? app_config.eager_load : nil
|
248
|
+
rails_config[:cache_classes] = app_config.respond_to?(:cache_classes) ? app_config.cache_classes : nil
|
249
|
+
rails_config[:consider_all_requests_local] =
|
250
|
+
app_config.respond_to?(:consider_all_requests_local) ? app_config.consider_all_requests_local : nil
|
251
|
+
|
252
|
+
# Fix long line by breaking it up and removing redundant else
|
253
|
+
perform_caching = if app_config.action_controller.respond_to?(:perform_caching)
|
254
|
+
app_config.action_controller.perform_caching
|
255
|
+
end
|
256
|
+
rails_config[:action_controller] = { perform_caching: perform_caching }
|
257
|
+
end
|
258
|
+
|
259
|
+
rails_config
|
260
|
+
rescue StandardError => e
|
261
|
+
log_error "Failed to get Rails config: #{e.message}"
|
262
|
+
{}
|
263
|
+
end
|
264
|
+
# rubocop:enable Metrics/MethodLength, Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
265
|
+
|
266
|
+
# Collect DBWatcher configuration
|
267
|
+
#
|
268
|
+
# @return [Hash] DBWatcher configuration
|
269
|
+
# rubocop:disable Metrics/MethodLength
|
270
|
+
def collect_dbwatcher_config
|
271
|
+
config = Dbwatcher.configuration
|
272
|
+
|
273
|
+
# Only include non-sensitive configuration options
|
274
|
+
# Split long lines to avoid line length issues
|
275
|
+
{
|
276
|
+
system_info_refresh_interval:
|
277
|
+
if config.respond_to?(:system_info_refresh_interval)
|
278
|
+
config.system_info_refresh_interval
|
279
|
+
else
|
280
|
+
300
|
281
|
+
end,
|
282
|
+
collect_sensitive_env_vars:
|
283
|
+
if config.respond_to?(:collect_sensitive_env_vars)
|
284
|
+
config.collect_sensitive_env_vars
|
285
|
+
else
|
286
|
+
false
|
287
|
+
end,
|
288
|
+
system_info_include_performance_metrics:
|
289
|
+
if config.respond_to?(:system_info_include_performance_metrics)
|
290
|
+
config.system_info_include_performance_metrics
|
291
|
+
else
|
292
|
+
true
|
293
|
+
end
|
294
|
+
}
|
295
|
+
rescue StandardError => e
|
296
|
+
log_error "Failed to get DBWatcher config: #{e.message}"
|
297
|
+
{}
|
298
|
+
end
|
299
|
+
# rubocop:enable Metrics/MethodLength
|
300
|
+
|
301
|
+
# Sanitize database configuration to remove sensitive information
|
302
|
+
#
|
303
|
+
# @param db_config [Hash] database configuration
|
304
|
+
# @return [Hash] sanitized database configuration
|
305
|
+
def sanitize_database_config(db_config)
|
306
|
+
return {} unless db_config.is_a?(Hash)
|
307
|
+
|
308
|
+
# Create a copy to avoid modifying the original
|
309
|
+
sanitized = db_config.dup
|
310
|
+
|
311
|
+
# Remove sensitive information
|
312
|
+
%w[password username user].each do |key|
|
313
|
+
sanitized.delete(key)
|
314
|
+
sanitized.delete(key.to_sym)
|
315
|
+
end
|
316
|
+
|
317
|
+
# Keep only basic connection info
|
318
|
+
safe_keys = %w[adapter host port database pool timeout]
|
319
|
+
sanitized.select { |k, _| safe_keys.include?(k.to_s) }
|
320
|
+
rescue StandardError => e
|
321
|
+
log_error "Failed to sanitize database config: #{e.message}"
|
322
|
+
{}
|
323
|
+
end
|
324
|
+
end
|
325
|
+
# rubocop:enable Metrics/ClassLength
|
326
|
+
end
|
327
|
+
end
|
328
|
+
end
|
@@ -0,0 +1,114 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "machine_info_collector"
|
4
|
+
require_relative "database_info_collector"
|
5
|
+
require_relative "runtime_info_collector"
|
6
|
+
require_relative "../../logging"
|
7
|
+
|
8
|
+
module Dbwatcher
|
9
|
+
module Services
|
10
|
+
module SystemInfo
|
11
|
+
# Main system information collector service
|
12
|
+
#
|
13
|
+
# Orchestrates the collection of system information from various sources
|
14
|
+
# including machine, database, and runtime information.
|
15
|
+
#
|
16
|
+
# @example
|
17
|
+
# info = SystemInfo::SystemInfoCollector.call
|
18
|
+
# puts info[:machine][:hostname]
|
19
|
+
# puts info[:database][:adapter]
|
20
|
+
# puts info[:runtime][:ruby_version]
|
21
|
+
class SystemInfoCollector
|
22
|
+
include Dbwatcher::Logging
|
23
|
+
|
24
|
+
# Class method to create instance and call
|
25
|
+
#
|
26
|
+
# @return [Hash] system information
|
27
|
+
def self.call
|
28
|
+
new.call
|
29
|
+
end
|
30
|
+
|
31
|
+
# Collect system information from all sources
|
32
|
+
#
|
33
|
+
# This method needs to be longer to properly handle all the collection
|
34
|
+
# steps and error handling in a consistent way.
|
35
|
+
#
|
36
|
+
# @return [Hash] collected system information
|
37
|
+
# rubocop:disable Metrics/MethodLength
|
38
|
+
def call
|
39
|
+
start_time = current_time
|
40
|
+
log_info "#{self.class.name}: Starting system information collection"
|
41
|
+
|
42
|
+
info = {
|
43
|
+
machine: collect_machine_info,
|
44
|
+
database: collect_database_info,
|
45
|
+
runtime: collect_runtime_info,
|
46
|
+
collected_at: current_time.iso8601,
|
47
|
+
collection_duration: nil
|
48
|
+
}
|
49
|
+
|
50
|
+
info[:collection_duration] = (current_time - start_time).round(3)
|
51
|
+
log_info "#{self.class.name}: Completed system information collection in #{info[:collection_duration]}s"
|
52
|
+
|
53
|
+
info
|
54
|
+
rescue StandardError => e
|
55
|
+
log_error "System information collection failed: #{e.message}"
|
56
|
+
{
|
57
|
+
machine: {},
|
58
|
+
database: {},
|
59
|
+
runtime: {},
|
60
|
+
collected_at: current_time.iso8601,
|
61
|
+
collection_duration: nil,
|
62
|
+
error: e.message
|
63
|
+
}
|
64
|
+
end
|
65
|
+
# rubocop:enable Metrics/MethodLength
|
66
|
+
|
67
|
+
private
|
68
|
+
|
69
|
+
# Get current time, using Rails Time.current if available, otherwise Time.now
|
70
|
+
#
|
71
|
+
# @return [Time] current time
|
72
|
+
def current_time
|
73
|
+
defined?(Time.current) ? Time.current : Time.now
|
74
|
+
end
|
75
|
+
|
76
|
+
# Collect machine information safely
|
77
|
+
#
|
78
|
+
# @return [Hash] machine information or empty hash on error
|
79
|
+
def collect_machine_info
|
80
|
+
return {} unless Dbwatcher.configuration.collect_system_info
|
81
|
+
|
82
|
+
MachineInfoCollector.call
|
83
|
+
rescue StandardError => e
|
84
|
+
log_error "Machine info collection failed: #{e.message}"
|
85
|
+
{ error: e.message }
|
86
|
+
end
|
87
|
+
|
88
|
+
# Collect database information safely
|
89
|
+
#
|
90
|
+
# @return [Hash] database information or empty hash on error
|
91
|
+
def collect_database_info
|
92
|
+
return {} unless Dbwatcher.configuration.collect_system_info
|
93
|
+
|
94
|
+
DatabaseInfoCollector.call
|
95
|
+
rescue StandardError => e
|
96
|
+
log_error "Database info collection failed: #{e.message}"
|
97
|
+
{ error: e.message }
|
98
|
+
end
|
99
|
+
|
100
|
+
# Collect runtime information safely
|
101
|
+
#
|
102
|
+
# @return [Hash] runtime information or empty hash on error
|
103
|
+
def collect_runtime_info
|
104
|
+
return {} unless Dbwatcher.configuration.collect_system_info
|
105
|
+
|
106
|
+
RuntimeInfoCollector.call
|
107
|
+
rescue StandardError => e
|
108
|
+
log_error "Runtime info collection failed: #{e.message}"
|
109
|
+
{ error: e.message }
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
@@ -28,16 +28,16 @@ module Dbwatcher
|
|
28
28
|
def safe_operation(operation_name, default_value = nil, &block)
|
29
29
|
block.call
|
30
30
|
rescue JSON::ParserError => e
|
31
|
-
|
31
|
+
log_error_with_exception("JSON parsing failed in #{operation_name}", e)
|
32
32
|
default_value
|
33
33
|
rescue Errno::ENOENT => e
|
34
|
-
|
34
|
+
log_error_with_exception("File not found in #{operation_name}", e)
|
35
35
|
default_value
|
36
36
|
rescue Errno::EACCES => e
|
37
|
-
|
37
|
+
log_error_with_exception("Permission denied in #{operation_name}", e)
|
38
38
|
raise StorageError, "Permission denied: #{e.message}"
|
39
39
|
rescue StandardError => e
|
40
|
-
|
40
|
+
log_error_with_exception("#{operation_name} failed", e)
|
41
41
|
default_value
|
42
42
|
end
|
43
43
|
|
@@ -51,7 +51,7 @@ module Dbwatcher
|
|
51
51
|
block.call
|
52
52
|
rescue StandardError => e
|
53
53
|
error_message = "Storage #{operation} failed: #{e.message}"
|
54
|
-
|
54
|
+
log_error_with_exception(error_message, e)
|
55
55
|
raise StorageError, error_message
|
56
56
|
end
|
57
57
|
|
@@ -62,7 +62,7 @@ module Dbwatcher
|
|
62
62
|
# @param message [String] the error message
|
63
63
|
# @param error [Exception] the exception that occurred
|
64
64
|
# @return [void]
|
65
|
-
def
|
65
|
+
def log_error_with_exception(message, error)
|
66
66
|
if defined?(Rails) && Rails.logger
|
67
67
|
Rails.logger.warn("#{message}: #{error.message}")
|
68
68
|
else
|