Module: Google::Cloud::Debugger

Defined in:
lib/google/cloud/debugger.rb,
lib/google/cloud/debugger/v2.rb,
lib/google/cloud/debugger/agent.rb,
lib/google/cloud/debugger/rails.rb,
lib/google/cloud/debugger/tracer.rb,
lib/google/cloud/debugger/backoff.rb,
lib/google/cloud/debugger/project.rb,
lib/google/cloud/debugger/service.rb,
lib/google/cloud/debugger/version.rb,
lib/google/cloud/debugger/debuggee.rb,
lib/google/cloud/debugger/logpoint.rb,
lib/google/cloud/debugger/snappoint.rb,
lib/google/cloud/debugger/breakpoint.rb,
lib/google/cloud/debugger/middleware.rb,
lib/google/cloud/debugger/credentials.rb,
lib/google/cloud/debugger/transmitter.rb,
lib/google/cloud/debugger/v2/credentials.rb,
lib/google/cloud/debugger/breakpoint_manager.rb,
lib/google/cloud/debugger/breakpoint/variable.rb,
lib/google/cloud/debugger/v2/debugger2_client.rb,
lib/google/cloud/debugger/breakpoint/evaluator.rb,
lib/google/cloud/debugger/breakpoint/validator.rb,
lib/google/cloud/debugger/request_quota_manager.rb,
lib/google/cloud/debugger/v2/controller2_client.rb,
lib/google/cloud/debugger/breakpoint/stack_frame.rb,
lib/google/cloud/debugger/breakpoint/status_message.rb,
lib/google/cloud/debugger/breakpoint/variable_table.rb,
lib/google/cloud/debugger/breakpoint/source_location.rb,
lib/google/cloud/debugger/debuggee/app_uniquifier_generator.rb

Overview

Stackdriver Debugger

Stackdriver Debugger is a feature of the Google Cloud Platform that lets you inspect the state of an application at any code location without using logging statements and without stopping or slowing down your applications. Your users are not impacted during debugging. Using the production debugger you can capture the local variables and call stack and link it back to a specific line location in your source code. You can use this to analyze the production state of your application and understand the behavior of your code in production.

For general information about Stackdriver Debugger, read Stackdriver Debugger Documentation.

The Stackdriver Debugger Ruby library, google-cloud-debugger, provides:

  • Easy-to-use debugger instrumentation that reports state data, such as value of program variables and the call stack, to Stackdriver Debugger when the code at a breakpoint location is executed in your Ruby application. See the instrumenting your app section for how to debug your application, in both development and production.
  • An idiomatic Ruby API for registerying debuggee application, and querying or manipulating breakpoints in registered Ruby debuggee application. See Debugger API section for an introduction to Stackdriver Debugger API.

Instrumenting Your App

This instrumentation library provides the following features to help you debug your applications in production:

  • Automatic application registration. It facilitates multiple running instances of same version of application when hosted in production.
  • A background debugger agent that runs side-by-side with your application that automatically collects state data when code is executed at breakpoint locations.
  • A Rack middleware and Railtie that automatically manages the debugger agent for Ruby on Rails and other Rack-based Ruby applications.

When this library is configured in your running application, and the source code and breakpoints are setup through the Google Cloud Console, You'll be able to interact with your application in real time through the Stackdriver Debugger UI. This library also integrates with Google App Engine Flexible to make debuggee application configuration more seemless.

Note that when no breakpoints are created, the debugger agent consumes very little resource and has no interference with the running application. Once breakpoints are created and depends on where the breakpoints are located, the debugger agent may add a little latency onto each request. The application performance will be back to normal after all breakpoints are finished being evaluated. Be aware the more breakpoints are created, or the harder to reach the breakpoints, the more resource the debugger agent would need to consume.

Using instrumentation with Ruby on Rails

To install application instrumentation in your Ruby on Rails app, add this gem, google-cloud-debugger, to your Gemfile and update your bundle. Then add the following line to your config/application.rb file:

require "google/cloud/debugger/rails"

This will load a Railtie that automatically integrates with the Rails framework by injecting a Rack middleware. The Railtie also takes in the following Rails configuration as parameter of the debugger agent initialization:

# Explicitly enable or disable Stackdriver Debugger Agent
config.google_cloud.use_debugger = true
# Shared Google Cloud Platform project identifier
config.google_cloud.project_id = "gcloud-project"
# Google Cloud Platform project identifier for Stackdriver Debugger only
config.google_cloud.debugger.project_id = "debugger-project"
# Shared Google Cloud authentication json file
config.google_cloud.keyfile = "/path/to/keyfile.json"
# Google Cloud authentication json file for Stackdriver Debugger only
config.google_cloud.debugger.keyfile = "/path/to/debugger/keyfile.json"
# Stackdriver Debugger Agent service name identifier
config.google_cloud.debugger.service_name = "my-ruby-app"
# Stackdriver Debugger Agent service version identifier
config.google_cloud.debugger.service_version = "v1"

See the Railtie class for more information.

Using instrumentation with Sinatra

To install application instrumentation in your Sinatra app, add this gem, google-cloud-debugger, to your Gemfile and update your bundle. Then add the following lines to your main application Ruby file:

require "google/cloud/debugger"
use Google::Cloud::Debugger::Middleware

This will install the debugger middleware in your application.

Configuration parameters may also be passed in as arguments to Middleware.

require "google/cloud/debugger"
use Google::Cloud::Debugger::Middleware project: "debugger-project-id",
                                        keyfile: "/path/to/keyfile.json",
                                        service_name: "my-ruby-app",
                                        service_version: "v1"

Using instrumentation with other Rack-based frameworks

To install application instrumentation in an app using another Rack-based web framework, add this gem, google-cloud-debugger, to your Gemfile and update your bundle. Then add install the debugger middleware in your middleware stack. In most cases, this means adding these lines to your config.ru Rack configuration file:

require "google/cloud/debugger"
use Google::Cloud::Debugger::Middleware

Some web frameworks have an alternate mechanism for modifying the middleware stack. Consult your web framework's documentation for more information.

The Stackdriver diagnostics suite

The debugger library is part of the Stackdriver diagnostics suite, which also includes error reporting, log analysis, and tracing analysis. If you include the stackdriver gem in your Gemfile, this debugger library will be included automatically. In addition, if you include the stackdriver gem in an application using Ruby On Rails, the Railties will be installed automatically. See the documentation for the "stackdriver" gem for more details.

Stackdriver Debugger API

This library also includes an easy to use Ruby client for the Stackdriver Debugger API. This API provides calls to register debuggee application, as well as creating or modifying breakpoints.

For further information on the Debugger API, see Project

Registering debuggee application

require "google/cloud/debugger/v2"

Controller2Client = Google::Cloud::Debugger::V2::Controller2Client
Debuggee = Google::Devtools::Clouddebugger::V2::Debuggee

controller2_client = Controller2Client.new
debuggee = Debuggee.new
response = controller2_client.register_debuggee(debuggee)
debuggee_id = response.debuggee.id

See Stackdriver Debugger Debuggee doc on fields necessary for registerying a debuggee.

Upon successful registration, the response debuggee object will contain a debuggee_id that's later needed to interact with the other Stackdriver Debugger API.

See V2::Controller2Client for details.

List Active Breakpoints

require "google/cloud/debugger/v2"

Controller2Client = Google::Cloud::Debugger::V2::Controller2Client
controller2_client = Controller2Client.new

debuggee_id = ''
response = controller2_client.list_active_breakpoints(debuggee_id)
breakpoints = response.breakpoints

See V2::Controller2Client for details.

Update Active Breakpoint

Users can send custom snapshots for active breakpoints using this API.

require "google/cloud/debugger/v2"

Breakpoint = Google::Devtools::Clouddebugger::V2::Breakpoint
Controller2Client = Google::Cloud::Debugger::V2::Controller2Client

controller2_client = Controller2Client.new
debuggee_id = ''
breakpoint = Breakpoint.new
response =
  controller2_client.update_active_breakpoint(debuggee_id, breakpoint)

See Stackdriver Debugger Breakpoint doc for all available fields for breakpoint.

See V2::Controller2Client for details.

Set Breakpoint

require "google/cloud/debugger/v2"

Breakpoint = Google::Devtools::Clouddebugger::V2::Breakpoint
Debugger2Client = Google::Cloud::Debugger::V2::Debugger2Client

debugger2_client = Debugger2Client.new
debuggee_id = ''
breakpoint = Breakpoint.new
client_version = ''
response = debugger2_client.set_breakpoint(
             debuggee_id, breakpoint, client_version)

See Stackdriver Debugger Breakpoint doc for fields needed to specify breakpoint location.

See V2::Debugger2Client for details.

Get Breakpoint

require "google/cloud/debugger/v2"

Debugger2Client = Google::Cloud::Debugger::V2::Debugger2Client

debugger2_client = Debugger2Client.new
debuggee_id = ''
breakpoint_id = ''
client_version = ''
response = debugger2_client.get_breakpoint(
             debuggee_id, breakpoint_id, client_version)

See V2::Debugger2Client for details.

Delete Breakpoint

require "google/cloud/debugger/v2"

Debugger2Client = Google::Cloud::Debugger::V2::Debugger2Client

debugger2_client = Debugger2Client.new
debuggee_id = ''
breakpoint_id = ''
client_version = ''
debugger2_client.delete_breakpoint(
  debuggee_id, breakpoint_id, client_version)

See V2::Debugger2Client for details.

List Breakpoints

require "google/cloud/debugger/v2"

Debugger2Client = Google::Cloud::Debugger::V2::Debugger2Client

Debugger2Client = Google::Cloud::Debugger::V2::Debugger2Client

debugger2_client = Debugger2Client.new
debuggee_id = ''
client_version = ''
response = debugger2_client.list_breakpoints(debuggee_id, client_version)

See V2::Debugger2Client for details.

List Debuggees

require "google/cloud/debugger/v2"

Debugger2Client = Google::Cloud::Debugger::V2::Debugger2Client

debugger2_client = Debugger2Client.new
project = ''
client_version = ''
response = debugger2_client.list_debuggees(project, client_version)

See V2::Debugger2Client for details.

Enabling Logging

To enable logging for this library, set the logger for the underlying gRPC library. The logger that you set may be a Ruby stdlib Logger as shown below, or a Google::Cloud::Logging::Logger that will write logs to Stackdriver Logging. See grpc/logconfig.rb and the gRPC spec_helper.rb for additional information.

Configuring a Ruby stdlib logger:

require "logger"

module MyLogger
  LOGGER = Logger.new $stderr, level: Logger::WARN
  def logger
    LOGGER
  end
end

# Define a gRPC module-level logger method before grpc/logconfig.rb loads.
module GRPC
  extend MyLogger
end

Defined Under Namespace

Modules: V2 Classes: Agent, Breakpoint, BreakpointManager, Credentials, Debuggee, Logpoint, Middleware, Project, Railtie, RequestQuotaManager, Snappoint, Tracer, Transmitter

Constant Summary collapse

VERSION =
"0.32.2".freeze

Class Method Summary collapse

Class Method Details

.allow_mutating_methods!(&block) ⇒ Object

Allow calling of potentially state-changing methods even if mutation detection is configured to be active.

Generally it is unwise to run code that may change the program state (e.g. modifying instance variables or causing other side effects) in a breakpoint expression, because it could change the behavior of your program. However, the checks are currently quite conservative, and may block code that is actually safe to run. If you are certain your expression is safe to evaluate, you may use this method to disable side effect checks.

This method may be called with a block, in which case checks are disabled within the block. It may also be called without a block to disable side effect checks for the rest of the current expression; the default setting will be restored for the next expression.

This method may be called only from a debugger condition or expression evaluation, and will throw an exception if you call it from normal application code. Set the allow_mutating_methods configuration if you want to disable the side effect checker globally for your app.

Examples:

Disabling side effect detection in a block

# This is an expression evaluated in a debugger snapshot
Google::Cloud::Debugger.allow_mutating_methods! do
  obj1.method_with_potential_side_effects
end

Disabling side effect detection for the rest of the expression

# This is an expression evaluated in a debugger snapshot
Google::Cloud::Debugger.allow_mutating_methods!
obj1.method_with_potential_side_effects
obj2.another_method_with_potential_side_effects

Globally disabling side effect detection at app initialization

require "google/cloud/debugger"
Google::Cloud::Debugger.configure.allow_mutating_methods = true


556
557
558
559
560
561
562
# File 'lib/google/cloud/debugger.rb', line 556

def self.allow_mutating_methods! &block
  evaluator = Breakpoint::Evaluator.current
  if evaluator.nil?
    raise "allow_mutating_methods can be called only during evaluation"
  end
  evaluator.allow_mutating_methods!(&block)
end

.configure {|Google::Cloud.configure.debugger| ... } ⇒ Google::Cloud::Config

Configure the Stackdriver Debugger agent.

The following Stackdriver Debugger configuration parameters are supported:

  • project_id - (String) Project identifier for the Stackdriver Debugger service you are connecting to. (The parameter project is considered deprecated, but may also be used.)
  • credentials - (String, Hash, Google::Auth::Credentials) The path to the keyfile as a String, the contents of the keyfile as a Hash, or a Google::Auth::Credentials object. (See Credentials) (The parameter keyfile is considered deprecated, but may also be used.)
  • service_name - (String) Name for the debuggee application.
  • service_version - (String) Version identifier for the debuggee application.
  • root - (String) The root directory of the debuggee application as an absolute file path.
  • scope - (String, Array) The OAuth 2.0 scopes controlling the set of resources and operations that the connection can access.
  • timeout - (Integer) Default timeout to use in requests.
  • client_config - (Hash) A hash of values to override the default behavior of the API client.
  • allow_mutating_methods - (boolean) Whether expressions and conditional breakpoints can call methods that could modify program state. Defaults to false.
  • evaluation_time_limit - (Numeric) Time limit in seconds for expression evaluation. Defaults to 0.05.

See the Configuration Guide for full configuration parameters.

Yields:

Returns:

  • (Google::Cloud::Config)

    The configuration object the Google::Cloud::Debugger module uses.



478
479
480
481
482
# File 'lib/google/cloud/debugger.rb', line 478

def self.configure
  yield Google::Cloud.configure.debugger if block_given?

  Google::Cloud.configure.debugger
end

.new(project_id: nil, credentials: nil, service_name: nil, service_version: nil, scope: nil, timeout: nil, client_config: nil, project: nil, keyfile: nil) ⇒ Google::Cloud::Debugger::Project

Creates a new debugger object for instrumenting Stackdriver Debugger for an application. Each call creates a new debugger agent with independent connection service.

For more information on connecting to Google Cloud see the Authentication Guide.

Examples:

require "google/cloud/debugger"

debugger = Google::Cloud::Debugger.new
debugger.start

Parameters:

  • project_id (String)

    Project identifier for the Stackdriver Debugger service you are connecting to. If not present, the default project for the credentials is used.

  • credentials (String, Hash, Google::Auth::Credentials)

    The path to the keyfile as a String, the contents of the keyfile as a Hash, or a Google::Auth::Credentials object. (See Credentials)

  • service_name (String)

    Name for the debuggee application. Optional.

  • service_version (String)

    Version identifier for the debuggee application. Optional.

  • scope (String, Array<String>)

    The OAuth 2.0 scopes controlling the set of resources and operations that the connection can access. See Using OAuth 2.0 to Access Google APIs.

    The default scope is:

    • https://www.googleapis.com/auth/cloud_debugger
    • https://www.googleapis.com/auth/logging.admin
  • timeout (Integer)

    Default timeout to use in requests. Optional.

  • client_config (Hash)

    A hash of values to override the default behavior of the API client. Optional.

  • project (String)

    Project identifier for the Stackdriver Debugger service.

  • keyfile (String, Hash)

    Keyfile downloaded from Google Cloud: either the JSON data or the path to a readable file.

Returns:

Raises:

  • (ArgumentError)


405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
# File 'lib/google/cloud/debugger.rb', line 405

def self.new project_id: nil, credentials: nil, service_name: nil,
             service_version: nil, scope: nil, timeout: nil,
             client_config: nil, project: nil, keyfile: nil
  project_id ||= (project || default_project_id)
  project_id = project_id.to_s # Always cast to a string

  service_name ||= default_service_name
  service_name = service_name.to_s

  service_version ||= default_service_version
  service_version = service_version.to_s

  raise ArgumentError, "project_id is missing" if project_id.empty?
  raise ArgumentError, "service_name is missing" if service_name.empty?
  if service_version.nil?
    raise ArgumentError, "service_version is missing"
  end

  scope ||= configure.scope
  timeout ||= configure.timeout
  client_config ||= configure.client_config

  credentials ||= (keyfile || default_credentials(scope: scope))
  unless credentials.is_a? Google::Auth::Credentials
    credentials = Debugger::Credentials.new credentials, scope: scope
  end

  Debugger::Project.new(
    Debugger::Service.new(project_id, credentials,
                          timeout: timeout, client_config: client_config),
    service_name: service_name,
    service_version: service_version
  )
end