Class: Sixty::Instrument::Rack
- Inherits:
-
Object
- Object
- Sixty::Instrument::Rack
- Defined in:
- lib/sixty/instrument/rack.rb
Overview
Inbound HTTP.
This is the root span every other span in a request hangs off, and it is
what makes "which endpoint got slower" answerable at all. It is Rack
middleware rather than a Rails hook so the same class covers Sinatra,
Roda, Hanami and a bare Rack app — the Node agent patches http.Server
for the same reason.
── Naming, and why the route matters so much ─────────────────────────────
Middleware runs before routing, so at span start all we have is the path.
/users/42 and /users/43 are different paths and the same endpoint, and
recording them separately would mint an operation per user id — the
cardinality cap would be hit within minutes and every one of those
operations would have too little traffic to compare against anything.
So the path is templated on the way in, and on the way out the real Rails route pattern replaces it if the router recorded one. The template is the fallback; the pattern is the truth.
Instance Method Summary collapse
-
#call(env) ⇒ Object
── The rule this method is written to ────────────────────────────────.
-
#initialize(app, config: nil) ⇒ Rack
constructor
A new instance of Rack.
Constructor Details
#initialize(app, config: nil) ⇒ Rack
Returns a new instance of Rack.
28 29 30 31 |
# File 'lib/sixty/instrument/rack.rb', line 28 def initialize(app, config: nil) @app = app @config = config end |
Instance Method Details
#call(env) ⇒ Object
── The rule this method is written to ────────────────────────────────
Nothing the agent does may change what the application returns, and
nothing the agent gets wrong may stop it returning at all. So every
line that belongs to us is inside a rescue, and the one line that
belongs to the application — @app.call(env) — is not wrapped in
anything that could swallow or alter it. A middleware that 500s a
request because a measurement failed has done more damage than every
finding it could ever produce.
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
# File 'lib/sixty/instrument/rack.rb', line 42 def call(env) span = begin start(env) rescue StandardError nil end return @app.call(env) unless span previous = Tracer.current Tracer.current = span begin status, headers, body = @app.call(env) rescue Exception => e # rubocop:disable Lint/RescueException Tracer.current = previous safely { span.attrs[:status] = 500 } safely { finish(span, env, e) } raise end Tracer.current = previous safely do span.attrs[:status] = status length = headers && (headers['content-length'] || headers['Content-Length']) span.attrs[:bytes] = length.to_i if length # A 5xx is an error whether or not anything was raised: the exception # may have been rescued into a rendered error page three layers down, # and from the outside those are the same failure. finish(span, env, status.to_i >= 500 ? StandardError.new("HTTP #{status}") : nil) end [status, headers, body] end |