forked from ManageIQ/manageiq
-
Notifications
You must be signed in to change notification settings - Fork 1
/
vim_performance_daily.rb
152 lines (122 loc) · 5.91 KB
/
vim_performance_daily.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
class VimPerformanceDaily < MetricRollup
def self.instances_are_derived? = true
INFO_COLS = [:resource_type, :resource_id, :resource_name]
PARENT_COLS = [:parent_host_id, :parent_ems_cluster_id, :parent_storage_id, :parent_ems_id].freeze
# @param ext_options [Hash] search options
# @opts ext_options :klass [Class] class for metrics (default: MetricRollup)
# @opts ext_options :time_profile [TimeProfile]
# @opts ext_options :tz [Timezone] (default: DEFAULT_TIMEZONE)
def self.find_entries(ext_options)
ext_options ||= {}
# TODO: remove changing ext_options once this side effect is no longer needed:
time_profile = ext_options[:time_profile] ||= TimeProfile.default_time_profile(ext_options[:tz])
klass = Metric::Helper.class_for_interval_name("daily", ext_options[:class])
klass.with_time_profile_or_tz(time_profile || ext_options[:tz]).where(:capture_interval_name => 'daily')
end
def self.process_hourly_for_one_day(recs, options = {})
only_cols = process_only_cols(recs)
result = {}
counts = {}
tz = Metric::Helper.get_time_zone(options)
tp = options[:time_profile]
ts = nil
recs.each do |perf|
# Get ts in desired time zone - converted to local midnight to strip off hours and become a date
ts ||= recs.first.timestamp.in_time_zone(tz).beginning_of_day
rtype = perf.resource_type
rid = perf.resource_id
key = [perf.capture_interval_name, rtype, rid]
result[key] ||= INFO_COLS.index_with { |c| perf.send(c) }
counts[key] ||= {}
if tp && tp.ts_in_profile?(perf.timestamp) == false
# Save timestamp and info cols for daily row but don't aggregate any values
_log.debug("Timestamp: [#{perf.timestamp.in_time_zone(tz)}] is outside of time profile: [#{tp.description}]")
next
end
relevant_cols(Metric::Rollup::ROLLUP_COLS, only_cols).each do |c|
result[key][c] ||= 0
counts[key][c] ||= 0
value = perf.send(c)
value *= 1.0 unless value.nil?
# Average all values, regardless of rollup type, when going from hourly
# to daily, since these are already rolled up and this is an average
# over the day.
Metric::Aggregation::Aggregate.average(c, nil, result[key], counts[key], value)
Metric::Rollup.rollup_min(c, result[key], value)
Metric::Rollup.rollup_max(c, result[key], value)
end
if rtype == 'VmOrTemplate' && perf.min_max.kind_of?(Hash)
result[key][:min_max] ||= {}
relevant_cols(Metric::Rollup::BURST_COLS, only_cols).each do |c|
Metric::Rollup::BURST_TYPES.each do |type|
ts_key, val_key = Metric::Rollup.burst_col_names(type, c)
# check the hourly row's min_max column's value for a key such as: "abs_min_mem_usage_absolute_average_value"
Metric::Rollup.rollup_burst(c, result[key][:min_max], perf.min_max[ts_key], perf.min_max[val_key], type)
end
end
end
Metric::Rollup.rollup_assoc(:assoc_ids, result[key], perf.assoc_ids) if only_cols.nil? || only_cols.include?(:assoc_ids)
Metric::Rollup.rollup_tags(:tag_names, result[key], perf.tag_names) if only_cols.nil? || only_cols.include?(:tag_names)
relevant_cols(PARENT_COLS, only_cols).each do |c|
val = perf.send(c)
result[key][c] = val if val
end
(options[:reflections] || []).each do |assoc|
next if perf.class.virtual_field?(assoc)
result[key][assoc.to_sym] = perf.send(assoc) if perf.respond_to?(assoc)
end
end
return [] if result.empty?
ts_utc = ts.utc.to_time
# Don't bother rolling up values if day is outside of time profile
rollup_day = tp.nil? || tp.ts_day_in_profile?(ts)
results = result.each_key.collect do |key|
_int, rtype, rid = key
if rollup_day
rollup_columns = (Metric::Rollup::ROLLUP_COLS & (only_cols || Metric::Rollup::ROLLUP_COLS))
average_columns = rollup_columns - Metric::Rollup::DAILY_SUM_COLUMNS
average_columns.each do |c|
Metric::Aggregation::Process.average(c, nil, result[key], counts[key])
end
rollup_columns.each do |c|
result[key][c] = result[key][c].round if columns_hash[c.to_s].type == :integer && !result[key][c].nil?
end
else
_log.debug("Daily Timestamp: [#{ts}] is outside of time profile: [#{tp.description}]")
end
result[key].merge(
:timestamp => ts_utc,
:resource_type => rtype,
:resource_id => rid,
:capture_interval => 1.day,
:capture_interval_name => "daily",
:intervals_in_rollup => Metric::Helper.max_count(counts[key])
)
end
# Clean up min_max values that are stored directly by moving into min_max property Hash
results.each do |h|
min_max = h.delete(:min_max)
h[:min_max] = h.keys.find_all { |k| k.to_s.starts_with?("min", "max") }.each_with_object({}) do |k, mm|
val = h.delete(k)
mm[k] = val unless val.nil?
end
h[:min_max].merge!(min_max) if min_max.kind_of?(Hash)
end
results
end
def self.relevant_cols(cols, only_cols)
only_cols ? (cols & only_cols) : cols
end
def self.process_only_cols(recs)
only_cols = recs.select_values.collect(&:to_sym).presence
return unless only_cols
only_cols += only_cols.select { |c| c.to_s.starts_with?("min_", "max_") }.collect { |c| c.to_s[4..-1].to_sym }
only_cols += only_cols.select { |c| c.to_s.starts_with?("abs_") }.collect { |c| c.to_s.split("_")[2..-2].join("_").to_sym }
if only_cols.detect { |c| c.to_s.starts_with?("v_pct_") }
only_cols += [:cpu_ready_delta_summation, :cpu_wait_delta_summation, :cpu_used_delta_summation]
end
only_cols += [:derived_storage_total, :derived_storage_free] if only_cols.include?(:v_derived_storage_used)
only_cols += Metric::BASE_COLS.collect(&:to_sym)
only_cols.uniq
end
end # class VimPerformanceDaily