diff --git a/app/models/chargeback/consumption_with_rollups.rb b/app/models/chargeback/consumption_with_rollups.rb index b826bd3b04fa..453133edce4d 100644 --- a/app/models/chargeback/consumption_with_rollups.rb +++ b/app/models/chargeback/consumption_with_rollups.rb @@ -54,7 +54,7 @@ def chargeback_container_labels def container_tag_list_with_prefix if resource.kind_of?(ContainerImage) - state = resource.vim_performance_state_for_ts(timestamp.to_s) + state = resource.vim_performance_state_for_ts(timestamp) image_tag_name = "#{state.image_tag_names}|" if state image_tag_name.split("|") diff --git a/app/models/metric/ci_mixin/capture.rb b/app/models/metric/ci_mixin/capture.rb index e225bb532bf1..aab039f249de 100644 --- a/app/models/metric/ci_mixin/capture.rb +++ b/app/models/metric/ci_mixin/capture.rb @@ -89,6 +89,10 @@ def calculate_gap(interval_name, start_time) end end + # @param interval_name ["realtime", "hourly", "historical"] + # @param start_time [String|nil] start time for historical capture (nil for all other captures) + # @param end_time [String|nil] end time for historical capture (nil for all other captures) + # @param metrics_capture [MetricCapture] def just_perf_capture(interval_name, start_time, end_time, metrics_capture) log_header = "[#{interval_name}]" log_time = '' diff --git a/app/models/metric/ci_mixin/state_finders.rb b/app/models/metric/ci_mixin/state_finders.rb index 7fa2c2cb0131..7308fef8f084 100644 --- a/app/models/metric/ci_mixin/state_finders.rb +++ b/app/models/metric/ci_mixin/state_finders.rb @@ -1,19 +1,30 @@ module Metric::CiMixin::StateFinders + # load from cache or create a VimPerformanceState for a given timestamp + # + # for a cache: + # use preload to populate vim_performance_states associations + # this loads all records + # the cache is indexed by a Time object + # used by Metric.rollup / rollup_hourly + # preload_vim_performance_state_for_ts_iso8601 to populate @states_by_ts + # contains a subset, typically now and the timestamp of interest + # the cache is indexed by a String in iso8601 form + # used by: CiMixin::Processing#perf_process + # @param ts [Time|String] prefer Time def vim_performance_state_for_ts(ts) + ts = Time.parse(ts).utc if ts.kind_of?(String) + ts_iso = ts.utc.iso8601 return nil unless self.respond_to?(:vim_performance_states) @states_by_ts ||= {} - state = @states_by_ts[ts] + state = @states_by_ts[ts_iso] if state.nil? - # TODO: vim_performance_states.loaded? works only when doing resource.vim_performance_states.all, not when loading - # a subset based on available timestamps + # using preloaded vim_performance_states association if vim_performance_states.loaded? # Look for requested time in cache - t = ts.to_time(:utc) - state = vim_performance_states.detect { |s| s.timestamp == t } + state = vim_performance_states.detect { |s| s.timestamp == ts } if state.nil? - # Look for state for current hour in cache if still nil because the - # capture will return a state for the current hour only. + # Look for state for current hour in cache t = Metric::Helper.nearest_hourly_timestamp(Time.now.utc).to_time(:utc) state = vim_performance_states.detect { |s| s.timestamp == t } end diff --git a/app/models/metric/rollup.rb b/app/models/metric/rollup.rb index aa433fe0da47..68a636795a7c 100644 --- a/app/models/metric/rollup.rb +++ b/app/models/metric/rollup.rb @@ -266,8 +266,13 @@ def self.rollup_realtime_perfs(obj, rt_perfs, new_perf = {}) new_perf end + # @param obj parent object + # @param timestamp [Time] + # @param interval_name ["realtime", "hourly", "historical"] + # @param assoc [Symbol] name of the association to rollup def self.rollup_child_metrics(obj, timestamp, interval_name, assoc) - ts = timestamp.kind_of?(Time) ? timestamp.utc.iso8601 : timestamp + timestamp = Time.parse(timestamp).utc if timestamp.kind_of?(String) + ts_iso = timestamp.utc.iso8601 recs = obj.vim_performance_state_association(timestamp, assoc).to_a result = {} @@ -280,7 +285,7 @@ def self.rollup_child_metrics(obj, timestamp, interval_name, assoc) result[c] = 0 end - perf_recs = Metric::Finders.hash_by_capture_interval_name_and_timestamp(recs, ts, ts, interval_name) + perf_recs = Metric::Finders.hash_by_capture_interval_name_and_timestamp(recs, ts_iso, ts_iso, interval_name) # Preload states for perf timestamp and the current hour. # in a single query bring back all relevant performance states @@ -290,7 +295,7 @@ def self.rollup_child_metrics(obj, timestamp, interval_name, assoc) # For infra, if that record is not found, use the current performance_state (can't capture in the past) if recs.present? rec_states = VimPerformanceState.where( - :timestamp => [ts, Metric::Helper.nearest_hourly_timestamp(Time.now.utc)], + :timestamp => [timestamp, Metric::Helper.nearest_hourly_timestamp(Time.now.utc)], :resource_type => recs.first.class.base_class.name, :resource_id => recs.map(&:id) ) @@ -298,7 +303,7 @@ def self.rollup_child_metrics(obj, timestamp, interval_name, assoc) end recs.each do |rec| - perf = perf_recs.fetch_path(rec.class.base_class.name, rec.id, interval_name, ts) + perf = perf_recs.fetch_path(rec.class.base_class.name, rec.id, interval_name, ts_iso) next unless perf state = rec.vim_performance_state_for_ts(timestamp) agg_cols.each do |c| diff --git a/app/models/vim_performance_state.rb b/app/models/vim_performance_state.rb index 2801953f4b1d..3ec1956457da 100644 --- a/app/models/vim_performance_state.rb +++ b/app/models/vim_performance_state.rb @@ -46,6 +46,8 @@ class VimPerformanceState < ApplicationRecord # => host_sockets (derive from assoc_ids) # TODO: do a single query for the finds + # @param objs [Array[Object]|Object] MetricsCapture#target - all should be the same object class + # @returns [Array[VimPerformanceState]|VimPerformanceState] return an array if an array was passed in # NOTE: a few calls (with a single object) do use the return and expect a single result def self.capture(objs) ts = Time.now.utc diff --git a/spec/models/vim_performance_state_spec.rb b/spec/models/vim_performance_state_spec.rb index 077b4356728b..fac9bde58642 100644 --- a/spec/models/vim_performance_state_spec.rb +++ b/spec/models/vim_performance_state_spec.rb @@ -1,4 +1,14 @@ RSpec.describe VimPerformanceState do + describe ".capture" do + it "uses now for Infra" do + host = FactoryBot.create(:host) + state = VimPerformanceState.capture(host) + + expect(state.timestamp).to be_within(1.minute).of(Time.now.utc.beginning_of_hour) + expect(state.capture_interval).to eq(3600) # 1.hour + end + end + describe ".capture_host_sockets" do it "returns the host sockets when given a host" do hardware = FactoryBot.build(:hardware, :cpu_sockets => 2)