module OneApm::Agent::Database
Constants
- OA_KNOWN_OPERATIONS
- OA_MAX_QUERY_LENGTH
- OA_QUERY_PLAN
- OA_RECORD_FOR
- OA_SQLITE_EXPLAIN_COLUMNS
- OA_SQL_COMMENT_REGEX
- OA_SUPPORTED_ADAPTERS_FOR_EXPLAIN
Public Instance Methods
adapter_from_config(config)
click to toggle source
# File lib/one_apm/agent/database.rb, line 82 def adapter_from_config(config) if config[:adapter] return config[:adapter].to_s elsif config[:uri] && config[:uri].to_s =~ /^jdbc:([^:]+):/ return $1 end end
capture_query(query)
click to toggle source
# File lib/one_apm/agent/database.rb, line 28 def capture_query(query) Helper.correctly_encoded(truncate_query(query)) end
close_connections()
click to toggle source
# File lib/one_apm/agent/database.rb, line 78 def close_connections ConnectionManager.instance.close_connections end
explain_sql(sql, connection_config, &explainer)
click to toggle source
# File lib/one_apm/agent/database.rb, line 90 def explain_sql(sql, connection_config, &explainer) return nil unless sql && connection_config statement = sql.split(";\n")[0] # only explain the first explain_plan = explain_statement(statement, connection_config, &explainer) return explain_plan || [] end
explain_statement(statement, config, &explainer)
click to toggle source
# File lib/one_apm/agent/database.rb, line 99 def explain_statement(statement, config, &explainer) return unless is_select?(statement) if statement[-3,3] == '...' OneApm::Manager.logger.debug('Unable to collect explain plan for truncated query.') return end if parameterized?(statement) OneApm::Manager.logger.debug('Unable to collect explain plan for parameterized query.') return end adapter = adapter_from_config(config) if !OA_SUPPORTED_ADAPTERS_FOR_EXPLAIN.include?(adapter) OneApm::Manager.logger.debug("Not collecting explain plan because an unknown connection adapter ('#{adapter}') was used.") return end handle_exception_in_explain do start = Time.now plan = explainer.call(config, statement) OneApm::Manager.record_metric("Supportability/Database/execute_explain_plan", Time.now - start) return process_resultset(plan, adapter) if plan end end
get_connection(config, &connector)
click to toggle source
# File lib/one_apm/agent/database.rb, line 74 def get_connection(config, &connector) ConnectionManager.instance.get_connection(config, &connector) end
handle_exception_in_explain() { || ... }
click to toggle source
# File lib/one_apm/agent/database.rb, line 200 def handle_exception_in_explain yield rescue => e begin # guarantees no throw from explain_sql OneApm::Manager.logger.error("Error getting query plan:", e) nil rescue # double exception. throw up your hands nil end end
is_select?(statement)
click to toggle source
# File lib/one_apm/agent/database.rb, line 237 def is_select?(statement) parse_operation_from_query(statement) == 'select' end
obfuscate_sql(sql)
click to toggle source
# File lib/one_apm/agent/database.rb, line 40 def obfuscate_sql(sql) Obfuscator.instance.obfuscator.call(sql) end
parameterized?(statement)
click to toggle source
# File lib/one_apm/agent/database.rb, line 241 def parameterized?(statement) Obfuscator.instance.obfuscate_single_quote_literals(statement) =~ /\$\d+/ end
parse_operation_from_query(sql)
click to toggle source
# File lib/one_apm/agent/database.rb, line 229 def parse_operation_from_query(sql) sql = sql.gsub(OA_SQL_COMMENT_REGEX, '') if sql =~ /(\w+)/ op = $1.downcase return op if OA_KNOWN_OPERATIONS.include?(op) end end
process_explain_results_mysql(results)
click to toggle source
# File lib/one_apm/agent/database.rb, line 162 def process_explain_results_mysql(results) return string_explain_plan_results(results) if results.is_a?(String) headers = [] values = [] if results.is_a?(Array) headers = results.first.keys results.each do |row| values << headers.map { |h| row[h] } end else results.each_hash do |row| headers = row.keys values << headers.map { |h| row[h] } end end [headers, values] end
process_explain_results_mysql2(results)
click to toggle source
# File lib/one_apm/agent/database.rb, line 180 def process_explain_results_mysql2(results) return string_explain_plan_results(results) if results.is_a?(String) headers = results.fields values = [] results.each { |row| values << row } [headers, values] end
process_explain_results_postgres(results)
click to toggle source
# File lib/one_apm/agent/database.rb, line 141 def process_explain_results_postgres(results) if results.is_a?(String) query_plan_string = results else lines = [] results.each { |row| lines << row[OA_QUERY_PLAN] } query_plan_string = lines.join("\n") end unless record_sql_method == :raw query_plan_string = OneApm::Agent::Database::PostgresExplainObfuscator.obfuscate(query_plan_string) end values = query_plan_string.split("\n").map { |line| [line] } [[OA_QUERY_PLAN], values] end
process_explain_results_sqlite(results)
click to toggle source
# File lib/one_apm/agent/database.rb, line 190 def process_explain_results_sqlite(results) return string_explain_plan_results(results) if results.is_a?(String) headers = OA_SQLITE_EXPLAIN_COLUMNS values = [] results.each do |row| values << headers.map { |h| row[h] } end [headers, values] end
process_resultset(results, adapter)
click to toggle source
# File lib/one_apm/agent/database.rb, line 126 def process_resultset(results, adapter) case adapter.to_s when 'postgres', 'postgresql' process_explain_results_postgres(results) when 'mysql2' process_explain_results_mysql2(results) when 'mysql' process_explain_results_mysql(results) when 'sqlite' process_explain_results_sqlite(results) end end
record_sql_method(config_section=:transaction_tracer)
click to toggle source
# File lib/one_apm/agent/database.rb, line 48 def record_sql_method(config_section=:transaction_tracer) case OneApm::Manager.config["#{config_section}.record_sql".to_sym].to_s when 'off' :off when 'none' :off when 'false' :off when 'raw' :raw else :obfuscated end end
set_sql_obfuscator(type, &block)
click to toggle source
# File lib/one_apm/agent/database.rb, line 44 def set_sql_obfuscator(type, &block) Obfuscator.instance.set_sql_obfuscator(type, &block) end
should_collect_explain_plans?(config_section=:transaction_tracer)
click to toggle source
# File lib/one_apm/agent/database.rb, line 69 def should_collect_explain_plans?(config_section=:transaction_tracer) should_record_sql?(config_section) && OneApm::Manager.config["#{config_section}.explain_enabled".to_sym] end
should_record_sql?(config_section=:transaction_tracer)
click to toggle source
# File lib/one_apm/agent/database.rb, line 65 def should_record_sql?(config_section=:transaction_tracer) OA_RECORD_FOR.include?(record_sql_method(config_section)) end
string_explain_plan_results(results)
click to toggle source
# File lib/one_apm/agent/database.rb, line 158 def string_explain_plan_results(results) [nil, [results]] end
truncate_query(query)
click to toggle source
# File lib/one_apm/agent/database.rb, line 32 def truncate_query(query) if query.length > (OA_MAX_QUERY_LENGTH - 4) query[0..OA_MAX_QUERY_LENGTH - 4] + '...' else query end end