Module: PgHero

Defined in:
lib/pghero.rb,
lib/pghero/query.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/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, Query, QueryStats, SpaceStats, Stats

Constant Summary collapse

MUTEX =
Mutex.new
VERSION =
"4.0.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.



40
41
42
# File 'lib/pghero.rb', line 40

def cache_hit_rate_threshold
  @cache_hit_rate_threshold
end

.config_pathObject

Returns the value of attribute config_path.



40
41
42
# File 'lib/pghero.rb', line 40

def config_path
  @config_path
end

.envObject

Returns the value of attribute env.



40
41
42
# File 'lib/pghero.rb', line 40

def env
  @env
end

.explain_timeout_secObject

Returns the value of attribute explain_timeout_sec.



40
41
42
# File 'lib/pghero.rb', line 40

def explain_timeout_sec
  @explain_timeout_sec
end

.filter_dataObject

Returns the value of attribute filter_data.



40
41
42
# File 'lib/pghero.rb', line 40

def filter_data
  @filter_data
end

.long_running_query_secObject

Returns the value of attribute long_running_query_sec.



40
41
42
# File 'lib/pghero.rb', line 40

def long_running_query_sec
  @long_running_query_sec
end

.show_migrationsObject

Returns the value of attribute show_migrations.



40
41
42
# File 'lib/pghero.rb', line 40

def show_migrations
  @show_migrations
end

.slow_query_callsObject

Returns the value of attribute slow_query_calls.



40
41
42
# File 'lib/pghero.rb', line 40

def slow_query_calls
  @slow_query_calls
end

.slow_query_msObject

Returns the value of attribute slow_query_ms.



40
41
42
# File 'lib/pghero.rb', line 40

def slow_query_ms
  @slow_query_ms
end

.total_connections_thresholdObject

Returns the value of attribute total_connections_threshold.



40
41
42
# File 'lib/pghero.rb', line 40

def total_connections_threshold
  @total_connections_threshold
end

Class Method Details

.analyze_all(**options) ⇒ Object



188
189
190
191
192
193
# File 'lib/pghero.rb', line 188

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



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

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



173
174
175
176
177
178
179
# File 'lib/pghero.rb', line 173

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



181
182
183
184
185
186
# File 'lib/pghero.rb', line 181

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 TODO clean queries



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

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

.clean_space_stats(before: nil) ⇒ Object



216
217
218
219
220
# File 'lib/pghero.rb', line 216

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

.configObject



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

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

.databasesObject

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



159
160
161
162
163
164
165
166
167
168
169
170
171
# File 'lib/pghero.rb', line 159

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



130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
# File 'lib/pghero.rb', line 130

def default_config
  databases = {}

  unless ENV["PGHERO_DATABASE_URL"]
    ActiveRecord::Base.configurations.configs_for(env_name: env, include_hidden: true).each do |db|
      databases[db.name] = {"spec" => db.name}
    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"]
    )
  end

  {
    "databases" => databases
  }
end

.explain_enabled?Boolean

private

Returns:

  • (Boolean)


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

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

.explain_modeObject

private



85
86
87
# File 'lib/pghero.rb', line 85

def explain_mode
  @config["explain"]
end

.file_configObject

private



102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
# File 'lib/pghero.rb', line 102

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 Error, "Invalid config file"
      else
        nil
      end
  end

  @file_config
end

.kill_enabled?Boolean

Returns:

  • (Boolean)


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

def kill_enabled?
  !config["disable_kill"]
end

.passwordObject

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



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

def password
  @password ||= (file_config || {})["password"] || ENV["PGHERO_PASSWORD"]
end

.pretty_size(value) ⇒ Object



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

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

.stats_database_urlObject



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

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

.time_zoneObject



58
59
60
# File 'lib/pghero.rb', line 58

def time_zone
  @time_zone || Time.zone
end

.time_zone=(time_zone) ⇒ Object



54
55
56
# File 'lib/pghero.rb', line 54

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



64
65
66
# File 'lib/pghero.rb', line 64

def username
  @username ||= (file_config || {})["username"] || ENV["PGHERO_USERNAME"]
end

.visualize_urlObject



89
90
91
# File 'lib/pghero.rb', line 89

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