Module: Sixty::Instrument::Mysql

Defined in:
lib/sixty/instrument/mysql.rb

Overview

The MySQL drivers — mysql2 and trilogy — patched directly.

Same audience as the pg patch: everything that is not ActiveRecord. A Rails app on MySQL is covered by sql.active_record, which is public API and does not care which driver is underneath; this covers Sinatra, Sequel, workers and scripts, both of whose drivers reach the server through one method each.

── The dialect is not a detail ──────────────────────────────────────────

Everything here normalizes with :mysql, because "alice@example.com" is a string literal in MySQL's default sql_mode and a quoted identifier in Postgres. Reading a MySQL statement with the Postgres rules would keep it — the one class of bug this agent must never have.

── Rows, and why the result is not iterated to find them ────────────────

Mysql2::Result is lazily populated when the client is streaming, and asking a streaming result for its size consumes it. The count is therefore only read where it is free — a buffered result already knows it — and a streaming query reports no row count rather than a wrong one, or a query this agent silently drained on the application's behalf.

Defined Under Namespace

Modules: Mysql2Patch, Mysql2PreparePatch, Mysql2StatementPatch, TrilogyPatch

Class Method Summary collapse

Class Method Details

.install(config = nil) ⇒ Object



33
34
35
36
37
38
39
# File 'lib/sixty/instrument/mysql.rb', line 33

def install(config = nil)
  @config = config
  installed = false
  installed |= install_mysql2
  installed |= install_trilogy
  installed
end

.installed?Boolean

Returns:

  • (Boolean)


41
42
43
# File 'lib/sixty/instrument/mysql.rb', line 41

def installed?
  @mysql2_installed == true || @trilogy_installed == true
end

.measure(sql, connection: nil, count_rows: true) ⇒ Object

One span for one statement, shared by both drivers.

count_rows is decided by the caller rather than here, because only the patch can see the query options that say whether the result will be streamed — and asking a streaming result for its size would consume it, which is a change in the application's behaviour rather than a measurement of it.



57
58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/sixty/instrument/mysql.rb', line 57

def measure(sql, connection: nil, count_rows: true)
  return yield unless Sixty.enabled? && sql.is_a?(String) && !sql.empty?

  normalized = Sql.normalize_sql(sql, :mysql)
  started = Tracer.monotonic_ms
  begin
    result = yield
  rescue StandardError => e
    record(normalized, Tracer.monotonic_ms - started, nil, nil, false, e)
    raise
  end
  record(normalized, Tracer.monotonic_ms - started, result, connection, count_rows, nil)
  result
end

.reset!Object



45
46
47
48
# File 'lib/sixty/instrument/mysql.rb', line 45

def reset!
  @mysql2_installed = false
  @trilogy_installed = false
end