pry-remote-em 1.0.0 → 1.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9891306377f0196004da3a9bd1c69beb92d49756
4
- data.tar.gz: d09d7572adf27c19d9b8f8fdf69290c4dc25264e
3
+ metadata.gz: e7817acab9f7eb7e0b26f10041062cfac6accfba
4
+ data.tar.gz: ad682bae7ee316f05debf4a80d73fa773415c0fb
5
5
  SHA512:
6
- metadata.gz: b15649c543deaa0b4e48fdb3ec1f8db2b7296709c50c62ac1e6e69f2b2cbf4abcaf3af61ca9270a7c850422f9afd940cd9fc38a5b2a3bfdd506e12f5bf0600ae
7
- data.tar.gz: e15c4019739eef9f214a63c6b064ca33564a12f8051da4cf25889885cfa31fca497c23b4a22110bbcb3d5a6bc15b9bbc4ed61dce7ce83ef85c5f233f1ea39c70
6
+ metadata.gz: 7da5179c0b004e65fdad81fa8706158d30cfd38275cb7710382acca32a8db54a1a85e27ac468eb20d4aa8ec15fc4fe6b24eecf14aeb353520cba1f42fcf620bf
7
+ data.tar.gz: ff0752cbb02b7c9ddc281b05c6f8feec007b09b29c50e1c30610ebb676f51fbf85b5b0f89fbf87293465fc2c18a7ad74d3521c1abe9ab66a4a8489e347bc3806
@@ -1,3 +1,12 @@
1
+ # 1.1.0
2
+
3
+ * Release separated gem version for JRuby because ruby-termios does not work on this platform
4
+ * Add `source_timestamp` to errors stored in sandbox
5
+ * Add `error_history` and `error_classes` methods to sandbox to view error list with comfort
6
+ * Add `PryRemoteEm::Sandbox.ignore_errors` to avoid capturing useless errors
7
+ * Add simple metrics collector, default `errors` metric from sandbox catcher, option to view metrics in the broker list (see Readme)
8
+ * Show server details and metrics on connect if any
9
+
1
10
  # 1.0.0
2
11
 
3
12
  ## Breaking changes
@@ -8,6 +17,7 @@
8
17
  * **BREAKING CHANGE** `PryRemoteEm::Server.run` returns whole server description instead of URL
9
18
  * **BREAKING CHANGE** Rename public constants to avoid confusing
10
19
  * **BREAKING CHANGE** Drop support for eventmachine prior to 1.0.0.beta4
20
+ * **BREAKING CHANGE** Inner transport protocol was changed, so broker, client and server of version 1.0.0 cannot work with brokers, clients and servers of previous versions
11
21
 
12
22
  ## Features
13
23
 
data/README.md CHANGED
@@ -469,6 +469,10 @@ $ pry-remote-em -P --sn -d environment
469
469
  (q) to quit; (r) to refresh; (c) to connect without proxy
470
470
  proxy to: 1
471
471
  [pry-remote-em] remote is PryRemoteEm 1.0.0 pryem
472
+
473
+ Server details:
474
+ environment: staging
475
+
472
476
  [1] Microservice A (sandbox)> u 13
473
477
  => {"id"=>13, "violations"=>4, "status"=>"active"}
474
478
  [2] Microservice A (sandbox)> @my_bad_user = _
@@ -480,6 +484,10 @@ proxy to: 1
480
484
  $
481
485
  $ pry-remote-em pryem://127.0.0.1:6463
482
486
  [pry-remote-em] remote is PryRemoteEm 1.0.0 pryem
487
+
488
+ Server details:
489
+ environment: staging
490
+
483
491
  [1] Microservice A (sandbox)> @my_bad_user
484
492
  => {"id"=>13, "violations"=>4, "status"=>"banned"}
485
493
  [2] Microservice A (sandbox)> exit
@@ -487,6 +495,10 @@ $ pry-remote-em pryem://127.0.0.1:6463
487
495
  $
488
496
  $ pry-remote-em pryem://127.0.0.1:6464
489
497
  [pry-remote-em] remote is PryRemoteEm 1.0.0 pryem
498
+
499
+ Server details:
500
+ environment: staging
501
+
490
502
  [1] Microservice A (sandbox)> ping :A # Or you can use it to check infrastructure and perform custom communications between servers
491
503
  => "pong"
492
504
  [2] Microservice A (sandbox)> exit
@@ -554,19 +566,28 @@ Then, in shell:
554
566
  $ pry-remote-em -P --sn -d hostname
555
567
  [pry-remote-em] client connected to pryem://127.0.0.1:6462/
556
568
  [pry-remote-em] remote is PryRemoteEm 1.0.0 pryem
557
- ------------------------------------
558
- | | name | hostname |
559
- ------------------------------------
560
- | 1 | Demo Server | local |
561
- ------------------------------------
569
+ ---------------------------------------------
570
+ | | name | hostname | errors |
571
+ ---------------------------------------------
572
+ | 1 | Demo Server | local | 1 |
573
+ ---------------------------------------------
562
574
  (q) to quit; (r) to refresh; (c) to connect without proxy
563
575
  proxy to: 1
564
576
  [pry-remote-em] remote is PryRemoteEm 1.0.0 pryem
577
+
578
+ Server details:
579
+ hostname: local
580
+
581
+ Server metrics:
582
+ errors: 1
583
+
565
584
  [1] Demo Server (sandbox)> any_errors?
566
585
  => true
567
586
  [2] Demo Server (sandbox)> last_error
568
587
  => #<ZeroDivisionError: divided by 0>
569
- [3] Demo Server (sandbox)> wtf?
588
+ [3] Demo Server (sandbox)> last_error.source_timestamp
589
+ => 2018-08-09 14:53:19 UTC
590
+ [4] Demo Server (sandbox)> wtf?
570
591
  Exception: ZeroDivisionError: divided by 0
571
592
  --
572
593
  0: demo_server.rb:13:in `/'
@@ -577,8 +598,8 @@ Exception: ZeroDivisionError: divided by 0
577
598
  5: /usr/local/lib/ruby/gems/2.4.0/gems/eventmachine-1.2.7/lib/eventmachine.rb:195:in `run_machine'
578
599
  6: /usr/local/lib/ruby/gems/2.4.0/gems/eventmachine-1.2.7/lib/eventmachine.rb:195:in `run'
579
600
  7: demo_server.rb:17:in `<main>'
580
- [4] Demo Server (sandbox)> cd last_error.source_binding
581
- [5] Demo Server (main):1> whereami
601
+ [5] Demo Server (sandbox)> cd last_error.source_binding
602
+ [6] Demo Server (main):1> whereami
582
603
 
583
604
  From: /Users/user/Projects/demo/demo_server.rb @ line 12 Object#danger_mathod:
584
605
 
@@ -588,15 +609,140 @@ From: /Users/user/Projects/demo/demo_server.rb @ line 12 Object#danger_mathod:
588
609
  14: end
589
610
  15: end
590
611
 
591
- [6] Demo Server (main):1> ls
612
+ [7] Demo Server (main):1> ls
592
613
  self.methods: inspect to_s
593
614
  locals: _ __ _dir_ _ex_ _file_ _in_ _out_ _pry_ a b
594
- [7] Demo Server (main):1> a
615
+ [8] Demo Server (main):1> a
595
616
  => 1
596
- [8] Demo Server (main):1> b
617
+ [9] Demo Server (main):1> b
597
618
  => 0
598
619
  ```
599
620
 
621
+ There is maximum number of errors to store in sandbox to avoid
622
+ memory leaks. It is 100 by default, but you can tune it with
623
+ PRYEMSANDBOXERRORS environment variable. You can see simple log
624
+ about errors in memory (not from server start) and also statistics
625
+ about errors class from server start (not in memory):
626
+
627
+ ```shell
628
+ [1] Demo Server (sandbox)> error_history
629
+ No errors, yay!
630
+ [2] Demo Server (sandbox)> 3.times { 1/0 rescue PryRemoteEm::Sandbox.add_error($!) }
631
+ => nil
632
+ [3] Demo Server (sandbox)> undefined_method rescue PryRemoteEm::Sandbox.add_error($!)
633
+ => nil
634
+ [4] Demo Server (sandbox)> error_history
635
+ 2018-08-10 10:25:21 +0300 ZeroDivisionError: divided by 0
636
+ 2018-08-10 10:25:21 +0300 ZeroDivisionError: divided by 0
637
+ 2018-08-10 10:25:21 +0300 ZeroDivisionError: divided by 0
638
+ 2018-08-10 10:25:32 +0300 NameError: undefined local variable or method `unde...
639
+ => nil
640
+ [5] Demo Server (sandbox)> error_classes
641
+ ZeroDivisionError: 3
642
+ NameError: 1
643
+ => nil
644
+ [6] Demo Server (sandbox)> 100.times { undefined_method rescue PryRemoteEm::Sandbox.add_error($!) }
645
+ => 100
646
+ [7] Demo Server (sandbox)> last_errors.size
647
+ => 100
648
+ [8] Demo Server (sandbox)> error_classes
649
+ ZeroDivisionError: 3
650
+ NameError: 101
651
+ [9] Demo Server (sandbox)> error_history
652
+ 2018-08-10 10:35:17 +0300 NameError: undefined local variable or method `unde...
653
+ 2018-08-10 10:35:17 +0300 NameError: undefined local variable or method `unde...
654
+ ... 100 entries total
655
+ ```
656
+
657
+ You can also ignore some error classes. For example, you already
658
+ monitor database disconnections with another tool and don't
659
+ interested in user's NotFound excaptions:
660
+
661
+ ```ruby
662
+ PryRemoteEm::Sandbox.ignore_errors.push ActiveRecord::ConnectionTimeoutError, ActiveRecord::RecordNotFound
663
+ User.find(-1) rescue PryRemoteEm::Sandbox.add_error($!)
664
+ PryRemoteEm::Sandbox.last_errors # => []
665
+ ```
666
+
667
+ * Simple metrics collector. It can store some instance-specific
668
+ integers like requests or errors counts, number of connected users,
669
+ latencies, reconnections, cache size etc. It is not full-featured
670
+ monitoring solution, but much better than nothing, and also it is
671
+ super-simple to use. Just call following methods from anywhere
672
+ in your code:
673
+
674
+ ```ruby
675
+ Metrics = PryRemoteEm::Metrics # Just simplify naming, not necessarily
676
+ Metrics.add :requests # Add 1 to `requests` metric, starting from 0
677
+ Metrics.add :profit, 42 # Add custom value
678
+ Metrics.reduce :waiting_jobs # Using custom value is possible too (pass positive numbers)
679
+ Metrics.maximum :daily_online, current_online # Set new value only if it is bigger than current
680
+ EM.add_periodic_timer(1.day) { Metrics.set :daily_online, 0 } # Set some value explicitly
681
+ Metrics.minimum :best_latency, last_latency # Set new value only if it is smaller than current
682
+ Metrics.any? # => true
683
+ Metrics.get :requests # => 100500
684
+ Metrics.list # Hash with current values
685
+ ```
686
+
687
+ You can see all the metrics when connecting to a server and also
688
+ in the sandbox console with `show_metrics` method:
689
+
690
+ ```shell
691
+ $ pry-remote-em pryem://127.0.0.1:6463
692
+ [pry-remote-em] remote is PryRemoteEm 1.0.0 pryem
693
+
694
+ Server details:
695
+ hostname: local
696
+
697
+ Server metrics:
698
+ requests: 100500
699
+ profit: 300000000
700
+ waiting_jobs: 0
701
+ daily_online: 70000
702
+ best_latency: 0.003
703
+
704
+ [1] Demo Server (sandbox)> show_metrics
705
+ requests: 100500
706
+ profit: 300000000
707
+ waiting_jobs: 0
708
+ daily_online: 70000
709
+ best_latency: 0.003
710
+ ```
711
+
712
+ You also can see the metrics in the broker's table with a new option:
713
+
714
+ ```shell
715
+ $ pry-remote-em -P --sn -d hostname -m requests
716
+ [pry-remote-em] client connected to pryem://127.0.0.1:6462/
717
+ [pry-remote-em] remote is PryRemoteEm 1.0.0 pryem
718
+ -----------------------------------------------
719
+ | | name | hostname | requests |
720
+ -----------------------------------------------
721
+ | 1 | Demo Server | local | 100500 |
722
+ -----------------------------------------------
723
+ (q) to quit; (r) to refresh; (c) to connect without proxy
724
+ proxy to: q
725
+ $
726
+ $ pry-remote-em -P --sn -d hostname -m @
727
+ [pry-remote-em] client connected to pryem://127.0.0.1:6462/
728
+ [pry-remote-em] remote is PryRemoteEm 1.0.0 pryem
729
+ ----------------------------------------------------------
730
+ | | name | hostname | metrics |
731
+ ----------------------------------------------------------
732
+ | 1 | Demo Server | local | requests: 100500 |
733
+ | | | | profit: 300000000 |
734
+ | | | | waiting_jobs: 0 |
735
+ | | | | daily_online: 70000 |
736
+ | | | | best_latency: 0.003 |
737
+ ----------------------------------------------------------
738
+ (q) to quit; (r) to refresh; (c) to connect without proxy
739
+ proxy to:
740
+ ```
741
+
742
+ One metric, `errors`, is enabled by default and will be shown in the
743
+ broker's table if it was incremented at least once. It will be
744
+ incremented on `PryRemoteEm::Sandbox.add_error` call.
745
+
600
746
  * `server` method to access PryRemoteEm::Server description object.
601
747
  For example, it can be useful for changing `details`:
602
748
 
@@ -632,6 +778,10 @@ $ pry-remote-em -P --sn -d hand_check
632
778
  --------------------------------------
633
779
  (q) to quit; (r) to refresh; (c) to connect without proxy
634
780
  proxy to: 3
781
+
782
+ Server details:
783
+ hand_check: false
784
+
635
785
  [1] Demo Server (sandbox)> HealthChecker.all_ok?
636
786
  => true
637
787
  [2] Demo Server (sandbox)> server[:details][:hand_check] = true
@@ -45,6 +45,10 @@ OptionParser.new do |opts|
45
45
  options[:show_details] = key
46
46
  end
47
47
 
48
+ opts.on('-m', '--metrics KEY', "show value from server's metrics by given key in a third column, use @ to show all metrics, default - errors (if any)") do |key|
49
+ options[:show_metrics] = key
50
+ end
51
+
48
52
  opts.on('-i', '--ignore-localhost', 'filter out localhost urls from list') do
49
53
  options[:ignore_localhost] = true
50
54
  end
@@ -34,7 +34,13 @@ module PryRemoteEm
34
34
  run(@host, @port, @opts) do
35
35
  PryRemoteEm.servers.each do |id, description|
36
36
  next unless EM.get_sockname(description[:server])
37
- register(id: description[:id], urls: description[:urls], name: description[:name], details: description[:details])
37
+ register(
38
+ id: description[:id],
39
+ urls: description[:urls],
40
+ name: description[:name],
41
+ details: description[:details],
42
+ metrics: PryRemoteEm::Metrics.list
43
+ )
38
44
  end
39
45
  end
40
46
  end
@@ -53,7 +59,7 @@ module PryRemoteEm
53
59
  end
54
60
 
55
61
  def register(description)
56
- client { |c| c.send_register_server(description[:id], description[:urls], description[:name], description[:details]) }
62
+ client { |c| c.send_register_server(description[:id], description[:urls], description[:name], description[:details], description[:metrics]) }
57
63
  end
58
64
 
59
65
  def unregister(id)
@@ -69,6 +75,7 @@ module PryRemoteEm
69
75
  def update_server(server, description)
70
76
  server.update(urls: description[:urls], name: description[:name])
71
77
  server[:details].update(description[:details])
78
+ server[:metrics].update(description[:metrics])
72
79
  end
73
80
 
74
81
  def unregister_server(id)
@@ -148,9 +155,9 @@ module PryRemoteEm
148
155
  send_server_list(Broker.servers)
149
156
  end
150
157
 
151
- def receive_register_server(id, urls, name, details)
158
+ def receive_register_server(id, urls, name, details, metrics)
152
159
  @ids.push(id)
153
- description = { urls: urls, name: name, details: details }
160
+ description = { urls: urls, name: name, details: details, metrics: metrics }
154
161
  Broker.hbeats[id] = Time.new
155
162
  server = Broker.servers[id]
156
163
  if server
@@ -11,21 +11,29 @@ module PryRemoteEm
11
11
  sc_col = list.map { |id, server| second_column_for_server(server) }
12
12
  sc_col_name = opts[:show_details] == '@' ? 'details' : opts[:show_details] || 'url'
13
13
  sc_col_len = [sc_col.flatten.map(&:size).max || 1, sc_col_name.size].max
14
- header = sprintf("| %-3s | %-#{nm_col_len}s | %-#{sc_col_len}s |", '', 'name', sc_col_name)
14
+ show_th_col = opts[:show_metrics] || list.any? { |id, server| server.has_key?('metrics') && server['metrics']['errors'] }
15
+ if show_th_col
16
+ th_col = list.map { |id, server| third_column_for_server(server) }
17
+ th_col_name = opts[:show_metrics] == '@' ? 'metrics' : opts[:show_metrics] || 'errors'
18
+ th_col_len = [th_col.flatten.map(&:size).max || 1, th_col_name.size].max
19
+ end
20
+ formatter = "| %-3s | %-#{nm_col_len}s | %-#{sc_col_len}s |#{" %-#{th_col_len}s |" if show_th_col}"
21
+ header = sprintf(formatter, '', 'name', sc_col_name, *th_col_name)
15
22
  border = ('-' * header.length)
16
23
  table = [border, header, border]
17
24
  list = list.to_a
18
25
  list = filter_server_list(list)
19
26
  list = sort_server_list(list)
20
27
  list.each.with_index do |(id, server), index|
21
- column = second_column_for_server(server)
28
+ index_column = [(index + 1).to_s]
29
+ first_column = [server['name']]
30
+ second_column = second_column_for_server(server)
31
+ third_column = third_column_for_server(server) if show_th_col
22
32
 
23
- table << sprintf("| %-2d | %-#{nm_col_len}s | %-#{sc_col_len}s |", index + 1, server['name'], column.first)
33
+ lines = show_th_col ? [second_column.size, third_column.size].max : second_column.size
24
34
 
25
- if column.size > 1
26
- column[1..-1].each do |element|
27
- table << sprintf("| %-2s | %-#{nm_col_len}s | %-#{sc_col_len}s |", '', '', element)
28
- end
35
+ lines.times do |index|
36
+ table << sprintf(formatter, index_column[index] || '', first_column[index] || '', second_column[index] || '', *(show_th_col ? third_column[index] || '' : nil))
29
37
  end
30
38
  end
31
39
  table << border
@@ -150,22 +158,36 @@ module PryRemoteEm
150
158
  end
151
159
 
152
160
  def second_column_for_server(server)
153
- column = case opts[:show_details]
161
+ data = case opts[:show_details]
154
162
  when nil then filtered_urls_list_for_server(server)
155
163
  when '@' then server['details']
156
164
  else server['details'][opts[:show_details]]
157
165
  end
158
166
 
159
- case column
160
- when Array then column.map(&:to_s)
161
- when Hash then column.map { |key, value| "#{key}: #{value}" }
162
- else [column.to_s]
163
- end
167
+ prepare_data_for_table(data)
164
168
  end
165
169
 
166
170
  def filtered_urls_list_for_server(server)
167
171
  opts[:ignore_localhost] ? server['urls'].reject { |url| %w[localhost 127.0.0.1 ::1].include?(URI.parse(url).host) } : server['urls']
168
172
  end
173
+
174
+ def third_column_for_server(server)
175
+ data = case opts[:show_metrics]
176
+ when nil then server['metrics']['errors']
177
+ when '@' then server['metrics']
178
+ else server['metrics'][opts[:show_metrics]]
179
+ end
180
+
181
+ prepare_data_for_table(data)
182
+ end
183
+
184
+ def prepare_data_for_table(data)
185
+ case data
186
+ when Array then data.map(&:to_s)
187
+ when Hash then data.map { |key, value| "#{key}: #{value}" }
188
+ else [data.to_s]
189
+ end
190
+ end
169
191
  end # module::InteractiveMenu
170
192
  end # module::Client
171
193
  end # module PryRemoteEm
@@ -1,4 +1,4 @@
1
- require 'termios'
1
+ require 'termios' unless RUBY_PLATFORM =~ /java/
2
2
 
3
3
  module PryRemoteEm
4
4
  module Client
@@ -31,7 +31,7 @@ module PryRemoteEm
31
31
  # In unbuffered mode read and select will not wait for "\n"; also will not echo characters.
32
32
  # This probably does not work on Windows.
33
33
  def bufferio(enable)
34
- return if (enable && @buff_enabled) || (!enable && !@buff_enabled)
34
+ return if !defined?(Termios) || enable && @buff_enabled || !enable && !@buff_enabled
35
35
  attr = Termios.getattr($stdin)
36
36
  enable ? (attr.c_lflag |= Termios::ICANON | Termios::ECHO) : (attr.c_lflag &= ~(Termios::ICANON|Termios::ECHO))
37
37
  Termios.setattr($stdin, Termios::TCSANOW, attr)
@@ -0,0 +1,39 @@
1
+ module PryRemoteEm
2
+ # Simple metrics system
3
+ # See Sandbox section in Readme for guide
4
+ module Metrics
5
+ def list
6
+ @list ||= Hash.new { |hash, key| hash[key] = 0 }
7
+ end
8
+
9
+ def add(name, value = 1)
10
+ list[name] += value
11
+ end
12
+
13
+ def reduce(name, value = 1)
14
+ add(name, -value)
15
+ end
16
+
17
+ def maximum(name, value)
18
+ list[name] = value if list[name] < value
19
+ end
20
+
21
+ def minimum(name, value)
22
+ list[name] = value if list[name] > value
23
+ end
24
+
25
+ def set(name, value)
26
+ list[name] = value
27
+ end
28
+
29
+ def get(name)
30
+ list[name]
31
+ end
32
+
33
+ def any?
34
+ list.any?
35
+ end
36
+
37
+ extend self
38
+ end
39
+ end
@@ -77,7 +77,7 @@ module PryRemoteEm
77
77
 
78
78
  def receive_start_tls; end
79
79
 
80
- def receive_register_server(id, urls, name, details); end
80
+ def receive_register_server(id, urls, name, details, metrics); end
81
81
  def receive_unregister_server(id); end
82
82
  def receive_server_list(list); end
83
83
  def receive_server_reload_list; end
@@ -125,8 +125,8 @@ module PryRemoteEm
125
125
  send_object({tls: true})
126
126
  end
127
127
 
128
- def send_register_server(id, urls, name, details)
129
- send_object({rs: [id, urls, name, details]})
128
+ def send_register_server(id, urls, name, details, metrics)
129
+ send_object({rs: [id, urls, name, details, metrics]})
130
130
  end
131
131
  def send_unregister_server(id)
132
132
  send_object({urs: id})
@@ -1,30 +1,32 @@
1
+ require 'pry-remote-em/metrics'
2
+
1
3
  module PryRemoteEm
2
4
  # See Readme for Sandbox using guide
3
5
  class Sandbox
4
- @@last_errors = []
5
-
6
6
  attr_accessor :pry, :server
7
7
 
8
+ # Use output methods as expected
9
+
8
10
  %w[puts putc print p pp].each do |method|
9
11
  define_method method do |*arguments|
10
12
  pry.output.puts(*arguments)
11
13
  end
12
14
  end
13
15
 
14
- def inspect
15
- 'sandbox'
16
- end
16
+ # Working with errors
17
17
 
18
- def any_errors?
19
- last_errors.any?
20
- end
18
+ @@last_errors = []
19
+ @@ignore_errors = []
20
+ @@error_classes = Hash.new { |hash, key| hash[key] = 0 }
21
21
 
22
- def last_error
23
- last_errors.last
22
+ def error_classes
23
+ return puts 'No errors, yay!' if @@error_classes.empty?
24
+ puts @@error_classes.map { |key, value| "#{key}: #{value}" }
24
25
  end
25
26
 
26
- def last_errors
27
- @@last_errors
27
+ def error_history
28
+ return puts 'No errors, yay!' unless any_errors?
29
+ puts @@last_errors.map { |error| "#{error.source_timestamp} #{"#{error.class}: #{error.message}".sub(/(?<=^.{51}).{4,}$/, '...')}" }
28
30
  end
29
31
 
30
32
  def self.add_error(exception, source_binding = nil)
@@ -32,16 +34,55 @@ module PryRemoteEm
32
34
  raise ArgumentError, 'exception with backtrace and optional binding expected'
33
35
  end
34
36
 
35
- return if @@last_errors.include?(exception)
37
+ return if @@last_errors.map(&:object_id).include?(exception.object_id) || @@ignore_errors.include?(exception.class)
38
+
39
+ timestamp = Time.now
40
+ exception.define_singleton_method(:source_timestamp) { timestamp }
36
41
 
37
42
  exception.define_singleton_method(:source_binding) { source_binding } if source_binding
38
43
 
39
44
  @@last_errors.push(exception)
45
+ @@error_classes[exception.class] += 1
46
+ Metrics.add(:errors)
40
47
 
41
48
  maximum_errors = ENV['PRYEMSANDBOXERRORS'].nil? || ENV['PRYEMSANDBOXERRORS'].empty? ? MAXIMUM_ERRORS_IN_SANDBOX : ENV['PRYEMSANDBOXERRORS'].to_i
42
49
  @@last_errors.shift if @@last_errors.size > maximum_errors
43
50
  end
44
51
 
52
+ def self.last_errors
53
+ @@last_errors
54
+ end
55
+
56
+ def self.any_errors?
57
+ @@last_errors.any?
58
+ end
59
+
60
+ def self.last_error
61
+ @@last_errors.last
62
+ end
63
+
64
+ def self.ignore_errors
65
+ @@ignore_errors
66
+ end
67
+
68
+ %w[any_errors? last_errors last_error ignore_errors].each do |method|
69
+ define_method(method) do |*arguments|
70
+ self.class.send(method, *arguments)
71
+ end
72
+ end
73
+
74
+ # Metrics related methods
75
+
76
+ def show_metrics
77
+ puts Metrics.list.map { |key, value| "#{key}: #{value}" }
78
+ end
79
+
80
+ # Safely show in Pry prompt
81
+
82
+ def inspect
83
+ 'sandbox'
84
+ end
85
+
45
86
  Pry.config.prompt_safe_objects.push(self)
46
87
  end
47
88
  end
@@ -147,7 +147,7 @@ module PryRemoteEm
147
147
  else
148
148
  description[:custom_name] = true
149
149
  end
150
- description[:name] = description[:name].first(57) + '...' if description[:name].size > 60
150
+ description[:name].sub!(/(?<=^.{57}).{4,}$/, '...')
151
151
  end
152
152
 
153
153
  def expand_url(url)
@@ -189,8 +189,18 @@ module PryRemoteEm
189
189
  end
190
190
 
191
191
  def register_in_broker(description)
192
- broker_description = { id: description[:id], urls: description[:urls], name: description[:name], details: description[:details] }
193
- broker_options = { tls: description[:tls], remote_broker: description[:remote_broker], logger: description[:logger] }
192
+ broker_description = {
193
+ id: description[:id],
194
+ urls: description[:urls],
195
+ name: description[:name],
196
+ details: description[:details],
197
+ metrics: PryRemoteEm::Metrics.list
198
+ }
199
+ broker_options = {
200
+ tls: description[:tls],
201
+ remote_broker: description[:remote_broker],
202
+ logger: description[:logger]
203
+ }
194
204
  Broker.run(description[:broker_host], description[:broker_port], broker_options) do |broker|
195
205
  broker.register(broker_description)
196
206
 
@@ -248,6 +258,16 @@ module PryRemoteEm
248
258
  @log.info("[pry-remote-em] received client connection from #{@ip}:#{@port}")
249
259
  # TODO include first level prompt in banner
250
260
  send_banner("PryRemoteEm #{VERSION} #{@opts[:tls] ? 'pryems' : 'pryem'}")
261
+ need_new_line = false
262
+ if @opts[:details].any?
263
+ send_raw("\nServer details:\n#{@opts[:details].map { |key, value| " #{key}: #{value}" } * "\n"}\n")
264
+ need_new_line = true
265
+ end
266
+ if PryRemoteEm::Metrics.any?
267
+ send_raw("\nServer metrics:\n#{PryRemoteEm::Metrics.list.map { |key, value| " #{key}: #{value}" } * "\n"}\n")
268
+ need_new_line = true
269
+ end
270
+ send_raw("\n") if need_new_line
251
271
  @log.info("#{url} PryRemoteEm #{VERSION} #{@opts[:tls] ? 'pryems' : 'pryem'}")
252
272
  @opts[:tls] ? start_tls : (@auth_required && send_auth(false))
253
273
  PryRemoteEm::Server.register(@obj, self)
@@ -394,7 +414,7 @@ module PryRemoteEm
394
414
  end
395
415
 
396
416
  def send_last_prompt
397
- @auth_required ? (after_auth { send_prompt(@last_prompt) }) : send_prompt(@last_prompt)
417
+ @auth_required ? (after_auth { send_prompt(@last_prompt) }) : send_prompt(@last_prompt)
398
418
  end
399
419
 
400
420
  def after_auth(&blk)
@@ -1,3 +1,3 @@
1
1
  module PryRemoteEm
2
- VERSION = '1.0.0'
2
+ VERSION = '1.1.0'
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pry-remote-em
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Caleb Crane
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2018-08-09 00:00:00.000000000 Z
12
+ date: 2018-08-10 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: eventmachine
@@ -102,6 +102,7 @@ files:
102
102
  - lib/pry-remote-em/client/interactive_menu.rb
103
103
  - lib/pry-remote-em/client/keyboard.rb
104
104
  - lib/pry-remote-em/client/proxy.rb
105
+ - lib/pry-remote-em/metrics.rb
105
106
  - lib/pry-remote-em/proto.rb
106
107
  - lib/pry-remote-em/sandbox.rb
107
108
  - lib/pry-remote-em/server.rb