forked from ManageIQ/manageiq
-
Notifications
You must be signed in to change notification settings - Fork 1
/
report_options.rb
172 lines (146 loc) · 5 KB
/
report_options.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
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
class Chargeback
# ReportOptions are usualy stored in MiqReport.db_options[:options]
ReportOptions = Struct.new(
:interval, # daily | weekly | monthly
:interval_size, # number of :intervals in the report (i.e. `12` months, `4` weeks)
:end_interval_offset, # report ends :intervals ago (i.e. `3` months ago, or `2` weeks ago)
:owner, # userid
:tenant_id,
:tag, # like /managed/environment/prod (Mutually exclusive with :user)
:report_cols, # cols visible in the final report
:provide_id,
:entity_id, # 1/2/3.../all rails id of entity (ContainerProject or Vm)
:service_id,
:groupby,
:groupby_tag,
:groupby_label,
:userid,
:ext_options,
:include_metrics, # enable charging allocated resources with C & U
:method_for_allocated_metrics,
:cumulative_rate_calculation
) do
def self.new_from_h(hash)
new(*hash.values_at(*members))
end
# skip metric value field because we don't want
# to accumulate metric values(only costs)
def skip_field_accumulation?(field, value)
return false if cumulative_rate_calculation? == false
return false unless field.ends_with?("_metric") && value
true
end
def cumulative_rate_calculation?
!!self[:cumulative_rate_calculation]
end
ALLOCATED_METHODS_WHITELIST = %i[max avg current_value].freeze
def method_for_allocated_metrics
method = (self[:method_for_allocated_metrics] || :max).to_sym
unless ALLOCATED_METHODS_WHITELIST.include?(method)
raise "Invalid method for allocated calculations #{method}"
end
return :sum_of_maxes_from_grouped_values if method == :max && group_by_tenant?
method
end
# include_metrics = nil is default value(true)
def include_metrics?
include_metrics.nil? || include_metrics
end
def initialize(*)
super
self.interval ||= 'daily'
self.end_interval_offset ||= 0
self.ext_options ||= {}
end
def tz
# TODO: Support time profiles via options[:ext_options][:time_profile]
@tz ||= Metric::Helper.get_time_zone(ext_options)
end
def report_time_range
raise _("Option 'interval_size' is required") if interval_size.nil?
start_interval_offset = (end_interval_offset + interval_size - 1)
ts = Time.now.in_time_zone(tz)
case interval
when 'daily'
start_time = (ts - start_interval_offset.days).beginning_of_day
end_time = (ts - end_interval_offset.days).end_of_day
when 'weekly'
start_time = (ts - start_interval_offset.weeks).beginning_of_week
end_time = (ts - end_interval_offset.weeks).end_of_week
when 'monthly'
start_time = (ts - start_interval_offset.months).beginning_of_month
end_time = (ts - end_interval_offset.months).end_of_month
else
raise _("interval '%{interval}' is not supported") % {:interval => interval}
end
start_time..end_time
end
def start_of_report_step(timestamp)
ts = timestamp.in_time_zone(tz)
case interval
when 'daily'
ts.beginning_of_day
when 'weekly'
ts.beginning_of_week
when 'monthly'
ts.beginning_of_month
else
raise _("interval '%{interval}' is not supported") % {:interval => interval}
end
end
def report_step_range(timestamp)
ts = timestamp.in_time_zone(tz)
case interval
when 'daily'
[ts.beginning_of_day, ts.end_of_day, ts.strftime('%m/%d/%Y')]
when 'weekly'
s_ts = ts.beginning_of_week
e_ts = ts.end_of_week
[s_ts, e_ts, "Week of #{s_ts.strftime('%m/%d/%Y')}"]
when 'monthly'
s_ts = ts.beginning_of_month
e_ts = ts.end_of_month
[s_ts, e_ts, s_ts.strftime('%b %Y')]
else
raise _("interval '%{interval}' is not supported") % {:interval => interval}
end
end
def duration_of_report_step
case interval
when 'daily' then 1.day
when 'weekly' then 1.week
when 'monthly' then 1.month
end
end
def tenant_for(consumption)
consumption.resource.tenant
end
def classification_for(consumption)
tags = consumption.tag_names.select do |x|
Array(groupby_tag).detect { |group_by_tag| x.starts_with?(group_by_tag) }
end.compact
tags.map { |x| tag_hash[x.split("/").second] } if tags.present?
end
def group_by_tenant?
self[:groupby] == 'tenant'
end
def group_by_date_first?
self[:groupby] == 'date-first'
end
def group_by_date_only?
self[:groupby] == 'date-only'
end
private
def tag_hash
categories = Array(groupby_tag)
if categories
@tag_hash ||= categories.each_with_object({}) do |category, return_value|
tags = Classification.hash_all_by_type_and_name[category][:entry]
tags.each do |key, value|
return_value[key] = value
end
end
end
end
end
end