Class: CloseYourIt::Configuration

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

Overview

Tiene tutte le opzioni del client. Costruita da CloseYourIt.init { |c| ... }. Senza endpoint_url/token/project_id (o con http:// in produzione) il client è no-op.

Constant Summary collapse

DEFAULT_EXCLUDED_EXCEPTIONS =
%w[
  ActionController::RoutingError
  ActiveRecord::RecordNotFound
].freeze
DEFAULT_REQUEST_HEADER_ALLOWLIST =

Header HTTP catturati nel contesto request (mai Authorization/Cookie → niente PII/segreti).

%w[Accept Content-Type User-Agent Referer].freeze
DEFAULT_EXCLUDED_QUERY_PATTERNS =

Tabelle di servizio del Solid stack: sono infrastruttura del framework, non codice dell'applicazione. Una loro query lenta non si può correggere leggendo il proprio repo — dice solo che il database è in contesa, cosa che le query dell'app raccontano già. Escluse per DEFAULT dalla misura dei rallentamenti perché altrimenti la sommergono: su closeyourit-rails il 2026-07-30 erano circa 2.740 campioni su 4.400 (62%), tutti fra i 250 e i 655 ms (CYRB-18).

[
  /\bsolid_queue_/,
  /\bsolid_cache_/,
  /\bsolid_cable_/
].freeze
SEMVER_TAG =

Un tag semver (con v opzionale) è preferito allo short SHA come release: converge con quello che registra la CI (che tagga), mentre lo short SHA crea release duplicate lato backend (CYRB-9).

/\Av?\d+\.\d+\.\d+([-+.].+)?\z/

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeConfiguration

Returns a new instance of Configuration.



49
50
51
52
53
54
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
118
119
120
121
122
123
124
125
126
127
128
129
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
156
157
# File 'lib/closeyourit/configuration.rb', line 49

def initialize
  @endpoint_url = ENV.fetch("CLOSEYOURIT_ENDPOINT_URL", nil)
  @token        = ENV.fetch("CLOSEYOURIT_TOKEN", nil)
  @project_id   = ENV.fetch("CLOSEYOURIT_PROJECT_ID", nil)
  @release      = ENV.fetch("CLOSEYOURIT_RELEASE", nil)
  @environment  = ENV.fetch("CLOSEYOURIT_ENVIRONMENT") { detect_environment }

  @excluded_exceptions = DEFAULT_EXCLUDED_EXCEPTIONS.dup
  @before_send         = nil

  # Hook diagnostico opt-in: `->(event, details) { ... }` invocato a ogni tappa del ciclo di vita
  # di un evento (:enqueue, :send, :drop, :timeout, :shutdown) con dettagli privi di dati sensibili
  # (es. `{ reason: :queue_full }`, `{ status: 429 }`). Locale e non ricorsivo: non invia telemetria
  # e non può innescare loop di auto-monitoraggio (vedi CloseYourIt.notify_diagnostic, CYRB-12).
  @on_diagnostic = nil

  @async_threads               = default_threads
  @background_worker_max_queue  = 30

  # Intercetta SIGTERM per garantire il flush di fine-vita (deploy/Kamal): SIGTERM di default
  # termina il processo SENZA eseguire gli at_exit. OPT-IN perché sovrascrive un eventuale handler
  # TERM dell'app ospite. Vedi CloseYourIt.shutdown / register_shutdown_flush (CYRB-5).
  @trap_signals = false

  @slow_query_threshold_ms  = 100
  @slow_method_threshold_ms = 200
  # Query da NON misurare come rallentamento (match sul testo SQL). Default: le tabelle di servizio
  # del Solid stack. Chi vuole misurarle davvero azzera la lista.
  @excluded_query_patterns = DEFAULT_EXCLUDED_QUERY_PATTERNS.dup

  @send_pii         = false
  @obfuscate_sql    = true
  @send_server_name = true

  # Contesto HTTP della richiesta (method/url/header allowlist). Body/query/IP solo con send_pii.
  @capture_request          = true
  @request_header_allowlist = DEFAULT_REQUEST_HEADER_ALLOWLIST.dup

  # Righe di sorgente attorno a ogni frame dello stacktrace (pre/context/post). 0 = disattivo.
  @context_lines = 3

  # Params del body della richiesta nell'evento (`request.data`), estratti LAZY solo quando
  # l'errore accade, sanitizzati e scrubbati (denylist + filter_parameters). Il backend
  # ri-scruba difensivamente. Upload → placeholder, cap 64 KB.
  @capture_request_body = true

  # Breadcrumbs: cronologia (query offuscate, eventi custom) allegata all'errore.
  @breadcrumbs_enabled = true
  @max_breadcrumbs     = 100

  # Sampling probabilistico di errori/messaggi (1.0 = invia tutto, 0.0 = niente).
  @sample_rate = 1.0

  # Cattura errori handled (Rails.error.report) e degli ActiveJob/Sidekiq (oggi persi).
  @capture_handled_errors   = true
  @report_active_job_errors = true

  # Cattura valori dei parametri — opt-in, default OFF (privacy). I bind/argomenti possono contenere PII.
  @capture_query_bindings   = false
  @capture_method_arguments = false

  # Log strutturati (CloseYourIt.log / .logger). Master switch + sampling + batching dedicati.
  @logs_enabled        = true
  @logs_sample_rate    = 1.0
  @logs_batch_size     = 50
  @logs_flush_interval = 5
  # Broadcast opt-in di Rails.logger → CloseYourIt.log (default OFF; spedisce solo ≥ soglia).
  @capture_rails_logs = false
  @logs_min_level     = :info
  # Soglia DEDICATA del broadcast Rails.logger, distinta da logs_min_level (che governa
  # CloseYourIt.log/.logger, dove è il dev a scegliere cosa loggare). Default :warn — conservativo:
  # senza, in produzione ad alto traffico OGNI riga info del framework (Started GET, Rendered, ...)
  # inonderebbe lo stream con decine di migliaia di log-entry/min (CYRB-7). Chi vuole anche gli info
  # del framework la abbassa esplicitamente (es. :info).
  @capture_rails_logs_min_level = :warn
  # Rumore del broadcast Rails.logger che NON è un'eccezione, e quindi excluded_exceptions non può
  # coprire: righe ripetute del framework o di una gemma. Regexp sul testo del messaggio, default
  # vuoto. Vale SOLO per il broadcast automatico, mai per CloseYourIt.log esplicito.
  @excluded_log_patterns = []

  # Performance issue detection (verdetti aggregati: N+1, slow request, HTTP esterne lente).
  # OPT-IN, default OFF: profila OGNI query della richiesta → overhead non trascurabile, va attivato
  # consapevolmente per-app. Le soglie sono conservative (poco rumore). Vedi Performance::Rollup.
  @detect_performance_issues = false
  @n_plus_one_threshold      = 10        # stesso fingerprint+call-site eseguito > N volte in una richiesta
  @query_count_threshold     = 100       # troppe query totali in una richiesta
  @query_time_threshold_ms   = 500       # tempo DB totale per richiesta oltre cui = high_query_count
  @slow_request_threshold_ms = 1000      # durata totale della richiesta
  @slow_external_threshold_ms = 1000     # singola chiamata HTTP esterna
  @capture_external_http     = true      # strumenta Net::HTTP (solo se detect_performance_issues)

  # Metriche dei background job: durata di esecuzione e attesa in coda (queue latency) per ActiveJob
  # e Sidekiq. ON di default (a differenza di detect_performance_issues): la visibilità dei job
  # lenti/in ritardo/ritentati non deve richiedere strumentazione manuale in ogni app (CYRB-14), e
  # l'overhead è basso — una notifica per job, non il profiling di ogni query. Il rumore è tenuto a
  # bada dalle soglie (job normali sotto soglia = niente metrica) e dal sampling. La label è il nome
  # della classe del job; gli argomenti non vengono MAI inviati.
  @monitor_jobs                   = true
  @slow_job_threshold_ms          = 5000     # durata del perform oltre cui = slow_job
  @job_queue_latency_threshold_ms = 60_000   # attesa enqueue→esecuzione oltre cui = job_queue_latency
  @jobs_sample_rate               = 1.0      # frazione dei candidati oltre soglia effettivamente inviata

  # Radice del progetto: base per il filename relativo dei frame (culprit cross-SDK). Lazy:
  # auto-rilevata da Rails.root o Dir.pwd al primo accesso se non impostata esplicitamente.
  @project_root = nil

  @filter_parameters      = []
  @scrub_message_patterns = []
end

Instance Attribute Details

#async_threadsObject

Returns the value of attribute async_threads.



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

def async_threads
  @async_threads
end

#background_worker_max_queueObject

Returns the value of attribute background_worker_max_queue.



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

def background_worker_max_queue
  @background_worker_max_queue
end

#before_sendObject

Returns the value of attribute before_send.



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

def before_send
  @before_send
end

Returns the value of attribute breadcrumbs_enabled.



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

def breadcrumbs_enabled
  @breadcrumbs_enabled
end

#capture_external_httpObject

Returns the value of attribute capture_external_http.



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

def capture_external_http
  @capture_external_http
end

#capture_handled_errorsObject

Returns the value of attribute capture_handled_errors.



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

def capture_handled_errors
  @capture_handled_errors
end

#capture_method_argumentsObject

Returns the value of attribute capture_method_arguments.



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

def capture_method_arguments
  @capture_method_arguments
end

#capture_query_bindingsObject

Returns the value of attribute capture_query_bindings.



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

def capture_query_bindings
  @capture_query_bindings
end

#capture_rails_logsObject

Returns the value of attribute capture_rails_logs.



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

def capture_rails_logs
  @capture_rails_logs
end

#capture_rails_logs_min_levelObject

Returns the value of attribute capture_rails_logs_min_level.



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

def capture_rails_logs_min_level
  @capture_rails_logs_min_level
end

#capture_requestObject

Returns the value of attribute capture_request.



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

def capture_request
  @capture_request
end

#capture_request_bodyObject

Returns the value of attribute capture_request_body.



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

def capture_request_body
  @capture_request_body
end

#context_linesObject

Returns the value of attribute context_lines.



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

def context_lines
  @context_lines
end

#detect_performance_issuesObject

Returns the value of attribute detect_performance_issues.



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

def detect_performance_issues
  @detect_performance_issues
end

#endpoint_urlObject

Returns the value of attribute endpoint_url.



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

def endpoint_url
  @endpoint_url
end

#environmentObject

Returns the value of attribute environment.



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

def environment
  @environment
end

#excluded_exceptionsObject

Returns the value of attribute excluded_exceptions.



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

def excluded_exceptions
  @excluded_exceptions
end

#excluded_log_patternsObject

Returns the value of attribute excluded_log_patterns.



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

def excluded_log_patterns
  @excluded_log_patterns
end

#excluded_query_patternsObject

Returns the value of attribute excluded_query_patterns.



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

def excluded_query_patterns
  @excluded_query_patterns
end

#filter_parametersObject

Returns the value of attribute filter_parameters.



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

def filter_parameters
  @filter_parameters
end

#job_queue_latency_threshold_msObject

Returns the value of attribute job_queue_latency_threshold_ms.



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

def job_queue_latency_threshold_ms
  @job_queue_latency_threshold_ms
end

#jobs_sample_rateObject

Returns the value of attribute jobs_sample_rate.



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

def jobs_sample_rate
  @jobs_sample_rate
end

#logs_batch_sizeObject

Returns the value of attribute logs_batch_size.



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

def logs_batch_size
  @logs_batch_size
end

#logs_enabledObject

Returns the value of attribute logs_enabled.



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

def logs_enabled
  @logs_enabled
end

#logs_flush_intervalObject

Returns the value of attribute logs_flush_interval.



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

def logs_flush_interval
  @logs_flush_interval
end

#logs_min_levelObject

Returns the value of attribute logs_min_level.



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

def logs_min_level
  @logs_min_level
end

#logs_sample_rateObject

Returns the value of attribute logs_sample_rate.



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

def logs_sample_rate
  @logs_sample_rate
end

#max_breadcrumbsObject

Returns the value of attribute max_breadcrumbs.



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

def max_breadcrumbs
  @max_breadcrumbs
end

#monitor_jobsObject

Returns the value of attribute monitor_jobs.



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

def monitor_jobs
  @monitor_jobs
end

#n_plus_one_thresholdObject

Returns the value of attribute n_plus_one_threshold.



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

def n_plus_one_threshold
  @n_plus_one_threshold
end

#obfuscate_sqlObject

Returns the value of attribute obfuscate_sql.



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

def obfuscate_sql
  @obfuscate_sql
end

#on_diagnosticObject

Returns the value of attribute on_diagnostic.



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

def on_diagnostic
  @on_diagnostic
end

#project_idObject

Returns the value of attribute project_id.



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

def project_id
  @project_id
end

#project_rootObject

Radice del progetto effettiva: quella impostata, altrimenti auto-rilevata (Rails.root o Dir.pwd). Usata per rendere frame.filename relativo (culprit confrontabile cross-SDK — CYRB-4).



215
216
217
218
219
# File 'lib/closeyourit/configuration.rb', line 215

def project_root
  return @project_root unless @project_root.nil?

  @project_root = detect_project_root
end

#query_count_thresholdObject

Returns the value of attribute query_count_threshold.



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

def query_count_threshold
  @query_count_threshold
end

#query_time_threshold_msObject

Returns the value of attribute query_time_threshold_ms.



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

def query_time_threshold_ms
  @query_time_threshold_ms
end

#releaseObject

Release effettiva: quella impostata, altrimenti auto-rilevata (ENV di deploy/CI o git).



207
208
209
210
211
# File 'lib/closeyourit/configuration.rb', line 207

def release
  return @release unless @release.nil?

  @release = detect_release
end

#report_active_job_errorsObject

Returns the value of attribute report_active_job_errors.



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

def report_active_job_errors
  @report_active_job_errors
end

#request_header_allowlistObject

Returns the value of attribute request_header_allowlist.



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

def request_header_allowlist
  @request_header_allowlist
end

#sample_rateObject

Returns the value of attribute sample_rate.



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

def sample_rate
  @sample_rate
end

#scrub_message_patternsObject

Returns the value of attribute scrub_message_patterns.



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

def scrub_message_patterns
  @scrub_message_patterns
end

#send_piiObject

Returns the value of attribute send_pii.



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

def send_pii
  @send_pii
end

#send_server_nameObject

Returns the value of attribute send_server_name.



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

def send_server_name
  @send_server_name
end

#slow_external_threshold_msObject

Returns the value of attribute slow_external_threshold_ms.



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

def slow_external_threshold_ms
  @slow_external_threshold_ms
end

#slow_job_threshold_msObject

Returns the value of attribute slow_job_threshold_ms.



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

def slow_job_threshold_ms
  @slow_job_threshold_ms
end

#slow_method_threshold_msObject

Returns the value of attribute slow_method_threshold_ms.



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

def slow_method_threshold_ms
  @slow_method_threshold_ms
end

#slow_query_threshold_msObject

Returns the value of attribute slow_query_threshold_ms.



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

def slow_query_threshold_ms
  @slow_query_threshold_ms
end

#slow_request_threshold_msObject

Returns the value of attribute slow_request_threshold_ms.



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

def slow_request_threshold_ms
  @slow_request_threshold_ms
end

#tokenObject

Returns the value of attribute token.



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

def token
  @token
end

#trap_signalsObject

Returns the value of attribute trap_signals.



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

def trap_signals
  @trap_signals
end

Instance Method Details

#detect_project_rootObject

Rails.root quando l'app gira sotto Rails, altrimenti la working directory. Mai solleva.



222
223
224
225
226
227
228
# File 'lib/closeyourit/configuration.rb', line 222

def detect_project_root
  return ::Rails.root.to_s if defined?(::Rails) && ::Rails.respond_to?(:root) && ::Rails.root

  Dir.pwd
rescue StandardError
  Dir.pwd
end

#detect_releaseObject

Auto-rilevamento release: prima un tag semver (APP_GIT_TAG/GIT_TAG), poi lo short SHA dalle env di deploy/CI o dal git. Mai solleva.



236
237
238
239
240
241
242
243
244
245
246
# File 'lib/closeyourit/configuration.rb', line 236

def detect_release
  detect_tag ||
    ENV["KAMAL_VERSION"] ||
    ENV["GIT_SHA"] ||
    ENV["GIT_REVISION"] ||
    ENV["SOURCE_VERSION"] ||
    ENV["HEROKU_SLUG_COMMIT"] ||
    git_revision
rescue StandardError
  nil
end

#enabled?Boolean

Il client invia solo con credenziali complete (endpoint + token + project_id) e trasporto sicuro (http:// ammesso fuori produzione).

Returns:

  • (Boolean)


190
191
192
193
194
195
# File 'lib/closeyourit/configuration.rb', line 190

def enabled?
  return false if blank?(endpoint_url) || blank?(token) || blank?(project_id)
  return false if insecure_endpoint? && production?

  true
end

#production?Boolean

Returns:

  • (Boolean)


184
185
186
# File 'lib/closeyourit/configuration.rb', line 184

def production?
  environment.to_s == "production"
end

#validate!Object

Logga i warning di configurazione (es. endpoint http://, project_id/endpoint malformati). Non solleva mai: coerente con la filosofia no-op del client. Chiamata da CloseYourIt.init.



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

def validate!
  CloseYourIt.internal_logger.warn(insecure_endpoint_message) if insecure_endpoint?
  CloseYourIt.internal_logger.warn(malformed_project_id_message) if malformed_project_id?
  CloseYourIt.internal_logger.warn(malformed_endpoint_message) if malformed_endpoint?
  self
end