diff --git a/db/migrate/20220609150626_add_partial_index_on_slack_integrations_with_bot_user_id.rb b/db/migrate/20220609150626_add_partial_index_on_slack_integrations_with_bot_user_id.rb new file mode 100644 index 0000000000000000000000000000000000000000..498c1da9e19ece82200162cb5ae6cb57fac26154 --- /dev/null +++ b/db/migrate/20220609150626_add_partial_index_on_slack_integrations_with_bot_user_id.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +class AddPartialIndexOnSlackIntegrationsWithBotUserId < Gitlab::Database::Migration[2.0] + disable_ddl_transaction! + + INDEX_NAME = 'partial_index_slack_integrations_with_bot_user_id' + + def up + add_concurrent_index :slack_integrations, :id, name: INDEX_NAME, where: 'bot_user_id IS NOT NULL' + end + + def down + remove_concurrent_index :slack_integrations, :id, name: INDEX_NAME + end +end diff --git a/db/schema_migrations/20220609150626 b/db/schema_migrations/20220609150626 new file mode 100644 index 0000000000000000000000000000000000000000..f0f54d885cf134aabe99e0e8ba96bd8c420a7912 --- /dev/null +++ b/db/schema_migrations/20220609150626 @@ -0,0 +1 @@ +93e90cbe1fff08de997134dab382dce7c341dd9f4cc16302cac09ce34a419d2d \ No newline at end of file diff --git a/db/structure.sql b/db/structure.sql index 0b12de3c2701faec308618b7d9ecd130496752cb..6973eed89d42c533ad8656c5b563f9d88f338e4d 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -29920,6 +29920,8 @@ CREATE INDEX partial_index_deployments_for_legacy_successful_deployments ON depl CREATE INDEX partial_index_deployments_for_project_id_and_tag ON deployments USING btree (project_id) WHERE (tag IS TRUE); +CREATE INDEX partial_index_slack_integrations_with_bot_user_id ON slack_integrations USING btree (id) WHERE (bot_user_id IS NOT NULL); + CREATE UNIQUE INDEX partial_index_sop_configs_on_namespace_id ON security_orchestration_policy_configurations USING btree (namespace_id) WHERE (namespace_id IS NOT NULL); CREATE UNIQUE INDEX partial_index_sop_configs_on_project_id ON security_orchestration_policy_configurations USING btree (project_id) WHERE (project_id IS NOT NULL); diff --git a/ee/app/models/slack_integration.rb b/ee/app/models/slack_integration.rb index 45ef2d1c91d5935fbaecce968646899838d025ce..3e4f74f2fe7c0155dd0f550800bb4ff274636424 100644 --- a/ee/app/models/slack_integration.rb +++ b/ee/app/models/slack_integration.rb @@ -10,6 +10,8 @@ class SlackIntegration < ApplicationRecord encode: false, encode_iv: false + scope :with_bot, -> { where.not(bot_user_id: nil) } + validates :team_id, presence: true validates :team_name, presence: true validates :alias, presence: true, diff --git a/ee/config/metrics/counts_all/20220607141129_slack_app_installations_gbp.yml b/ee/config/metrics/counts_all/20220607141129_slack_app_installations_gbp.yml new file mode 100644 index 0000000000000000000000000000000000000000..23a44b32f83768940ebb334e4efc820f424a8023 --- /dev/null +++ b/ee/config/metrics/counts_all/20220607141129_slack_app_installations_gbp.yml @@ -0,0 +1,21 @@ +--- +key_path: counts.slack_app_installations_gbp +description: Count of Slack app installations using the new GBP version +product_section: dev +product_stage: ecosystem +product_group: group::integrations +product_category: integrations +value_type: number +status: active +milestone: "15.1" +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/89130 +time_frame: all +data_source: database +data_category: optional +instrumentation_class: CountSlackAppInstallationsGbpMetric +distribution: +- ee +tier: +- free +- premium +- ultimate diff --git a/ee/config/metrics/counts_all/20220607141417_slack_app_installations.yml b/ee/config/metrics/counts_all/20220607141417_slack_app_installations.yml new file mode 100644 index 0000000000000000000000000000000000000000..86f747b695bc3fe495b65271a9d942ae50a12cca --- /dev/null +++ b/ee/config/metrics/counts_all/20220607141417_slack_app_installations.yml @@ -0,0 +1,21 @@ +--- +key_path: counts.slack_app_installations +description: Count of Slack app installations +product_section: dev +product_stage: ecosystem +product_group: group::integrations +product_category: integrations +value_type: number +status: active +milestone: "15.1" +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/89130 +time_frame: all +data_source: database +data_category: optional +instrumentation_class: CountSlackAppInstallationsMetric +distribution: +- ee +tier: +- free +- premium +- ultimate diff --git a/ee/lib/gitlab/usage/metrics/instrumentations/count_slack_app_installations_gbp_metric.rb b/ee/lib/gitlab/usage/metrics/instrumentations/count_slack_app_installations_gbp_metric.rb new file mode 100644 index 0000000000000000000000000000000000000000..0a796c9fae92021e059bff3a4a32d18771b4b27e --- /dev/null +++ b/ee/lib/gitlab/usage/metrics/instrumentations/count_slack_app_installations_gbp_metric.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +module Gitlab + module Usage + module Metrics + module Instrumentations + class CountSlackAppInstallationsGbpMetric < DatabaseMetric + operation :count + + relation { SlackIntegration.with_bot } + end + end + end + end +end diff --git a/ee/lib/gitlab/usage/metrics/instrumentations/count_slack_app_installations_metric.rb b/ee/lib/gitlab/usage/metrics/instrumentations/count_slack_app_installations_metric.rb new file mode 100644 index 0000000000000000000000000000000000000000..af9cf957dab82075e2002b60f7cb0b8f29486ee9 --- /dev/null +++ b/ee/lib/gitlab/usage/metrics/instrumentations/count_slack_app_installations_metric.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +module Gitlab + module Usage + module Metrics + module Instrumentations + class CountSlackAppInstallationsMetric < DatabaseMetric + operation :count + + relation { SlackIntegration } + end + end + end + end +end diff --git a/ee/spec/factories/slack_integrations.rb b/ee/spec/factories/slack_integrations.rb index f7b058f9310a52d3301354ed0b463995a4f942ef..b782c3fec40b5583f70882793b4783b1ce16728c 100644 --- a/ee/spec/factories/slack_integrations.rb +++ b/ee/spec/factories/slack_integrations.rb @@ -4,9 +4,16 @@ factory :slack_integration do sequence(:team_id) { |n| "T123#{n}" } sequence(:user_id) { |n| "U123#{n}" } + sequence(:bot_user_id) { |n| "U123#{n}" } + sequence(:bot_access_token) { |n| OpenSSL::Digest::SHA256.hexdigest(n.to_s) } sequence(:team_name) { |n| "team#{n}" } sequence(:alias) { |n| "namespace#{n}/project_name#{n}" } integration factory: :gitlab_slack_application_integration + + trait :legacy do + bot_user_id { nil } + bot_access_token { nil } + end end end diff --git a/ee/spec/lib/gitlab/usage/metrics/instrumentations/count_slack_app_installations_gbp_metric_spec.rb b/ee/spec/lib/gitlab/usage/metrics/instrumentations/count_slack_app_installations_gbp_metric_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..af94ae7e935b450005c30723154dc2511c7d4fc1 --- /dev/null +++ b/ee/spec/lib/gitlab/usage/metrics/instrumentations/count_slack_app_installations_gbp_metric_spec.rb @@ -0,0 +1,16 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Gitlab::Usage::Metrics::Instrumentations::CountSlackAppInstallationsGbpMetric do + let_it_be(:slack_integration) { create(:slack_integration) } + let_it_be(:slack_integration_legacy) { create(:slack_integration, :legacy) } + + let(:expected_value) { 1 } + let(:expected_query) do + 'SELECT COUNT("slack_integrations"."id") FROM "slack_integrations" ' \ + 'WHERE "slack_integrations"."bot_user_id" IS NOT NULL' + end + + it_behaves_like 'a correct instrumented metric value and query', { time_frame: 'all' } +end diff --git a/ee/spec/lib/gitlab/usage/metrics/instrumentations/count_slack_app_installations_metric_spec.rb b/ee/spec/lib/gitlab/usage/metrics/instrumentations/count_slack_app_installations_metric_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..ce13f87b1efeb9f283a73a7d79128d4e597d32e2 --- /dev/null +++ b/ee/spec/lib/gitlab/usage/metrics/instrumentations/count_slack_app_installations_metric_spec.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Gitlab::Usage::Metrics::Instrumentations::CountSlackAppInstallationsMetric do + let_it_be(:slack_integration) { create(:slack_integration) } + let_it_be(:slack_integration_legacy) { create(:slack_integration, :legacy) } + + let(:expected_value) { 2 } + let(:expected_query) { 'SELECT COUNT("slack_integrations"."id") FROM "slack_integrations"' } + + it_behaves_like 'a correct instrumented metric value and query', { time_frame: 'all' } +end diff --git a/ee/spec/models/slack_integration_spec.rb b/ee/spec/models/slack_integration_spec.rb index ffe1786f2d40620e61cd1b9c2392d62d6e61d1ed..c98bb3186cd0864deb7fa0939b9e4bf5f89411db 100644 --- a/ee/spec/models/slack_integration_spec.rb +++ b/ee/spec/models/slack_integration_spec.rb @@ -7,6 +7,17 @@ it { is_expected.to belong_to(:integration) } end + describe 'Scopes' do + let_it_be(:with_bot) { create(:slack_integration) } + let_it_be(:without_bot) { create(:slack_integration, :legacy) } + + describe '#with_bot' do + it 'returns records with bot data' do + expect(described_class.with_bot).to contain_exactly(with_bot) + end + end + end + describe 'Validations' do it { is_expected.to validate_presence_of(:team_id) } it { is_expected.to validate_presence_of(:team_name) } diff --git a/lib/gitlab/usage_data.rb b/lib/gitlab/usage_data.rb index 47c927642b2bdebab30252a35da48dc46a912055..f86394971e77c6ccf5bba4abf57eb6775c6a9868 100644 --- a/lib/gitlab/usage_data.rb +++ b/lib/gitlab/usage_data.rb @@ -155,7 +155,7 @@ def system_usage_data notes: count(Note) }.merge( runners_usage, - services_usage, + integrations_usage, usage_counters, user_preferences_usage, container_expiration_policies_usage, @@ -365,7 +365,7 @@ def container_expiration_policies_usage results end - def services_usage + def integrations_usage # rubocop: disable UsageData/LargeTable: Integration.available_integration_names(include_dev: false).each_with_object({}) do |name, response| type = Integration.integration_name_to_type(name)