truex-skylight 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (122) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +277 -0
  3. data/CLA.md +9 -0
  4. data/CONTRIBUTING.md +1 -0
  5. data/LICENSE.md +79 -0
  6. data/README.md +4 -0
  7. data/bin/skylight +3 -0
  8. data/ext/extconf.rb +186 -0
  9. data/ext/libskylight.yml +6 -0
  10. data/ext/skylight_memprof.c +115 -0
  11. data/ext/skylight_native.c +416 -0
  12. data/ext/skylight_native.h +20 -0
  13. data/lib/skylight.rb +2 -0
  14. data/lib/skylight/api.rb +79 -0
  15. data/lib/skylight/cli.rb +146 -0
  16. data/lib/skylight/compat.rb +47 -0
  17. data/lib/skylight/config.rb +498 -0
  18. data/lib/skylight/core.rb +122 -0
  19. data/lib/skylight/data/cacert.pem +3894 -0
  20. data/lib/skylight/formatters/http.rb +17 -0
  21. data/lib/skylight/gc.rb +107 -0
  22. data/lib/skylight/helpers.rb +137 -0
  23. data/lib/skylight/instrumenter.rb +290 -0
  24. data/lib/skylight/middleware.rb +75 -0
  25. data/lib/skylight/native.rb +69 -0
  26. data/lib/skylight/normalizers.rb +133 -0
  27. data/lib/skylight/normalizers/action_controller/process_action.rb +35 -0
  28. data/lib/skylight/normalizers/action_controller/send_file.rb +76 -0
  29. data/lib/skylight/normalizers/action_view/render_collection.rb +18 -0
  30. data/lib/skylight/normalizers/action_view/render_partial.rb +18 -0
  31. data/lib/skylight/normalizers/action_view/render_template.rb +18 -0
  32. data/lib/skylight/normalizers/active_record/sql.rb +79 -0
  33. data/lib/skylight/normalizers/active_support/cache.rb +50 -0
  34. data/lib/skylight/normalizers/active_support/cache_clear.rb +16 -0
  35. data/lib/skylight/normalizers/active_support/cache_decrement.rb +16 -0
  36. data/lib/skylight/normalizers/active_support/cache_delete.rb +16 -0
  37. data/lib/skylight/normalizers/active_support/cache_exist.rb +16 -0
  38. data/lib/skylight/normalizers/active_support/cache_fetch_hit.rb +16 -0
  39. data/lib/skylight/normalizers/active_support/cache_generate.rb +16 -0
  40. data/lib/skylight/normalizers/active_support/cache_increment.rb +16 -0
  41. data/lib/skylight/normalizers/active_support/cache_read.rb +16 -0
  42. data/lib/skylight/normalizers/active_support/cache_read_multi.rb +16 -0
  43. data/lib/skylight/normalizers/active_support/cache_write.rb +16 -0
  44. data/lib/skylight/normalizers/default.rb +21 -0
  45. data/lib/skylight/normalizers/moped/query.rb +141 -0
  46. data/lib/skylight/probes.rb +91 -0
  47. data/lib/skylight/probes/excon.rb +25 -0
  48. data/lib/skylight/probes/excon/middleware.rb +65 -0
  49. data/lib/skylight/probes/net_http.rb +44 -0
  50. data/lib/skylight/probes/redis.rb +30 -0
  51. data/lib/skylight/probes/sequel.rb +30 -0
  52. data/lib/skylight/probes/sinatra.rb +74 -0
  53. data/lib/skylight/probes/tilt.rb +27 -0
  54. data/lib/skylight/railtie.rb +122 -0
  55. data/lib/skylight/sinatra.rb +4 -0
  56. data/lib/skylight/subscriber.rb +92 -0
  57. data/lib/skylight/trace.rb +191 -0
  58. data/lib/skylight/util.rb +16 -0
  59. data/lib/skylight/util/allocation_free.rb +17 -0
  60. data/lib/skylight/util/clock.rb +53 -0
  61. data/lib/skylight/util/gzip.rb +15 -0
  62. data/lib/skylight/util/hostname.rb +17 -0
  63. data/lib/skylight/util/http.rb +218 -0
  64. data/lib/skylight/util/inflector.rb +110 -0
  65. data/lib/skylight/util/logging.rb +87 -0
  66. data/lib/skylight/util/multi_io.rb +21 -0
  67. data/lib/skylight/util/native_ext_fetcher.rb +205 -0
  68. data/lib/skylight/util/platform.rb +67 -0
  69. data/lib/skylight/util/ssl.rb +50 -0
  70. data/lib/skylight/vendor/active_support/notifications.rb +207 -0
  71. data/lib/skylight/vendor/active_support/notifications/fanout.rb +159 -0
  72. data/lib/skylight/vendor/active_support/notifications/instrumenter.rb +72 -0
  73. data/lib/skylight/vendor/active_support/per_thread_registry.rb +52 -0
  74. data/lib/skylight/vendor/cli/highline.rb +1034 -0
  75. data/lib/skylight/vendor/cli/highline/color_scheme.rb +134 -0
  76. data/lib/skylight/vendor/cli/highline/compatibility.rb +16 -0
  77. data/lib/skylight/vendor/cli/highline/import.rb +41 -0
  78. data/lib/skylight/vendor/cli/highline/menu.rb +381 -0
  79. data/lib/skylight/vendor/cli/highline/question.rb +481 -0
  80. data/lib/skylight/vendor/cli/highline/simulate.rb +48 -0
  81. data/lib/skylight/vendor/cli/highline/string_extensions.rb +111 -0
  82. data/lib/skylight/vendor/cli/highline/style.rb +181 -0
  83. data/lib/skylight/vendor/cli/highline/system_extensions.rb +242 -0
  84. data/lib/skylight/vendor/cli/thor.rb +473 -0
  85. data/lib/skylight/vendor/cli/thor/actions.rb +318 -0
  86. data/lib/skylight/vendor/cli/thor/actions/create_file.rb +105 -0
  87. data/lib/skylight/vendor/cli/thor/actions/create_link.rb +60 -0
  88. data/lib/skylight/vendor/cli/thor/actions/directory.rb +119 -0
  89. data/lib/skylight/vendor/cli/thor/actions/empty_directory.rb +137 -0
  90. data/lib/skylight/vendor/cli/thor/actions/file_manipulation.rb +314 -0
  91. data/lib/skylight/vendor/cli/thor/actions/inject_into_file.rb +109 -0
  92. data/lib/skylight/vendor/cli/thor/base.rb +652 -0
  93. data/lib/skylight/vendor/cli/thor/command.rb +136 -0
  94. data/lib/skylight/vendor/cli/thor/core_ext/hash_with_indifferent_access.rb +80 -0
  95. data/lib/skylight/vendor/cli/thor/core_ext/io_binary_read.rb +12 -0
  96. data/lib/skylight/vendor/cli/thor/core_ext/ordered_hash.rb +100 -0
  97. data/lib/skylight/vendor/cli/thor/error.rb +28 -0
  98. data/lib/skylight/vendor/cli/thor/group.rb +282 -0
  99. data/lib/skylight/vendor/cli/thor/invocation.rb +172 -0
  100. data/lib/skylight/vendor/cli/thor/parser.rb +4 -0
  101. data/lib/skylight/vendor/cli/thor/parser/argument.rb +74 -0
  102. data/lib/skylight/vendor/cli/thor/parser/arguments.rb +171 -0
  103. data/lib/skylight/vendor/cli/thor/parser/option.rb +121 -0
  104. data/lib/skylight/vendor/cli/thor/parser/options.rb +218 -0
  105. data/lib/skylight/vendor/cli/thor/rake_compat.rb +72 -0
  106. data/lib/skylight/vendor/cli/thor/runner.rb +322 -0
  107. data/lib/skylight/vendor/cli/thor/shell.rb +88 -0
  108. data/lib/skylight/vendor/cli/thor/shell/basic.rb +393 -0
  109. data/lib/skylight/vendor/cli/thor/shell/color.rb +148 -0
  110. data/lib/skylight/vendor/cli/thor/shell/html.rb +127 -0
  111. data/lib/skylight/vendor/cli/thor/util.rb +270 -0
  112. data/lib/skylight/vendor/cli/thor/version.rb +3 -0
  113. data/lib/skylight/vendor/thread_safe.rb +126 -0
  114. data/lib/skylight/vendor/thread_safe/non_concurrent_cache_backend.rb +133 -0
  115. data/lib/skylight/vendor/thread_safe/synchronized_cache_backend.rb +76 -0
  116. data/lib/skylight/version.rb +4 -0
  117. data/lib/skylight/vm/gc.rb +70 -0
  118. data/lib/sql_lexer.rb +6 -0
  119. data/lib/sql_lexer/lexer.rb +579 -0
  120. data/lib/sql_lexer/string_scanner.rb +11 -0
  121. data/lib/sql_lexer/version.rb +3 -0
  122. metadata +179 -0
@@ -0,0 +1,50 @@
1
+ require 'openssl'
2
+
3
+ module Skylight
4
+ module Util
5
+ class SSL
6
+ DEFAULT_CA_FILE = File.expand_path('../../data/cacert.pem', __FILE__)
7
+
8
+ def self.detect_ca_cert_file!
9
+ @ca_cert_file = false
10
+ if defined?(OpenSSL::X509::DEFAULT_CERT_FILE)
11
+ f = OpenSSL::X509::DEFAULT_CERT_FILE
12
+
13
+ if f && File.exist?(f)
14
+ @ca_cert_file = f
15
+ end
16
+ end
17
+ end
18
+
19
+ def self.detect_ca_cert_dir!
20
+ @ca_cert_dir = false
21
+ if defined?(OpenSSL::X509::DEFAULT_CERT_DIR)
22
+ d = OpenSSL::X509::DEFAULT_CERT_DIR
23
+
24
+ if d && File.exist?(d)
25
+ @ca_cert_dir = d
26
+ end
27
+ end
28
+ end
29
+
30
+ detect_ca_cert_file!
31
+ detect_ca_cert_dir!
32
+
33
+ def self.ca_cert_file?
34
+ !!@ca_cert_file
35
+ end
36
+
37
+ def self.ca_cert_dir?
38
+ !!@ca_cert_dir
39
+ end
40
+
41
+ def self.ca_cert_file_or_default
42
+ @ca_cert_file || DEFAULT_CA_FILE
43
+ end
44
+
45
+ def self.ca_cert_dir
46
+ @ca_cert_dir
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,207 @@
1
+ require 'skylight/vendor/active_support/notifications/instrumenter'
2
+ require 'skylight/vendor/active_support/notifications/fanout'
3
+ require 'skylight/vendor/active_support/per_thread_registry'
4
+
5
+ module ActiveSupport
6
+ # = Notifications
7
+ #
8
+ # <tt>ActiveSupport::Notifications</tt> provides an instrumentation API for
9
+ # Ruby.
10
+ #
11
+ # == Instrumenters
12
+ #
13
+ # To instrument an event you just need to do:
14
+ #
15
+ # ActiveSupport::Notifications.instrument('render', extra: :information) do
16
+ # render text: 'Foo'
17
+ # end
18
+ #
19
+ # That executes the block first and notifies all subscribers once done.
20
+ #
21
+ # In the example above +render+ is the name of the event, and the rest is called
22
+ # the _payload_. The payload is a mechanism that allows instrumenters to pass
23
+ # extra information to subscribers. Payloads consist of a hash whose contents
24
+ # are arbitrary and generally depend on the event.
25
+ #
26
+ # == Subscribers
27
+ #
28
+ # You can consume those events and the information they provide by registering
29
+ # a subscriber.
30
+ #
31
+ # ActiveSupport::Notifications.subscribe('render') do |name, start, finish, id, payload|
32
+ # name # => String, name of the event (such as 'render' from above)
33
+ # start # => Time, when the instrumented block started execution
34
+ # finish # => Time, when the instrumented block ended execution
35
+ # id # => String, unique ID for this notification
36
+ # payload # => Hash, the payload
37
+ # end
38
+ #
39
+ # For instance, let's store all "render" events in an array:
40
+ #
41
+ # events = []
42
+ #
43
+ # ActiveSupport::Notifications.subscribe('render') do |*args|
44
+ # events << ActiveSupport::Notifications::Event.new(*args)
45
+ # end
46
+ #
47
+ # That code returns right away, you are just subscribing to "render" events.
48
+ # The block is saved and will be called whenever someone instruments "render":
49
+ #
50
+ # ActiveSupport::Notifications.instrument('render', extra: :information) do
51
+ # render text: 'Foo'
52
+ # end
53
+ #
54
+ # event = events.first
55
+ # event.name # => "render"
56
+ # event.duration # => 10 (in milliseconds)
57
+ # event.payload # => { extra: :information }
58
+ #
59
+ # The block in the <tt>subscribe</tt> call gets the name of the event, start
60
+ # timestamp, end timestamp, a string with a unique identifier for that event
61
+ # (something like "535801666f04d0298cd6"), and a hash with the payload, in
62
+ # that order.
63
+ #
64
+ # If an exception happens during that particular instrumentation the payload will
65
+ # have a key <tt>:exception</tt> with an array of two elements as value: a string with
66
+ # the name of the exception class, and the exception message.
67
+ #
68
+ # As the previous example depicts, the class <tt>ActiveSupport::Notifications::Event</tt>
69
+ # is able to take the arguments as they come and provide an object-oriented
70
+ # interface to that data.
71
+ #
72
+ # It is also possible to pass an object as the second parameter passed to the
73
+ # <tt>subscribe</tt> method instead of a block:
74
+ #
75
+ # module ActionController
76
+ # class PageRequest
77
+ # def call(name, started, finished, unique_id, payload)
78
+ # Rails.logger.debug ['notification:', name, started, finished, unique_id, payload].join(' ')
79
+ # end
80
+ # end
81
+ # end
82
+ #
83
+ # ActiveSupport::Notifications.subscribe('process_action.action_controller', ActionController::PageRequest.new)
84
+ #
85
+ # resulting in the following output within the logs including a hash with the payload:
86
+ #
87
+ # notification: process_action.action_controller 2012-04-13 01:08:35 +0300 2012-04-13 01:08:35 +0300 af358ed7fab884532ec7 {
88
+ # controller: "Devise::SessionsController",
89
+ # action: "new",
90
+ # params: {"action"=>"new", "controller"=>"devise/sessions"},
91
+ # format: :html,
92
+ # method: "GET",
93
+ # path: "/login/sign_in",
94
+ # status: 200,
95
+ # view_runtime: 279.3080806732178,
96
+ # db_runtime: 40.053
97
+ # }
98
+ #
99
+ # You can also subscribe to all events whose name matches a certain regexp:
100
+ #
101
+ # ActiveSupport::Notifications.subscribe(/render/) do |*args|
102
+ # ...
103
+ # end
104
+ #
105
+ # and even pass no argument to <tt>subscribe</tt>, in which case you are subscribing
106
+ # to all events.
107
+ #
108
+ # == Temporary Subscriptions
109
+ #
110
+ # Sometimes you do not want to subscribe to an event for the entire life of
111
+ # the application. There are two ways to unsubscribe.
112
+ #
113
+ # WARNING: The instrumentation framework is designed for long-running subscribers,
114
+ # use this feature sparingly because it wipes some internal caches and that has
115
+ # a negative impact on performance.
116
+ #
117
+ # === Subscribe While a Block Runs
118
+ #
119
+ # You can subscribe to some event temporarily while some block runs. For
120
+ # example, in
121
+ #
122
+ # callback = lambda {|*args| ... }
123
+ # ActiveSupport::Notifications.subscribed(callback, "sql.active_record") do
124
+ # ...
125
+ # end
126
+ #
127
+ # the callback will be called for all "sql.active_record" events instrumented
128
+ # during the execution of the block. The callback is unsubscribed automatically
129
+ # after that.
130
+ #
131
+ # === Manual Unsubscription
132
+ #
133
+ # The +subscribe+ method returns a subscriber object:
134
+ #
135
+ # subscriber = ActiveSupport::Notifications.subscribe("render") do |*args|
136
+ # ...
137
+ # end
138
+ #
139
+ # To prevent that block from being called anymore, just unsubscribe passing
140
+ # that reference:
141
+ #
142
+ # ActiveSupport::Notifications.unsubscribe(subscriber)
143
+ #
144
+ # == Default Queue
145
+ #
146
+ # Notifications ships with a queue implementation that consumes and publish events
147
+ # to log subscribers in a thread. You can use any queue implementation you want.
148
+ #
149
+ module Notifications
150
+ class << self
151
+ attr_accessor :notifier
152
+
153
+ def publish(name, *args)
154
+ notifier.publish(name, *args)
155
+ end
156
+
157
+ def instrument(name, payload = {})
158
+ if notifier.listening?(name)
159
+ instrumenter.instrument(name, payload) { yield payload if block_given? }
160
+ else
161
+ yield payload if block_given?
162
+ end
163
+ end
164
+
165
+ def subscribe(*args, &block)
166
+ notifier.subscribe(*args, &block)
167
+ end
168
+
169
+ def subscribed(callback, *args, &block)
170
+ subscriber = subscribe(*args, &callback)
171
+ yield
172
+ ensure
173
+ unsubscribe(subscriber)
174
+ end
175
+
176
+ def unsubscribe(args)
177
+ notifier.unsubscribe(args)
178
+ end
179
+
180
+ def instrumenter
181
+ InstrumentationRegistry.instrumenter_for(notifier)
182
+ end
183
+ end
184
+
185
+ # This class is a registry which holds all of the +Instrumenter+ objects
186
+ # in a particular thread local. To access the +Instrumenter+ object for a
187
+ # particular +notifier+, you can call the following method:
188
+ #
189
+ # InstrumentationRegistry.instrumenter_for(notifier)
190
+ #
191
+ # The instrumenters for multiple notifiers are held in a single instance of
192
+ # this class.
193
+ class InstrumentationRegistry # :nodoc:
194
+ extend ActiveSupport::PerThreadRegistry
195
+
196
+ def initialize
197
+ @registry = {}
198
+ end
199
+
200
+ def instrumenter_for(notifier)
201
+ @registry[notifier] ||= Instrumenter.new(notifier)
202
+ end
203
+ end
204
+
205
+ self.notifier = Fanout.new
206
+ end
207
+ end
@@ -0,0 +1,159 @@
1
+ require 'mutex_m'
2
+ begin
3
+ require 'thread_safe'
4
+ rescue LoadError
5
+ require 'skylight/vendor/thread_safe'
6
+ end
7
+
8
+ module ActiveSupport
9
+ module Notifications
10
+ # This is a default queue implementation that ships with Notifications.
11
+ # It just pushes events to all registered log subscribers.
12
+ #
13
+ # This class is thread safe. All methods are reentrant.
14
+ class Fanout
15
+ include Mutex_m
16
+
17
+ def initialize
18
+ @subscribers = []
19
+ @listeners_for = ThreadSafe::Cache.new
20
+ super
21
+ end
22
+
23
+ def subscribe(pattern = nil, block = Proc.new)
24
+ subscriber = Subscribers.new pattern, block
25
+ synchronize do
26
+ @subscribers << subscriber
27
+ @listeners_for.clear
28
+ end
29
+ subscriber
30
+ end
31
+
32
+ def unsubscribe(subscriber)
33
+ synchronize do
34
+ @subscribers.reject! { |s| s.matches?(subscriber) }
35
+ @listeners_for.clear
36
+ end
37
+ end
38
+
39
+ def start(name, id, payload)
40
+ listeners_for(name).each { |s| s.start(name, id, payload) }
41
+ end
42
+
43
+ def finish(name, id, payload)
44
+ listeners_for(name).each { |s| s.finish(name, id, payload) }
45
+ end
46
+
47
+ def publish(name, *args)
48
+ listeners_for(name).each { |s| s.publish(name, *args) }
49
+ end
50
+
51
+ def listeners_for(name)
52
+ # this is correctly done double-checked locking (ThreadSafe::Cache's lookups have volatile semantics)
53
+ @listeners_for[name] || synchronize do
54
+ # use synchronisation when accessing @subscribers
55
+ @listeners_for[name] ||= @subscribers.select { |s| s.subscribed_to?(name) }
56
+ end
57
+ end
58
+
59
+ def listening?(name)
60
+ listeners_for(name).any?
61
+ end
62
+
63
+ # This is a sync queue, so there is no waiting.
64
+ def wait
65
+ end
66
+
67
+ module Subscribers # :nodoc:
68
+ def self.new(pattern, listener)
69
+ if listener.respond_to?(:start) and listener.respond_to?(:finish)
70
+ subscriber = Evented.new pattern, listener
71
+ else
72
+ subscriber = Timed.new pattern, listener
73
+ end
74
+
75
+ unless pattern
76
+ AllMessages.new(subscriber)
77
+ else
78
+ subscriber
79
+ end
80
+ end
81
+
82
+ class Evented #:nodoc:
83
+ def initialize(pattern, delegate)
84
+ @pattern = pattern
85
+ @delegate = delegate
86
+ @can_publish = delegate.respond_to?(:publish)
87
+ end
88
+
89
+ def publish(name, *args)
90
+ if @can_publish
91
+ @delegate.publish name, *args
92
+ end
93
+ end
94
+
95
+ def start(name, id, payload)
96
+ @delegate.start name, id, payload
97
+ end
98
+
99
+ def finish(name, id, payload)
100
+ @delegate.finish name, id, payload
101
+ end
102
+
103
+ def subscribed_to?(name)
104
+ @pattern === name.to_s
105
+ end
106
+
107
+ def matches?(subscriber_or_name)
108
+ self === subscriber_or_name ||
109
+ @pattern && @pattern === subscriber_or_name
110
+ end
111
+ end
112
+
113
+ class Timed < Evented
114
+ def initialize(pattern, delegate)
115
+ @timestack = []
116
+ super
117
+ end
118
+
119
+ def publish(name, *args)
120
+ @delegate.call name, *args
121
+ end
122
+
123
+ def start(name, id, payload)
124
+ @timestack.push Time.now
125
+ end
126
+
127
+ def finish(name, id, payload)
128
+ started = @timestack.pop
129
+ @delegate.call(name, started, Time.now, id, payload)
130
+ end
131
+ end
132
+
133
+ class AllMessages # :nodoc:
134
+ def initialize(delegate)
135
+ @delegate = delegate
136
+ end
137
+
138
+ def start(name, id, payload)
139
+ @delegate.start name, id, payload
140
+ end
141
+
142
+ def finish(name, id, payload)
143
+ @delegate.finish name, id, payload
144
+ end
145
+
146
+ def publish(name, *args)
147
+ @delegate.publish name, *args
148
+ end
149
+
150
+ def subscribed_to?(name)
151
+ true
152
+ end
153
+
154
+ alias :matches? :===
155
+ end
156
+ end
157
+ end
158
+ end
159
+ end
@@ -0,0 +1,72 @@
1
+ require 'securerandom'
2
+
3
+ module ActiveSupport
4
+ module Notifications
5
+ # Instrumenters are stored in a thread local.
6
+ class Instrumenter
7
+ attr_reader :id
8
+
9
+ def initialize(notifier)
10
+ @id = unique_id
11
+ @notifier = notifier
12
+ end
13
+
14
+ # Instrument the given block by measuring the time taken to execute it
15
+ # and publish it. Notice that events get sent even if an error occurs
16
+ # in the passed-in block.
17
+ def instrument(name, payload={})
18
+ start name, payload
19
+ begin
20
+ yield payload
21
+ rescue Exception => e
22
+ payload[:exception] = [e.class.name, e.message]
23
+ raise e
24
+ ensure
25
+ finish name, payload
26
+ end
27
+ end
28
+
29
+ # Send a start notification with +name+ and +payload+.
30
+ def start(name, payload)
31
+ @notifier.start name, @id, payload
32
+ end
33
+
34
+ # Send a finish notification with +name+ and +payload+.
35
+ def finish(name, payload)
36
+ @notifier.finish name, @id, payload
37
+ end
38
+
39
+ private
40
+
41
+ def unique_id
42
+ ::SecureRandom.hex(10)
43
+ end
44
+ end
45
+
46
+ class Event
47
+ attr_reader :name, :time, :transaction_id, :payload, :children
48
+ attr_accessor :end
49
+
50
+ def initialize(name, start, ending, transaction_id, payload)
51
+ @name = name
52
+ @payload = payload.dup
53
+ @time = start
54
+ @transaction_id = transaction_id
55
+ @end = ending
56
+ @children = []
57
+ end
58
+
59
+ def duration
60
+ 1000.0 * (self.end - time)
61
+ end
62
+
63
+ def <<(event)
64
+ @children << event
65
+ end
66
+
67
+ def parent_of?(event)
68
+ @children.include? event
69
+ end
70
+ end
71
+ end
72
+ end