Module: Sixty::Instrument::ActiveRecord
- Defined in:
- lib/sixty/instrument/active_record.rb
Overview
ActiveRecord.
What is captured beyond timing is the point of the product:
rows — how many the statement returned. The 30 -> 30,000 signal, and the
one an ORM makes easy to lose: `.where(...)` without a limit is
one character away from `.all`, and on a development database
both take four milliseconds.
calls — every query, credited to every enclosing method and to the
request. One query becoming twelve is an N+1 being born.
── Why a notification subscriber and not a patched adapter ───────────────
sql.active_record is a public, stable interface that every adapter emits
and every Rails version has. Patching exec_query would work on one
adapter and one version and break quietly on the next, and "quietly" is
the failure mode this project refuses. The cost is that the event arrives
after the query — so the span is assembled from the event's own start
and finish times rather than measured around it, which is exactly what
Tracer.record exists for.
Constant Summary collapse
- IGNORED_NAMES =
Statements Rails issues about itself rather than on the application's behalf. A schema load at boot is not an operation anyone can act on, and a cached query never reached the database at all — recording it would report database work that did not happen.
['SCHEMA', 'TRANSACTION', 'EXPLAIN'].freeze
Class Method Summary collapse
-
.dialect ⇒ Object
Which SQL dialect this application speaks.
- .install(config) ⇒ Object
- .installed? ⇒ Boolean
Class Method Details
.dialect ⇒ Object
Which SQL dialect this application speaks.
It decides whether "alice@example.com" is an identifier to keep or a
string literal to strip, so guessing from the text is not an option —
a wrong guess in one direction transmits a customer's data. Asked of
the adapter, which knows, and cached because the answer cannot change
for the life of a process.
connection_db_config rather than a live connection: reading this
must never be a reason to open one.
64 65 66 67 68 69 70 71 72 73 |
# File 'lib/sixty/instrument/active_record.rb', line 64 def dialect return @dialect if defined?(@dialect) && @dialect @dialect = begin name = ::ActiveRecord::Base.connection_db_config.adapter.to_s name.match?(/mysql|trilogy|maria/i) ? :mysql : :postgres rescue StandardError :postgres end end |
.install(config) ⇒ Object
37 38 39 40 41 42 43 44 45 46 47 48 |
# File 'lib/sixty/instrument/active_record.rb', line 37 def install(config) return false if @installed return false unless defined?(::ActiveSupport::Notifications) @config = config @subscriber = ::ActiveSupport::Notifications.monotonic_subscribe('sql.active_record') do |_name, started, finished, _id, payload| record(payload, (finished - started) * 1000.0) end Sixty.before_flush { capture_plans } if config.capture_plans @installed = true end |
.installed? ⇒ Boolean
50 51 52 |
# File 'lib/sixty/instrument/active_record.rb', line 50 def installed? @installed == true end |