From a3f8a7a1bedfff742f767c1257c385292b5981c3 Mon Sep 17 00:00:00 2001
From: Stan Hu <stanhu@gmail.com>
Date: Tue, 2 Mar 2021 16:52:10 -0800
Subject: [PATCH] Improve Marginalia comments for API requests

This change adds a `endpoint_id` annotation to the Marginalia comments
to help trace SQL queries to their origin. Examples:

* For Grape API requests, this is the route
  (e.g. `/api/:version/users/:id`).
* For GraphQL requests, this is `GraphqlController#execute`.
* For Rails requests, this is in the controller and action
  (e.g. `Projects::BlobController#show`).

Relates to https://gitlab.com/gitlab-org/gitlab/-/issues/323161
---
 .../sh-improve-api-marginalia-comments.yml    |  5 +++++
 config/initializers/0_marginalia.rb           |  2 +-
 lib/gitlab/marginalia/comment.rb              |  4 ++++
 spec/requests/api/api_spec.rb                 | 22 +++++++++++++++++++
 4 files changed, 32 insertions(+), 1 deletion(-)
 create mode 100644 changelogs/unreleased/sh-improve-api-marginalia-comments.yml

diff --git a/changelogs/unreleased/sh-improve-api-marginalia-comments.yml b/changelogs/unreleased/sh-improve-api-marginalia-comments.yml
new file mode 100644
index 0000000000000..ad4823edadf5a
--- /dev/null
+++ b/changelogs/unreleased/sh-improve-api-marginalia-comments.yml
@@ -0,0 +1,5 @@
+---
+title: Improve Marginalia comments for API
+merge_request: 55564
+author:
+type: changed
diff --git a/config/initializers/0_marginalia.rb b/config/initializers/0_marginalia.rb
index 33d677fdf7f01..ab21f936cd81d 100644
--- a/config/initializers/0_marginalia.rb
+++ b/config/initializers/0_marginalia.rb
@@ -13,7 +13,7 @@
 # matching against the raw SQL, and prepending the comment prevents color
 # coding from working in the development log.
 Marginalia::Comment.prepend_comment = true if Rails.env.production?
-Marginalia::Comment.components = [:application, :controller, :action, :correlation_id, :jid, :job_class]
+Marginalia::Comment.components = [:application, :controller, :action, :correlation_id, :jid, :job_class, :endpoint_id]
 
 # As mentioned in https://github.com/basecamp/marginalia/pull/93/files,
 # adding :line has some overhead because a regexp on the backtrace has
diff --git a/lib/gitlab/marginalia/comment.rb b/lib/gitlab/marginalia/comment.rb
index 7b4e4b06f00d9..ed641b38945d1 100644
--- a/lib/gitlab/marginalia/comment.rb
+++ b/lib/gitlab/marginalia/comment.rb
@@ -37,6 +37,10 @@ def bg_job
           job
         end
       end
+
+      def endpoint_id
+        Labkit::Context.current.to_h['meta.caller_id']
+      end
     end
   end
 end
diff --git a/spec/requests/api/api_spec.rb b/spec/requests/api/api_spec.rb
index 8bd6049e6fabb..67b3a32230f00 100644
--- a/spec/requests/api/api_spec.rb
+++ b/spec/requests/api/api_spec.rb
@@ -133,6 +133,28 @@
     end
   end
 
+  describe 'Marginalia comments' do
+    context 'GET /user/:id' do
+      let_it_be(:user) { create(:user) }
+      let(:component_map) do
+        {
+          "application"       => "test",
+          "endpoint_id"       => "/api/:version/users/:id"
+        }
+      end
+
+      subject { ActiveRecord::QueryRecorder.new { get api("/users/#{user.id}", user) } }
+
+      it 'generates a query that includes the expected annotations' do
+        expect(subject.log.last).to match(/correlation_id:.*/)
+
+        component_map.each do |component, value|
+          expect(subject.log.last).to include("#{component}:#{value}")
+        end
+      end
+    end
+  end
+
   describe 'supported content-types' do
     context 'GET /user/:id.txt' do
       let_it_be(:user) { create(:user) }
-- 
GitLab