rbkit 0.0.1 → 0.1.6

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.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +5 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +17 -0
  5. data/CHANGELOG.md +5 -0
  6. data/Gemfile +6 -2
  7. data/LICENSE.txt +22 -0
  8. data/README.md +74 -11
  9. data/Rakefile +27 -3
  10. data/docs/EVENT_FORMAT.md +195 -0
  11. data/experiments/object_dump.rb +1 -1
  12. data/experiments/rbkit_command_test.rb +3 -1
  13. data/experiments/using_rbkit.rb +1 -1
  14. data/ext/extconf.rb +95 -12
  15. data/ext/rbkit_allocation_info.c +91 -0
  16. data/ext/rbkit_allocation_info.h +17 -0
  17. data/ext/rbkit_event.c +71 -0
  18. data/ext/rbkit_event.h +63 -0
  19. data/ext/rbkit_event_packer.c +251 -0
  20. data/ext/rbkit_event_packer.h +23 -0
  21. data/ext/rbkit_message_aggregator.c +9 -16
  22. data/ext/rbkit_message_aggregator.h +0 -1
  23. data/ext/rbkit_object_graph.c +6 -49
  24. data/ext/rbkit_object_graph.h +12 -3
  25. data/ext/rbkit_test_helper.c +25 -0
  26. data/ext/rbkit_test_helper.h +1 -0
  27. data/ext/rbkit_tracer.c +106 -323
  28. data/ext/rbkit_tracer.h +2 -10
  29. data/lib/rbkit.rb +57 -35
  30. data/lib/rbkit/rbkit_gc.rb +79 -0
  31. data/lib/rbkit/version.rb +1 -1
  32. data/logo.png +0 -0
  33. data/rbkit.gemspec +1 -0
  34. data/setup.rb +37 -0
  35. data/spec/gc_stat_spec.rb +31 -0
  36. data/spec/hash_event_spec.rb +29 -0
  37. data/spec/obj_created_spec.rb +52 -0
  38. data/spec/obj_destroyed_spec.rb +44 -0
  39. data/spec/object_space_dump_spec.rb +77 -0
  40. data/spec/rbkit_helpful_messages_spec.rb +61 -0
  41. data/spec/spec_helper.rb +11 -6
  42. data/spec/start_server_spec.rb +29 -0
  43. data/spec/status_spec.rb +48 -0
  44. data/spec/support/foo_bar_sample_class.rb +24 -0
  45. data/spec/support/have_message_matcher.rb +26 -0
  46. metadata +40 -4
  47. data/schema/tracing_info.md +0 -8
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9c98d007ffcab15624f4463ba9220cfe0b02635f
4
- data.tar.gz: 4de1af44a5313d96dc359dac2e5929616c8362af
3
+ metadata.gz: 739b3af12258b89ecfdae05d06c03889329d496d
4
+ data.tar.gz: c7144822b77d0173352ef6c184c7c8ddaa046311
5
5
  SHA512:
6
- metadata.gz: 3b867812d99bcc5b41da934789e26f0053419757928db46d9f23f0faaac30757ef1eec6083d3b28e21277d99f5b8d4cf0e566fffc89c80b790005916492689f4
7
- data.tar.gz: 001c0549d008515fc411499c94b4fe72768d801e1040ff44ab39e1ee0e79f7830de0aa3816be738a90a66aff728b2c34c9630a3e27231a163aee06af8200a09f
6
+ metadata.gz: b46dc7d9c12bd100c59177e0afc0d0021ede93328d4e5444f4cbefac70bfd960046f88e20ebd4aa2cdde458a9a9caa01f5e9697a4a8e542e43df7840476f7889
7
+ data.tar.gz: d8e462c46b173086ce21f04d1350ebdaae5023a6da9407c50841a2dfb8755d2b281908450136db079570a3ab3ea6f53789039e5391ad3bf30cf51406407f51fa
data/.gitignore CHANGED
@@ -14,3 +14,8 @@ Gemfile.lock
14
14
  /mkmf.log
15
15
  /coverage
16
16
  *.xcodeproj
17
+ /ext/libzmq.a
18
+ /ext/zeromq*
19
+ /ext/libmsgpack.a
20
+ /ext/msgpack*
21
+ /ext/TAGS
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format progress
@@ -0,0 +1,17 @@
1
+ language: ruby
2
+ bundler_args: "--without exclude_in_travis"
3
+ rvm:
4
+ - 2.1.3
5
+ - 2.2.0
6
+ - ruby-head
7
+ os:
8
+ - linux
9
+ - osx
10
+ script: bundle exec rake run_spec
11
+ notifications:
12
+ hipchat:
13
+ rooms:
14
+ secure: KdhzB9VueLEJp9p/ZUFaXAMO0u1CEbT0sjdRt10jqseAJCld9CAK1KAb1f/mNO/+cbVd+7W9UdHA0cEGUZ9dLP9Mcpmy31QxOJSITUCrRiLOF1ti13Lq4WHpMM46Tz6p7vVYd4zpPj9Mup+lCTGOeCovReX+neIoZw0UjDg9oGs=
15
+ template:
16
+ - '%{result}: %{repository_slug}#%{branch} - <a href="%{compare_url}">%{commit}</a>(%{commit_message}) by %{author} (<a href="%{build_url}">Details</a>)'
17
+ format: html
@@ -0,0 +1,5 @@
1
+ v0.1.6
2
+ ======
3
+
4
+ * First final public release
5
+ * CHANGELOG.md created
data/Gemfile CHANGED
@@ -1,7 +1,11 @@
1
1
  source "https://rubygems.org"
2
2
 
3
- gem "rbczmq"
4
3
  gem "msgpack"
5
- gem "rake-compiler"
4
+
5
+ group :exclude_in_travis do
6
+ gem 'pry-byebug'
7
+ gem 'rbczmq'
8
+ end
9
+
6
10
 
7
11
  gemspec
@@ -0,0 +1,22 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2014 Emil Soman, Hemant Kumar
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md CHANGED
@@ -1,5 +1,8 @@
1
- Rbkit
2
- =====
1
+ <img src="./logo.png" height="30px" /> Rbkit
2
+ ============================================
3
+
4
+ [![Gem Version](https://badge.fury.io/rb/rbkit.svg)](http://badge.fury.io/rb/rbkit)
5
+ [![Build Status](https://travis-ci.org/code-mancers/rbkit.svg?branch=tests)](https://travis-ci.org/code-mancers/rbkit)
3
6
 
4
7
  `rbkit` is a Ruby gem that plugs into your ruby process, taps profiling data
5
8
  in realtime and sends it across the wire to the [rbkit-client](https://github.com/code-mancers/rbkit-client)
@@ -16,24 +19,87 @@ then follow these steps :
16
19
  Add the following to the project's Gemfiles
17
20
 
18
21
  ```
19
- gem 'rbkit', path: <RBKIT_PATH>`
22
+ gem 'rbkit', path: <RBKIT_PATH>
20
23
  ```
24
+
25
+
21
26
  and run `bundle install`
22
27
 
28
+ #### Installation without Rubygems
29
+
30
+ You can also install `rbkit` without bundler/rubygems. This can
31
+ be useful, if you are profiling a Ruby app where you want to measure
32
+ overhead of Rubygems/Bundler.
33
+
34
+ Just clone the repository or download from a release tag and run:
35
+
36
+ ```
37
+ # Run from root of rbkit directory.
38
+ ~> ruby setup.rb
39
+ ```
40
+
41
+ This should install `rbkit`
42
+ in ruby's `site_dir` and then you don't need `rbkit` added to your
43
+ `Gemfile` for requiring `rbkit`.
44
+
23
45
  #### Inject `rbkit` into code
24
46
 
25
47
  Wherever you want to start profiling, add the following :
48
+
49
+ ```ruby
50
+ require 'rbkit' # Not needed in Rails
51
+ Rbkit.start_server
26
52
  ```
27
- require 'rbkit'
28
- Rbkit.start_profiling
29
- ```
53
+
30
54
  If using Rails, and you want to measure everything from the boot process,
31
55
  a good place to put this would be at the end of `config/boot.rb`.
32
56
 
57
+ ## Rbkit API
58
+
59
+ ### Rbkit.start_server(pub_port: nil, request_port: nil)
60
+
61
+ Starts the Rbkit server and waits for a client to connect and issue
62
+ commands to the request_port, until then there's zero performance overhead.
63
+ Profiling data is sent asynchronously over pub_port.
64
+ This method can be called early in a ruby application so that
65
+ whenever profiling needs to be done, the client can attach itself to the
66
+ inactive server, do the profiling and leave. Returns true if server was
67
+ started successfully.
68
+
69
+
70
+ |argument | valid values | default value | description |
71
+ |--------------|--------------|---------------|---------------------------------------------------|
72
+ |pub_port | nil, fixnum | nil | Override default message publishing port of 5555 |
73
+ |request_port | nil, fixnum | nil | Override default command listener port of 5556 |
74
+
75
+
76
+ ### Rbkit.start_profiling(pub_port: nil, request_port: nil, enable_object_trace: true, enable_gc_stats: true)
77
+
78
+ Starts the server with all tracepoints enabled by default. User can
79
+ optionally disable tracepoints using the optional arguments.
80
+ This method can be used to profile the startup process of a ruby
81
+ application where sending commands from the client to enable
82
+ profiling is not feasible. Returns true if server was started successfully.
83
+
84
+ Arguments:
85
+
86
+ |argument | valid values | default value | description |
87
+ |---------------------|--------------|---------------|--------------------------------------------------|
88
+ |pub_port | nil, fixnum | nil | Override default message publishing port of 5555 |
89
+ |request_port | nil, fixnum | nil | Override default command listener port of 5556 |
90
+ |enable_object_trace | true/false | true | Enables object creation/deletion events |
91
+ |enable_gc_stats | true/false | true | Enables GC stats which is sent every 5 seconds |
92
+
93
+
33
94
  ## Development
34
95
 
35
96
  #### Install zmq and msgpack
36
97
 
98
+ If zmq and msgpack are not installed, Rbkit automatically downloads
99
+ and installs the two libraries from source during gem installation.
100
+ But if you are developing Rbkit, it makes sense to have these
101
+ preinstalled:
102
+
37
103
  On OSX - Using `homebrew` following command should suffice:
38
104
 
39
105
  ```
@@ -45,9 +111,6 @@ On Linux - we recommend to download these libraries
45
111
  from their respective home pages and manually compiling
46
112
  and installing.
47
113
 
48
- At some point, we will bundle these two C libraries during gem installations
49
- but for now, this has to suffice.
50
-
51
114
  #### Clone the repo
52
115
 
53
116
  `git clone git@github.com:code-mancers/rbkit.git`
@@ -66,7 +129,7 @@ This compiles the C extension with debug flag and also sets a macro named
66
129
 
67
130
  Two ways to do this :
68
131
 
69
- ##### Using rake-compiler
132
+ ##### Using rake
70
133
 
71
134
  ```
72
135
  cd <RBKIT_PATH>
@@ -81,7 +144,7 @@ bundle exec rake compile
81
144
  cd <RBKIT_PATH/ext>
82
145
  ruby extconf.rb
83
146
  make
84
- # Create a symlink at `lib/rbkit_tracer.bundle`
147
+ # Create a symlink at `lib/rbkit_tracer.bundle` (or .so if on linux)
85
148
  # that points to `ext/rbkit_tracer.bundle`
86
149
  # (in order to use `rbkit` gem in Gemfiles using `path` option)
87
150
  ```
data/Rakefile CHANGED
@@ -1,7 +1,31 @@
1
1
  require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
2
3
 
3
- require 'rake/extensiontask'
4
+ RSpec::Core::RakeTask.new
4
5
 
5
- Rake::ExtensionTask.new('rbkit_tracer') do |ext|
6
- ext.ext_dir = 'ext'
6
+ task :compile do
7
+ symlink_bundle_path = File.absolute_path "lib/rbkit_tracer.#{RbConfig::MAKEFILE_CONFIG['DLEXT']}"
8
+ original_bundle_path = File.absolute_path "ext/rbkit_tracer.#{RbConfig::MAKEFILE_CONFIG['DLEXT']}"
9
+ Dir.chdir 'ext' do
10
+ system("#{Gem.ruby} extconf.rb")
11
+ system("make")
12
+ File.delete(symlink_bundle_path) if File.symlink? symlink_bundle_path
13
+ File.symlink(original_bundle_path, symlink_bundle_path)
14
+ end
7
15
  end
16
+
17
+ desc "Run each spec in isolated process"
18
+ task :run_spec => [:compile] do
19
+ command_output = []
20
+ Dir["spec/*_spec.rb"].each do |file|
21
+ puts "Running #{file}.."
22
+ command_output << system("bundle exec rspec #{file}")
23
+ end
24
+ if command_output.all?
25
+ exit(0)
26
+ else
27
+ exit(-1)
28
+ end
29
+ end
30
+
31
+ task :default => [:compile, :spec]
@@ -0,0 +1,195 @@
1
+ Refer [issue #11](https://github.com/code-mancers/rbkit/issues/11) for some history.
2
+
3
+ ## Event types
4
+
5
+ EventType is an integer value indicating the type of event
6
+ contained in the message. It's basically the following enum :
7
+
8
+ ```c
9
+ enum EventType {
10
+ obj_created,
11
+ obj_destroyed,
12
+ gc_start,
13
+ gc_end_m,
14
+ gc_end_s,
15
+ object_space_dump,
16
+ gc_stats,
17
+ event_collection,
18
+ handshake
19
+ }
20
+ ```
21
+
22
+ ie,
23
+
24
+ ```ruby
25
+ # Rbkit::EVENT_TYPES
26
+ {
27
+ "obj_created" => 0,
28
+ "obj_destroyed" => 1,
29
+ "gc_start" => 2,
30
+ "gc_end_m" => 3,
31
+ "gc_end_s" => 4,
32
+ "object_space_dump" => 5,
33
+ "gc_stats" => 6,
34
+ "event_collection" => 7,
35
+ "handshake" => 8
36
+ }
37
+ ```
38
+
39
+ The keys of all event message hashes are integer values whose enum names
40
+ are used below. `Rbkit::MESSAGE_FIELDS` gives you the exhaustive list of
41
+ enums used.
42
+
43
+ ```ruby
44
+ # Rbkit::MESSAGE_FIELDS
45
+ {
46
+ 'event_type' => 0,
47
+ 'timestamp' => 1,
48
+ 'payload' => 2,
49
+ 'object_id' => 3,
50
+ 'class_name' => 4,
51
+ 'references' => 5,
52
+ 'file' => 6,
53
+ 'line' => 7,
54
+ 'size' => 8,
55
+ 'message_counter' => 9
56
+ }
57
+ ```
58
+
59
+ ## Message frames
60
+
61
+ Generic message frame is of the format :
62
+
63
+ ```yaml
64
+ {
65
+ event_type: <EventType>,
66
+ timestamp: <timestamp in milliseconds>,
67
+ payload: <PAYLOAD> # Optional
68
+ }
69
+ ```
70
+
71
+ ### Message frame for event_collection :
72
+
73
+ All events are aggregated in the server and sent as the payload of a special
74
+ type of event named `event_collection`. The payload will be an array containing
75
+ other event messages.
76
+
77
+ ```yaml
78
+ {
79
+ event_type: "event_collection",
80
+ message_counter: <incrementing counter>,
81
+ timestamp: <timestamp in milliseconds>,
82
+ payload: [
83
+ {event_type: <EVENT_TYPE>, timestamp: <TIMESTAMP>, payload: <PAYLOAD>},
84
+ {event_type: <EVENT_TYPE>, timestamp: <TIMESTAMP>, payload: <PAYLOAD>}
85
+ ]
86
+ }
87
+ ```
88
+
89
+ ### Message frame for HANDSHAKE :
90
+
91
+ Handshake is a special message which is sent synchronously over the REQ-REP
92
+ socket pair and not on the PUB socket. When a "handshake" command is send by
93
+ the client, the server responses with the Rbkit status. The handshake reply
94
+ is of the following format :
95
+
96
+ ```yaml
97
+ {
98
+ event_type: "handshake",
99
+ timestamp: <timestamp in milliseconds>,
100
+ payload: {
101
+ "process_name" => <Name of the process>,
102
+ "pwd" => <working directory of the app>,
103
+ "pid" => <PID of the ruby process>,
104
+ "object_trace_enabled" => <0 or 1>
105
+ }
106
+ }
107
+ ```
108
+
109
+ ### Message frame for NEW_OBJECT :
110
+
111
+ When the NEW_OBJECT event is triggered, the object id and the class name
112
+ are sent as the payload.
113
+
114
+ ```yaml
115
+ {
116
+ event_type: obj_created,
117
+ timestamp: <timestamp in milliseconds>,
118
+ payload: {
119
+ object_id: <OBJECT_ID>,
120
+ class_name: <CLASS_NAME>
121
+ }
122
+ }
123
+ ```
124
+
125
+ ### Message frame for FREE_OBJECT :
126
+
127
+ ```yaml
128
+ {
129
+ event_type: obj_destroyed,
130
+ timestamp: <timestamp in milliseconds>,
131
+ payload: {
132
+ object_id: <OBJECT_ID>
133
+ }
134
+ }
135
+ ```
136
+
137
+ ### Message frame for GC_START :
138
+
139
+ When the GC_START event is triggered, no payload is sent.
140
+
141
+ ```yaml
142
+ {
143
+ event_type: gc_start,
144
+ timestamp: <timestamp in milliseconds>,
145
+ }
146
+ ```
147
+
148
+ ### Message frame for GC_END_SWEEP :
149
+
150
+ When the GC_END_SWEEP event is triggered, no payload is sent.
151
+
152
+ ```yaml
153
+ {
154
+ event_type: gc_end_s,
155
+ timestamp: <timestamp in milliseconds>,
156
+ }
157
+ ```
158
+
159
+ ### Message frame for OBJECT_SPACE_DUMP :
160
+
161
+ ```yaml
162
+ {
163
+ event_type: object_space_dump
164
+ timestamp: <timestamp in milliseconds>,
165
+ payload: [
166
+ {
167
+ object_id: <OBJECT_ID>,
168
+ snapshot_no: <SNAPSHOT_COUNT>,
169
+ class_name: <CLASS_NAME>,
170
+ references: [<OBJECT_ID>, <OBJECT_ID>, ... ],
171
+ file: <FILE_PATH>,
172
+ line: <LINE_NUMBER>,
173
+ size: <SIZE>
174
+ },
175
+ ...
176
+ ]
177
+ }
178
+ ```
179
+
180
+ ### Message from GC stats:
181
+ **Note: GC stat payload uses strings for keys**
182
+
183
+ ```yaml
184
+ {
185
+ event_type: "gc_stats",
186
+ timestamp: <timestamp in milliseconds>,
187
+ payload: {
188
+ count:
189
+ heap_user:
190
+ heap_length:
191
+ heap_increment:
192
+ ...
193
+ }
194
+ }
195
+ ```