aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack/lib/action_dispatch
diff options
context:
space:
mode:
authorDavid Heinemeier Hansson <david@loudthinking.com>2011-10-19 12:59:33 -0500
committerDavid Heinemeier Hansson <david@loudthinking.com>2011-10-19 12:59:33 -0500
commitafde6fdd5ef3e6b0693a7e330777e85ef4cffddb (patch)
treee8cc45b642d1908a1768117eb343ee3bf99c5596 /actionpack/lib/action_dispatch
parent3a746f7c48936bac1c08dcf229c7c8fc74fdfc13 (diff)
downloadrails-afde6fdd5ef3e6b0693a7e330777e85ef4cffddb.tar.gz
rails-afde6fdd5ef3e6b0693a7e330777e85ef4cffddb.tar.bz2
rails-afde6fdd5ef3e6b0693a7e330777e85ef4cffddb.zip
Added X-Request-Id tracking and TaggedLogging to easily log that and other production concerns
Diffstat (limited to 'actionpack/lib/action_dispatch')
-rw-r--r--actionpack/lib/action_dispatch/http/request.rb10
-rw-r--r--actionpack/lib/action_dispatch/middleware/request_id.rb38
2 files changed, 48 insertions, 0 deletions
diff --git a/actionpack/lib/action_dispatch/http/request.rb b/actionpack/lib/action_dispatch/http/request.rb
index 37d0a3e0b8..7a5237dcf3 100644
--- a/actionpack/lib/action_dispatch/http/request.rb
+++ b/actionpack/lib/action_dispatch/http/request.rb
@@ -177,6 +177,16 @@ module ActionDispatch
@remote_ip ||= (@env["action_dispatch.remote_ip"] || ip).to_s
end
+ # Returns the unique request id, which is based off either the X-Request-Id header that can
+ # be generated by a firewall, load balancer, or web server or by the RequestId middleware
+ # (which sets the action_dispatch.request_id environment variable).
+ #
+ # This unique ID is useful for tracing a request from end-to-end as part of logging or debugging.
+ # This relies on the rack variable set by the ActionDispatch::RequestId middleware.
+ def uuid
+ @uuid ||= env["action_dispatch.request_id"]
+ end
+
# Returns the lowercase name of the HTTP server software.
def server_software
(@env['SERVER_SOFTWARE'] && /^([a-zA-Z]+)/ =~ @env['SERVER_SOFTWARE']) ? $1.downcase : nil
diff --git a/actionpack/lib/action_dispatch/middleware/request_id.rb b/actionpack/lib/action_dispatch/middleware/request_id.rb
new file mode 100644
index 0000000000..968ad6c28d
--- /dev/null
+++ b/actionpack/lib/action_dispatch/middleware/request_id.rb
@@ -0,0 +1,38 @@
+require 'digest/md5'
+
+module ActionDispatch
+ # Makes a unique request id available to the action_dispatch.request_id env variable (which is then accessible through
+ # ActionDispatch::Request#uuid) and sends the same id to the client via the X-Request-Id header.
+ #
+ # The unique request id is either based off the X-Request-Id header in the request, which would typically be generated
+ # by a firewall, load balancer, or the web server, or, if this header is not available, a random uuid. If the
+ # header is accepted from the outside world, we sanitize it to a max of 255 chars and alphanumeric and dashes only.
+ #
+ # The unique request id can be used to trace a request end-to-end and would typically end up being part of log files
+ # from multiple pieces of the stack.
+ class RequestId
+ def initialize(app)
+ @app = app
+ end
+
+ def call(env)
+ env["action_dispatch.request_id"] = external_request_id(env) || internal_request_id
+
+ status, headers, body = @app.call(env)
+
+ headers["X-Request-Id"] = env["action_dispatch.request_id"]
+ [ status, headers, body ]
+ end
+
+ private
+ def external_request_id(env)
+ if env["HTTP_X_REQUEST_ID"].present?
+ env["HTTP_X_REQUEST_ID"].gsub(/[^\w\d\-]/, "").first(255)
+ end
+ end
+
+ def internal_request_id
+ SecureRandom.uuid
+ end
+ end
+end