google-cloud-debugger 0.30.0 → 0.31.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +111 -75
- data/ext/google/cloud/debugger/debugger_c/evaluator.c +14 -9
- data/lib/google-cloud-debugger.rb +55 -0
- data/lib/google/cloud/debugger.rb +140 -22
- data/lib/google/cloud/debugger/agent.rb +4 -4
- data/lib/google/cloud/debugger/breakpoint.rb +2 -2
- data/lib/google/cloud/debugger/breakpoint/evaluator.rb +885 -828
- data/lib/google/cloud/debugger/breakpoint/source_location.rb +1 -2
- data/lib/google/cloud/debugger/breakpoint/validator.rb +6 -6
- data/lib/google/cloud/debugger/breakpoint/variable.rb +7 -8
- data/lib/google/cloud/debugger/breakpoint_manager.rb +1 -1
- data/lib/google/cloud/debugger/credentials.rb +7 -7
- data/lib/google/cloud/debugger/debuggee.rb +4 -8
- data/lib/google/cloud/debugger/debuggee/app_uniquifier_generator.rb +0 -2
- data/lib/google/cloud/debugger/logpoint.rb +1 -1
- data/lib/google/cloud/debugger/middleware.rb +16 -18
- data/lib/google/cloud/debugger/project.rb +2 -28
- data/lib/google/cloud/debugger/rails.rb +21 -9
- data/lib/google/cloud/debugger/service.rb +4 -2
- data/lib/google/cloud/debugger/snappoint.rb +1 -1
- data/lib/google/cloud/debugger/tracer.rb +2 -1
- data/lib/google/cloud/debugger/transmitter.rb +1 -1
- data/lib/google/cloud/debugger/version.rb +1 -1
- metadata +11 -11
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 71f28cd2cdbb26aeb952111ceed9989d726fe066c7b42b15dc6abc01b77c6d80
         | 
| 4 | 
            +
              data.tar.gz: 212961fe1b440ca8934468eedc899ce0304523443944fd4e882e7d07bca60157
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 557129ab5d5b4010df8d7ff0baebe95fe3b20ea5615c2b50e542db0da479c14be7f8ec49e2e72bbfe0eb25d65ca630204f0097657fe26bf7d5e24b08cdc14ab4
         | 
| 7 | 
            +
              data.tar.gz: e87fece9e975bd6b6a194029b880d6a682890af4df8c866b0424bed021744e689752a9454ef824ed26b2cebbb1d07157c8422c3718fbd123dc83997bcc729cf6
         | 
    
        data/README.md
    CHANGED
    
    | @@ -1,6 +1,12 @@ | |
| 1 1 | 
             
            # google-cloud-debugger
         | 
| 2 2 |  | 
| 3 | 
            -
            [Stackdriver Debugger](https://cloud.google.com/debugger/) lets you inspect the | 
| 3 | 
            +
            [Stackdriver Debugger](https://cloud.google.com/debugger/) lets you inspect the
         | 
| 4 | 
            +
            state of a running application at any code location in real time, without
         | 
| 5 | 
            +
            stopping or slowing down the application, and without modifying the code to add
         | 
| 6 | 
            +
            logging statements. You can use Stackdriver Debugger with any deployment of
         | 
| 7 | 
            +
            your application, including test, development, and production. The Ruby
         | 
| 8 | 
            +
            debugger adds minimal request latency, typically less than 50ms, and only when
         | 
| 9 | 
            +
            application state is captured. In most cases, this is not noticeable by users.
         | 
| 4 10 |  | 
| 5 11 | 
             
            - [google-cloud-debugger documentation](http://googlecloudplatform.github.io/google-cloud-ruby/#/docs/google-cloud-debugger/master/google/cloud/debugger)
         | 
| 6 12 | 
             
            - [google-cloud-debugger on RubyGems](https://rubygems.org/gems/google-cloud-debugger)
         | 
| @@ -8,44 +14,28 @@ | |
| 8 14 |  | 
| 9 15 | 
             
            ## Quick Start
         | 
| 10 16 |  | 
| 11 | 
            -
             | 
| 17 | 
            +
            ### Installing the gem
         | 
| 12 18 |  | 
| 13 | 
            -
             | 
| 14 | 
            -
            $ gem install google-cloud-debugger
         | 
| 15 | 
            -
            ```
         | 
| 16 | 
            -
             | 
| 17 | 
            -
            Or install through Bundler:
         | 
| 18 | 
            -
             | 
| 19 | 
            -
            1. Add the `google-cloud-debugger` gem to your Gemfile:
         | 
| 19 | 
            +
            Add the `google-cloud-debugger` gem to your Gemfile:
         | 
| 20 20 |  | 
| 21 21 | 
             
            ```ruby
         | 
| 22 22 | 
             
            gem "google-cloud-debugger"
         | 
| 23 23 | 
             
            ```
         | 
| 24 24 |  | 
| 25 | 
            -
             | 
| 26 | 
            -
             | 
| 27 | 
            -
             | 
| 28 | 
            -
            $ bundle install
         | 
| 29 | 
            -
            ```
         | 
| 25 | 
            +
            Alternatively, consider installing the [`stackdriver`](../stackdriver) gem. It
         | 
| 26 | 
            +
            includes the `google-cloud-debugger` gem as a dependency, and automatically
         | 
| 27 | 
            +
            initializes it for some application frameworks.
         | 
| 30 28 |  | 
| 31 | 
            -
             | 
| 32 | 
            -
            the `google-cloud-debugger` gem.
         | 
| 29 | 
            +
            ### Initializing the Debugger
         | 
| 33 30 |  | 
| 34 | 
            -
             | 
| 31 | 
            +
            The Stackdriver Debugger library provides a Debugger agent that helps create
         | 
| 32 | 
            +
            breakpoints in your running applications. It then collects application snapshot
         | 
| 33 | 
            +
            data and transmits it to the Stackdriver Debugger service for you to view on
         | 
| 34 | 
            +
            the Google Cloud Console. The library also comes with a Railtie and a Rack
         | 
| 35 | 
            +
            Middleware to help control the Debugger agent in popular Rack based frameworks,
         | 
| 36 | 
            +
            such as Ruby on Rails and Sinatra.
         | 
| 35 37 |  | 
| 36 | 
            -
             | 
| 37 | 
            -
            API](https://console.cloud.google.com/apis/library/clouddebugger.googleapis.com)
         | 
| 38 | 
            -
            to be enabled on your Google Cloud project. Make sure it's enabled if not
         | 
| 39 | 
            -
            already.
         | 
| 40 | 
            -
             | 
| 41 | 
            -
            ## Enabling the Debugger agent
         | 
| 42 | 
            -
             | 
| 43 | 
            -
            The Stackdriver Debugger library provides a Debugger agent that helps instrument
         | 
| 44 | 
            -
            breakpoints in your running applications. The library also comes with a Railtie
         | 
| 45 | 
            -
            and a Rack Middleware to help control the Debugger agent in popular Rack based
         | 
| 46 | 
            -
            frameworks, such as Ruby on Rails and Sinatra.
         | 
| 47 | 
            -
             | 
| 48 | 
            -
            ### With Ruby on Rails
         | 
| 38 | 
            +
            #### Setup with Ruby on Rails
         | 
| 49 39 |  | 
| 50 40 | 
             
            You can load the Railtie that comes with the library into your Ruby
         | 
| 51 41 | 
             
            on Rails application by explicitly requiring it during the application startup:
         | 
| @@ -58,7 +48,7 @@ require "google/cloud/debugger/rails" | |
| 58 48 | 
             
            If you're using the `stackdriver` gem, it automatically loads the Railtie into
         | 
| 59 49 | 
             
            your application when it starts.
         | 
| 60 50 |  | 
| 61 | 
            -
             | 
| 51 | 
            +
            #### Setup with other Rack-based frameworks
         | 
| 62 52 |  | 
| 63 53 | 
             
            Other Rack-based frameworks, such as Sinatra, can use the Rack Middleware
         | 
| 64 54 | 
             
            provided by the library:
         | 
| @@ -68,38 +58,42 @@ require "google/cloud/debugger" | |
| 68 58 | 
             
            use Google::Cloud::Debugger::Middleware
         | 
| 69 59 | 
             
            ```
         | 
| 70 60 |  | 
| 71 | 
            -
             | 
| 61 | 
            +
            #### Setup without a Rack-based framework
         | 
| 72 62 |  | 
| 73 | 
            -
            Non-rack-based applications can start the agent explicitly  | 
| 74 | 
            -
             | 
| 63 | 
            +
            Non-rack-based applications can start the agent explicitly during the
         | 
| 64 | 
            +
            initialization code:
         | 
| 75 65 |  | 
| 76 66 | 
             
            ```ruby
         | 
| 77 67 | 
             
            require "google/cloud/debugger"
         | 
| 78 68 | 
             
            Google::Cloud::Debugger.new.start
         | 
| 79 69 | 
             
            ```
         | 
| 80 70 |  | 
| 81 | 
            -
            ###  | 
| 71 | 
            +
            ### Connecting to the Debugger
         | 
| 82 72 |  | 
| 83 | 
            -
            You can  | 
| 84 | 
            -
             | 
| 85 | 
            -
             | 
| 73 | 
            +
            You can set breakpoints and view snapshots using the Google Cloud Console.
         | 
| 74 | 
            +
            If your app is hosted on Google Cloud (such as on Google App Engine, Google
         | 
| 75 | 
            +
            Kubernetes Engine, or Google Compute Engine), you can use the same project.
         | 
| 76 | 
            +
            Otherwise, if your application is hosted elsewhere, create a new project on
         | 
| 77 | 
            +
            [Google Cloud](https://console.cloud.google.com/).
         | 
| 86 78 |  | 
| 87 | 
            -
             | 
| 79 | 
            +
            Make sure the
         | 
| 80 | 
            +
            [Stackdriver Debugger API](https://console.cloud.google.com/apis/library/clouddebugger.googleapis.com)
         | 
| 81 | 
            +
            is enabled on your Google Cloud project.
         | 
| 88 82 |  | 
| 89 | 
            -
             | 
| 90 | 
            -
             | 
| 91 | 
            -
             | 
| 83 | 
            +
            To connect to the Stackdriver Debugger service, the agent needs to be
         | 
| 84 | 
            +
            authenticated. If your application is hosted on Google Cloud Platform, much of
         | 
| 85 | 
            +
            this is handled for you automatically.
         | 
| 92 86 |  | 
| 93 | 
            -
             | 
| 87 | 
            +
            #### Connecting from Google App Engine (GAE)
         | 
| 94 88 |  | 
| 95 | 
            -
             | 
| 96 | 
            -
            default, and  | 
| 97 | 
            -
             | 
| 89 | 
            +
            If your app is running on Google App Engine, the Stackdriver Debugger agent
         | 
| 90 | 
            +
            authenticates automatically by default, and no additional configuration is
         | 
| 91 | 
            +
            required.
         | 
| 98 92 |  | 
| 99 | 
            -
             | 
| 93 | 
            +
            #### Connecting from Google Kubernetes Engine (GKE)
         | 
| 100 94 |  | 
| 101 | 
            -
             | 
| 102 | 
            -
            scope when creating the cluster:
         | 
| 95 | 
            +
            If your app is running on Google Kubernetes Engine, you must explicitly add the
         | 
| 96 | 
            +
            `cloud_debugger` OAuth scope when creating the cluster:
         | 
| 103 97 |  | 
| 104 98 | 
             
            ```sh
         | 
| 105 99 | 
             
            $ gcloud container clusters create example-cluster-name --scopes https://www.googleapis.com/auth/cloud_debugger
         | 
| @@ -108,11 +102,14 @@ $ gcloud container clusters create example-cluster-name --scopes https://www.goo | |
| 108 102 | 
             
            You can also do this through the Google Cloud Platform Console. Select
         | 
| 109 103 | 
             
            **Enabled** in the Cloud Platform section of **Create a container cluster**.
         | 
| 110 104 |  | 
| 111 | 
            -
             | 
| 105 | 
            +
            After the OAuth scope is enabled, the Stackdriver Debugger agent authenticates
         | 
| 106 | 
            +
            automatically by default, and no additional configuration is required.
         | 
| 112 107 |  | 
| 113 | 
            -
             | 
| 114 | 
            -
             | 
| 115 | 
            -
             | 
| 108 | 
            +
            #### Connecting from Google Compute Engine (GCE)
         | 
| 109 | 
            +
             | 
| 110 | 
            +
            If your app is running on Google Compute Engine, its VM instances should have
         | 
| 111 | 
            +
            one of the following access scopes. These are only relevant when you use
         | 
| 112 | 
            +
            Compute Engine's default service account:
         | 
| 116 113 |  | 
| 117 114 | 
             
            * `https://www.googleapis.com/auth/cloud-platform`
         | 
| 118 115 | 
             
            * `https://www.googleapis.com/auth/cloud_debugger`
         | 
| @@ -122,25 +119,21 @@ through the Google Cloud Platform Console. Select **Allow full access to all | |
| 122 119 | 
             
            Cloud APIs** in the **Identity and API access** section of **Create an
         | 
| 123 120 | 
             
            instance**.
         | 
| 124 121 |  | 
| 125 | 
            -
            The `cloud_debugger` access scope  | 
| 122 | 
            +
            The `cloud_debugger` access scope can be supplied manually using the SDK's
         | 
| 126 123 | 
             
            `gcloud compute instances create` command or the `gcloud compute instances
         | 
| 127 124 | 
             
            set-service-account` command.
         | 
| 128 125 |  | 
| 129 | 
            -
             | 
| 126 | 
            +
            After the OAuth scope is enabled, the Stackdriver Debugger agent authenticates
         | 
| 127 | 
            +
            automatically by default using the VM's service account, and no additional
         | 
| 128 | 
            +
            configuration is required.
         | 
| 129 | 
            +
             | 
| 130 | 
            +
            #### Connecting from other hosting environments
         | 
| 130 131 |  | 
| 131 132 | 
             
            To run the Stackdriver Debugger agent outside of Google Cloud Platform, you must
         | 
| 132 133 | 
             
            supply your GCP project ID and appropriate service account credentials directly
         | 
| 133 134 | 
             
            to the Stackdriver Debugger agent. This applies to running the agent on your own
         | 
| 134 135 | 
             
            workstation, on your datacenter's computers, or on the VM instances of another
         | 
| 135 | 
            -
            cloud provider. | 
| 136 | 
            -
            instructions on how to do so.
         | 
| 137 | 
            -
             | 
| 138 | 
            -
            ## Authentication
         | 
| 139 | 
            -
             | 
| 140 | 
            -
            This library uses Service Account credentials to connect to Google Cloud
         | 
| 141 | 
            -
            services. When running on Compute Engine the credentials will be discovered
         | 
| 142 | 
            -
            automatically. When running on other environments the Service Account
         | 
| 143 | 
            -
            credentials can be specified by providing in several ways.
         | 
| 136 | 
            +
            cloud provider.
         | 
| 144 137 |  | 
| 145 138 | 
             
            The best way to provide authentication information if you're using Ruby on Rails
         | 
| 146 139 | 
             
            is through the Rails configuration interface:
         | 
| @@ -150,25 +143,25 @@ is through the Rails configuration interface: | |
| 150 143 | 
             
            Rails.application.configure do |config|
         | 
| 151 144 | 
             
              # Shared parameters
         | 
| 152 145 | 
             
              config.google_cloud.project_id = "your-project-id"
         | 
| 153 | 
            -
              config.google_cloud. | 
| 146 | 
            +
              config.google_cloud.credentials = "/path/to/key.json"
         | 
| 154 147 | 
             
              # Or Stackdriver Debugger agent specific parameters
         | 
| 155 148 | 
             
              config.google_cloud.debugger.project_id = "your-project-id"
         | 
| 156 | 
            -
              config.google_cloud.debugger. | 
| 149 | 
            +
              config.google_cloud.debugger.credentials = "/path/to/key.json"
         | 
| 157 150 | 
             
            end
         | 
| 158 151 | 
             
            ```
         | 
| 159 152 |  | 
| 160 | 
            -
            Other Rack-based applications that are loading the Rack Middleware directly can | 
| 161 | 
            -
            the configration interface:
         | 
| 153 | 
            +
            Other Rack-based applications that are loading the Rack Middleware directly can
         | 
| 154 | 
            +
            use the configration interface:
         | 
| 162 155 |  | 
| 163 156 | 
             
            ```ruby
         | 
| 164 157 | 
             
            require "google/cloud/debugger"
         | 
| 165 158 | 
             
            Google::Cloud.configure do |config|
         | 
| 166 159 | 
             
              # Shared parameters
         | 
| 167 160 | 
             
              config.project_id = "your-project-id"
         | 
| 168 | 
            -
              config. | 
| 161 | 
            +
              config.credentials = "/path/to/key.json"
         | 
| 169 162 | 
             
              # Or Stackdriver Debugger agent specific parameters
         | 
| 170 163 | 
             
              config.debugger.project_id = "your-project-id"
         | 
| 171 | 
            -
              config.debugger. | 
| 164 | 
            +
              config.debugger.credentials = "/path/to/key.json"
         | 
| 172 165 | 
             
            end
         | 
| 173 166 | 
             
            ```
         | 
| 174 167 |  | 
| @@ -184,15 +177,58 @@ This library also supports the other authentication methods provided by the | |
| 184 177 | 
             
            `google-cloud-ruby` suite. Instructions and configuration options are covered
         | 
| 185 178 | 
             
            in the [Authentication Guide](https://googlecloudplatform.github.io/google-cloud-ruby/#/docs/google-cloud-debugger/guides/authentication).
         | 
| 186 179 |  | 
| 187 | 
            -
             | 
| 180 | 
            +
            ### Using the Debugger
         | 
| 181 | 
            +
             | 
| 182 | 
            +
            When you set a breakpoint in the Stackdriver Debugger console, the agent takes
         | 
| 183 | 
            +
            a snapshot of application data when the breakpoint is hit. The application then
         | 
| 184 | 
            +
            continues running with minimal slowdown, and you can view the snapshot offline
         | 
| 185 | 
            +
            in the console.
         | 
| 186 | 
            +
             | 
| 187 | 
            +
            By default, the snapshot includes the local variables from the current and four
         | 
| 188 | 
            +
            most recent stack frames. You may include additional data in the snapshot by
         | 
| 189 | 
            +
            providing a list of _expressions_ when you create the breakpoint. Expressions
         | 
| 190 | 
            +
            may be instance variables, global variables, or the result of calling Ruby
         | 
| 191 | 
            +
            methods, or indeed, any Ruby expression.
         | 
| 192 | 
            +
             | 
| 193 | 
            +
            For more information on using the debugger features, see the
         | 
| 194 | 
            +
            [Stackdriver Debugger Documentation](https://cloud.google.com/debugger/docs/).
         | 
| 195 | 
            +
             | 
| 196 | 
            +
            #### Working with Mutation Protection
         | 
| 197 | 
            +
             | 
| 198 | 
            +
            To reduce the risk of corrupting your application data or changing your
         | 
| 199 | 
            +
            application's behavior, the debugger agent checks all expressions you provide
         | 
| 200 | 
            +
            for possible side effects before it runs them. If an expression calls any code
         | 
| 201 | 
            +
            that could modify the program state, by changing an instance variable for
         | 
| 202 | 
            +
            example, it is not evaluated.
         | 
| 203 | 
            +
             | 
| 204 | 
            +
            This check is rather conservative, so if you are receiving mutation errors on
         | 
| 205 | 
            +
            an expression you know to be safe, you may disable the check by wrapping your
         | 
| 206 | 
            +
            expression in a call to `Google::Cloud::Debugger.allow_mutating_methods!`. For
         | 
| 207 | 
            +
            example:
         | 
| 208 | 
            +
             | 
| 209 | 
            +
            ```ruby
         | 
| 210 | 
            +
            Google::Cloud::Debugger.allow_mutating_methods! { my_expression() }
         | 
| 211 | 
            +
            ```
         | 
| 212 | 
            +
             | 
| 213 | 
            +
            You may disable side effect checks globally by setting the
         | 
| 214 | 
            +
            `allow_mutating_methods` configuration. See the next section on configuring the
         | 
| 215 | 
            +
            agent.
         | 
| 216 | 
            +
             | 
| 217 | 
            +
            #### Configuring the agent
         | 
| 188 218 |  | 
| 189 | 
            -
             | 
| 219 | 
            +
            You can customize the behavior of the Stackdriver Debugger agent. This includes
         | 
| 220 | 
            +
            setting the Google Cloud project and authentication, and customizing the
         | 
| 221 | 
            +
            behavior of the debugger itself, such as side effect protection and data
         | 
| 222 | 
            +
            size limits. See [agent configuration](../stackdriver/docs/configuration.md)
         | 
| 223 | 
            +
            for a list of possible configuration options.
         | 
| 190 224 |  | 
| 191 | 
            -
            ##  | 
| 225 | 
            +
            ## Compatibility
         | 
| 192 226 |  | 
| 193 | 
            -
            This library  | 
| 227 | 
            +
            This library is supported on Ruby 2.2 or later.
         | 
| 194 228 |  | 
| 195 | 
            -
             | 
| 229 | 
            +
            This library follows [Semantic Versioning](http://semver.org/). It is currently
         | 
| 230 | 
            +
            in major version zero (0.y.z), which means that anything may change at any time
         | 
| 231 | 
            +
            and the public API should not be considered stable.
         | 
| 196 232 |  | 
| 197 233 | 
             
            ## Contributing
         | 
| 198 234 |  | 
| @@ -21,8 +21,8 @@ | |
| 21 21 | 
             
            static void
         | 
| 22 22 | 
             
            eval_trace_callback(void *data, rb_trace_arg_t *trace_arg)
         | 
| 23 23 | 
             
            {
         | 
| 24 | 
            -
                rb_event_flag_t event | 
| 25 | 
            -
                VALUE evaluator | 
| 24 | 
            +
                rb_event_flag_t event;
         | 
| 25 | 
            +
                VALUE evaluator;
         | 
| 26 26 | 
             
                VALUE klass;
         | 
| 27 27 | 
             
                VALUE obj;
         | 
| 28 28 | 
             
                VALUE method_id;
         | 
| @@ -32,15 +32,16 @@ eval_trace_callback(void *data, rb_trace_arg_t *trace_arg) | |
| 32 32 | 
             
                CONST_ID(trace_func_cb_id, "trace_func_callback");
         | 
| 33 33 | 
             
                CONST_ID(trace_c_func_cb_id, "trace_c_func_callback");
         | 
| 34 34 |  | 
| 35 | 
            +
                event = rb_tracearg_event_flag(trace_arg);
         | 
| 36 | 
            +
                evaluator = (VALUE)data;
         | 
| 35 37 | 
             
                obj = rb_tracearg_self(trace_arg);
         | 
| 36 38 | 
             
                method_id = rb_tracearg_method_id(trace_arg);
         | 
| 39 | 
            +
                klass = rb_tracearg_defined_class(trace_arg);
         | 
| 37 40 |  | 
| 38 41 | 
             
                if (event & RUBY_EVENT_CALL) {
         | 
| 39 | 
            -
                    rb_funcall(evaluator, trace_func_cb_id,  | 
| 42 | 
            +
                    rb_funcall(evaluator, trace_func_cb_id, 3, obj, klass, method_id);
         | 
| 40 43 | 
             
                }
         | 
| 41 44 | 
             
                if (event & RUBY_EVENT_C_CALL) {
         | 
| 42 | 
            -
                    klass = rb_tracearg_defined_class(trace_arg);
         | 
| 43 | 
            -
             | 
| 44 45 | 
             
                    rb_funcall(evaluator, trace_c_func_cb_id, 3, obj, klass, method_id);
         | 
| 45 46 | 
             
                }
         | 
| 46 47 |  | 
| @@ -79,10 +80,13 @@ rb_enable_method_trace_for_thread(VALUE self) | |
| 79 80 | 
             
                VALUE current_thread;
         | 
| 80 81 | 
             
                VALUE thread_variables_hash;
         | 
| 81 82 | 
             
                VALUE trace_set;
         | 
| 83 | 
            +
                VALUE evaluator;
         | 
| 84 | 
            +
                ID current_evaluator_id;
         | 
| 82 85 | 
             
                ID locals_id;
         | 
| 83 86 | 
             
                ID eval_trace_thread_id;
         | 
| 84 87 | 
             
                VALUE eval_trace_thread_flag;
         | 
| 85 88 |  | 
| 89 | 
            +
                CONST_ID(current_evaluator_id, "current");
         | 
| 86 90 | 
             
                CONST_ID(locals_id, "locals");
         | 
| 87 91 | 
             
                CONST_ID(eval_trace_thread_id, "gcloud_eval_trace_set");
         | 
| 88 92 | 
             
                eval_trace_thread_flag = ID2SYM(eval_trace_thread_id);
         | 
| @@ -90,9 +94,10 @@ rb_enable_method_trace_for_thread(VALUE self) | |
| 90 94 | 
             
                current_thread = rb_thread_current();
         | 
| 91 95 | 
             
                thread_variables_hash = rb_ivar_get(current_thread, locals_id);
         | 
| 92 96 | 
             
                trace_set = rb_hash_aref(thread_variables_hash, eval_trace_thread_flag);
         | 
| 97 | 
            +
                evaluator = rb_funcall(self, current_evaluator_id, 0);
         | 
| 93 98 |  | 
| 94 99 | 
             
                if (!RTEST(trace_set)) {
         | 
| 95 | 
            -
                    rb_thread_add_event_hook2(current_thread, (rb_event_hook_func_t)eval_trace_callback, RUBY_EVENT_CALL | RUBY_EVENT_C_CALL,  | 
| 100 | 
            +
                    rb_thread_add_event_hook2(current_thread, (rb_event_hook_func_t)eval_trace_callback, RUBY_EVENT_CALL | RUBY_EVENT_C_CALL, evaluator, RUBY_EVENT_HOOK_FLAG_RAW_ARG | RUBY_EVENT_HOOK_FLAG_SAFE);
         | 
| 96 101 | 
             
                    rb_hash_aset(thread_variables_hash, eval_trace_thread_flag, Qtrue);
         | 
| 97 102 | 
             
                }
         | 
| 98 103 |  | 
| @@ -103,8 +108,8 @@ void | |
| 103 108 | 
             
            Init_evaluator(VALUE mDebugger)
         | 
| 104 109 | 
             
            {
         | 
| 105 110 | 
             
                VALUE cBreakpoint = rb_define_class_under(mDebugger, "Breakpoint", rb_cObject);
         | 
| 106 | 
            -
                VALUE  | 
| 111 | 
            +
                VALUE cEvaluator  = rb_define_class_under(cBreakpoint, "Evaluator", rb_cObject);
         | 
| 107 112 |  | 
| 108 | 
            -
                rb_define_module_function( | 
| 109 | 
            -
                rb_define_module_function( | 
| 113 | 
            +
                rb_define_module_function(cEvaluator, "enable_method_trace_for_thread", rb_enable_method_trace_for_thread, 0);
         | 
| 114 | 
            +
                rb_define_module_function(cEvaluator, "disable_method_trace_for_thread", rb_disable_method_trace_for_thread, 0);
         | 
| 110 115 | 
             
            }
         | 
| @@ -20,6 +20,8 @@ | |
| 20 20 |  | 
| 21 21 | 
             
            gem "google-cloud-core"
         | 
| 22 22 | 
             
            require "google/cloud"
         | 
| 23 | 
            +
            require "google/cloud/config"
         | 
| 24 | 
            +
            require "googleauth"
         | 
| 23 25 |  | 
| 24 26 | 
             
            module Google
         | 
| 25 27 | 
             
              module Cloud
         | 
| @@ -42,6 +44,8 @@ module Google | |
| 42 44 | 
             
                #   The default scope is:
         | 
| 43 45 | 
             
                #
         | 
| 44 46 | 
             
                #   * `https://www.googleapis.com/auth/cloud_debugger`
         | 
| 47 | 
            +
                #   * `https://www.googleapis.com/auth/logging.admin`
         | 
| 48 | 
            +
                #
         | 
| 45 49 | 
             
                # @param [Integer] timeout Default timeout to use in requests. Optional.
         | 
| 46 50 | 
             
                # @param [Hash] client_config A hash of values to override the default
         | 
| 47 51 | 
             
                #   behavior of the API client. Optional.
         | 
| @@ -97,6 +101,8 @@ module Google | |
| 97 101 | 
             
                #   The default scope is:
         | 
| 98 102 | 
             
                #
         | 
| 99 103 | 
             
                #   * `https://www.googleapis.com/auth/cloud_debugger`
         | 
| 104 | 
            +
                #   * `https://www.googleapis.com/auth/logging.admin`
         | 
| 105 | 
            +
                #
         | 
| 100 106 | 
             
                # @param [Integer] timeout Default timeout to use in requests. Optional.
         | 
| 101 107 | 
             
                # @param [Hash] client_config A hash of values to override the default
         | 
| 102 108 | 
             
                #   behavior of the API client. Optional.
         | 
| @@ -123,3 +129,52 @@ module Google | |
| 123 129 | 
             
                end
         | 
| 124 130 | 
             
              end
         | 
| 125 131 | 
             
            end
         | 
| 132 | 
            +
             | 
| 133 | 
            +
            # Add debugger to top-level configuration
         | 
| 134 | 
            +
            Google::Cloud.configure do |config|
         | 
| 135 | 
            +
              unless config.field? :use_debugger
         | 
| 136 | 
            +
                config.add_field! :use_debugger, nil, enum: [true, false]
         | 
| 137 | 
            +
              end
         | 
| 138 | 
            +
              unless config.field? :service_name
         | 
| 139 | 
            +
                config.add_field! :service_name, nil, match: String
         | 
| 140 | 
            +
              end
         | 
| 141 | 
            +
              unless config.field? :service_version
         | 
| 142 | 
            +
                config.add_field! :service_version, nil, match: String
         | 
| 143 | 
            +
              end
         | 
| 144 | 
            +
            end
         | 
| 145 | 
            +
             | 
| 146 | 
            +
            # Set the default debugger configuration
         | 
| 147 | 
            +
            Google::Cloud.configure.add_config! :debugger do |config|
         | 
| 148 | 
            +
              default_project = Google::Cloud::Config.deferred do
         | 
| 149 | 
            +
                ENV["DEBUGGER_PROJECT"]
         | 
| 150 | 
            +
              end
         | 
| 151 | 
            +
              default_creds = Google::Cloud::Config.deferred do
         | 
| 152 | 
            +
                Google::Cloud::Config.credentials_from_env \
         | 
| 153 | 
            +
                  "DEBUGGER_CREDENTIALS", "DEBUGGER_CREDENTIALS_JSON",
         | 
| 154 | 
            +
                  "DEBUGGER_KEYFILE", "DEBUGGER_KEYFILE_JSON"
         | 
| 155 | 
            +
              end
         | 
| 156 | 
            +
              default_service = Google::Cloud::Config.deferred do
         | 
| 157 | 
            +
                ENV["DEBUGGER_SERVICE_NAME"]
         | 
| 158 | 
            +
              end
         | 
| 159 | 
            +
              default_version = Google::Cloud::Config.deferred do
         | 
| 160 | 
            +
                ENV["DEBUGGER_SERVICE_VERSION"]
         | 
| 161 | 
            +
              end
         | 
| 162 | 
            +
             | 
| 163 | 
            +
              config.add_field! :project_id, default_project, match: String, allow_nil: true
         | 
| 164 | 
            +
              config.add_alias! :project, :project_id
         | 
| 165 | 
            +
              config.add_field! :credentials, default_creds,
         | 
| 166 | 
            +
                                match: [String, Hash, Google::Auth::Credentials],
         | 
| 167 | 
            +
                                allow_nil: true
         | 
| 168 | 
            +
              config.add_alias! :keyfile, :credentials
         | 
| 169 | 
            +
              config.add_field! :service_name, default_service,
         | 
| 170 | 
            +
                                match: String, allow_nil: true
         | 
| 171 | 
            +
              config.add_field! :service_version, default_version,
         | 
| 172 | 
            +
                                match: String, allow_nil: true
         | 
| 173 | 
            +
              config.add_field! :app_root, nil, match: String
         | 
| 174 | 
            +
              config.add_field! :root, nil, match: String
         | 
| 175 | 
            +
              config.add_field! :scope, nil, match: [String, Array]
         | 
| 176 | 
            +
              config.add_field! :timeout, nil, match: Integer
         | 
| 177 | 
            +
              config.add_field! :client_config, nil, match: Hash
         | 
| 178 | 
            +
              config.add_field! :allow_mutating_methods, false
         | 
| 179 | 
            +
              config.add_field! :evaluation_time_limit, 0.05, match: Numeric
         | 
| 180 | 
            +
            end
         | 
| @@ -15,6 +15,8 @@ | |
| 15 15 |  | 
| 16 16 | 
             
            require "google-cloud-debugger"
         | 
| 17 17 | 
             
            require "google/cloud/debugger/project"
         | 
| 18 | 
            +
            require "google/cloud/config"
         | 
| 19 | 
            +
            require "google/cloud/env"
         | 
| 18 20 | 
             
            require "stackdriver/core"
         | 
| 19 21 |  | 
| 20 22 | 
             
            module Google
         | 
| @@ -320,15 +322,7 @@ module Google | |
| 320 322 | 
             
                # See {Google::Cloud::Debugger::V2::Debugger2Client} for details.
         | 
| 321 323 | 
             
                #
         | 
| 322 324 | 
             
                module Debugger
         | 
| 323 | 
            -
                  #  | 
| 324 | 
            -
                  # Google::Cloud if haven't already
         | 
| 325 | 
            -
                  unless Google::Cloud.configure.option? :debugger
         | 
| 326 | 
            -
                    Google::Cloud.configure.add_options :debugger
         | 
| 327 | 
            -
             | 
| 328 | 
            -
                    Google::Cloud.configure.define_singleton_method :debugger do
         | 
| 329 | 
            -
                      Google::Cloud.configure[:debugger]
         | 
| 330 | 
            -
                    end
         | 
| 331 | 
            -
                  end
         | 
| 325 | 
            +
                  # rubocop:disable all
         | 
| 332 326 |  | 
| 333 327 | 
             
                  ##
         | 
| 334 328 | 
             
                  # Creates a new debugger object for instrumenting Stackdriver Debugger for
         | 
| @@ -353,8 +347,15 @@ module Google | |
| 353 347 | 
             
                  #   the set of resources and operations that the connection can access.
         | 
| 354 348 | 
             
                  #   See [Using OAuth 2.0 to Access Google
         | 
| 355 349 | 
             
                  #   APIs](https://developers.google.com/identity/protocols/OAuth2).
         | 
| 356 | 
            -
                  # | 
| 350 | 
            +
                  #
         | 
| 351 | 
            +
                  #   The default scope is:
         | 
| 352 | 
            +
                  #
         | 
| 353 | 
            +
                  #   * `https://www.googleapis.com/auth/cloud_debugger`
         | 
| 354 | 
            +
                  #   * `https://www.googleapis.com/auth/logging.admin`
         | 
| 355 | 
            +
                  #
         | 
| 357 356 | 
             
                  # @param [Integer] timeout Default timeout to use in requests. Optional.
         | 
| 357 | 
            +
                  # @param [Hash] client_config A hash of values to override the default
         | 
| 358 | 
            +
                  #   behavior of the API client. Optional.
         | 
| 358 359 | 
             
                  # @param [String] project Project identifier for the Stackdriver Debugger
         | 
| 359 360 | 
             
                  #   service.
         | 
| 360 361 | 
             
                  # @param [String, Hash] keyfile Keyfile downloaded from Google Cloud:
         | 
| @@ -371,18 +372,26 @@ module Google | |
| 371 372 | 
             
                  def self.new project_id: nil, credentials: nil, service_name: nil,
         | 
| 372 373 | 
             
                               service_version: nil, scope: nil, timeout: nil,
         | 
| 373 374 | 
             
                               client_config: nil, project: nil, keyfile: nil
         | 
| 374 | 
            -
                    project_id ||= (project ||  | 
| 375 | 
            +
                    project_id ||= (project || default_project_id)
         | 
| 375 376 | 
             
                    project_id = project_id.to_s # Always cast to a string
         | 
| 376 | 
            -
             | 
| 377 | 
            +
             | 
| 378 | 
            +
                    service_name ||= default_service_name
         | 
| 377 379 | 
             
                    service_name = service_name.to_s
         | 
| 378 | 
            -
             | 
| 380 | 
            +
             | 
| 381 | 
            +
                    service_version ||= default_service_version
         | 
| 379 382 | 
             
                    service_version = service_version.to_s
         | 
| 380 383 |  | 
| 381 | 
            -
                     | 
| 382 | 
            -
                     | 
| 383 | 
            -
                     | 
| 384 | 
            +
                    raise ArgumentError, "project_id is missing" if project_id.empty?
         | 
| 385 | 
            +
                    raise ArgumentError, "service_name is missing" if service_name.empty?
         | 
| 386 | 
            +
                    if service_version.nil?
         | 
| 387 | 
            +
                      raise ArgumentError, "service_version is missing"
         | 
| 388 | 
            +
                    end
         | 
| 389 | 
            +
             | 
| 390 | 
            +
                    scope ||= configure.scope
         | 
| 391 | 
            +
                    timeout ||= configure.timeout
         | 
| 392 | 
            +
                    client_config ||= configure.client_config
         | 
| 384 393 |  | 
| 385 | 
            -
                    credentials ||= (keyfile ||  | 
| 394 | 
            +
                    credentials ||= (keyfile || default_credentials(scope: scope))
         | 
| 386 395 | 
             
                    unless credentials.is_a? Google::Auth::Credentials
         | 
| 387 396 | 
             
                      credentials = Debugger::Credentials.new credentials, scope: scope
         | 
| 388 397 | 
             
                    end
         | 
| @@ -391,23 +400,132 @@ module Google | |
| 391 400 | 
             
                      Debugger::Service.new(project_id, credentials,
         | 
| 392 401 | 
             
                                            timeout: timeout, client_config: client_config),
         | 
| 393 402 | 
             
                      service_name: service_name,
         | 
| 394 | 
            -
                      service_version: service_version | 
| 403 | 
            +
                      service_version: service_version
         | 
| 404 | 
            +
                    )
         | 
| 395 405 | 
             
                  end
         | 
| 396 406 |  | 
| 407 | 
            +
                  # rubocop:enable all
         | 
| 408 | 
            +
             | 
| 397 409 | 
             
                  ##
         | 
| 398 410 | 
             
                  # Configure the Stackdriver Debugger agent.
         | 
| 399 411 | 
             
                  #
         | 
| 412 | 
            +
                  # The following Stackdriver Debugger configuration parameters are
         | 
| 413 | 
            +
                  # supported:
         | 
| 414 | 
            +
                  #
         | 
| 415 | 
            +
                  # * `project_id` - (String) Project identifier for the Stackdriver
         | 
| 416 | 
            +
                  #   Debugger service you are connecting to. (The parameter `project` is
         | 
| 417 | 
            +
                  #   considered deprecated, but may also be used.)
         | 
| 418 | 
            +
                  # * `credentials` - (String, Hash, Google::Auth::Credentials) The path to
         | 
| 419 | 
            +
                  #   the keyfile as a String, the contents of the keyfile as a Hash, or a
         | 
| 420 | 
            +
                  #   Google::Auth::Credentials object. (See {Debugger::Credentials}) (The
         | 
| 421 | 
            +
                  #   parameter `keyfile` is considered deprecated, but may also be used.)
         | 
| 422 | 
            +
                  # * `service_name` - (String) Name for the debuggee application.
         | 
| 423 | 
            +
                  # * `service_version` - (String) Version identifier for the debuggee
         | 
| 424 | 
            +
                  #   application.
         | 
| 425 | 
            +
                  # * `root` - (String) The root directory of the debuggee application as an
         | 
| 426 | 
            +
                  #   absolute file path.
         | 
| 427 | 
            +
                  # * `scope` - (String, Array<String>) The OAuth 2.0 scopes controlling
         | 
| 428 | 
            +
                  #   the set of resources and operations that the connection can access.
         | 
| 429 | 
            +
                  # * `timeout` - (Integer) Default timeout to use in requests.
         | 
| 430 | 
            +
                  # * `client_config` - (Hash) A hash of values to override the default
         | 
| 431 | 
            +
                  #   behavior of the API client.
         | 
| 432 | 
            +
                  # * `allow_mutating_methods` - (boolean) Whether expressions and
         | 
| 433 | 
            +
                  #   conditional breakpoints can call methods that could modify program
         | 
| 434 | 
            +
                  #   state. Defaults to false.
         | 
| 435 | 
            +
                  # * `evaluation_time_limit` - (Numeric) Time limit in seconds for
         | 
| 436 | 
            +
                  #   expression evaluation. Defaults to 0.05.
         | 
| 437 | 
            +
                  #
         | 
| 400 438 | 
             
                  # See the [Configuration
         | 
| 401 439 | 
             
                  # Guide](https://googlecloudplatform.github.io/google-cloud-ruby/#/docs/stackdriver/guides/instrumentation_configuration)
         | 
| 402 440 | 
             
                  # for full configuration parameters.
         | 
| 403 441 | 
             
                  #
         | 
| 404 | 
            -
                  # @return [ | 
| 405 | 
            -
                  #    | 
| 442 | 
            +
                  # @return [Google::Cloud::Config] The configuration object the
         | 
| 443 | 
            +
                  #   Google::Cloud::Debugger module uses.
         | 
| 406 444 | 
             
                  #
         | 
| 407 445 | 
             
                  def self.configure
         | 
| 408 | 
            -
                    yield Google::Cloud.configure | 
| 446 | 
            +
                    yield Google::Cloud.configure.debugger if block_given?
         | 
| 447 | 
            +
             | 
| 448 | 
            +
                    Google::Cloud.configure.debugger
         | 
| 449 | 
            +
                  end
         | 
| 450 | 
            +
             | 
| 451 | 
            +
                  ##
         | 
| 452 | 
            +
                  # @private Default project.
         | 
| 453 | 
            +
                  def self.default_project_id
         | 
| 454 | 
            +
                    Google::Cloud.configure.debugger.project_id ||
         | 
| 455 | 
            +
                      Google::Cloud.configure.project_id ||
         | 
| 456 | 
            +
                      Google::Cloud.env.project_id
         | 
| 457 | 
            +
                  end
         | 
| 409 458 |  | 
| 410 | 
            -
             | 
| 459 | 
            +
                  ##
         | 
| 460 | 
            +
                  # @private Default service name identifier.
         | 
| 461 | 
            +
                  def self.default_service_name
         | 
| 462 | 
            +
                    Google::Cloud.configure.debugger.service_name ||
         | 
| 463 | 
            +
                      Google::Cloud.configure.service_name ||
         | 
| 464 | 
            +
                      Google::Cloud.env.app_engine_service_id ||
         | 
| 465 | 
            +
                      "ruby-app"
         | 
| 466 | 
            +
                  end
         | 
| 467 | 
            +
             | 
| 468 | 
            +
                  ##
         | 
| 469 | 
            +
                  # @private Default service version identifier.
         | 
| 470 | 
            +
                  def self.default_service_version
         | 
| 471 | 
            +
                    Google::Cloud.configure.debugger.service_version ||
         | 
| 472 | 
            +
                      Google::Cloud.configure.service_version ||
         | 
| 473 | 
            +
                      Google::Cloud.env.app_engine_service_version ||
         | 
| 474 | 
            +
                      ""
         | 
| 475 | 
            +
                  end
         | 
| 476 | 
            +
             | 
| 477 | 
            +
                  ##
         | 
| 478 | 
            +
                  # @private Default credentials.
         | 
| 479 | 
            +
                  def self.default_credentials scope: nil
         | 
| 480 | 
            +
                    Google::Cloud.configure.debugger.credentials ||
         | 
| 481 | 
            +
                      Google::Cloud.configure.credentials ||
         | 
| 482 | 
            +
                      Debugger::Credentials.default(scope: scope)
         | 
| 483 | 
            +
                  end
         | 
| 484 | 
            +
             | 
| 485 | 
            +
                  ##
         | 
| 486 | 
            +
                  # Allow calling of potentially state-changing methods even if mutation
         | 
| 487 | 
            +
                  # detection is configured to be active.
         | 
| 488 | 
            +
                  #
         | 
| 489 | 
            +
                  # Generally it is unwise to run code that may change the program state
         | 
| 490 | 
            +
                  # (e.g. modifying instance variables or causing other side effects) in a
         | 
| 491 | 
            +
                  # breakpoint expression, because it could change the behavior of your
         | 
| 492 | 
            +
                  # program. However, the checks are currently quite conservative, and may
         | 
| 493 | 
            +
                  # block code that is actually safe to run. If you are certain your
         | 
| 494 | 
            +
                  # expression is safe to evaluate, you may use this method to disable
         | 
| 495 | 
            +
                  # side effect checks.
         | 
| 496 | 
            +
                  #
         | 
| 497 | 
            +
                  # This method may be called with a block, in which case checks are
         | 
| 498 | 
            +
                  # disabled within the block. It may also be called without a block to
         | 
| 499 | 
            +
                  # disable side effect checks for the rest of the current expression; the
         | 
| 500 | 
            +
                  # default setting will be restored for the next expression.
         | 
| 501 | 
            +
                  #
         | 
| 502 | 
            +
                  # This method may be called only from a debugger condition or expression
         | 
| 503 | 
            +
                  # evaluation, and will throw an exception if you call it from normal
         | 
| 504 | 
            +
                  # application code. Set the `allow_mutating_methods` configuration if you
         | 
| 505 | 
            +
                  # want to disable the side effect checker globally for your app.
         | 
| 506 | 
            +
                  #
         | 
| 507 | 
            +
                  # @example Disabling side effect detection in a block
         | 
| 508 | 
            +
                  #   # This is an expression evaluated in a debugger snapshot
         | 
| 509 | 
            +
                  #   Google::Cloud::Debugger.allow_mutating_methods! do
         | 
| 510 | 
            +
                  #     obj1.method_with_potential_side_effects
         | 
| 511 | 
            +
                  #   end
         | 
| 512 | 
            +
                  #
         | 
| 513 | 
            +
                  # @example Disabling side effect detection for the rest of the expression
         | 
| 514 | 
            +
                  #   # This is an expression evaluated in a debugger snapshot
         | 
| 515 | 
            +
                  #   Google::Cloud::Debugger.allow_mutating_methods!
         | 
| 516 | 
            +
                  #   obj1.method_with_potential_side_effects
         | 
| 517 | 
            +
                  #   obj2.another_method_with_potential_side_effects
         | 
| 518 | 
            +
                  #
         | 
| 519 | 
            +
                  # @example Globally disabling side effect detection at app initialization
         | 
| 520 | 
            +
                  #   require "google/cloud/debugger"
         | 
| 521 | 
            +
                  #   Google::Cloud::Debugger.configure.allow_mutating_methods = true
         | 
| 522 | 
            +
                  #
         | 
| 523 | 
            +
                  def self.allow_mutating_methods! &block
         | 
| 524 | 
            +
                    evaluator = Breakpoint::Evaluator.current
         | 
| 525 | 
            +
                    if evaluator.nil?
         | 
| 526 | 
            +
                      raise "allow_mutating_methods can be called only during evaluation"
         | 
| 527 | 
            +
                    end
         | 
| 528 | 
            +
                    evaluator.allow_mutating_methods!(&block)
         | 
| 411 529 | 
             
                  end
         | 
| 412 530 | 
             
                end
         | 
| 413 531 | 
             
              end
         |