Module: PgHero

Extended by:
Forwardable
Defined in:
lib/pghero.rb,
lib/pghero/stats.rb,
lib/pghero/engine.rb,
lib/pghero/version.rb,
lib/pghero/database.rb,
lib/pghero/connection.rb,
lib/pghero/query_stats.rb,
lib/pghero/space_stats.rb,
lib/pghero/methods/kill.rb,
lib/pghero/methods/basic.rb,
lib/pghero/methods/space.rb,
lib/pghero/methods/users.rb,
lib/pghero/methods/system.rb,
lib/pghero/methods/tables.rb,
lib/pghero/methods/explain.rb,
lib/pghero/methods/indexes.rb,
lib/pghero/methods/queries.rb,
lib/pghero/methods/settings.rb,
lib/pghero/methods/sequences.rb,
lib/pghero/methods/connections.rb,
lib/pghero/methods/constraints.rb,
lib/pghero/methods/maintenance.rb,
lib/pghero/methods/query_stats.rb,
lib/pghero/methods/replication.rb,
app/helpers/pg_hero/home_helper.rb,
lib/pghero/methods/suggested_indexes.rb,
app/controllers/pg_hero/home_controller.rb

Defined Under Namespace

Modules: HomeHelper, Methods Classes: Connection, Database, Engine, Error, HomeController, NotEnabled, QueryStats, SpaceStats, Stats

Constant Summary collapse

MUTEX =
Mutex.new
VERSION =
"3.6.1"

Class Attribute Summary collapse

Class Method Summary collapse

Class Attribute Details

.cache_hit_rate_thresholdObject

Returns the value of attribute cache_hit_rate_threshold.



43
44
45
# File 'lib/pghero.rb', line 43

def cache_hit_rate_threshold
  @cache_hit_rate_threshold
end

.config_pathObject

Returns the value of attribute config_path.



43
44
45
# File 'lib/pghero.rb', line 43

def config_path
  @config_path
end

.envObject

Returns the value of attribute env.



43
44
45
# File 'lib/pghero.rb', line 43

def env
  @env
end

.explain_timeout_secObject

Returns the value of attribute explain_timeout_sec.



43
44
45
# File 'lib/pghero.rb', line 43

def explain_timeout_sec
  @explain_timeout_sec
end

.filter_dataObject

Returns the value of attribute filter_data.



43
44
45
# File 'lib/pghero.rb', line 43

def filter_data
  @filter_data
end

.long_running_query_secObject

Returns the value of attribute long_running_query_sec.



43
44
45
# File 'lib/pghero.rb', line 43

def long_running_query_sec
  @long_running_query_sec
end

.show_migrationsObject

Returns the value of attribute show_migrations.



43
44
45
# File 'lib/pghero.rb', line 43

def show_migrations
  @show_migrations
end

.slow_query_callsObject

Returns the value of attribute slow_query_calls.



43
44
45
# File 'lib/pghero.rb', line 43

def slow_query_calls
  @slow_query_calls
end

.slow_query_msObject

Returns the value of attribute slow_query_ms.



43
44
45
# File 'lib/pghero.rb', line 43

def slow_query_ms
  @slow_query_ms
end

.total_connections_thresholdObject

Returns the value of attribute total_connections_threshold.



43
44
45
# File 'lib/pghero.rb', line 43

def total_connections_threshold
  @total_connections_threshold
end

Class Method Details

.analyze_all(**options) ⇒ Object



211
212
213
214
215
216
# File 'lib/pghero.rb', line 211

def analyze_all(**options)
  each_database do |database|
    next if database.replica?
    database.analyze_tables(**options)
  end
end

.autoindex_all(create: false, verbose: true) ⇒ Object



218
219
220
221
222
223
# File 'lib/pghero.rb', line 218

def autoindex_all(create: false, verbose: true)
  each_database do |database|
    puts "Autoindexing #{database.id}..." if verbose
    database.autoindex(create: create)
  end
end

.capture_query_stats(verbose: false) ⇒ Object



196
197
198
199
200
201
202
# File 'lib/pghero.rb', line 196

def capture_query_stats(verbose: false)
  each_database do |database|
    next unless database.capture_query_stats?
    puts "Capturing query stats for #{database.id}..." if verbose
    database.capture_query_stats(raise_errors: true)
  end
end

.capture_space_stats(verbose: false) ⇒ Object



204
205
206
207
208
209
# File 'lib/pghero.rb', line 204

def capture_space_stats(verbose: false)
  each_database do |database|
    puts "Capturing space stats for #{database.id}..." if verbose
    database.capture_space_stats
  end
end

.clean_query_stats(before: nil) ⇒ Object

delete previous stats go database by database to use an index stats for old databases are not cleaned up since we can’t use an index



232
233
234
235
236
# File 'lib/pghero.rb', line 232

def clean_query_stats(before: nil)
  each_database do |database|
    database.clean_query_stats(before: before)
  end
end

.clean_space_stats(before: nil) ⇒ Object



238
239
240
241
242
# File 'lib/pghero.rb', line 238

def clean_space_stats(before: nil)
  each_database do |database|
    database.clean_space_stats(before: before)
  end
end

.configObject



110
111
112
# File 'lib/pghero.rb', line 110

def config
  @config ||= file_config || default_config
end

.connection_config(model) ⇒ Object

private



245
246
247
# File 'lib/pghero.rb', line 245

def connection_config(model)
  model.connection_db_config.configuration_hash
end

.databasesObject

ensure we only have one copy of databases so there’s only one connection pool per database



178
179
180
181
182
183
184
185
186
187
188
189
190
# File 'lib/pghero.rb', line 178

def databases
  unless defined?(@databases)
    # only use mutex on initialization
    MUTEX.synchronize do
      # return if another process initialized while we were waiting
      return @databases if defined?(@databases)

      @databases = config["databases"].map { |id, c| [id.to_sym, Database.new(id, c)] }.to_h
    end
  end

  @databases
end

.default_configObject

private



143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
# File 'lib/pghero.rb', line 143

def default_config
  databases = {}

  unless ENV["PGHERO_DATABASE_URL"]
    ActiveRecord::Base.configurations.configs_for(env_name: env, include_replicas_key => true).each do |db|
      databases[db.send(spec_name_key)] = {"spec" => db.send(spec_name_key)}
    end
  end

  if databases.empty?
    databases["primary"] = {
      "url" => ENV["PGHERO_DATABASE_URL"] || default_connection_config
    }
  end

  if databases.size == 1
    databases.values.first.merge!(
      "aws_db_instance_identifier" => ENV["PGHERO_DB_INSTANCE_IDENTIFIER"],
      "gcp_database_id" => ENV["PGHERO_GCP_DATABASE_ID"],
      "azure_resource_id" => ENV["PGHERO_AZURE_RESOURCE_ID"]
    )
  end

  {
    "databases" => databases
  }
end

.default_connection_configObject

private



172
173
174
# File 'lib/pghero.rb', line 172

def default_connection_config
  connection_config(ActiveRecord::Base) if ActiveRecord::VERSION::STRING.to_f < 7.1
end

.explain_enabled?Boolean

private

Returns:

  • (Boolean)


97
98
99
# File 'lib/pghero.rb', line 97

def explain_enabled?
  explain_mode.nil? || explain_mode == true || explain_mode == "analyze"
end

.explain_modeObject

private



102
103
104
# File 'lib/pghero.rb', line 102

def explain_mode
  @config["explain"]
end

.file_configObject

private



115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
# File 'lib/pghero.rb', line 115

def file_config
  unless defined?(@file_config)
    require "erb"
    require "yaml"

    path = config_path

    config_file_exists = File.exist?(path)

    config = YAML.safe_load(ERB.new(File.read(path)).result, aliases: true) if config_file_exists
    config ||= {}

    @file_config =
      if config[env]
        config[env]
      elsif config["databases"] # preferred format
        config
      elsif config_file_exists
        raise "Invalid config file"
      else
        nil
      end
  end

  @file_config
end

.include_replicas_keyObject

private Rails 7.0 deprecates ‘include_replicas` for `include_hidden`



256
257
258
# File 'lib/pghero.rb', line 256

def include_replicas_key
  ActiveRecord::VERSION::MAJOR >= 7 ? :include_hidden : :include_replicas
end

.passwordObject

use method instead of attr_accessor to ensure this works if variable set after PgHero is loaded



87
88
89
# File 'lib/pghero.rb', line 87

def password
  @password ||= config["password"] || ENV["PGHERO_PASSWORD"]
end

.pretty_size(value) ⇒ Object



225
226
227
# File 'lib/pghero.rb', line 225

def pretty_size(value)
  ActiveSupport::NumberHelper.number_to_human_size(value, precision: 3)
end

.primary_databaseObject



192
193
194
# File 'lib/pghero.rb', line 192

def primary_database
  databases.values.first
end

.spec_name_keyObject

private



250
251
252
# File 'lib/pghero.rb', line 250

def spec_name_key
  :name
end

.stats_database_urlObject



92
93
94
# File 'lib/pghero.rb', line 92

def stats_database_url
  @stats_database_url ||= (file_config || {})["stats_database_url"] || ENV["PGHERO_STATS_DATABASE_URL"]
end

.time_zoneObject



75
76
77
# File 'lib/pghero.rb', line 75

def time_zone
  @time_zone || Time.zone
end

.time_zone=(time_zone) ⇒ Object



71
72
73
# File 'lib/pghero.rb', line 71

def time_zone=(time_zone)
  @time_zone = time_zone.is_a?(ActiveSupport::TimeZone) ? time_zone : ActiveSupport::TimeZone[time_zone.to_s]
end

.usernameObject

use method instead of attr_accessor to ensure this works if variable set after PgHero is loaded



81
82
83
# File 'lib/pghero.rb', line 81

def username
  @username ||= config["username"] || ENV["PGHERO_USERNAME"]
end

.visualize_urlObject



106
107
108
# File 'lib/pghero.rb', line 106

def visualize_url
  @visualize_url ||= config["visualize_url"] || ENV["PGHERO_VISUALIZE_URL"] || "https://tatiyants.com/pev/#/plans/new"
end