Commit 0e7c29d5 authored by Mikołaj Wawrzyniak's avatar Mikołaj Wawrzyniak

Merge branch '339447-container-scanning-jobs-instrumentation-class' into 'master'

Add CiBuildDistinctCountMetric instrumentation class

See merge request gitlab-org/gitlab!75606
parents 3dc62724 c0437cc5
......@@ -9,6 +9,9 @@ product_category: container_scanning
value_type: number
status: active
time_frame: 28d
instrumentation_class: CiBuildDistinctCountMetric
options:
secure_type: container_scanning
data_source: database
distribution:
- ee
......
......@@ -9,6 +9,9 @@ product_category: container_scanning
value_type: number
status: active
time_frame: all
instrumentation_class: CiBuildDistinctCountMetric
options:
secure_type: container_scanning
data_source: database
distribution:
- ee
......
......@@ -19,7 +19,8 @@ module EE
SECURE_PRODUCT_TYPES = {
container_scanning: {
name: :container_scanning_jobs
name: :container_scanning_jobs,
instrumentation_class_migrated: true
},
dast: {
name: :dast_jobs
......@@ -373,11 +374,18 @@ module EE
user_preferences_group_overview_security_dashboard: count(::User.active.group_view_security_dashboard.where(time_period))
}
time_frame = metric_time_period(time_period)
SECURE_PRODUCT_TYPES.each do |secure_type, attribs|
results["#{prefix}#{attribs[:name]}".to_sym] = distinct_count(::Ci::Build.where(name: secure_type).where(time_period),
:user_id,
start: minimum_id(::User),
finish: maximum_id(::User))
results["#{prefix}#{attribs[:name]}".to_sym] =
if attribs[:instrumentation_class_migrated]
add_metric('CiBuildDistinctCountMetric', time_frame: time_frame, options: { secure_type: secure_type })
else
distinct_count(::Ci::Build.where(name: secure_type).where(time_period),
:user_id,
start: minimum_id(::User),
finish: maximum_id(::User))
end
end
results.merge!(count_secure_user_scans)
......
# frozen_string_literal: true
module Gitlab
module Usage
module Metrics
module Instrumentations
class CiBuildDistinctCountMetric < DatabaseMetric
operation :distinct_count, column: :user_id
cache_start_and_finish_as :ci_build_distinct_count_user
relation { ::Ci::Build }
start { ::User.minimum(:id) }
finish { ::User.maximum(:id) }
def initialize(time_frame:, options: {})
super
raise ArgumentError, "secure_type options attribute is required" unless secure_type.present?
raise ArgumentError, "Attribute: #{secure_type} it not allowed" unless ::EE::Gitlab::UsageData::SECURE_PRODUCT_TYPES.key?(secure_type.to_sym)
end
private
def relation
super.where(name: secure_type) # rubocop: disable CodeReuse/ActiveRecord
end
def secure_type
options[:secure_type]
end
end
end
end
end
end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Gitlab::Usage::Metrics::Instrumentations::CiBuildDistinctCountMetric do
before_all do
user = create(:user)
create(:ci_build, name: 'dast')
create(:ci_build, name: 'container_scanning', user: user)
create(:ci_build, name: 'container_scanning', user: user)
end
it_behaves_like 'a correct instrumented metric value', { time_frame: 'all', data_source: 'database', options: { secure_type: 'container_scanning' } } do
let(:expected_value) { 1 }
end
it 'raises an exception if secure_type option is not present' do
expect { described_class.new }.to raise_error(ArgumentError)
end
it 'raises an exception if secure_type option is invalid' do
expect { described_class.new(option: { secure_type: 'invalid_type' }) }.to raise_error(ArgumentError)
end
context 'with cache_start_and_finish_as called' do
before do
allow_next_instance_of(Gitlab::Database::BatchCounter) do |batch_counter|
allow(batch_counter).to receive(:transaction_open?).and_return(false)
end
end
it 'caches using the key name passed', :request_store, :use_clean_rails_redis_caching do
expect(Gitlab::Cache).to receive(:fetch_once).with('metric_instrumentation/ci_build_distinct_count_user_minimum_id', any_args).and_call_original
expect(Gitlab::Cache).to receive(:fetch_once).with('metric_instrumentation/ci_build_distinct_count_user_maximum_id', any_args).and_call_original
described_class.new(time_frame: 'all', options: { secure_type: 'container_scanning' }).value
expect(Rails.cache.read('metric_instrumentation/ci_build_distinct_count_user_minimum_id')).to eq(::User.minimum(:id))
expect(Rails.cache.read('metric_instrumentation/ci_build_distinct_count_user_maximum_id')).to eq(::User.maximum(:id))
end
end
end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment