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.7.0"

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



206
207
208
209
210
211
# File 'lib/pghero.rb', line 206

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



213
214
215
216
217
218
# File 'lib/pghero.rb', line 213

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



191
192
193
194
195
196
197
# File 'lib/pghero.rb', line 191

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



199
200
201
202
203
204
# File 'lib/pghero.rb', line 199

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



227
228
229
230
231
# File 'lib/pghero.rb', line 227

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

.clean_space_stats(before: nil) ⇒ Object



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

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



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

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



173
174
175
176
177
178
179
180
181
182
183
184
185
# File 'lib/pghero.rb', line 173

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"]
    }
  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

.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



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

def include_replicas_key
  :include_hidden
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 ||= (file_config || {})["password"] || ENV["PGHERO_PASSWORD"]
end

.pretty_size(value) ⇒ Object



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

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

.primary_databaseObject



187
188
189
# File 'lib/pghero.rb', line 187

def primary_database
  databases.values.first
end

.spec_name_keyObject

private



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

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 ||= (file_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