Commit fc5c4c4e authored by Mikołaj Wawrzyniak's avatar Mikołaj Wawrzyniak

Merge branch '338029-merge-instrumentation-classes-data-to-service-ping-data' into 'master'

Merge instrumentation classes data to service ping data

See merge request gitlab-org/gitlab!68808
parents 10d7ca38 2d4a09ef
---
name: usage_data_instrumentation
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/68808
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/338029
milestone: '14.5'
type: development
group: group::product intelligence
default_enabled: false
......@@ -86,11 +86,38 @@ RSpec.describe 'Every metric definition' do
stub_usage_data_connections
end
context 'with usage_data_instrumentation feature flag' do
let(:msg) { 'see https://docs.gitlab.com/ee/development/service_ping/metrics_dictionary.html#metrics-added-dynamic-to-service-ping-payload' }
context 'when enabled' do
let(:instrumentation_class_keys) do
Gitlab::Usage::MetricDefinition.with_instrumentation_class.map(&:key)
.reject { |v| v =~ Regexp.union(ignored_usage_ping_key_patterns) }
end
let(:files_key_paths) do
(metric_files_key_paths + instrumentation_class_keys).to_set
end
before do
stub_feature_flags(usage_data_instrumentation: true)
end
it 'is included in the Usage Ping hash structure', :aggregate_failures do
expect(files_key_paths).to eql(usage_ping_key_paths.to_set), msg
end
end
context 'when disabled' do
before do
stub_feature_flags(usage_data_instrumentation: false)
end
it 'is included in the Usage Ping hash structure', :aggregate_failures do
msg = "see https://docs.gitlab.com/ee/development/service_ping/metrics_dictionary.html#metrics-added-dynamic-to-service-ping-payload"
expect(metric_files_key_paths).to match_array(usage_ping_key_paths)
expect(metric_files_key_paths).to match_array(usage_ping_key_paths), msg
end
end
end
context 'with value json schema' do
it 'has a valid structure', :aggregate_failures do
......
......@@ -10,7 +10,7 @@ RSpec.describe Gitlab::UsageDataNonSqlMetrics do
end
describe '.uncached_data' do
it 'does not make DB calls' do
it 'does make instrumentations_class DB calls' do
recorder = ActiveRecord::QueryRecorder.new do
described_class.uncached_data
end
......
......@@ -62,7 +62,7 @@ RSpec.describe Gitlab::UsageData do
subject { described_class.data }
it 'gathers usage data' do
expect(subject.keys).to include(*%i(
expect(subject.keys).to include(*%w(
historical_max_users
license_add_ons
license_plan
......@@ -85,7 +85,7 @@ RSpec.describe Gitlab::UsageData do
expect(count_data[:boards]).to eq(1)
expect(count_data[:projects]).to eq(3)
expect(count_data.keys).to include(*%i(
expect(count_data.keys).to include(*%w(
confidential_epics
container_scanning_jobs
coverage_fuzzing_jobs
......@@ -200,10 +200,7 @@ RSpec.describe Gitlab::UsageData do
it 'gathers license data' do
license = ::License.current
expect(subject[:license_md5]).to eq(Digest::MD5.hexdigest(license.data))
expect(subject[:license_id]).to eq(license.license_id)
expect(subject[:historical_max_users]).to eq(license.historical_max)
expect(subject[:licensee]).to eq(license.licensee)
expect(subject[:license_user_count]).to eq(license.restricted_user_count)
expect(subject[:license_starts_at]).to eq(license.starts_at)
expect(subject[:license_expires_at]).to eq(license.expires_at)
......@@ -212,6 +209,39 @@ RSpec.describe Gitlab::UsageData do
expect(subject[:license_subscription_id]).to eq(license.subscription_id)
expect(subject[:license_billable_users]).to eq(license.daily_billable_users_count)
end
context 'with usage_data_instrumentation feature flag' do
let(:license) { ::License.current }
context 'when enabled' do
before do
stub_feature_flags(usage_data_instrumentation: true)
end
it 'returns fallback value to be overriden' do
expect(subject[:licensee]).to eq(Gitlab::Utils::UsageData::INSTRUMENTATION_CLASS_FALLBACK)
expect(subject[:license_md5]).to eq(Gitlab::Utils::UsageData::INSTRUMENTATION_CLASS_FALLBACK)
expect(subject[:historical_max_users]).to eq(Gitlab::Utils::UsageData::INSTRUMENTATION_CLASS_FALLBACK)
uncached_data = described_class.uncached_data
expect(uncached_data[:licensee]).to eq(license.licensee)
expect(uncached_data[:license_md5]).to eq(Digest::MD5.hexdigest(license.data))
expect(uncached_data[:historical_max_users]).to eq(license.historical_max)
end
end
context 'when disabled' do
before do
stub_feature_flags(usage_data_instrumentation: false)
end
it 'computes historical_max_users, licensee and license_md5 values' do
expect(subject[:licensee]).to eq(license.licensee)
expect(subject[:license_md5]).to eq(Digest::MD5.hexdigest(license.data))
expect(subject[:historical_max_users]).to eq(license.historical_max)
end
end
end
end
describe '.requirements_counts' do
......@@ -541,7 +571,7 @@ RSpec.describe Gitlab::UsageData do
end
describe 'usage_activity_by_stage_release' do
it 'includes accurate usage_activity_by_stage data' do
before do
stub_licensed_features(group_milestone_project_releases: true)
group_milestone = create(:milestone, :on_group)
project = create(:project, group: group_milestone.group)
......@@ -551,15 +581,41 @@ RSpec.describe Gitlab::UsageData do
create(:release, created_at: 3.days.ago, project: project, milestones: [group_milestone])
end
end
expect(described_class.usage_activity_by_stage_release({})).to include(
projects_mirrored_with_pipelines_enabled: 2,
releases_with_group_milestones: 2
)
expect(described_class.usage_activity_by_stage_release(described_class.monthly_time_range_db_params)).to include(
projects_mirrored_with_pipelines_enabled: 1,
releases_with_group_milestones: 1
)
it 'includes accurate usage_activity_by_stage data' do
expect(described_class.usage_activity_by_stage_release({})).to include(projects_mirrored_with_pipelines_enabled: 2)
expect(described_class.usage_activity_by_stage_release(described_class.monthly_time_range_db_params)).to include(projects_mirrored_with_pipelines_enabled: 1)
end
context 'with usage_data_instrumentation feature flag' do
let(:license) { ::License.current }
context 'when enabled' do
before do
stub_feature_flags(usage_data_instrumentation: true)
end
it 'returns fallback value to be overriden' do
expect(described_class.usage_activity_by_stage_release({})).to include(releases_with_group_milestones: Gitlab::Utils::UsageData::INSTRUMENTATION_CLASS_FALLBACK)
expect(described_class.usage_activity_by_stage_release(described_class.monthly_time_range_db_params)).to include(releases_with_group_milestones: Gitlab::Utils::UsageData::INSTRUMENTATION_CLASS_FALLBACK)
uncached_data = described_class.uncached_data
expect(uncached_data[:usage_activity_by_stage][:release]).to include(releases_with_milestones: 2)
expect(uncached_data[:usage_activity_by_stage_monthly][:release]).to include(releases_with_milestones: 1)
end
end
context 'when disabled' do
before do
stub_feature_flags(usage_data_instrumentation: false)
end
it 'computes releases_with_group_milestones values' do
expect(described_class.usage_activity_by_stage_release({})).to include(releases_with_group_milestones: 2)
expect(described_class.usage_activity_by_stage_release(described_class.monthly_time_range_db_params)).to include(releases_with_group_milestones: 1)
end
end
end
end
......
......@@ -25,6 +25,10 @@ module Gitlab
unflatten_key_path(intrumentation_object.instrumentation)
end
def with_suggested_name
unflatten_key_path(intrumentation_object.suggested_name)
end
private
def unflatten_key_path(value)
......
......@@ -18,6 +18,10 @@ module Gitlab
private
def instrumentation_metrics
::Gitlab::UsageDataMetrics.suggested_names
end
def count(relation, column = nil, batch: true, batch_size: nil, start: nil, finish: nil)
Gitlab::Usage::Metrics::NameSuggestion.for(:count, column: column, relation: relation)
end
......
......@@ -45,23 +45,10 @@ module Gitlab
clear_memoized
with_finished_at(:recording_ce_finished_at) do
license_usage_data
.merge(system_usage_data_license)
.merge(system_usage_data_settings)
.merge(system_usage_data)
.merge(system_usage_data_monthly)
.merge(system_usage_data_weekly)
.merge(features_usage_data)
.merge(components_usage_data)
.merge(object_store_usage_data)
.merge(topology_usage_data)
.merge(usage_activity_by_stage)
.merge(usage_activity_by_stage(:usage_activity_by_stage_monthly, monthly_time_range_db_params))
.merge(analytics_unique_visits_data)
.merge(compliance_unique_visits_data)
.merge(search_unique_visits_data)
.merge(redis_hll_counters)
.deep_merge(aggregated_metrics_data)
usage_data = usage_data_metrics
usage_data = usage_data.with_indifferent_access.deep_merge(instrumentation_metrics.with_indifferent_access) if Feature.enabled?(:usage_data_instrumentation)
usage_data
end
end
......@@ -729,6 +716,30 @@ module Gitlab
private
def usage_data_metrics
license_usage_data
.merge(system_usage_data_license)
.merge(system_usage_data_settings)
.merge(system_usage_data)
.merge(system_usage_data_monthly)
.merge(system_usage_data_weekly)
.merge(features_usage_data)
.merge(components_usage_data)
.merge(object_store_usage_data)
.merge(topology_usage_data)
.merge(usage_activity_by_stage)
.merge(usage_activity_by_stage(:usage_activity_by_stage_monthly, monthly_time_range_db_params))
.merge(analytics_unique_visits_data)
.merge(compliance_unique_visits_data)
.merge(search_unique_visits_data)
.merge(redis_hll_counters)
.deep_merge(aggregated_metrics_data)
end
def instrumentation_metrics
Gitlab::UsageDataMetrics.uncached_data # rubocop:disable UsageData/LargeTable
end
def metric_time_period(time_period)
time_period.present? ? '28d' : 'none'
end
......
......@@ -5,7 +5,17 @@ module Gitlab
class << self
# Build the Usage Ping JSON payload from metrics YAML definitions which have instrumentation class set
def uncached_data
::Gitlab::Usage::Metric.all.map(&:with_value).reduce({}, :deep_merge)
build_payload(:with_value)
end
def suggested_names
build_payload(:with_suggested_name)
end
private
def build_payload(method_symbol)
::Gitlab::Usage::Metric.all.map(&method_symbol).reduce({}, :deep_merge)
end
end
end
......
......@@ -6,7 +6,10 @@ module Gitlab
class << self
def uncached_data
super.with_indifferent_access.deep_merge(instrumentation_metrics_queries.with_indifferent_access)
# instrumentation_metrics is already included with feature flag enabled
return super if Feature.enabled?(:usage_data_instrumentation)
super.with_indifferent_access.deep_merge(instrumentation_metrics.with_indifferent_access)
end
def add_metric(metric, time_frame: 'none')
......@@ -50,7 +53,7 @@ module Gitlab
private
def instrumentation_metrics_queries
def instrumentation_metrics
::Gitlab::Usage::Metric.all.map(&:with_instrumentation).reduce({}, :deep_merge)
end
end
......
......@@ -6,7 +6,10 @@ module Gitlab
class UsageDataQueries < UsageData
class << self
def uncached_data
super.with_indifferent_access.deep_merge(instrumentation_metrics_queries.with_indifferent_access)
# instrumentation_metrics is already included with feature flag enabled
return super if Feature.enabled?(:usage_data_instrumentation)
super.with_indifferent_access.deep_merge(instrumentation_metrics.with_indifferent_access)
end
def add_metric(metric, time_frame: 'none')
......@@ -71,7 +74,7 @@ module Gitlab
private
def instrumentation_metrics_queries
def instrumentation_metrics
::Gitlab::Usage::Metric.all.map(&:with_instrumentation).reduce({}, :deep_merge)
end
end
......
......@@ -43,8 +43,13 @@ module Gitlab
HISTOGRAM_FALLBACK = { '-1' => -1 }.freeze
DISTRIBUTED_HLL_FALLBACK = -2
MAX_BUCKET_SIZE = 100
INSTRUMENTATION_CLASS_FALLBACK = -100
def add_metric(metric, time_frame: 'none')
# Results of this method should be overwritten by instrumentation class values
# -100 indicates the metric was not properly merged.
return INSTRUMENTATION_CLASS_FALLBACK if Feature.enabled?(:usage_data_instrumentation)
metric_class = "Gitlab::Usage::Metrics::Instrumentations::#{metric}".constantize
metric_class.new(time_frame: time_frame).value
......
......@@ -45,4 +45,10 @@ RSpec.describe Gitlab::Usage::Metric do
expect(described_class.new(issue_count_metric_definiton).with_instrumentation).to eq({ counts: { issues: "SELECT COUNT(\"issues\".\"id\") FROM \"issues\"" } })
end
end
describe '#with_suggested_name' do
it 'returns key_path metric with the corresponding generated query' do
expect(described_class.new(issue_count_metric_definiton).with_suggested_name).to eq({ counts: { issues: 'count_issues' } })
end
end
end
......@@ -25,12 +25,32 @@ RSpec.describe Gitlab::Usage::Metrics::NamesSuggestions::Generator do
end
context 'for count with default column metrics' do
context 'with usage_data_instrumentation feature flag' do
context 'when enabled' do
before do
stub_feature_flags(usage_data_instrumentation: true)
end
it_behaves_like 'name suggestion' do
# corresponding metric is collected with ::Gitlab::UsageDataMetrics.suggested_names
let(:key_path) { 'counts.boards' }
let(:name_suggestion) { /count_boards/ }
end
end
context 'when disabled' do
before do
stub_feature_flags(usage_data_instrumentation: false)
end
it_behaves_like 'name suggestion' do
# corresponding metric is collected with count(Board)
let(:key_path) { 'counts.boards' }
let(:name_suggestion) { /count_boards/ }
end
end
end
end
context 'for count distinct with column defined metrics' do
it_behaves_like 'name suggestion' do
......
......@@ -76,4 +76,16 @@ RSpec.describe Gitlab::UsageDataMetrics do
end
end
end
describe '.suggested_names' do
subject { described_class.suggested_names }
let(:suggested_names) do
::Gitlab::Usage::Metric.all.map(&:with_suggested_name).reduce({}, :deep_merge)
end
it 'includes Service Ping suggested names' do
expect(subject).to match_array(suggested_names)
end
end
end
......@@ -80,6 +80,12 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
end
end
end
it 'allows indifferent access' do
allow(::Gitlab::UsageDataCounters::HLLRedisCounter).to receive(:unique_events).and_return(1)
expect(subject[:search_unique_visits][:search_unique_visits_for_any_target_monthly]).to eq(1)
expect(subject[:search_unique_visits]['search_unique_visits_for_any_target_monthly']).to eq(1)
end
end
describe 'usage_activity_by_stage_package' do
......@@ -428,7 +434,6 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
end
expect(described_class.usage_activity_by_stage_plan({})).to include(
issues: 3,
notes: 2,
projects: 2,
todos: 2,
......@@ -439,7 +444,6 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
projects_jira_dvcs_server_active: 2
)
expect(described_class.usage_activity_by_stage_plan(described_class.monthly_time_range_db_params)).to include(
issues: 2,
notes: 1,
projects: 1,
todos: 1,
......@@ -450,6 +454,44 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
projects_jira_dvcs_server_active: 1
)
end
context 'with usage_data_instrumentation feature flag' do
context 'when enabled' do
it 'merges the data from instrumentation classes' do
stub_feature_flags(usage_data_instrumentation: true)
for_defined_days_back do
user = create(:user)
project = create(:project, creator: user)
create(:issue, project: project, author: user)
create(:issue, project: project, author: User.support_bot)
end
expect(described_class.usage_activity_by_stage_plan({})).to include(issues: Gitlab::Utils::UsageData::INSTRUMENTATION_CLASS_FALLBACK)
expect(described_class.usage_activity_by_stage_plan(described_class.monthly_time_range_db_params)).to include(issues: Gitlab::Utils::UsageData::INSTRUMENTATION_CLASS_FALLBACK)
uncached_data = described_class.uncached_data
expect(uncached_data[:usage_activity_by_stage][:plan]).to include(issues: 3)
expect(uncached_data[:usage_activity_by_stage_monthly][:plan]).to include(issues: 2)
end
end
context 'when disabled' do
it 'does not merge the data from instrumentation classes' do
stub_feature_flags(usage_data_instrumentation: false)
for_defined_days_back do
user = create(:user)
project = create(:project, creator: user)
create(:issue, project: project, author: user)
create(:issue, project: project, author: User.support_bot)
end
expect(described_class.usage_activity_by_stage_plan({})).to include(issues: 3)
expect(described_class.usage_activity_by_stage_plan(described_class.monthly_time_range_db_params)).to include(issues: 2)
end
end
end
end
describe 'usage_activity_by_stage_release' do
......@@ -466,17 +508,53 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
deployments: 2,
failed_deployments: 2,
releases: 2,
successful_deployments: 2,
releases_with_milestones: 2
successful_deployments: 2
)
expect(described_class.usage_activity_by_stage_release(described_class.monthly_time_range_db_params)).to include(
deployments: 1,
failed_deployments: 1,
releases: 1,
successful_deployments: 1,
releases_with_milestones: 1
successful_deployments: 1
)
end
context 'with usage_data_instrumentation feature flag' do
before do
for_defined_days_back do
user = create(:user)
create(:deployment, :failed, user: user)
release = create(:release, author: user)
create(:milestone, project: release.project, releases: [release])
create(:deployment, :success, user: user)
end
end
context 'when enabled' do
before do
stub_feature_flags(usage_data_instrumentation: true)
end
it 'merges data from instrumentation classes' do
expect(described_class.usage_activity_by_stage_release({})).to include(releases_with_milestones: Gitlab::Utils::UsageData::INSTRUMENTATION_CLASS_FALLBACK)
expect(described_class.usage_activity_by_stage_release(described_class.monthly_time_range_db_params)).to include(releases_with_milestones: Gitlab::Utils::UsageData::INSTRUMENTATION_CLASS_FALLBACK)
uncached_data = described_class.uncached_data
expect(uncached_data[:usage_activity_by_stage][:release]).to include(releases_with_milestones: 2)
expect(uncached_data[:usage_activity_by_stage_monthly][:release]).to include(releases_with_milestones: 1)
end
end
context 'when disabled' do
before do
stub_feature_flags(usage_data_instrumentation: false)
end
it 'does not merge data from instrumentation classes' do
expect(described_class.usage_activity_by_stage_release({})).to include(releases_with_milestones: 2)
expect(described_class.usage_activity_by_stage_release(described_class.monthly_time_range_db_params)).to include(releases_with_milestones: 1)
end
end
end
end
describe 'usage_activity_by_stage_verify' do
......@@ -525,16 +603,16 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
subject { described_class.data }
it 'gathers usage data' do
expect(subject.keys).to include(*UsageDataHelpers::USAGE_DATA_KEYS)
expect(subject.keys).to include(*UsageDataHelpers::USAGE_DATA_KEYS.map(&:to_s))
end
it 'gathers usage counts', :aggregate_failures do
count_data = subject[:counts]
expect(count_data[:boards]).to eq(1)
expect(count_data[:projects]).to eq(4)
expect(count_data.keys).to include(*UsageDataHelpers::COUNTS_KEYS)
expect(UsageDataHelpers::COUNTS_KEYS - count_data.keys).to be_empty
count_keys = UsageDataHelpers::COUNTS_KEYS.map(&:to_s)
expect(count_data.keys).to include(*count_keys)
expect(count_keys - count_data.keys).to be_empty
expect(count_data.values).to all(be_a_kind_of(Integer))
end
......@@ -619,7 +697,7 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
external_diffs: { enabled: false },
lfs: { enabled: true, object_store: { enabled: false, direct_upload: true, background_upload: false, provider: "AWS" } },
uploads: { enabled: nil, object_store: { enabled: false, direct_upload: true, background_upload: false, provider: "AWS" } },
packages: { enabled: true, object_store: { enabled: false, direct_upload: false, background_upload: true, provider: "AWS" } } }
packages: { enabled: true, object_store: { enabled: false, direct_upload: false, background_upload: true, provider: "AWS" } } }.with_indifferent_access
)
end
......@@ -793,12 +871,37 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
subject { described_class.license_usage_data }
it 'gathers license data' do
expect(subject[:uuid]).to eq(Gitlab::CurrentSettings.uuid)
expect(subject[:version]).to eq(Gitlab::VERSION)
expect(subject[:installation_type]).to eq('gitlab-development-kit')
expect(subject[:active_user_count]).to eq(User.active.size)
expect(subject[:recorded_at]).to be_a(Time)
end
context 'with usage_data_instrumentation feature flag' do
context 'when enabled' do
it 'merges uuid and hostname data from instrumentation classes' do
stub_feature_flags(usage_data_instrumentation: true)
expect(subject[:uuid]).to eq(Gitlab::Utils::UsageData::INSTRUMENTATION_CLASS_FALLBACK)
expect(subject[:hostname]).to eq(Gitlab::Utils::UsageData::INSTRUMENTATION_CLASS_FALLBACK)
expect(subject[:active_user_count]).to eq(Gitlab::Utils::UsageData::INSTRUMENTATION_CLASS_FALLBACK)
uncached_data = described_class.data
expect(uncached_data[:uuid]).to eq(Gitlab::CurrentSettings.uuid)
expect(uncached_data[:hostname]).to eq(Gitlab.config.gitlab.host)
expect(uncached_data[:active_user_count]).to eq(User.active.size)
end
end
context 'when disabled' do
it 'does not merge uuid and hostname data from instrumentation classes' do
stub_feature_flags(usage_data_instrumentation: false)
expect(subject[:uuid]).to eq(Gitlab::CurrentSettings.uuid)
expect(subject[:hostname]).to eq(Gitlab.config.gitlab.host)
expect(subject[:active_user_count]).to eq(User.active.size)
end
end
end
end
context 'when not relying on database records' do
......@@ -1061,6 +1164,32 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
expect(subject[:settings][:gitaly_apdex]).to be_within(0.001).of(0.95)
end
context 'with usage_data_instrumentation feature flag' do
context 'when enabled' do
before do
stub_feature_flags(usage_data_instrumentation: true)
end
it 'reports collected data categories' do
expected_value = %w[standard subscription operational optional]
allow_next_instance_of(ServicePing::PermitDataCategoriesService) do |instance|
expect(instance).to receive(:execute).and_return(expected_value)
end
expect(described_class.data[:settings][:collected_data_categories]).to eq(expected_value)
end
it 'gathers service_ping_features_enabled' do
expect(described_class.data[:settings][:service_ping_features_enabled]).to eq(Gitlab::CurrentSettings.usage_ping_features_enabled)
end
end
context 'when disabled' do
before do
stub_feature_flags(usage_data_instrumentation: false)
end
it 'reports collected data categories' do
expected_value = %w[standard subscription operational optional]
......@@ -1074,6 +1203,8 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
it 'gathers service_ping_features_enabled' do
expect(subject[:settings][:service_ping_features_enabled]).to eq(Gitlab::CurrentSettings.usage_ping_features_enabled)
end
end
end
it 'gathers user_cap_feature_enabled' do
expect(subject[:settings][:user_cap_feature_enabled]).to eq(Gitlab::CurrentSettings.new_user_signups_cap)
......
......@@ -8,10 +8,28 @@ RSpec.describe Gitlab::Utils::UsageData do
describe '#add_metric' do
let(:metric) { 'UuidMetric'}
context 'with usage_data_instrumentation feature flag' do
context 'when enabled' do
before do
stub_feature_flags(usage_data_instrumentation: true)
end
it 'returns -100 value to be overriden' do
expect(described_class.add_metric(metric)).to eq(-100)
end
end
context 'when disabled' do
before do
stub_feature_flags(usage_data_instrumentation: false)
end
it 'computes the metric value for given metric' do
expect(described_class.add_metric(metric)).to eq(Gitlab::CurrentSettings.uuid)
end
end
end
end
describe '#count' do
let(:relation) { double(:relation) }
......
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