diff --git a/app/services/billable_metrics/aggregations/count_service.rb b/app/services/billable_metrics/aggregations/count_service.rb index 40aa7942ab8..b186702be1c 100644 --- a/app/services/billable_metrics/aggregations/count_service.rb +++ b/app/services/billable_metrics/aggregations/count_service.rb @@ -3,7 +3,7 @@ module BillableMetrics module Aggregations class CountService < BillableMetrics::Aggregations::BaseService - def aggregate(options: {}) + def compute_aggregation(options: {}) result.aggregation = event_store.count result.current_usage_units = result.aggregation result.count = result.aggregation @@ -12,6 +12,29 @@ def aggregate(options: {}) result end + # NOTE: Apply the grouped_by filter to the aggregation + # Result will have an aggregations attribute + # containing the aggregation result of each group. + # + # This logic is only applicable for in arrears aggregation + # (exept for the current_usage update) + # as pay in advance aggregation will be computed on a single group + # with the grouped_by_values filter + def compute_grouped_by_aggregation(*) + aggregations = event_store.grouped_count + + result.aggregations = aggregations.map do |aggregation| + group_result = BaseService::Result.new + group_result.grouped_by = aggregation[:groups] + group_result.aggregation = aggregation[:value] + group_result.count = aggregation[:value] + group_result.current_usage_units = aggregation[:value] + group_result + end + + result + end + # NOTE: Return cumulative sum of event count based on the number of free units # (per_events or per_total_aggregation). def running_total(options) @@ -26,6 +49,12 @@ def running_total(options) def compute_per_event_aggregation (0...event_store.count).map { |_| 1 } end + + protected + + def support_grouped_aggregation? + true + end end end end diff --git a/spec/services/billable_metrics/aggregations/count_service_spec.rb b/spec/services/billable_metrics/aggregations/count_service_spec.rb index 56d13595d3f..92f2e8f31f9 100644 --- a/spec/services/billable_metrics/aggregations/count_service_spec.rb +++ b/spec/services/billable_metrics/aggregations/count_service_spec.rb @@ -12,19 +12,18 @@ from_datetime:, to_datetime:, }, - filters: { - group:, - event: pay_in_advance_event, - }, + filters:, ) end let(:event_store_class) { Events::Stores::PostgresStore } + let(:filters) { { group:, event: pay_in_advance_event, grouped_by: } } let(:subscription) { create(:subscription) } let(:organization) { subscription.organization } let(:customer) { subscription.customer } let(:group) { nil } + let(:grouped_by) { nil } let(:billable_metric) do create( @@ -46,7 +45,7 @@ let(:pay_in_advance_event) { nil } - before do + let(:event_list) do create_list( :event, 4, @@ -57,6 +56,10 @@ ) end + before do + event_list + end + it 'aggregates the events' do result = count_service.aggregate @@ -88,45 +91,47 @@ ) end - before do - create( - :event, - code: billable_metric.code, - customer:, - subscription:, - timestamp: Time.zone.now - 1.day, - properties: { - total_count: 12, - cloud: 'AWS', - region: 'europe', - }, - ) - - create( - :event, - code: billable_metric.code, - customer:, - subscription:, - timestamp: Time.zone.now - 1.day, - properties: { - total_count: 8, - cloud: 'AWS', - region: 'europe', - }, - ) - - create( - :event, - code: billable_metric.code, - customer:, - subscription:, - timestamp: Time.zone.now - 1.day, - properties: { - total_count: 12, - cloud: 'AWS', - region: 'africa', - }, - ) + let(:event_list) do + [ + create( + :event, + code: billable_metric.code, + customer:, + subscription:, + timestamp: Time.zone.now - 1.day, + properties: { + total_count: 12, + cloud: 'AWS', + region: 'europe', + }, + ), + + create( + :event, + code: billable_metric.code, + customer:, + subscription:, + timestamp: Time.zone.now - 1.day, + properties: { + total_count: 8, + cloud: 'AWS', + region: 'europe', + }, + ), + + create( + :event, + code: billable_metric.code, + customer:, + subscription:, + timestamp: Time.zone.now - 1.day, + properties: { + total_count: 12, + cloud: 'AWS', + region: 'africa', + }, + ), + ] end it 'aggregates the events' do @@ -153,4 +158,47 @@ expect(result.event_aggregation).to eq([1, 1, 1, 1]) end end + + describe '.grouped_by_aggregation' do + let(:grouped_by) { ['agent_name'] } + let(:agent_names) { %w[aragorn frodo gimli legolas] } + + let(:event_list) do + agent_names.map do |agent_name| + create( + :event, + code: billable_metric.code, + customer:, + subscription:, + timestamp: Time.zone.now - 1.day, + properties: { + agent_name:, + }, + ) + end + [ + create( + :event, + code: billable_metric.code, + customer:, + subscription:, + timestamp: Time.zone.now - 1.day, + properties: {}, + ), + ] + end + + it 'returns a grouped aggregations' do + result = count_service.aggregate + + expect(result.aggregations.count).to eq(5) + + result.aggregations.sort_by { |a| a.grouped_by['agent_name'] || '' }.each_with_index do |aggregation, index| + expect(aggregation.aggregation).to eq(1) + expect(aggregation.count).to eq(1) + expect(aggregation.current_usage_units).to eq(1) + + expect(aggregation.grouped_by['agent_name']).to eq(agent_names[index - 1]) if index.positive? + end + end + end end