rbkit 0.0.1 → 0.1.6

Sign up to get free protection for your applications and to get access to all the features.
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
+ ```