Class: PgReports::Configuration

Inherits:
Object
  • Object
show all
Defined in:
lib/pg_reports/configuration.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeConfiguration

Returns a new instance of Configuration.



55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
# File 'lib/pg_reports/configuration.rb', line 55

def initialize
  # Telegram
  @telegram_bot_token = ENV.fetch("PG_REPORTS_TELEGRAM_TOKEN", nil)
  @telegram_chat_id = ENV.fetch("PG_REPORTS_TELEGRAM_CHAT_ID", nil)

  # Query thresholds
  @slow_query_threshold_ms = 100
  @heavy_query_threshold_calls = 1000
  @expensive_query_threshold_ms = 10_000

  # Index thresholds
  @unused_index_threshold_scans = 50
  @inefficient_index_threshold_ratio = 10

  # Table thresholds
  @bloat_threshold_percent = 20
  @dead_rows_threshold = 10_000

  # Connection
  @connection_pool = nil

  # Output
  @max_query_length = 200

  # Dashboard
  @dashboard_auth = nil
  @standalone = false

  # Assets / privacy
  @load_external_fonts = ActiveModel::Type::Boolean.new.cast(ENV.fetch("PG_REPORTS_LOAD_EXTERNAL_FONTS", false))

  # Development/testing
  @fake_source_data = ENV.fetch("PG_REPORTS_FAKE_SOURCE_DATA", "false") == "true"

  # Query monitoring
  @query_monitor_log_file = defined?(Rails) ? Rails.root.join("log", "pg_reports.log") : nil
  @query_monitor_max_queries = 100
  @query_monitor_backtrace_filter = ->(location) {
    # Exclude gem paths, framework paths
    !location.path.match?(%r{/(gems|ruby|railties)/})
  }

  # Security
  @allow_raw_query_execution = ActiveModel::Type::Boolean.new.cast(
    ENV.fetch("PG_REPORTS_ALLOW_RAW_QUERY_EXECUTION", false)
  )
  # Migration creation defaults to Rails dev — preserves prior behavior —
  # but is now explicitly togglable so it can be disabled even in dev.
  env_override = ENV["PG_REPORTS_ALLOW_MIGRATION_CREATION"]
  @allow_migration_creation = if env_override.nil?
    defined?(Rails) && Rails.respond_to?(:env) && Rails.env.development?
  else
    ActiveModel::Type::Boolean.new.cast(env_override)
  end
  @raw_query_statement_timeout_ms = ENV.fetch("PG_REPORTS_RAW_QUERY_STATEMENT_TIMEOUT_MS", 5_000).to_i
  @raw_query_rate_limit = ENV.fetch("PG_REPORTS_RAW_QUERY_RATE_LIMIT", 30).to_i
  @raw_query_rate_limit_window_seconds = ENV.fetch("PG_REPORTS_RAW_QUERY_RATE_LIMIT_WINDOW_SECONDS", 60).to_i

  # Grafana / Prometheus exporter
  @grafana_favorites = []
  @grafana_metrics_token = ENV.fetch("PG_REPORTS_METRICS_TOKEN", nil)
  @grafana_cache_ttl = 60
end

Instance Attribute Details

#allow_migration_creationObject

Allow dashboard's "Generate Migration" button to write files into db/migrate/



45
46
47
# File 'lib/pg_reports/configuration.rb', line 45

def allow_migration_creation
  @allow_migration_creation
end

#allow_raw_query_executionObject

Security settings



44
45
46
# File 'lib/pg_reports/configuration.rb', line 44

def allow_raw_query_execution
  @allow_raw_query_execution
end

#bloat_threshold_percentObject

Table analysis thresholds



19
20
21
# File 'lib/pg_reports/configuration.rb', line 19

def bloat_threshold_percent
  @bloat_threshold_percent
end

#connection_poolObject

Connection settings



23
24
25
# File 'lib/pg_reports/configuration.rb', line 23

def connection_pool
  @connection_pool
end

#dashboard_authObject

Dashboard settings



29
30
31
# File 'lib/pg_reports/configuration.rb', line 29

def dashboard_auth
  @dashboard_auth
end

#dead_rows_thresholdObject

Tables with more dead rows need vacuum



20
21
22
# File 'lib/pg_reports/configuration.rb', line 20

def dead_rows_threshold
  @dead_rows_threshold
end

#expensive_query_threshold_msObject

Total time threshold for expensive queries



12
13
14
# File 'lib/pg_reports/configuration.rb', line 12

def expensive_query_threshold_ms
  @expensive_query_threshold_ms
end

#fake_source_dataObject

Development/testing settings



36
37
38
# File 'lib/pg_reports/configuration.rb', line 36

def fake_source_data
  @fake_source_data
end

#grafana_cache_ttlObject

Default cache TTL for collected reports, seconds



53
54
55
# File 'lib/pg_reports/configuration.rb', line 53

def grafana_cache_ttl
  @grafana_cache_ttl
end

#grafana_favoritesObject

Grafana / Prometheus exporter settings



51
52
53
# File 'lib/pg_reports/configuration.rb', line 51

def grafana_favorites
  @grafana_favorites
end

#grafana_metrics_tokenObject

Bearer token required to access /metrics (nil = no auth)



52
53
54
# File 'lib/pg_reports/configuration.rb', line 52

def grafana_metrics_token
  @grafana_metrics_token
end

#heavy_query_threshold_callsObject

Queries with more calls than this are heavy



11
12
13
# File 'lib/pg_reports/configuration.rb', line 11

def heavy_query_threshold_calls
  @heavy_query_threshold_calls
end

#inefficient_index_threshold_ratioObject

Read/fetch ratio above this is inefficient



16
17
18
# File 'lib/pg_reports/configuration.rb', line 16

def inefficient_index_threshold_ratio
  @inefficient_index_threshold_ratio
end

#load_external_fontsObject

Assets / privacy settings



33
34
35
# File 'lib/pg_reports/configuration.rb', line 33

def load_external_fonts
  @load_external_fonts
end

#max_query_lengthObject

Output settings



26
27
28
# File 'lib/pg_reports/configuration.rb', line 26

def max_query_length
  @max_query_length
end

#query_monitor_backtrace_filterObject

Proc to filter backtrace lines



41
42
43
# File 'lib/pg_reports/configuration.rb', line 41

def query_monitor_backtrace_filter
  @query_monitor_backtrace_filter
end

#query_monitor_log_fileObject

Query monitoring settings



39
40
41
# File 'lib/pg_reports/configuration.rb', line 39

def query_monitor_log_file
  @query_monitor_log_file
end

#query_monitor_max_queriesObject

Maximum number of queries to keep in buffer



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

def query_monitor_max_queries
  @query_monitor_max_queries
end

#raw_query_rate_limitObject

Max privileged requests (raw query execution / Generate Migration) per client IP per window. nil disables rate limiting.



47
48
49
# File 'lib/pg_reports/configuration.rb', line 47

def raw_query_rate_limit
  @raw_query_rate_limit
end

#raw_query_rate_limit_window_secondsObject

Window size (seconds) for raw_query_rate_limit



48
49
50
# File 'lib/pg_reports/configuration.rb', line 48

def raw_query_rate_limit_window_seconds
  @raw_query_rate_limit_window_seconds
end

#raw_query_statement_timeout_msObject

Postgres statement_timeout (ms) applied to Execute Query / EXPLAIN ANALYZE / SQL Console. 0 disables it.



46
47
48
# File 'lib/pg_reports/configuration.rb', line 46

def raw_query_statement_timeout_ms
  @raw_query_statement_timeout_ms
end

#slow_query_threshold_msObject

Query analysis thresholds



10
11
12
# File 'lib/pg_reports/configuration.rb', line 10

def slow_query_threshold_ms
  @slow_query_threshold_ms
end

#standaloneObject

True when running via PgReports::Standalone (no host app)



30
31
32
# File 'lib/pg_reports/configuration.rb', line 30

def standalone
  @standalone
end

#telegram_bot_tokenObject

Telegram settings



6
7
8
# File 'lib/pg_reports/configuration.rb', line 6

def telegram_bot_token
  @telegram_bot_token
end

#telegram_chat_idObject

Returns the value of attribute telegram_chat_id.



7
8
9
# File 'lib/pg_reports/configuration.rb', line 7

def telegram_chat_id
  @telegram_chat_id
end

#unused_index_threshold_scansObject

Index analysis thresholds



15
16
17
# File 'lib/pg_reports/configuration.rb', line 15

def unused_index_threshold_scans
  @unused_index_threshold_scans
end

Instance Method Details

#add_target(name, spec) ⇒ Object

Register an additional named target (besides the auto-detected :primary). Spec accepts the same keys as ActiveRecord::Base.establish_connection.

Example:

config.add_target :analytics,
host: "...", user: "...", password: ENV["..."], database: "warehouse"


131
132
133
# File 'lib/pg_reports/configuration.rb', line 131

def add_target(name, spec)
  PgReports.connection_registry.register(name, spec)
end

#connectionObject



119
120
121
122
123
# File 'lib/pg_reports/configuration.rb', line 119

def connection
  return @connection_pool if @connection_pool

  PgReports.connection_registry.current_connection
end

#default_targetObject



140
141
142
# File 'lib/pg_reports/configuration.rb', line 140

def default_target
  PgReports.connection_registry.default_name
end

#default_target=(name) ⇒ Object

Override the default target name (default is :primary).



136
137
138
# File 'lib/pg_reports/configuration.rb', line 136

def default_target=(name)
  PgReports.connection_registry.default_name = name
end

#telegram_configured?Boolean

Returns:

  • (Boolean)


144
145
146
# File 'lib/pg_reports/configuration.rb', line 144

def telegram_configured?
  telegram_bot_token.present? && telegram_chat_id.present?
end