canvas-lms/gems/request_context
Isaac Moore c3f03e6186 Add Sentry trace ID to X-Canvas-Meta response header
This change adds Sentry's distributed trace ID to the `X-Canvas-Meta`
response header, so that it may be ingested by the logging pipeline and
accessed downstream.

flag=none
refs DE-1032

test plan:
- with Sentry initialized with a valid DSN, verify that the
  `X-Canvas-Meta` header contains a `st` value containing the Sentry
  trace ID
- verify that the trace ID present in the response header matches the one
  in the `meta` tag inside the body's `<head>`
- verify that when Sentry is not initialized with a valid DSN, the value
  is omitted from the response header, and the app still renders
  responses correctly

Change-Id: I63580b4d5057cebf55e6a4fdbc628d58ed7973f7
Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/284991
Tested-by: Service Cloud Jenkins <svc.cloudjenkins@instructure.com>
Reviewed-by: Jeremy Stanley <jeremy@instructure.com>
Product-Review: Isaac Moore <isaac.moore@instructure.com>
QA-Review: Jeremy Stanley <jeremy@instructure.com>
2022-02-15 23:48:15 +00:00
..
lib Add Sentry trace ID to X-Canvas-Meta response header 2022-02-15 23:48:15 +00:00
spec Add Sentry trace ID to X-Canvas-Meta response header 2022-02-15 23:48:15 +00:00
Gemfile RuboCop: Style/StringLiterals, Style/StringLiteralsInInterpolation 2021-11-25 14:03:06 +00:00
README.md request_context as a gem 2021-03-02 23:02:40 +00:00
request_context.gemspec RuboCop: Style/StringLiterals, Style/StringLiteralsInInterpolation 2021-11-25 14:03:06 +00:00
test.sh request_context as a gem 2021-03-02 23:02:40 +00:00

README.md

RequestContext

Keeping the state for canvas requests.

Usage

RequestContext is a combination of middleware for rails and a kind of global "what is my current state" access from anywhere.

Generator

RequestContext::Generator, when added to the middleware stack for an application, makes sure that every request has a request_context_id on it:

# application.rb
initializer("extend_middleware_stack") do |app|
  app.config.middleware.swap(ActionDispatch::RequestId, RequestContext::Generator)\
  app.config.middleware.insert_after(config.session_store, RequestContext::Session)
end

Why replace the build in RequestId middleware? this one reads the incoming environment for potentially provided request IDs from other services in the 'HTTP_X_REQUEST_CONTEXT_ID' header. This class also provides an interface for accessing the current request id from pretty much anywhere in the app without having to know where it's stored (we use the thread context):

RequestContext::Generator.request_id

In order for this to work, you need the cookie jar to have the right data loaded into it, which you can find being written in the RequestContext::Session middleware. The reason is middleware ordering, the Generator runs after the cookie jar has already been written to on the way out.

You need to use both.

Running Tests

This gem is tested with rspec. You can use test.sh to run it, or do it yourself with bundle exec rspec spec.