callstacking-rails 0.1.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 +7 -0
- data/LICENSE +621 -0
- data/README.md +95 -0
- data/Rakefile +8 -0
- data/app/assets/config/callstacking_rails_manifest.js +1 -0
- data/app/assets/stylesheets/callstacking/rails/application.css +15 -0
- data/app/controllers/callstacking/rails/application_controller.rb +6 -0
- data/app/helpers/callstacking/rails/application_helper.rb +6 -0
- data/app/jobs/callstacking/rails/application_job.rb +6 -0
- data/app/mailers/callstacking/rails/application_mailer.rb +8 -0
- data/app/models/callstacking/rails/application_record.rb +7 -0
- data/config/routes.rb +4 -0
- data/exe/callstacking-rails +32 -0
- data/lib/callstacking/rails/client/authenticate.rb +23 -0
- data/lib/callstacking/rails/client/base.rb +56 -0
- data/lib/callstacking/rails/client/trace.rb +35 -0
- data/lib/callstacking/rails/engine.rb +49 -0
- data/lib/callstacking/rails/env.rb +17 -0
- data/lib/callstacking/rails/instrument.rb +88 -0
- data/lib/callstacking/rails/loader.rb +29 -0
- data/lib/callstacking/rails/settings.rb +54 -0
- data/lib/callstacking/rails/setup.rb +115 -0
- data/lib/callstacking/rails/spans.rb +72 -0
- data/lib/callstacking/rails/trace.rb +126 -0
- data/lib/callstacking/rails/traces_helper.rb +39 -0
- data/lib/callstacking/rails/version.rb +5 -0
- data/lib/callstacking/rails.rb +7 -0
- data/lib/tasks/checkpoint/rails_tasks.rake +4 -0
- metadata +115 -0
data/README.md
ADDED
@@ -0,0 +1,95 @@
|
|
1
|
+
# Callstacking::Rails
|
2
|
+
|
3
|
+
Callstacking is a rolling, checkpoint debugger for Rails. It records all of the critical method calls within your app, along with their important context (param/argument/return/local variable values).
|
4
|
+
|
5
|
+
You no longer need to debug with `binding.pry` or `puts` statements, as the entire callstack for a given request is captured.
|
6
|
+
|
7
|
+
Demo video:
|
8
|
+
[](https://www.youtube.com/watch?v=NGqnwcNWv_k)
|
9
|
+
|
10
|
+
Class method calls are labeled. Return values for those calls are denoted with ↳
|
11
|
+
|
12
|
+
Arguments for a method will be listed along with their calling values.
|
13
|
+
|
14
|
+
For method returns ↳, the final values of the local variables will be listed when you hover over the entry.
|
15
|
+
|
16
|
+
<img width="1695" alt="CleanShot 2022-09-17 at 21 10 32@2x" src="https://user-images.githubusercontent.com/4600/190882603-a99e9358-9754-4cbf-ac68-a41d53afe747.png">
|
17
|
+
|
18
|
+
Subsequent calls within a method are visibly nested.
|
19
|
+
|
20
|
+
Callstacking is a Rails engine that you mount within your Rails app.
|
21
|
+
|
22
|
+
Here's a sample debugging sessions recorded from a Jumpstart Rails based app I've been working on. This is a request for the main page ( https://smartk.id/ ).
|
23
|
+
|
24
|
+

|
25
|
+
|
26
|
+
Callstacking Rails records all of the critical method calls within your app, along with their important context (param/argument/return/local variable values).
|
27
|
+
|
28
|
+
All in a rolling panel, so that you can debug your call chains from any point in the stack.
|
29
|
+
|
30
|
+
You'll never have to debug with `puts` statements ever again.
|
31
|
+
|
32
|
+
Calls are visibly nested so that it's easy to see which calls are issued from which parent methods.
|
33
|
+
|
34
|
+
## Installation
|
35
|
+
Add this line to your application's Gemfile:
|
36
|
+
|
37
|
+
```ruby
|
38
|
+
gem "callstacking-rails"
|
39
|
+
```
|
40
|
+
|
41
|
+
And then execute:
|
42
|
+
```bash
|
43
|
+
$ bundle
|
44
|
+
```
|
45
|
+
|
46
|
+
Register an account at Callstacking.com
|
47
|
+
```bash
|
48
|
+
callstacking-rails register
|
49
|
+
```
|
50
|
+
|
51
|
+
Authenticate to your newly created account.
|
52
|
+
|
53
|
+
```bash
|
54
|
+
callstacking-rails setup
|
55
|
+
```
|
56
|
+
|
57
|
+
You're now ready to start tracing.
|
58
|
+
|
59
|
+
## Usage
|
60
|
+
Usage:
|
61
|
+
|
62
|
+
> callstacking-rails enable
|
63
|
+
|
64
|
+
Enables the callstacking tracing.
|
65
|
+
|
66
|
+
> callstacking-rails disable
|
67
|
+
|
68
|
+
Disables the callstacking tracing.
|
69
|
+
|
70
|
+
> callstacking-rails register
|
71
|
+
|
72
|
+
Opens a browser window to register as a callstacking.com user.
|
73
|
+
|
74
|
+
> callstacking-rails setup
|
75
|
+
|
76
|
+
Interactively prompts you for your callstacking.com username/password.
|
77
|
+
Stores auth details in `~/.callstacking-rails`.
|
78
|
+
|
79
|
+
You can have multiple environments.
|
80
|
+
The default is `development`.
|
81
|
+
|
82
|
+
The `development:` section in the `~/.callstacking-rails` config contains your credentials.
|
83
|
+
|
84
|
+
By setting the RAILS_ENV environment you can maintain multiple settings.
|
85
|
+
|
86
|
+
Questions? Create an issue: https://github.com/callstacking/callstacking-rails/issues
|
87
|
+
|
88
|
+
|
89
|
+
## Trace Output
|
90
|
+
When you open a page for your app, once the page has rendered, you will see an `<<` arrow on the right hand side.
|
91
|
+
|
92
|
+
Click the arrows, and observe the full callstack context.
|
93
|
+
|
94
|
+
## License
|
95
|
+
The gem is available as open source under the terms of the [GPLv3 License](https://www.gnu.org/licenses/gpl-3.0.en.html).
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
//= link_directory ../stylesheets/callstacking/rails .css
|
@@ -0,0 +1,15 @@
|
|
1
|
+
/*
|
2
|
+
* This is a manifest file that'll be compiled into application.css, which will include all the files
|
3
|
+
* listed below.
|
4
|
+
*
|
5
|
+
* Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
|
6
|
+
* or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path.
|
7
|
+
*
|
8
|
+
* You're free to add application-wide styles to this file and they'll appear at the bottom of the
|
9
|
+
* compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS
|
10
|
+
* files in this directory. Styles in this file should be added after the last require_* statement.
|
11
|
+
* It is generally better to create a new file per style scope.
|
12
|
+
*
|
13
|
+
*= require_tree .
|
14
|
+
*= require_self
|
15
|
+
*/
|
data/config/routes.rb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "callstacking/rails/setup"
|
5
|
+
require "callstacking/rails/settings"
|
6
|
+
|
7
|
+
include Callstacking::Rails::Settings
|
8
|
+
|
9
|
+
action = ARGV[0]&.downcase&.strip
|
10
|
+
|
11
|
+
if action.nil?
|
12
|
+
Callstacking::Rails::Setup.instructions
|
13
|
+
exit!(1)
|
14
|
+
end
|
15
|
+
|
16
|
+
read_settings
|
17
|
+
|
18
|
+
case action
|
19
|
+
when 'register'
|
20
|
+
`open #{settings.url || Callstacking::Rails::Settings::PRODUCTION_URL}/users/sign_up`
|
21
|
+
|
22
|
+
when 'setup'
|
23
|
+
Callstacking::Rails::Setup.new.start
|
24
|
+
|
25
|
+
when 'enable'
|
26
|
+
Callstacking::Rails::Setup.new.enable_disable
|
27
|
+
puts "Callstacking tracing enabled (#{Callstacking::Rails::Env.environment})"
|
28
|
+
|
29
|
+
when 'disable'
|
30
|
+
Callstacking::Rails::Setup.new.enable_disable(enabled: false)
|
31
|
+
puts "Callstacking tracing disabled (#{Callstacking::Rails::Env.environment})"
|
32
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'json'
|
2
|
+
require "callstacking/rails/client/base"
|
3
|
+
|
4
|
+
module Callstacking
|
5
|
+
module Rails
|
6
|
+
module Client
|
7
|
+
class Error < StandardError; end
|
8
|
+
|
9
|
+
class Authenticate < Base
|
10
|
+
URL = "/api/v1/auth.json"
|
11
|
+
|
12
|
+
def login(email, password)
|
13
|
+
resp = post(URL, email: email, password: password)
|
14
|
+
|
15
|
+
raise Faraday::UnauthorizedError if resp&.body.nil?
|
16
|
+
|
17
|
+
body = resp&.body || {}
|
18
|
+
body["token"]
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'faraday'
|
2
|
+
require 'faraday/follow_redirects'
|
3
|
+
require "callstacking/rails/settings"
|
4
|
+
|
5
|
+
module Callstacking
|
6
|
+
module Rails
|
7
|
+
module Client
|
8
|
+
class Error < StandardError; end
|
9
|
+
|
10
|
+
class Base
|
11
|
+
include Callstacking::Rails::Settings
|
12
|
+
|
13
|
+
def initialize
|
14
|
+
read_settings
|
15
|
+
end
|
16
|
+
|
17
|
+
def connection
|
18
|
+
# https://github.com/lostisland/awesome-faraday
|
19
|
+
@connection ||= Faraday.new(url) do |c|
|
20
|
+
c.response :json
|
21
|
+
c.use Faraday::Response::Logger, Logger.new('/tmp/callstacking-rails.log')
|
22
|
+
# c.use Faraday::Response::Logger, nil, { headers: false, bodies: false }
|
23
|
+
c.response :follow_redirects
|
24
|
+
c.use Faraday::Response::RaiseError # raise exceptions on 40x, 50x responses
|
25
|
+
c.request :json # This will set the "Content-Type" header to application/json and call .to_json on the body
|
26
|
+
c.adapter Faraday.default_adapter
|
27
|
+
|
28
|
+
if auth_token?
|
29
|
+
c.request :authorization, :Bearer, auth_token
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def get(url, params = {})
|
35
|
+
connection.get(url, params, headers)
|
36
|
+
end
|
37
|
+
|
38
|
+
def post(url, params = {}, body = {}, headers_ext = {})
|
39
|
+
r(:post, url, params, body, headers_ext)
|
40
|
+
end
|
41
|
+
|
42
|
+
def patch(url, params = {}, body = {}, headers_ext = {})
|
43
|
+
r(:patch, url, params, body, headers_ext)
|
44
|
+
end
|
45
|
+
|
46
|
+
def r(action, url, params = {}, body = {}, _headers_ext = {})
|
47
|
+
connection.send(action, url) do |req|
|
48
|
+
req.params.merge!(params)
|
49
|
+
req.body = body
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require "callstacking/rails/client/base"
|
2
|
+
|
3
|
+
module Callstacking
|
4
|
+
module Rails
|
5
|
+
module Client
|
6
|
+
class Trace < Base
|
7
|
+
CREATE_URL = "/api/v1/traces.json"
|
8
|
+
UPDATE_URL = "/api/v1/traces/:id.json"
|
9
|
+
|
10
|
+
def create(method_name, klass, action_name, format_name, root_path, url, request_id, headers, params)
|
11
|
+
resp = post(CREATE_URL,
|
12
|
+
{},
|
13
|
+
{ method_name: method_name,
|
14
|
+
klass: klass,
|
15
|
+
action_name: action_name,
|
16
|
+
format_name: format_name,
|
17
|
+
root_path: root_path,
|
18
|
+
url: url,
|
19
|
+
request_id: request_id,
|
20
|
+
h: headers.to_h,
|
21
|
+
p: params.to_h,
|
22
|
+
})
|
23
|
+
|
24
|
+
return resp.body["trace_id"], resp.body["pulse_interval"]
|
25
|
+
end
|
26
|
+
|
27
|
+
def upsert(trace_id, traces)
|
28
|
+
resp = patch(UPDATE_URL.gsub(':id', trace_id), {}, traces)
|
29
|
+
|
30
|
+
resp.status
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require "rails"
|
2
|
+
require "callstacking/rails/trace"
|
3
|
+
require "callstacking/rails/instrument"
|
4
|
+
require 'callstacking/rails/spans'
|
5
|
+
require "callstacking/rails/setup"
|
6
|
+
require "callstacking/rails/settings"
|
7
|
+
require "callstacking/rails/loader"
|
8
|
+
require "callstacking/rails/client/base"
|
9
|
+
require "callstacking/rails/client/authenticate"
|
10
|
+
require "callstacking/rails/client/trace"
|
11
|
+
require "callstacking/rails/traces_helper"
|
12
|
+
|
13
|
+
module Callstacking
|
14
|
+
module Rails
|
15
|
+
class Engine < ::Rails::Engine
|
16
|
+
include Settings
|
17
|
+
isolate_namespace Callstacking::Rails
|
18
|
+
|
19
|
+
read_settings
|
20
|
+
|
21
|
+
spans = Spans.new
|
22
|
+
trace = Trace.new(spans)
|
23
|
+
|
24
|
+
initializer "engine_name.assets.precompile" do |app|
|
25
|
+
app.config.assets.precompile << "checkpoint_rails_manifest.js"
|
26
|
+
end
|
27
|
+
|
28
|
+
initializer 'local_helper.action_controller' do
|
29
|
+
ActiveSupport.on_load :action_controller do
|
30
|
+
helper Callstacking::Rails::TracesHelper
|
31
|
+
include Callstacking::Rails::TracesHelper
|
32
|
+
end
|
33
|
+
|
34
|
+
Callstacking::Rails::Loader.new.on_load(spans) if enabled?
|
35
|
+
end
|
36
|
+
|
37
|
+
initializer :append_before_action do
|
38
|
+
ActionController::Base.send :after_action, :inject_hud
|
39
|
+
end
|
40
|
+
|
41
|
+
if enabled?
|
42
|
+
puts "Callstacking enabled (#{Callstacking::Rails::Env.environment})"
|
43
|
+
trace.tracing
|
44
|
+
else
|
45
|
+
puts "Callstacking disabled (#{Callstacking::Rails::Env.environment})"
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require "active_support/inflector"
|
2
|
+
|
3
|
+
module Callstacking
|
4
|
+
module Rails
|
5
|
+
class Env
|
6
|
+
DEFAULT_ENVIRONMENT = "development"
|
7
|
+
|
8
|
+
cattr_accessor :environment
|
9
|
+
|
10
|
+
@@environment = (ENV['RAILS_ENV'] || DEFAULT_ENVIRONMENT).parameterize(separator: '_').to_sym
|
11
|
+
|
12
|
+
def self.production?
|
13
|
+
@@environment == DEFAULT_ENVIRONMENT.parameterize(separator: '_').to_sym
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
require 'rails'
|
2
|
+
|
3
|
+
# https://stackoverflow.com/q/52932516
|
4
|
+
module Callstacking
|
5
|
+
module Rails
|
6
|
+
class Instrument
|
7
|
+
attr_accessor :spans, :klass
|
8
|
+
attr_reader :root
|
9
|
+
|
10
|
+
def initialize(spans, klass)
|
11
|
+
@spans = spans
|
12
|
+
@klass = klass
|
13
|
+
@root = Regexp.new(::Rails.root.to_s)
|
14
|
+
end
|
15
|
+
|
16
|
+
def instrument_method(method_name, application_level: true)
|
17
|
+
method_path = (klass.instance_method(method_name).source_location.first rescue nil) ||
|
18
|
+
(klass.method(method_name).source_location.first rescue nil)
|
19
|
+
|
20
|
+
# Application level method definitions
|
21
|
+
return unless method_path =~ root if application_level
|
22
|
+
|
23
|
+
tmp_module = find_or_initialize_module
|
24
|
+
|
25
|
+
return if tmp_module.instance_methods.include?(method_name) ||
|
26
|
+
tmp_module.singleton_methods.include?(method_name)
|
27
|
+
|
28
|
+
tmp_module.define_method(method_name) do |*args, &block|
|
29
|
+
method_name = __method__
|
30
|
+
|
31
|
+
path = method(__method__).super_method.source_location.first
|
32
|
+
line_no = method(__method__).super_method.source_location.last
|
33
|
+
|
34
|
+
p, l = caller.find { |c| c.to_s =~ /#{::Rails.root.to_s}/}&.split(':')
|
35
|
+
|
36
|
+
spans = tmp_module.instance_variable_get(:@spans)
|
37
|
+
klass = tmp_module.instance_variable_get(:@klass)
|
38
|
+
|
39
|
+
spans.call_entry(klass, method_name, p || path, l || line_no)
|
40
|
+
return_val = super(*args, &block)
|
41
|
+
spans.call_return(klass, method_name, p || path, l || line_no, return_val)
|
42
|
+
|
43
|
+
return_val
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def find_or_initialize_module
|
48
|
+
module_name = "#{klass.name.gsub('::', '')}Span"
|
49
|
+
module_index = klass.ancestors.map(&:to_s).index(module_name)
|
50
|
+
|
51
|
+
unless module_index
|
52
|
+
new_module = Object.const_set(module_name, Module.new)
|
53
|
+
|
54
|
+
new_module.instance_variable_set("@klass", klass)
|
55
|
+
new_module.instance_variable_set("@spans", spans)
|
56
|
+
|
57
|
+
klass.prepend new_module
|
58
|
+
klass.singleton_class.prepend new_module if klass.class == Module
|
59
|
+
|
60
|
+
return find_or_initialize_module
|
61
|
+
end
|
62
|
+
|
63
|
+
klass.ancestors[module_index]
|
64
|
+
end
|
65
|
+
|
66
|
+
def instrument_klass(application_level: true)
|
67
|
+
relevant = all_methods - filtered
|
68
|
+
relevant.each { |method| instrument_method(method, application_level: application_level) }
|
69
|
+
end
|
70
|
+
|
71
|
+
private
|
72
|
+
|
73
|
+
def all_methods
|
74
|
+
@all_methods ||= (klass.instance_methods +
|
75
|
+
klass.private_instance_methods(false) +
|
76
|
+
klass.protected_instance_methods(false) +
|
77
|
+
klass.methods +
|
78
|
+
klass.singleton_methods).uniq
|
79
|
+
end
|
80
|
+
|
81
|
+
def filtered
|
82
|
+
@filtered ||= (Object.instance_methods + Object.private_instance_methods +
|
83
|
+
Object.protected_instance_methods + Object.methods(false)).uniq
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require "rails"
|
2
|
+
|
3
|
+
module Callstacking
|
4
|
+
module Rails
|
5
|
+
class Loader
|
6
|
+
attr_accessor :loader, :root, :once
|
7
|
+
def initialize
|
8
|
+
@root = Regexp.new(::Rails.root.to_s)
|
9
|
+
end
|
10
|
+
|
11
|
+
def on_load(spans)
|
12
|
+
trace = TracePoint.new(:end) do |tp|
|
13
|
+
klass = tp.self
|
14
|
+
path = tp.path
|
15
|
+
|
16
|
+
Instrument.new(spans, klass).instrument_klass if path =~ root
|
17
|
+
end
|
18
|
+
|
19
|
+
trace.enable
|
20
|
+
|
21
|
+
Instrument.new(spans, ActionView::PartialRenderer).instrument_method(:render,
|
22
|
+
application_level: false)
|
23
|
+
|
24
|
+
Instrument.new(spans, ActionView::TemplateRenderer).instrument_method( :render,
|
25
|
+
application_level: false)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require "active_support/concern"
|
2
|
+
require "active_support/core_ext/class/attribute_accessors"
|
3
|
+
require "callstacking/rails/env"
|
4
|
+
|
5
|
+
module Callstacking
|
6
|
+
module Rails
|
7
|
+
module Settings
|
8
|
+
extend ActiveSupport::Concern
|
9
|
+
|
10
|
+
included do |base|
|
11
|
+
attr_accessor :settings
|
12
|
+
end
|
13
|
+
|
14
|
+
SETTINGS_FILE = "#{Dir.home}/.callstacking-rails"
|
15
|
+
PRODUCTION_URL = "https://callstacking.com"
|
16
|
+
|
17
|
+
def url
|
18
|
+
settings[:url]
|
19
|
+
end
|
20
|
+
|
21
|
+
def auth_token
|
22
|
+
settings[:auth_token]
|
23
|
+
end
|
24
|
+
|
25
|
+
def auth_token?
|
26
|
+
auth_token.present?
|
27
|
+
end
|
28
|
+
|
29
|
+
def write_settings(new_settings)
|
30
|
+
File.write(SETTINGS_FILE, new_settings.to_yaml)
|
31
|
+
end
|
32
|
+
|
33
|
+
def enabled?
|
34
|
+
settings[:enabled]
|
35
|
+
end
|
36
|
+
|
37
|
+
def disabled?
|
38
|
+
!enabled?
|
39
|
+
end
|
40
|
+
|
41
|
+
def read_settings
|
42
|
+
@@settings = @settings = complete_settings.dig(::Callstacking::Rails::Env.environment, :settings)
|
43
|
+
rescue StandardError => e
|
44
|
+
puts e.full_message
|
45
|
+
puts e.backtrace.join("\n")
|
46
|
+
return {}
|
47
|
+
end
|
48
|
+
|
49
|
+
def complete_settings
|
50
|
+
YAML.load(File.read(SETTINGS_FILE)) rescue {}
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,115 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
require "callstacking/rails/settings"
|
3
|
+
require "callstacking/rails/client/authenticate"
|
4
|
+
require "callstacking/rails/env"
|
5
|
+
|
6
|
+
module Callstacking
|
7
|
+
module Rails
|
8
|
+
class Setup
|
9
|
+
include ::Callstacking::Rails::Settings
|
10
|
+
extend ::Callstacking::Rails::Settings
|
11
|
+
|
12
|
+
attr_accessor :client
|
13
|
+
|
14
|
+
def initialize
|
15
|
+
read_settings
|
16
|
+
end
|
17
|
+
|
18
|
+
def client
|
19
|
+
@client = Callstacking::Rails::Client::Authenticate.new
|
20
|
+
end
|
21
|
+
|
22
|
+
def start
|
23
|
+
email = prompt("Enter email:")
|
24
|
+
password = prompt("Enter password:")
|
25
|
+
|
26
|
+
url = if Callstacking::Rails::Env.production? && ENV['CHECKPOINT_RAILS_LOCAL_TEST'].nil?
|
27
|
+
PRODUCTION_URL
|
28
|
+
else
|
29
|
+
prompt("Enter URL for #{Callstacking::Rails::Env.environment} API calls [#{PRODUCTION_URL}]:") || PRODUCTION_URL
|
30
|
+
end
|
31
|
+
|
32
|
+
save(email, password, url)
|
33
|
+
|
34
|
+
puts "Authentication successful."
|
35
|
+
puts "Settings saved to #{SETTINGS_FILE}"
|
36
|
+
rescue StandardError => e
|
37
|
+
puts "Problem authenticating: #{e.message}"
|
38
|
+
end
|
39
|
+
|
40
|
+
def enable_disable(enabled: true)
|
41
|
+
settings[:enabled] = enabled
|
42
|
+
|
43
|
+
props = { Callstacking::Rails::Env.environment => {
|
44
|
+
settings: settings
|
45
|
+
} }
|
46
|
+
|
47
|
+
write_settings(complete_settings.merge(props))
|
48
|
+
end
|
49
|
+
|
50
|
+
def prompt(label)
|
51
|
+
puts label
|
52
|
+
value = STDIN.gets.chomp
|
53
|
+
puts
|
54
|
+
|
55
|
+
return nil if value == ''
|
56
|
+
value
|
57
|
+
end
|
58
|
+
|
59
|
+
def token(email, password)
|
60
|
+
client.login(email, password)
|
61
|
+
end
|
62
|
+
|
63
|
+
def save(email, password, url)
|
64
|
+
props = { auth_token: '',
|
65
|
+
url: url,
|
66
|
+
enabled: true
|
67
|
+
}
|
68
|
+
|
69
|
+
props = { Callstacking::Rails::Env.environment => {
|
70
|
+
settings: props
|
71
|
+
} }
|
72
|
+
|
73
|
+
write_settings(complete_settings.merge(props))
|
74
|
+
|
75
|
+
props[Callstacking::Rails::Env.environment][:settings][:auth_token] = token(email, password)
|
76
|
+
|
77
|
+
write_settings(complete_settings.merge(props))
|
78
|
+
|
79
|
+
read_settings
|
80
|
+
end
|
81
|
+
|
82
|
+
def self.instructions
|
83
|
+
read_settings
|
84
|
+
puts "loading environment #{Callstacking::Rails::Env.environment}"
|
85
|
+
puts
|
86
|
+
puts "Usage: "
|
87
|
+
puts
|
88
|
+
puts " > callstacking-rails enable"
|
89
|
+
puts
|
90
|
+
puts " Enables the callstacking tracing."
|
91
|
+
puts
|
92
|
+
puts " > callstacking-rails disable"
|
93
|
+
puts
|
94
|
+
puts " Disables the callstacking tracing."
|
95
|
+
puts
|
96
|
+
puts " > callstacking-rails register"
|
97
|
+
puts
|
98
|
+
puts " Opens a browser window to register as a callstacking.com user."
|
99
|
+
puts
|
100
|
+
puts " > callstacking-rails setup"
|
101
|
+
puts
|
102
|
+
puts " Interactively prompts you for your callstacking.com username/password."
|
103
|
+
puts " Stores auth details in #{SETTINGS_FILE}"
|
104
|
+
puts
|
105
|
+
puts " You can have multiple environments."
|
106
|
+
puts " The default is #{Callstacking::Rails::Env::DEFAULT_ENVIRONMENT}."
|
107
|
+
puts
|
108
|
+
puts " The #{Callstacking::Rails::Env.environment}: section in the #{SETTINGS_FILE} contains your credentials."
|
109
|
+
puts " By setting the RAILS_ENV environment you can maintain multiple settings."
|
110
|
+
puts
|
111
|
+
puts "Questions? Create an issue: https://github.com/callstacking/callstacking-rails/issues"
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|