class ActiveTracker::Plugin::Query

Public Class Methods

capture_query(event) click to toggle source
# File lib/active_tracker/plugin/query.rb, line 78
def self.capture_query(event)
  tags = {
    sql: event.payload[:sql],
    name: event.payload[:name],
  }

  return if filter_query?(tags)

  ActiveTracker::Model.find_or_create("Query", tags:tags, data_type: "full") do |obj|
    if obj.persisted
      ActiveTracker::Model.delete(obj.key)
    end
    obj.data ||= {}
    obj.data["last_duration"] = event.duration
    obj.data["count"] = (obj.data["count"] || 0) + 1
    # Enough for most git commits to be referenced
    # so should be fine for SQL query hashes within an application
    obj.id = "Q" + Digest::SHA2.hexdigest(tags.inspect)[0,8]
    obj.expiry = 7.days
    obj.log_at = Time.now

    obj.data["at_requests"] ||= []
    if ActiveTracker::Plugin::Request.registered?
      begin
        id = ActiveTracker::Plugin::Request.current_tags[:id] rescue nil
        obj.data["at_requests"].prepend(id) if id.present?
        obj.data["at_requests"] = obj.data["at_requests"][0,20]
        ActiveTracker::Plugin::Request.current_tags[:at_queries] ||= []
        ActiveTracker::Plugin::Request.current_tags[:at_queries] << obj.id
      rescue Exception, ActiveRecord::StatementInvalid, NoMethodError
        # Sometimes during initial DB migration this will fail to insert
        # the current object
      end
    end
  end
end
filter_query?(details) click to toggle source
# File lib/active_tracker/plugin/query.rb, line 115
def self.filter_query?(details)
  ActiveTracker::Plugin::Query.filters.each do |filter|
    if filter.is_a?(Regexp)
      if filter.match(details[:sql] || "") || filter.match(details[:name] || "")
        return true
      end
    else
      if (details[:sql] || "").include?(filter) || (details[:name] || "").include?(filter)
        return true
      end
    end
  end

  false
end
filters() click to toggle source
# File lib/active_tracker/plugin/query.rb, line 66
def self.filters
  @filters ||= ["SCHEMA", /^$/]
end
filters=(value) click to toggle source
# File lib/active_tracker/plugin/query.rb, line 62
def self.filters=(value)
  @filters = value
end
min_slow_duration_ms() click to toggle source
# File lib/active_tracker/plugin/query.rb, line 74
def self.min_slow_duration_ms
  @min_slow_duration_ms ||= 100
end
min_slow_duration_ms=(value) click to toggle source
# File lib/active_tracker/plugin/query.rb, line 70
def self.min_slow_duration_ms=(value)
  @min_slow_duration_ms = value
end
nav_svg() click to toggle source
nav_title() click to toggle source
register() click to toggle source
# File lib/active_tracker/plugin/query.rb, line 6
def self.register
  ActiveSupport::Notifications.subscribe "sql.active_record" do |*args|
    event = ActiveSupport::Notifications::Event.new(*args)
    capture_query(event)
  end

  @@registered = true
end
registered?() click to toggle source
# File lib/active_tracker/plugin/query.rb, line 15
def self.registered?
  @@registered rescue false
end
resources_name() click to toggle source
# File lib/active_tracker/plugin/query.rb, line 19
def self.resources_name
  :queries
end
statistics() click to toggle source
# File lib/active_tracker/plugin/query.rb, line 34
def self.statistics
  ret = []
  queries = ActiveTracker::Model.all("Query")
  queries = queries.select {|e| e.log_at >= 60.minutes.ago}

  num_queries = 0
  slow_queries = 0
  total_duration = 0

  queries.each do |query|
    actual_query = ActiveTracker::Model.find(query.key)
    next unless actual_query
    slow_queries += actual_query.count if actual_query.last_duration > self.min_slow_duration_ms
    num_queries += actual_query.count
    total_duration += actual_query.last_duration * actual_query.count
  end

  ret << {plugin: self, label: "Queries/hour", value: num_queries}
  if slow_queries == 0
    ret << {plugin: self, label: "Slow queries/hour", value: slow_queries}
  else
    ret << {plugin: self, label: "Slow queries/hour", value: slow_queries, error: true}
  end
  ret << {plugin: self, label: "Avg time/query", value: "%.2fms" % (total_duration/num_queries)} if num_queries > 0

  ret
end