-
Notifications
You must be signed in to change notification settings - Fork 900
/
Copy pathrollup.rb
146 lines (124 loc) · 6.62 KB
/
rollup.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
module Metric::CiMixin::Rollup
def perf_rollup_to_parents(interval_name, start_time, end_time = nil)
parent_rollups, next_rollup_interval = case interval_name
when 'realtime' then [perf_rollup_parents(interval_name), 'hourly']
when 'hourly', 'historical' then [perf_rollup_parents('hourly'), 'daily']
when 'daily' then [nil, nil]
else raise ArgumentError, _("invalid interval name %{name}") %
{:name => interval_name}
end
parents = parent_rollups.to_a.compact.flat_map { |p| [p, interval_name] }
parents += [self, next_rollup_interval] unless next_rollup_interval.nil?
parents.each_slice(2) do |parent, new_interval|
next if parent.nil?
case new_interval
when 'hourly', 'historical' then
times = Metric::Helper.hours_from_range(start_time, end_time)
log_header = "Queueing [#{new_interval}] rollup to #{parent.class.name} id: [#{parent.id}] for times: #{times.inspect}"
_log.info "#{log_header}..."
times.each { |t| parent.perf_rollup_queue(t, new_interval) }
_log.info "#{log_header}...Complete"
when 'daily' then
times_by_tp = Metric::Helper.days_from_range_by_time_profile(start_time, end_time)
times_by_tp.each do |tp, times|
log_header = "Queueing [#{new_interval}] rollup to #{parent.class.name} id: [#{parent.id}] in time profile: [#{tp.description}] for times: #{times.inspect}"
_log.info "#{log_header}..."
times.each { |t| parent.perf_rollup_queue(t, new_interval, tp) }
_log.info "#{log_header}...Complete"
end
end
end
end
def perf_rollup_parents(_interval_name = nil)
raise NotImplementedError, _("perf_rollup_parents must be overridden in the mixed-in class")
end
def perf_rollup_queue(time, interval_name, time_profile = nil)
if interval_name == 'daily' && time_profile.nil?
raise ArgumentError, _("time_profile must be passed if interval name is 'daily'")
end
time_profile = TimeProfile.extract_objects(time_profile)
deliver_on = case interval_name
when 'realtime' then nil
when 'hourly', 'historical' then Metric::Helper.next_hourly_timestamp(time)
when 'daily' then Metric::Helper.next_daily_timestamp(time, time_profile.tz_or_default)
end
args = [time, interval_name]
args << time_profile.id if interval_name == 'daily'
MiqQueue.put_unless_exists(
:class_name => self.class.name,
:instance_id => id,
:method_name => 'perf_rollup',
:args => args,
:msg_timeout => Metric::Rollup::TIMEOUT_PROCESS,
:zone => my_zone,
:role => 'ems_metrics_processor',
:queue_name => 'ems_metrics_processor',
:deliver_on => deliver_on,
:priority => Metric::Capture.const_get("#{interval_name.upcase}_PRIORITY")
) do |msg|
_log.debug "Skipping queueing [#{interval_name}] rollup of #{self.class.name} name: [#{name}], id: [#{id}] for time: [#{time}], since it is already queued" unless msg.nil?
end
end
def perf_rollup(time, interval_name, time_profile = nil)
if interval_name == 'daily' && time_profile.nil?
raise ArgumentError, _("time_profile must be passed if interval name is 'daily'")
end
time_profile = TimeProfile.extract_objects(time_profile)
klass, meth = Metric::Helper.class_and_association_for_interval_name(interval_name)
log_header = "[#{interval_name}] Rollup for #{self.class.name} name: [#{name}], id: [#{id}] for time: [#{time}]"
_log.info("#{log_header}...")
dummy, t = Benchmark.realtime_block(:total_time) do
new_perf = {
:timestamp => time,
:capture_interval_name => (interval_name == 'historical' ? 'hourly' : interval_name)
}
new_perf[:time_profile_id] = time_profile.id if time_profile
perf = nil
Benchmark.realtime_block(:db_find_prev_perf) do
perf = send(meth).find_by(new_perf)
perf ||= send(meth).build(:resource_name => name)
end
Benchmark.realtime_block(:rollup_perfs) do
new_perf = Metric::Rollup.send("rollup_#{interval_name}", self, time, interval_name, time_profile, new_perf, perf.attributes.symbolize_keys)
end
Benchmark.realtime_block(:db_update_perf) { perf.update_attributes(new_perf) }
Benchmark.realtime_block(:process_perfs_tag) { VimPerformanceTagValue.build_from_performance_record(perf) }
case interval_name
when "hourly"
Benchmark.realtime_block(:process_bottleneck) { BottleneckEvent.generate_future_events(self) }
when "daily"
Benchmark.realtime_block(:process_operating_ranges) { generate_vim_performance_operating_range(time_profile) }
end
perf_rollup_to_parents(interval_name, time)
end
_log.info("#{log_header}...Complete - Timings: #{t.inspect}")
end
def perf_rollup_range(start_time, end_time, interval_name, time_profile = nil)
times = case interval_name
when 'realtime'
Metric::Helper.realtime_timestamps_from_range(start_time, end_time)
when 'hourly'
Metric::Helper.hours_from_range(start_time, end_time)
when 'daily'
raise ArgumentError, _("time_profile must be passed if interval name is 'daily'") if time_profile.nil?
time_profile = TimeProfile.extract_objects(time_profile)
return if time_profile.nil? || !time_profile.rollup_daily_metrics
Metric::Helper.days_from_range(start_time, end_time, time_profile.tz_or_default)
end
times.reverse_each { |t| perf_rollup(t, interval_name, time_profile) }
# Raise <class>_perf_complete alert event if realtime so alerts can be evaluated.
MiqEvent.raise_evm_alert_event_queue(self, MiqEvent.event_name_for_target(self, "perf_complete")) if interval_name == "realtime"
end
def perf_rollup_range_queue(start_time, end_time, interval_name, time_profile_id = nil, priority = MiqQueue::NORMAL_PRIORITY)
MiqQueue.put_unless_exists(
:class_name => self.class.name,
:method_name => "perf_rollup_range",
:instance_id => id,
:zone => my_zone,
:role => 'ems_metrics_processor',
:queue_name => 'ems_metrics_processor',
:priority => priority,
:args => [start_time, end_time, interval_name, time_profile_id]
)
end
end