truex-skylight 0.6.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.
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