diff --git a/config/metrics/counts_all/count_total_invoke_internal_events.yml b/config/metrics/counts_all/count_total_invoke_internal_events.yml
new file mode 100644
index 0000000000000000000000000000000000000000..04a44b612313a4bc0d76130d9ff9534cdbf9a8ed
--- /dev/null
+++ b/config/metrics/counts_all/count_total_invoke_internal_events.yml
@@ -0,0 +1,21 @@
+---
+key_path: counts.count_total_invocations_of_internal_events
+description: Count of number of times internal events was invoked
+product_group: analytics_instrumentation
+product_categories:
+- application_instrumentation
+performance_indicator_type: []
+value_type: number
+status: active
+milestone: '17.10'
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/184038
+time_frame:
+- 28d
+- 7d
+data_source: system
+instrumentation_class: SumNumberOfInternalEventInvocationsMetric
+data_category: optional
+tiers:
+- free
+- premium
+- ultimate
diff --git a/lib/gitlab/usage/metrics/instrumentations/sum_number_of_internal_event_invocations_metric.rb b/lib/gitlab/usage/metrics/instrumentations/sum_number_of_internal_event_invocations_metric.rb
new file mode 100644
index 0000000000000000000000000000000000000000..965ce13bd799a4d2aa85d8d7b5097513b1e7a088
--- /dev/null
+++ b/lib/gitlab/usage/metrics/instrumentations/sum_number_of_internal_event_invocations_metric.rb
@@ -0,0 +1,37 @@
+# frozen_string_literal: true
+
+module Gitlab
+  module Usage
+    module Metrics
+      module Instrumentations
+        class SumNumberOfInternalEventInvocationsMetric < GenericMetric
+          include Gitlab::UsageDataCounters::RedisCounter
+
+          def value
+            all_internal_event_keys.sum do |key|
+              redis_usage_data do
+                total_count(key)
+              end
+            end
+          end
+
+          private
+
+          def all_internal_event_keys
+            internal_event_definitions = Gitlab::Tracking::EventDefinition.definitions.select(&:internal_events?)
+
+            internal_event_definitions.flat_map do |event_definition|
+              keys_for_event_definition(event_definition)
+            end
+          end
+
+          def keys_for_event_definition(event_definition)
+            event_selection_rule = EventSelectionRule.new(name: event_definition.action, time_framed: true)
+
+            event_selection_rule.redis_keys_for_time_frame(time_frame)
+          end
+        end
+      end
+    end
+  end
+end
diff --git a/spec/lib/gitlab/usage/metrics/instrumentations/sum_number_of_internal_event_invocations_metric_spec.rb b/spec/lib/gitlab/usage/metrics/instrumentations/sum_number_of_internal_event_invocations_metric_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..774f6d546aa20223d9ecdd0057d7166d00747c22
--- /dev/null
+++ b/spec/lib/gitlab/usage/metrics/instrumentations/sum_number_of_internal_event_invocations_metric_spec.rb
@@ -0,0 +1,102 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Usage::Metrics::Instrumentations::SumNumberOfInternalEventInvocationsMetric,
+  :clean_gitlab_redis_shared_state, feature_category: :product_analytics do
+  before do
+    event_definition1 = instance_double(
+      Gitlab::Tracking::EventDefinition,
+      action: 'internal_event1',
+      internal_events?: true
+    )
+
+    event_definition2 = instance_double(
+      Gitlab::Tracking::EventDefinition,
+      action: 'internal_event2',
+      internal_events?: true
+    )
+
+    # Non-internal event that should be excluded
+    event_definition3 = instance_double(
+      Gitlab::Tracking::EventDefinition,
+      action: 'non_internal_event',
+      internal_events?: false
+    )
+
+    definitions = [event_definition1, event_definition2, event_definition3]
+    allow(Gitlab::Tracking::EventDefinition)
+      .to receive_messages(internal_event_exists?: true, definitions: definitions)
+  end
+
+  context 'with multiple internal events' do
+    let(:event_selection_rule1) { Gitlab::Usage::EventSelectionRule.new(name: 'internal_event1', time_framed: true) }
+    let(:event_selection_rule2) { Gitlab::Usage::EventSelectionRule.new(name: 'internal_event2', time_framed: true) }
+
+    before do
+      last_week = Time.zone.today - 7.days
+      two_weeks_ago = last_week - 1.week
+
+      # Create Redis data for internal_event1
+      2.times do
+        redis_counter_key = event_selection_rule1.redis_key_for_date(last_week)
+        Gitlab::Redis::SharedState.with { |redis| redis.incr(redis_counter_key) }
+      end
+
+      3.times do
+        redis_counter_key = event_selection_rule1.redis_key_for_date(two_weeks_ago)
+        Gitlab::Redis::SharedState.with { |redis| redis.incr(redis_counter_key) }
+      end
+
+      # Create Redis data for internal_event2
+      4.times do
+        redis_counter_key = event_selection_rule2.redis_key_for_date(last_week)
+        Gitlab::Redis::SharedState.with { |redis| redis.incr(redis_counter_key) }
+      end
+
+      5.times do
+        redis_counter_key = event_selection_rule2.redis_key_for_date(two_weeks_ago)
+        Gitlab::Redis::SharedState.with { |redis| redis.incr(redis_counter_key) }
+      end
+
+      # Create Redis data for non-internal event (should be ignored)
+      non_internal_event_rule = Gitlab::Usage::EventSelectionRule.new(name: 'non_internal_event', time_framed: true)
+      8.times do
+        redis_counter_key = non_internal_event_rule.redis_key_for_date(last_week)
+        Gitlab::Redis::SharedState.with { |redis| redis.incr(redis_counter_key) }
+      end
+    end
+
+    context "with a '7d' time_frame" do
+      let(:expected_value) { 6 } # 2 from event1 + 4 from event2
+
+      it_behaves_like 'a correct instrumented metric value', { time_frame: '7d' }
+    end
+
+    context "with a '28d' time_frame" do
+      let(:expected_value) { 14 } # 5 from event1 + 9 from event2
+
+      it_behaves_like 'a correct instrumented metric value', { time_frame: '28d' }
+    end
+  end
+
+  context "with an invalid time_frame" do
+    let(:metric) { described_class.new(time_frame: '14d') }
+
+    it 'raises an exception' do
+      expect { metric.value }.to raise_error(/Unknown time frame/)
+    end
+  end
+
+  context "with no internal events" do
+    before do
+      allow(Gitlab::Tracking::EventDefinition).to receive(:definitions).and_return([])
+    end
+
+    context "with a '7d' time_frame" do
+      let(:expected_value) { 0 }
+
+      it_behaves_like 'a correct instrumented metric value', { time_frame: '7d' }
+    end
+  end
+end