app/models/vim_performance_tag_value.rb
class VimPerformanceTagValue
attr_accessor :tag_name, :association_type, :category, :column_name, :value, :assoc_ids
TAG_SEP = "|"
TAG_COLS = {
:Storage => [
"derived_storage_vm_count_managed",
"derived_storage_used_managed",
"derived_storage_disk_managed",
"derived_storage_snapshot_managed",
"derived_storage_mem_managed",
"assoc_ids"
],
:default => [
"cpu_usagemhz_rate_average",
"cpu_usage_rate_average",
"v_pct_cpu_ready_delta_summation",
"derived_memory_used",
"disk_usage_rate_average",
"net_usage_rate_average",
"assoc_ids"
]
}
RESOURCE_TYPE_TO_ASSOCIATIONS = {
"MiqEnterprise" => [:miq_regions],
"MiqRegion" => [:ext_management_systems],
"ExtManagementSystem" => [:vms, :hosts, :ems_clusters],
"Storage" => [:vms, :hosts],
"EmsCluster" => [:vms, :hosts],
"Host" => [:vms],
"AvailabilityZone" => [:vms],
"VmOrTemplate" => [],
"ContainerNode" => [],
"Container" => [],
"ContainerGroup" => [],
"ContainerImage" => [:containers],
"ContainerProject" => [],
"ContainerService" => [],
"ContainerReplicator" => [],
"Service" => [:vms]
}
def initialize(options = {})
options.each { |k, v| public_send(:"#{k}=", v) }
end
def self.build_from_performance_record(parent_perf, options = {})
RESOURCE_TYPE_TO_ASSOCIATIONS[parent_perf.resource_type].collect { |assoc| build_for_association(parent_perf, assoc, options) }.flatten
end
cache_with_timeout(:eligible_categories, 5.minutes) { Classification.category_names_for_perf_by_tag }
def self.build_for_association(parent_perf, assoc, options = {})
eligible_cats = eligible_categories
return [] if eligible_cats.empty?
ts = parent_perf.timestamp
children = parent_perf.resource.vim_performance_state_association(ts, assoc).to_a
return [] if children.empty?
vim_performance_daily = parent_perf.kind_of?(VimPerformanceDaily)
recs = get_metrics(children, ts, parent_perf.capture_interval_name, vim_performance_daily, options[:category])
result = {}
counts = {}
association_type = nil
tag_cols = TAG_COLS.fetch(parent_perf.resource_type.to_sym) { TAG_COLS[:default] }
perf_data = {}
perf_data[:perf_recs] = recs
perf_data[:categories] = perf_data[:perf_recs].collect do |perf|
perf.tag_names.split(TAG_SEP).collect { |t| t.split("/").first } unless perf.tag_names.nil?
end.flatten.compact.uniq
cats_to_process = (eligible_cats & perf_data[:categories]) # Process subset of perf_data[:categories] that are eligible for tag grouping
return [] if cats_to_process.empty?
perf_data[:perf_recs].each do |perf|
association_type = perf.resource_type
cats_to_process.each do |category|
if !perf.tag_names.nil? && perf.tag_names.include?(category)
tag_names = perf.tag_names.split(TAG_SEP).select { |t| t.starts_with?(category) }
else
tag_names = ["#{category}/_none_"]
end
tag_names.each do |tag|
next if tag.starts_with?("power_state")
next if tag.starts_with?("folder_path")
tag_cols.each do |c|
value = perf.send(c)
c = [c.to_s, tag].join(TAG_SEP).to_sym
if c.to_s.starts_with?("assoc_ids")
assoc = perf.resource.class.table_name.to_sym
result[c] ||= {assoc => {:on => []}}
result[c][assoc][:on].push(perf.resource_id)
else
result[c] ||= 0
counts[c] ||= 0
value *= 1.0 unless value.nil?
Metric::Aggregation::Aggregate.average(c, nil, result, counts, value)
end
end
end
end
end
result.keys.inject([]) do |a, key|
col, tag = key.to_s.split(TAG_SEP)
category = tag.split("/").first
tag_name = tag.split("/").last
Metric::Aggregation::Process.average(key, nil, result, counts) unless col.to_s.starts_with?("assoc_ids", "derived_storage_vm_count")
new_rec = {
:association_type => association_type,
:category => category,
:tag_name => tag_name,
:column_name => col
}
attr = col == 'assoc_ids' ? :assoc_ids : :value
new_rec[attr] = result[key]
a << new(new_rec)
end
end
def self.get_metrics(resources, timestamp, capture_interval_name, vim_performance_daily, category)
if vim_performance_daily
MetricRollup.with_interval_and_time_range("hourly", timestamp..(timestamp + 1.day)).where(:resource => resources)
.for_tag_names([[category, ""]]) # append trailing slash
else
Metric::Helper.class_for_interval_name(capture_interval_name).where(:resource => resources)
.with_interval_and_time_range(capture_interval_name, timestamp)
end
end
private_class_method :get_metrics
def self.tag_cols(name)
return TAG_COLS[name.to_sym] if TAG_COLS.key?(name.to_sym)
TAG_COLS[:default]
end
end # class VimPerformanceTagValue