Class: Google::Cloud::Debugger::Middleware

Inherits:
Object
  • Object
show all
Defined in:
lib/google/cloud/debugger/middleware.rb

Overview

Rack Middleware implementation that supports Stackdriver Debugger Agent in Rack-based Ruby frameworks. It instantiates a new debugger agent if one isn't given already. It helps optimize Debugger Agent Tracer performance by suspending and resuming the tracer between each request.

To use this middleware, simply install it in your Rack configuration. The middleware will take care of registering itself with the Stackdriver Debugger and activating the debugger agent. The location of the middleware in the middleware stack matters: breakpoints will be detected in middleware appearing after but not before this middleware.

For best results, you should also call Middleware.start_agents during application initialization. See its documentation for details.

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(app, debugger: nil, **kwargs) ⇒ Google::Cloud::Debugger::Middleware

Create a new Debugger Middleware.

Parameters:

  • app (Rack Application)

    Rack application

  • debugger (Google::Cloud::Debugger::Project)

    A debugger to be used by this middleware. If not given, will construct a new one using the other parameters.

  • *kwargs (Hash)

    Hash of configuration settings. Used for backward API compatibility. See the Configuration Guide for the prefered way to set configuration parameters.



108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
# File 'lib/google/cloud/debugger/middleware.rb', line 108

def initialize app, debugger: nil, **kwargs
  @app = app

  load_config kwargs

  if debugger
    @debugger = debugger
  else
    @debugger =
      Debugger.new(project_id: configuration.project_id,
                   credentials: configuration.credentials,
                   service_name: configuration.service_name,
                   service_version: configuration.service_version)

    @debugger.agent.quota_manager =
      Google::Cloud::Debugger::RequestQuotaManager.new
  end

  Middleware.deferred_start(@debugger)
end

Class Method Details

.start_agentsObject

This should be called once the application determines that it is safe to start background threads and open gRPC connections. It informs the middleware system that it can start debugger agents.

Generally, this matters if the application forks worker processes; this method should be called only after workers are forked, since threads and network connections interact badly with fork. For example, when running Puma in clustered mode, this method should be called in an on_worker_boot block.

If the application does no forking, this method can be called any time early in the application initialization process.

If start_agents is never called, the debugger agent will be started when the first request is received. This should be safe, but it will probably mean breakpoints will not be recognized during that first request. For best results, an application should call this method at the appropriate time.



87
88
89
90
91
# File 'lib/google/cloud/debugger/middleware.rb', line 87

def self.start_agents
  return unless @debuggers_to_start
  @debuggers_to_start.each(&:start)
  @debuggers_to_start = nil
end

Instance Method Details

#call(env) ⇒ Rack::Response

Rack middleware entry point. In most Rack based frameworks, a request is served by one thread. It enables/resume the debugger breakpoints tracing and stops/pauses the tracing afterwards to help improve debugger performance.

Parameters:

  • env (Hash)

    Rack environment hash

Returns:

  • (Rack::Response)

    The response from downstream Rack app



139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
# File 'lib/google/cloud/debugger/middleware.rb', line 139

def call env
  # Ensure the agent is running. (Note the start method is idempotent.)
  @debugger.start

  # Enable/resume breakpoints tracing
  @debugger.agent.tracer.start

  # Use Stackdriver Logger for debugger if available
  if env["rack.logger"].is_a? Google::Cloud::Logging::Logger
    @debugger.agent.logger = env["rack.logger"]
  end

  @app.call env
ensure
  # Stop breakpoints tracing beyond this point
  @debugger.agent.tracer.disable_traces_for_thread

  # Reset quotas after each request finishes.
  @debugger.agent.quota_manager.reset if @debugger.agent.quota_manager
end