module PulseMeter module Sensor class Base attr_accessor :color end end end require 'pulse-meter/visualizer' module PulseToolbox module Sensor class Manager extend PulseToolbox::Sensor::Mixins::Iterators # @!attribute [rw] default_options # @return [Hash] default sensor options class_attribute :default_options # @!attribute [rw] sensors_config # @return [Hash] sensors config class_attribute :sensors_config # @!attribute [rw] configurator # @return [PulseMeter::Sensor::Configuration] configurator instance class_attribute :configurator # @!attribute [rw] monitoring_layout # @return [PulseMeter::Visualize::DSL::Layout] layout for monitoring page class_attribute :monitoring_layout self.monitoring_layout = PulseMeter::Visualize::DSL::Layout.new self.default_options = { :ttl => 1.day, :interval => 1.minute, :raw_data_ttl => 1.hour, :reduce_delay => 2.minutes }.freeze self.sensors_config = { :max => { :title => "Max times", :sensors => { :db_time => { :sensor_type => 'timelined/max', :color => '#0000FF', :args => { :annotation => "DB" } }, :view_time => { :sensor_type => 'timelined/max', :color => '#00FF00', :args => { :annotation => "View" } }, :total_time => { :sensor_type => 'timelined/max', :color => '#FF0000', :args => { :annotation => "Total" } } } }, :p95 => { :title => "95% percentile times", :sensors => { :db_time => { :sensor_type => 'timelined/percentile', :color => '#0000FF', :args => { :annotation => "DB", :p => 0.95 } }, :view_time => { :sensor_type => 'timelined/percentile', :color => '#00FF00', :args => { :annotation => "View", :p => 0.95 } }, :total_time => { :sensor_type => 'timelined/percentile', :color => '#FF0000', :args => { :annotation => "Total", :p => 0.95 } } } } } # Creates all sensors from sensors_config def self.create_sensors PulseToolbox.maybe_reconnect config = cfg self.configurator = PulseMeter::Sensor::Configuration.new(cfg) each_sensor do |s| s.color = config[s.name.to_sym][:color] end end class << self # Logs rails request timing to various sensors # @param total_time [Float] total request time # @param view_time [Float] view time of request # @param db_time [Float] db time of request def log_request(total_time, view_time, db_time) [ [:max_db_time, db_time], [:p95_db_time, db_time], [:max_view_time, view_time], [:p95_view_time, view_time], [:max_total_time, total_time], [:p95_total_time, total_time] ].each {|name, value = e| event(name, value)} end # Sends value to sensor by name # @param sensor [Symbol] sensor name # @param value [Float] event value def event(sensor, value) lazy_configurator.sensor(sensor).event(value.to_i) end # Adds group to config # @param name [Symbol] group name # @param title [String] group title def add_group(name, title = nil) name = name.to_sym sensors_config[name] ||= {} sensors_config[name][:title] = title if title sensors_config[name][:sensors] ||= {} return name end # Adds sensor to group in config # @param group [Symbol] group name # @param name [Symbol] sensor name # @param options [Hash] sensor options def add_sensor(group, name, options) name = name.to_sym g = add_group(group) sensors_config[g][:sensors][name] = options return name_in_group(group, name) end # Returns monitoring page layout def layout yield(monitoring_layout) monitoring_layout end private def cfg cfg = {} each_group do |group| sensors_config[group][:sensors].each_pair do |key, params| name = name_in_group(group, key) full_args = default_options.merge(params[:args]) params[:args] = default_options.merge(params[:args]) cfg[name] = params end end cfg end def name_in_group(group, sensor_name) "#{group}_#{sensor_name}".to_sym end def get_sensor(group, name) lazy_configurator.sensor(name_in_group(group, name)) end def lazy_configurator create_sensors unless configurator configurator end end end end end