diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index 379da90827a12b11849f866322b74f3a10198b0d..99fab68d24c5fdd4b99086083f9a74320f87bb34 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -463,7 +463,7 @@ def set_current_context(&block)
       feature_category: feature_category) do
       yield
     ensure
-      @current_context = Labkit::Context.current.to_h
+      @current_context = Gitlab::ApplicationContext.current
     end
   end
 
diff --git a/app/graphql/mutations/admin/sidekiq_queues/delete_jobs.rb b/app/graphql/mutations/admin/sidekiq_queues/delete_jobs.rb
index 32ca6de9b96c3d1349fb9aa7ce004518801312cd..ea1502d4b62d6411e161008fe47d371207addcc3 100644
--- a/app/graphql/mutations/admin/sidekiq_queues/delete_jobs.rb
+++ b/app/graphql/mutations/admin/sidekiq_queues/delete_jobs.rb
@@ -8,7 +8,7 @@ class DeleteJobs < BaseMutation
 
         ADMIN_MESSAGE = 'You must be an admin to use this mutation'
 
-        Labkit::Context::KNOWN_KEYS.each do |key|
+        Gitlab::ApplicationContext::KNOWN_KEYS.each do |key|
           argument key,
                    GraphQL::STRING_TYPE,
                    required: false,
diff --git a/app/workers/concerns/application_worker.rb b/app/workers/concerns/application_worker.rb
index d101ef100d8b25013f36def0fb7af00251ad62eb..0de26e27631106c1e6a31d09d0055a08fdded1d4 100644
--- a/app/workers/concerns/application_worker.rb
+++ b/app/workers/concerns/application_worker.rb
@@ -18,7 +18,7 @@ module ApplicationWorker
     set_queue
 
     def structured_payload(payload = {})
-      context = Labkit::Context.current.to_h.merge(
+      context = Gitlab::ApplicationContext.current.merge(
         'class' => self.class.name,
         'job_status' => 'running',
         'queue' => self.class.queue,
diff --git a/app/workers/concerns/cronjob_queue.rb b/app/workers/concerns/cronjob_queue.rb
index 955387b5ad4d71d23ce50016193475283ef08455..b89d6bba72ce84ec76a672c5e3a2bd9440c2c075 100644
--- a/app/workers/concerns/cronjob_queue.rb
+++ b/app/workers/concerns/cronjob_queue.rb
@@ -15,7 +15,7 @@ module CronjobQueue
     # Cronjobs never get scheduled with arguments, so this is safe to
     # override
     def context_for_arguments(_args)
-      return if Gitlab::ApplicationContext.current_context_include?('meta.caller_id')
+      return if Gitlab::ApplicationContext.current_context_include?(:caller_id)
 
       Gitlab::ApplicationContext.new(caller_id: "Cronjob")
     end
diff --git a/ee/app/services/elastic/indexing_control_service.rb b/ee/app/services/elastic/indexing_control_service.rb
index 0fe722ba299582db08f76006471e44409fa3aa6d..1b0aef0217a2d28dc22bdd3820bb220a78ccca48 100644
--- a/ee/app/services/elastic/indexing_control_service.rb
+++ b/ee/app/services/elastic/indexing_control_service.rb
@@ -6,7 +6,7 @@ module Elastic
   # This class should only be used with sidekiq workers which extend Elastic::IndexingControl module
   class IndexingControlService
     LIMIT = 1000
-    PROJECT_CONTEXT_KEY = "#{Labkit::Context::LOG_KEY}.project"
+    PROJECT_CONTEXT_KEY = "#{Gitlab::ApplicationContext::LOG_KEY}.project"
 
     def initialize(klass)
       raise ArgumentError, "passed class must extend Elastic::IndexingControl" unless klass.include?(Elastic::IndexingControl)
@@ -93,7 +93,7 @@ def deserialize(json)
     end
 
     def send_to_processing_queue(job)
-      Labkit::Context.with_context(job['context']) do
+      Gitlab::ApplicationContext.with_raw_context(job['context']) do
         klass.perform_async(*job['args'])
       end
     end
diff --git a/ee/app/workers/concerns/elastic/indexing_control.rb b/ee/app/workers/concerns/elastic/indexing_control.rb
index 0bd71deed8ab4f0a15b83eb1b4f03906dd97db6e..b51ad59234c11bdcb3acec5a863f06291038204b 100644
--- a/ee/app/workers/concerns/elastic/indexing_control.rb
+++ b/ee/app/workers/concerns/elastic/indexing_control.rb
@@ -51,7 +51,7 @@ def logger
     end
 
     def current_context
-      Labkit::Context.current.to_h
+      Gitlab::ApplicationContext.current
     end
   end
 end
diff --git a/ee/spec/services/elastic/indexing_control_service_spec.rb b/ee/spec/services/elastic/indexing_control_service_spec.rb
index d58b75fe2093305b1e5e529f4bc71b1efa7145cc..16deef940906c1841409e916ac5baef98b92242c 100644
--- a/ee/spec/services/elastic/indexing_control_service_spec.rb
+++ b/ee/spec/services/elastic/indexing_control_service_spec.rb
@@ -20,7 +20,7 @@ def self.name
   end
 
   let(:stored_context) do
-    { "#{Labkit::Context::LOG_KEY}.project" => 'gitlab-org/gitlab' }
+    { "#{Gitlab::ApplicationContext::LOG_KEY}.project" => 'gitlab-org/gitlab' }
   end
 
   let(:worker_args) { [1, 2] }
@@ -133,7 +133,7 @@ def self.name
         subject.add_to_waiting_queue!(j, worker_context)
       end
 
-      expect(Labkit::Context).to receive(:with_context).with(stored_context).exactly(jobs.count).times.and_call_original
+      expect(Gitlab::ApplicationContext).to receive(:with_raw_context).with(stored_context).exactly(jobs.count).times.and_call_original
       expect(worker_class).to receive(:perform_async).exactly(jobs.count).times
 
       expect { subject.resume_processing! }.to change { subject.has_jobs_in_waiting_queue? }.from(true).to(false)
diff --git a/ee/spec/workers/concerns/elastic/indexing_control_spec.rb b/ee/spec/workers/concerns/elastic/indexing_control_spec.rb
index 5d07e68804454639da9c76eb78843fe1c6d6ae08..d24c01f611e4b3558ce4f9265166159e5826c04d 100644
--- a/ee/spec/workers/concerns/elastic/indexing_control_spec.rb
+++ b/ee/spec/workers/concerns/elastic/indexing_control_spec.rb
@@ -75,7 +75,7 @@ def self.name
         expect_any_instance_of(Gitlab::Elastic::Indexer).not_to receive(:run)
         expect(Elastic::IndexingControlService).to receive(:add_to_waiting_queue!).with(worker.class, worker_args, worker_context)
 
-        Labkit::Context.with_context(worker_context) do
+        Gitlab::ApplicationContext.with_raw_context(worker_context) do
           worker.perform(*worker_args)
         end
       end
diff --git a/ee/spec/workers/update_all_mirrors_worker_spec.rb b/ee/spec/workers/update_all_mirrors_worker_spec.rb
index cca1f21bce8678b500ab51219848410d55187e41..4669616ffc7a9384ca81ee9f5d057d8ccbedd318 100644
--- a/ee/spec/workers/update_all_mirrors_worker_spec.rb
+++ b/ee/spec/workers/update_all_mirrors_worker_spec.rb
@@ -32,10 +32,10 @@
       outer_context = nil
 
       Gitlab::ApplicationContext.with_context(project: build(:project)) do
-        outer_context = Labkit::Context.current.to_h
+        outer_context = Gitlab::ApplicationContext.current
 
         expect(worker).to receive(:schedule_mirrors!) do
-          inner_context = Labkit::Context.current.to_h
+          inner_context = Gitlab::ApplicationContext.current
 
           # `schedule_mirrors!` needs to return an integer.
           0
diff --git a/lib/api/admin/sidekiq.rb b/lib/api/admin/sidekiq.rb
index 7e561783685cbe8e55f33bf93534f4478c28c34f..d91d4a0d4d5d132585a7d1c40dbee1518f75aa17 100644
--- a/lib/api/admin/sidekiq.rb
+++ b/lib/api/admin/sidekiq.rb
@@ -12,11 +12,11 @@ class Sidekiq < ::API::Base
           namespace 'queues' do
             desc 'Drop jobs matching the given metadata from the Sidekiq queue'
             params do
-              Labkit::Context::KNOWN_KEYS.each do |key|
+              Gitlab::ApplicationContext::KNOWN_KEYS.each do |key|
                 optional key, type: String, allow_blank: false
               end
 
-              at_least_one_of(*Labkit::Context::KNOWN_KEYS)
+              at_least_one_of(*Gitlab::ApplicationContext::KNOWN_KEYS)
             end
             delete ':queue_name' do
               result =
diff --git a/lib/gitlab/application_context.rb b/lib/gitlab/application_context.rb
index 5d07610feb543d9e271d6fdc9a2e9b8cf89731a3..5675019ce836e74a9dbbc245bdb6c960512e40dd 100644
--- a/lib/gitlab/application_context.rb
+++ b/lib/gitlab/application_context.rb
@@ -7,6 +7,9 @@ class ApplicationContext
 
     Attribute = Struct.new(:name, :type)
 
+    LOG_KEY = Labkit::Context::LOG_KEY
+    KNOWN_KEYS = Labkit::Context::KNOWN_KEYS
+
     APPLICATION_ATTRIBUTES = [
       Attribute.new(:project, Project),
       Attribute.new(:namespace, Namespace),
@@ -22,6 +25,10 @@ def self.with_context(args, &block)
       application_context.use(&block)
     end
 
+    def self.with_raw_context(attributes = {}, &block)
+      Labkit::Context.with_context(attributes, &block)
+    end
+
     def self.push(args)
       application_context = new(**args)
       Labkit::Context.push(application_context.to_lazy_hash)
diff --git a/lib/gitlab/gitaly_client.rb b/lib/gitlab/gitaly_client.rb
index e3788814dd5eb381e476a666e7315a547368ff39..f4a89edecd15aa0054d57a1d685e8bc3636c8fb7 100644
--- a/lib/gitlab/gitaly_client.rb
+++ b/lib/gitlab/gitaly_client.rb
@@ -215,7 +215,7 @@ def self.request_kwargs(storage, timeout:, remote_storage: nil)
         'client_name' => CLIENT_NAME
       }
 
-      context_data = Labkit::Context.current&.to_h
+      context_data = Gitlab::ApplicationContext.current
 
       feature_stack = Thread.current[:gitaly_feature_stack]
       feature = feature_stack && feature_stack[0]
diff --git a/lib/gitlab/grape_logging/loggers/context_logger.rb b/lib/gitlab/grape_logging/loggers/context_logger.rb
index 0a8f0872fbe303b03ec6831afeab64cc9578e0a7..468a296886eb1d92c3b6511eb6635e853e623699 100644
--- a/lib/gitlab/grape_logging/loggers/context_logger.rb
+++ b/lib/gitlab/grape_logging/loggers/context_logger.rb
@@ -6,7 +6,7 @@ module GrapeLogging
     module Loggers
       class ContextLogger < ::GrapeLogging::Loggers::Base
         def parameters(_, _)
-          Labkit::Context.current.to_h
+          Gitlab::ApplicationContext.current
         end
       end
     end
diff --git a/lib/gitlab/sidekiq_queue.rb b/lib/gitlab/sidekiq_queue.rb
index 807c27a71ffc7201f350e50d1e2b70a5a4f32157..4b71dfc0c1b31ad18f6cde28e32b20e78ffebaa8 100644
--- a/lib/gitlab/sidekiq_queue.rb
+++ b/lib/gitlab/sidekiq_queue.rb
@@ -21,7 +21,7 @@ def drop_jobs!(search_metadata, timeout:)
       job_search_metadata =
         search_metadata
           .stringify_keys
-          .slice(*Labkit::Context::KNOWN_KEYS)
+          .slice(*Gitlab::ApplicationContext::KNOWN_KEYS)
           .transform_keys { |key| "meta.#{key}" }
           .compact
 
diff --git a/spec/controllers/application_controller_spec.rb b/spec/controllers/application_controller_spec.rb
index 4a729008e67c676bdc10ddb48ccca60e96e02bc6..6641a3ed9148c3ce164279f6580b647a1cdfeade 100644
--- a/spec/controllers/application_controller_spec.rb
+++ b/spec/controllers/application_controller_spec.rb
@@ -900,7 +900,7 @@ def index
       feature_category :issue_tracking
 
       def index
-        Labkit::Context.with_context do |context|
+        Gitlab::ApplicationContext.with_raw_context do |context|
           render json: context.to_h
         end
       end
diff --git a/spec/controllers/sessions_controller_spec.rb b/spec/controllers/sessions_controller_spec.rb
index c31ba6fe156d86e8d692da5fa45dccf6a28b9f1d..5bee7698c3f479e532617d18fc6a09857c35609d 100644
--- a/spec/controllers/sessions_controller_spec.rb
+++ b/spec/controllers/sessions_controller_spec.rb
@@ -524,7 +524,7 @@ def authenticate_2fa_u2f(user_params)
 
       it 'sets the username and caller_id in the context' do
         expect(controller).to receive(:destroy).and_wrap_original do |m, *args|
-          expect(Labkit::Context.current.to_h)
+          expect(Gitlab::ApplicationContext.current)
             .to include('meta.user' => user.username,
                         'meta.caller_id' => 'SessionsController#destroy')
 
@@ -538,9 +538,9 @@ def authenticate_2fa_u2f(user_params)
     context 'when not signed in' do
       it 'sets the caller_id in the context' do
         expect(controller).to receive(:new).and_wrap_original do |m, *args|
-          expect(Labkit::Context.current.to_h)
+          expect(Gitlab::ApplicationContext.current)
             .to include('meta.caller_id' => 'SessionsController#new')
-          expect(Labkit::Context.current.to_h)
+          expect(Gitlab::ApplicationContext.current)
             .not_to include('meta.user')
 
           m.call(*args)
@@ -557,9 +557,9 @@ def authenticate_2fa_u2f(user_params)
 
       it 'sets the caller_id in the context' do
         allow_any_instance_of(User).to receive(:lock_access!).and_wrap_original do |m, *args|
-          expect(Labkit::Context.current.to_h)
+          expect(Gitlab::ApplicationContext.current)
             .to include('meta.caller_id' => 'SessionsController#create')
-          expect(Labkit::Context.current.to_h)
+          expect(Gitlab::ApplicationContext.current)
             .not_to include('meta.user')
 
           m.call(*args)
diff --git a/spec/lib/gitlab/application_context_spec.rb b/spec/lib/gitlab/application_context_spec.rb
index 88f865adea761d1061a0335f385f617e54f34295..44e90994975eb464e4db6dd2ed6e1014b9a20298 100644
--- a/spec/lib/gitlab/application_context_spec.rb
+++ b/spec/lib/gitlab/application_context_spec.rb
@@ -27,6 +27,20 @@
     end
   end
 
+  describe '.with_raw_context' do
+    it 'yields the block' do
+      expect { |b| described_class.with_raw_context({}, &b) }.to yield_control
+    end
+
+    it 'passes the attributes unaltered on to labkit' do
+      attrs = { foo: :bar }
+
+      expect(Labkit::Context).to receive(:with_context).with(attrs)
+
+      described_class.with_raw_context(attrs) {}
+    end
+  end
+
   describe '.push' do
     it 'passes the expected context on to labkit' do
       fake_proc = duck_type(:call)
@@ -110,7 +124,7 @@ def result(context)
     it 'does not cause queries' do
       context = described_class.new(project: create(:project), namespace: create(:group, :nested), user: create(:user))
 
-      expect { context.use { Labkit::Context.current.to_h } }.not_to exceed_query_limit(0)
+      expect { context.use { Gitlab::ApplicationContext.current } }.not_to exceed_query_limit(0)
     end
   end
 end
diff --git a/spec/lib/gitlab/sidekiq_middleware/worker_context/server_spec.rb b/spec/lib/gitlab/sidekiq_middleware/worker_context/server_spec.rb
index ca473462d2e95671306d168fedba36f0694426cc..f736a7db774d0630aec42e7a40ce17ef15ee3089 100644
--- a/spec/lib/gitlab/sidekiq_middleware/worker_context/server_spec.rb
+++ b/spec/lib/gitlab/sidekiq_middleware/worker_context/server_spec.rb
@@ -18,7 +18,7 @@ def self.name
       worker_context user: nil
 
       def perform(identifier, *args)
-        self.class.contexts.merge!(identifier => Labkit::Context.current.to_h)
+        self.class.contexts.merge!(identifier => Gitlab::ApplicationContext.current)
       end
     end
   end
diff --git a/spec/requests/api/api_spec.rb b/spec/requests/api/api_spec.rb
index e1050d0b5f786dfe3c2eb733a6f8a449f4cf9d1e..4eae5678184b11a44d377be3e8dd81e823abd165 100644
--- a/spec/requests/api/api_spec.rb
+++ b/spec/requests/api/api_spec.rb
@@ -105,7 +105,7 @@
 
     it 'logs all application context fields' do
       allow_any_instance_of(Gitlab::GrapeLogging::Loggers::ContextLogger).to receive(:parameters) do
-        Labkit::Context.current.to_h.tap do |log_context|
+        Gitlab::ApplicationContext.current.tap do |log_context|
           expect(log_context).to match('correlation_id' => an_instance_of(String),
                                        'meta.caller_id' => '/api/:version/projects/:id/issues',
                                        'meta.remote_ip' => an_instance_of(String),
@@ -121,7 +121,7 @@
 
     it 'skips fields that do not apply' do
       allow_any_instance_of(Gitlab::GrapeLogging::Loggers::ContextLogger).to receive(:parameters) do
-        Labkit::Context.current.to_h.tap do |log_context|
+        Gitlab::ApplicationContext.current.tap do |log_context|
           expect(log_context).to match('correlation_id' => an_instance_of(String),
                                        'meta.caller_id' => '/api/:version/users',
                                        'meta.remote_ip' => an_instance_of(String),
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index ddda3ede083a7c50568d2c1c879bd73a12e99363..9a49c57e48c7c411f08f552089198192e98fbe94 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -304,10 +304,10 @@
     RequestStore.clear!
   end
 
-  config.around do |example|
+  config.around(:example, :context_aware) do |example|
     # Wrap each example in it's own context to make sure the contexts don't
     # leak
-    Labkit::Context.with_context { example.run }
+    Gitlab::ApplicationContext.with_raw_context { example.run }
   end
 
   config.around do |example|
diff --git a/spec/support/shared_examples/lib/api/ci/runner_shared_examples.rb b/spec/support/shared_examples/lib/api/ci/runner_shared_examples.rb
index bdb0316bf5abcfec2e84706ba6e67feca2b17fdf..c775ca182e615d9c6e42d2c66592cdcafc0fdcfd 100644
--- a/spec/support/shared_examples/lib/api/ci/runner_shared_examples.rb
+++ b/spec/support/shared_examples/lib/api/ci/runner_shared_examples.rb
@@ -1,14 +1,14 @@
 # frozen_string_literal: true
 
 RSpec.shared_examples 'API::CI::Runner application context metadata' do |api_route|
-  it 'contains correct context metadata' do
+  it 'contains correct context metadata', :context_aware do
     # Avoids popping the context from the thread so we can
     # check its content after the request.
     allow(Labkit::Context).to receive(:pop)
 
     send_request
 
-    Labkit::Context.with_context do |context|
+    Gitlab::ApplicationContext.with_raw_context do |context|
       expected_context = {
         'meta.caller_id' => api_route,
         'meta.user' => job.user.username,
diff --git a/spec/support/shared_examples/requests/api/logging_application_context_shared_examples.rb b/spec/support/shared_examples/requests/api/logging_application_context_shared_examples.rb
index 4a71b696d57d6c098674d01f54eb961d4eebd3a2..57e28e6df57c5fbc003679795a4e4411856ee876 100644
--- a/spec/support/shared_examples/requests/api/logging_application_context_shared_examples.rb
+++ b/spec/support/shared_examples/requests/api/logging_application_context_shared_examples.rb
@@ -1,21 +1,13 @@
 # frozen_string_literal: true
 
 RSpec.shared_examples 'storing arguments in the application context' do
-  around do |example|
-    Labkit::Context.with_context { example.run }
-  end
-
-  it 'places the expected params in the application context' do
+  it 'places the expected params in the application context', :context_aware do
     # Stub the clearing of the context so we can validate it later
-    # The `around` block above makes sure we do clean it up later
     allow(Labkit::Context).to receive(:pop)
 
     subject
 
-    Labkit::Context.with_context do |context|
-      expect(context.to_h)
-        .to include(log_hash(expected_params))
-    end
+    expect(Gitlab::ApplicationContext.current).to include(log_hash(expected_params))
   end
 
   def log_hash(hash)
diff --git a/spec/workers/background_migration_worker_spec.rb b/spec/workers/background_migration_worker_spec.rb
index 8094efcaf04aadf0f47171b58f7c902455c23e71..4575c270042640504c9ae4d803bb3b9299025f0f 100644
--- a/spec/workers/background_migration_worker_spec.rb
+++ b/spec/workers/background_migration_worker_spec.rb
@@ -101,7 +101,7 @@
 
     it 'sets the class that will be executed as the caller_id' do
       expect(Gitlab::BackgroundMigration).to receive(:perform) do
-        expect(Labkit::Context.current.to_h).to include('meta.caller_id' => 'Foo')
+        expect(Gitlab::ApplicationContext.current).to include('meta.caller_id' => 'Foo')
       end
 
       worker.perform('Foo', [10, 20])
diff --git a/spec/workers/concerns/worker_context_spec.rb b/spec/workers/concerns/worker_context_spec.rb
index 3de37b99aba2e3addb90e8e75ae4ca2783c48397..ebdb752d900a75cae308e42979fa616857b1c9db 100644
--- a/spec/workers/concerns/worker_context_spec.rb
+++ b/spec/workers/concerns/worker_context_spec.rb
@@ -103,7 +103,7 @@ def self.name
   describe '#with_context' do
     it 'allows modifying context when the job is running' do
       worker.new.with_context(user: build_stubbed(:user, username: 'jane-doe')) do
-        expect(Labkit::Context.current.to_h).to include('meta.user' => 'jane-doe')
+        expect(Gitlab::ApplicationContext.current).to include('meta.user' => 'jane-doe')
       end
     end