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,75 @@
1
+ module Skylight
2
+ # @api private
3
+ class Middleware
4
+
5
+ class BodyProxy
6
+ def initialize(body, &block)
7
+ @body, @block, @closed = body, block, false
8
+ end
9
+
10
+ def respond_to?(*args)
11
+ return false if args.first.to_s =~ /^to_ary$/
12
+ super or @body.respond_to?(*args)
13
+ end
14
+
15
+ def close
16
+ return if @closed
17
+ @closed = true
18
+ begin
19
+ @body.close if @body.respond_to? :close
20
+ ensure
21
+ @block.call
22
+ end
23
+ end
24
+
25
+ def closed?
26
+ @closed
27
+ end
28
+
29
+ # N.B. This method is a special case to address the bug described by #434.
30
+ # We are applying this special case for #each only. Future bugs of this
31
+ # class will be handled by requesting users to patch their ruby
32
+ # implementation, to save adding too many methods in this class.
33
+ def each(*args, &block)
34
+ @body.each(*args, &block)
35
+ end
36
+
37
+ def method_missing(*args, &block)
38
+ super if args.first.to_s =~ /^to_ary$/
39
+ @body.__send__(*args, &block)
40
+ end
41
+ end
42
+
43
+ include Util::Logging
44
+
45
+ # For Util::Logging
46
+ attr_reader :config
47
+
48
+ def initialize(app, opts={})
49
+ @app = app
50
+ @config = opts[:config]
51
+ end
52
+
53
+ def call(env)
54
+ if env["REQUEST_METHOD"] == "HEAD"
55
+ t { "middleware skipping HEAD" }
56
+ @app.call(env)
57
+ else
58
+ begin
59
+ t { "middleware beginning trace" }
60
+ trace = Skylight.trace "Rack", 'app.rack.request'
61
+ resp = @app.call(env)
62
+ resp[2] = BodyProxy.new(resp[2]) { trace.submit } if trace
63
+ resp
64
+ rescue Exception
65
+ t { "middleware exception: #{trace}"}
66
+ trace.submit if trace
67
+ raise
68
+ ensure
69
+ t { "middleware release: #{trace}"}
70
+ trace.release if trace
71
+ end
72
+ end
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,69 @@
1
+ require 'skylight/util/platform'
2
+
3
+ module Skylight
4
+ # @api private
5
+ # Whether or not the native extension is present
6
+ @@has_native_ext = false
7
+
8
+ def self.native?
9
+ @@has_native_ext
10
+ end
11
+
12
+ def self.libskylight_path
13
+ ENV['SKYLIGHT_LIB_PATH'] || File.expand_path("../native/#{Util::Platform.tuple}", __FILE__)
14
+ end
15
+
16
+ skylight_required = ENV.key?("SKYLIGHT_REQUIRED") && ENV['SKYLIGHT_REQUIRED'] !~ /^false$/i
17
+
18
+ begin
19
+ unless ENV.key?("SKYLIGHT_DISABLE_AGENT") && ENV['SKYLIGHT_DISABLE_AGENT'] !~ /^false$/i
20
+ lib = "#{libskylight_path}/libskylight.#{Util::Platform.libext}"
21
+
22
+ if File.exist?(lib)
23
+ # First attempt to require the native extension
24
+ require "skylight_native"
25
+
26
+ # Attempt to link the dylib
27
+ load_libskylight(lib)
28
+
29
+ # If nothing was thrown, then the native extension is present
30
+ @@has_native_ext = true
31
+ elsif skylight_required
32
+ raise LoadError, "Cannot find native extensions in #{libskylight_path}"
33
+ end
34
+ end
35
+ rescue LoadError => e
36
+ raise if skylight_required
37
+ end
38
+
39
+ unless Skylight.native?
40
+ class Instrumenter
41
+ def self.native_new(*args)
42
+ allocate
43
+ end
44
+ end
45
+ end
46
+
47
+ # @api private
48
+ def self.check_install_errors(config)
49
+ # Note: An unsupported arch doesn't count as an error.
50
+ install_log = File.expand_path("../../ext/install.log", __FILE__)
51
+
52
+ if File.exist?(install_log) && File.read(install_log) =~ /ERROR/
53
+ config.alert_logger.error \
54
+ "[SKYLIGHT] [#{Skylight::VERSION}] The Skylight native extension failed to install. " \
55
+ "Please check #{install_log} and notify support@skylight.io." \
56
+ "The missing extension will not affect the functioning of your application."
57
+ end
58
+ end
59
+
60
+ # @api private
61
+ def self.warn_skylight_native_missing(config)
62
+ config.alert_logger.error \
63
+ "[SKYLIGHT] [#{Skylight::VERSION}] The Skylight native extension for " \
64
+ "your platform wasn't found. Supported operating systems are " \
65
+ "Linux 2.6.18+ and Mac OS X 10.8+. The missing extension will not " \
66
+ "affect the functioning of your application. If you are on a " \
67
+ "supported platform, please contact support at support@skylight.io."
68
+ end
69
+ end
@@ -0,0 +1,133 @@
1
+ require 'skylight/normalizers/default'
2
+
3
+ module Skylight
4
+ # @api private
5
+ # Convert AS::N events to Skylight events
6
+ module Normalizers
7
+
8
+ DEFAULT = Default.new
9
+
10
+ def self.register(name, klass)
11
+ (@registry ||= {})[name] = klass
12
+ klass
13
+ end
14
+
15
+ def self.build(config)
16
+ normalizers = {}
17
+
18
+ (@registry || {}).each do |k, klass|
19
+ unless klass.method_defined?(:normalize)
20
+ # TODO: Warn
21
+ next
22
+ end
23
+
24
+ normalizers[k] = klass.new(config)
25
+ end
26
+
27
+ Container.new(normalizers)
28
+ end
29
+
30
+ class Normalizer
31
+ def self.register(name)
32
+ Normalizers.register(name, self)
33
+ end
34
+
35
+ attr_reader :config
36
+
37
+ def initialize(config)
38
+ @config = config
39
+ setup if respond_to?(:setup)
40
+ end
41
+ end
42
+
43
+ class RenderNormalizer < Normalizer
44
+ include Util::AllocationFree
45
+
46
+ def setup
47
+ @paths = config['normalizers.render.view_paths'] || []
48
+ end
49
+
50
+ def normalize_render(category, payload, annotations)
51
+ if path = payload[:identifier]
52
+ title = relative_path(path, annotations)
53
+ path = nil if path == title
54
+ end
55
+
56
+ [ category, title, nil, annotations ]
57
+ end
58
+
59
+ def relative_path(path, annotations)
60
+ return path if relative_path?(path)
61
+
62
+ root = array_find(@paths) { |p| path.start_with?(p) }
63
+ type = :project
64
+
65
+ unless root
66
+ root = array_find(Gem.path) { |p| path.start_with?(p) }
67
+ type = :gem
68
+ end
69
+
70
+ if root
71
+ start = root.size
72
+ start += 1 if path.getbyte(start) == SEPARATOR_BYTE
73
+ if type == :gem
74
+ "$GEM_PATH/#{path[start, path.size]}"
75
+ else
76
+ path[start, path.size]
77
+ end
78
+ else
79
+ "Absolute Path"
80
+ end
81
+ end
82
+
83
+ private
84
+ def relative_path?(path)
85
+ !absolute_path?(path)
86
+ end
87
+
88
+ SEPARATOR_BYTE = File::SEPARATOR.ord
89
+
90
+ if File.const_defined?(:NULL) ? File::NULL == "NUL" : RbConfig::CONFIG['host_os'] =~ /mingw|mswin32/
91
+ # This is a DOSish environment
92
+ ALT_SEPARATOR_BYTE = File::ALT_SEPARATOR && File::ALT_SEPARATOR.ord
93
+ COLON_BYTE = ":".ord
94
+ def absolute_path?(path)
95
+ if alpha?(path.getbyte(0)) && path.getbyte(1) == COLON_BYTE
96
+ byte2 = path.getbyte(2)
97
+ byte2 == SEPARATOR_BYTE || byte2 == ALT_SEPARATOR_BYTE
98
+ end
99
+ end
100
+
101
+ def alpha?(byte)
102
+ byte >= 65 and byte <= 90 || byte >= 97 and byte <= 122
103
+ end
104
+ else
105
+ def absolute_path?(path)
106
+ path.getbyte(0) == SEPARATOR_BYTE
107
+ end
108
+ end
109
+ end
110
+
111
+ class Container
112
+ def initialize(normalizers)
113
+ @normalizers = normalizers
114
+ end
115
+
116
+ def normalize(trace, name, payload)
117
+ normalizer = @normalizers[name] || DEFAULT
118
+ normalizer.normalize(trace, name, payload)
119
+ end
120
+ end
121
+
122
+ %w( action_controller/process_action
123
+ action_controller/send_file
124
+ action_view/render_collection
125
+ action_view/render_partial
126
+ action_view/render_template
127
+ active_record/sql
128
+ active_support/cache
129
+ moped/query).each do |file|
130
+ require "skylight/normalizers/#{file}"
131
+ end
132
+ end
133
+ end
@@ -0,0 +1,35 @@
1
+ module Skylight
2
+ module Normalizers
3
+ module ActionController
4
+ class ProcessAction < Normalizer
5
+ register "process_action.action_controller"
6
+
7
+ CAT = "app.controller.request".freeze
8
+ PAYLOAD_KEYS = %w[ controller action params format method path ].map(&:to_sym).freeze
9
+
10
+ def normalize(trace, name, payload)
11
+ trace.endpoint = controller_action(payload)
12
+ [ CAT, trace.endpoint, nil, normalize_payload(payload) ]
13
+ end
14
+
15
+ private
16
+
17
+ def controller_action(payload)
18
+ "#{payload[:controller]}##{payload[:action]}"
19
+ end
20
+
21
+ def normalize_payload(payload)
22
+ normalized = {}
23
+
24
+ PAYLOAD_KEYS.each do |key|
25
+ val = payload[key]
26
+ val = val.inspect unless val.is_a?(String) || val.is_a?(Numeric)
27
+ normalized[key] = val
28
+ end
29
+
30
+ normalized
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,76 @@
1
+ module Skylight
2
+ module Normalizers
3
+ module ActionController
4
+
5
+ # Temporary hacks
6
+ begin
7
+ require "action_dispatch/http/mime_type"
8
+ require "action_dispatch/http/mime_types"
9
+ require "rack/utils"
10
+
11
+ class SendFile < Normalizer
12
+ register "send_file.action_controller"
13
+
14
+ CAT = "app.controller.send_file".freeze
15
+ TITLE = "send file".freeze
16
+
17
+ def normalize(trace, name, payload)
18
+ path = payload[:path]
19
+
20
+ annotations = {
21
+ path: path,
22
+ filename: payload[:filename],
23
+ type: normalize_type(payload),
24
+ disposition: normalize_disposition(payload),
25
+ status: normalize_status(payload) }
26
+
27
+ title = TITLE
28
+
29
+ # depending on normalization, we probably want this to eventually
30
+ # include the full path, but we need to make sure we have a good
31
+ # deduping strategy first.
32
+ desc = nil
33
+
34
+ [ CAT, title, desc, annotations ]
35
+ end
36
+
37
+ private
38
+
39
+ OCTET_STREAM = "application/octet-stream".freeze
40
+ ATTACHMENT = "attachment".freeze
41
+
42
+ def initialize(*)
43
+ super
44
+
45
+ @mimes = Mime::SET.reduce({}) do |hash, mime|
46
+ hash[mime.symbol] = mime.to_s.dup.freeze
47
+ hash
48
+ end
49
+ end
50
+
51
+ def normalize_type(payload)
52
+ type = payload[:type] || OCTET_STREAM
53
+ type = @mimes[type] if type.is_a?(Symbol)
54
+ type
55
+ end
56
+
57
+ def mime_for(type)
58
+ @mimes[type] ||= Mime[type].to_s.freeze
59
+ end
60
+
61
+ def normalize_status(payload)
62
+ status = payload[:status] || 200
63
+ Rack::Utils.status_code(status)
64
+ end
65
+
66
+ def normalize_disposition(payload)
67
+ payload[:disposition] || ATTACHMENT
68
+ end
69
+ end
70
+
71
+ rescue LoadError
72
+ end
73
+
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,18 @@
1
+ module Skylight
2
+ module Normalizers
3
+ module ActionView
4
+ class RenderCollection < RenderNormalizer
5
+ register "render_collection.action_view"
6
+
7
+ CAT = "view.render.collection".freeze
8
+
9
+ def normalize(trace, name, payload)
10
+ normalize_render(
11
+ CAT,
12
+ payload,
13
+ count: payload[:count])
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,18 @@
1
+ module Skylight
2
+ module Normalizers
3
+ module ActionView
4
+ class RenderPartial < RenderNormalizer
5
+ register "render_partial.action_view"
6
+
7
+ CAT = "view.render.template".freeze
8
+
9
+ def normalize(trace, name, payload)
10
+ normalize_render(
11
+ CAT,
12
+ payload,
13
+ partial: 1)
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,18 @@
1
+ module Skylight
2
+ module Normalizers
3
+ module ActionView
4
+ class RenderTemplate < RenderNormalizer
5
+ register "render_template.action_view"
6
+
7
+ CAT = "view.render.template".freeze
8
+
9
+ def normalize(trace, name, payload)
10
+ normalize_render(
11
+ CAT,
12
+ payload,
13
+ partial: 0)
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end