skylight 5.0.0.beta2 → 5.0.0.beta3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2b77ca3f00aac3011421d279776acf31f9259debecb3319689250e49fbd3310f
4
- data.tar.gz: 6cee4d4a09aa991c3e5d3cf65bc9534797f59fc8951a7d088025271068d9e9cc
3
+ metadata.gz: c951c13914411fa23c37504ba022bd55229c2c4c59dc4dcf0a751b24b9dad33c
4
+ data.tar.gz: 93734aa403e74cbcc5c7afda5473800b962a1fe4a0b06fff0cbfab2a23d7d316
5
5
  SHA512:
6
- metadata.gz: 98649cab11fb628dcfdade4a7dc5507d7640f5f90b6aa9230305fc1c5261d5f73ff3014bc399595f4bc6c85fafb334668f1b81e9020ea5e1f644f3e60ad966d7
7
- data.tar.gz: edfacb9d5322768a0dbdd9acbdd31ea5305a077dee1a24076078c448c73a9cd7b0b1889ead269db9e661ed49d11e02e2da38326bad90448b12db72718b949a81
6
+ metadata.gz: 7901ffd7e863387424ab384d8276472a6d2c3dfabef2075cb859db8e1ff8f81643cce80f2ac9ffba1f3cb1c27d06338a6b6477347f7e7db58745d9ede000a78b
7
+ data.tar.gz: a404ebc97ac20f763f21df54e444e0abf72b4ad442bb39efca1c6b19a408f0d8edab2021032237aac044cb39c333815ed101ad6015fdd4246d3a66932cd9b7e9
@@ -1,3 +1,9 @@
1
+ ## 5.0.0.beta3
2
+ * [IMPROVEMENT] Optimizations for the Source Locations extension
3
+ * [FEATURE] Configuration for the Source Locations caches via `SYLIGHT_SOURCE_LOCATION_CACHE_SIZE`
4
+ * [BUGFIX] Fix issue with missing metadata in MongoDB probe
5
+ * [BUGFIX] Resolve an inability to parse certain SQL queries containing arrays
6
+
1
7
  ## 5.0.0.beta2
2
8
  * [FEATURE] Source Locations detection and reporting is now enabled by default (can be disabled with `SKYLIGHT_ENABLE_SOURCE_LOCATIONS=false`)
3
9
  * [BREAKING] Rename `environment` keyword argument to `priority_key`. Note `env` has not changed.
@@ -1,6 +1,6 @@
1
- version: "5.0.0-45b02dd"
1
+ version: "5.0.0-7111415"
2
2
  checksums:
3
- x86-linux: "218a51683cbe3f6e7f1d31097a7e732c6bac3e3780a707312f8441dd45d8f3a6"
4
- x86_64-linux: "2426968fef8cd7fe0fd0ea582fd8098db78025ce936bac9d72b7753995bd1ea9"
5
- x86_64-linux-musl: "ca07748d43fac0b4a05b38b5ce0fc4cb7e43469a183919c5d9980a8b2e0b01ab"
6
- x86_64-darwin: "8b19eb2ffd19f78ee6e547b37fcf5cad2e49aa9a8bc2b9615a791ccfc91c2552"
3
+ x86-linux: "c304b73401b82adcbede23886168ca3487ca5901ebeddd6377d8ce758bf9d72d"
4
+ x86_64-linux: "4005f06b71295c77dccc7369f313452c7a26fe4c8de1108988e4d06d8f5fb36e"
5
+ x86_64-linux-musl: "0b8c582f99cc65ef466a506b9f589d634c8b502d4de5991c80c38e9efa812909"
6
+ x86_64-darwin: "efbd36e1cbea562ca9b76342cc3e938a6c0c506e7e7e1c0daaafff71da68364e"
@@ -101,7 +101,7 @@ module Skylight
101
101
  message: e.message, klass: e.class)]
102
102
  end
103
103
 
104
- if config&.respond_to?("log_#{level}") && config&.respond_to?(:log_trace)
104
+ if config.respond_to?("log_#{level}") && config.respond_to?(:log_trace)
105
105
  config.send("log_#{level}", message)
106
106
  config.log_trace e.backtrace.join("\n")
107
107
  else
@@ -194,10 +194,17 @@ module Skylight
194
194
  opts = {}
195
195
  end
196
196
 
197
+ # NOTE: unless we have `:internal` (indicating a built-in Skylight instrument block),
198
+ # or we already have a `source_file` or `source_line` (probably set by `instrument_method`),
199
+ # we set the caller location to the second item on the stack
200
+ # (immediate caller of the `instrument` method).
201
+ unless opts[:source_file] || opts[:source_line] || opts[:internal]
202
+ opts = opts.merge(sk_instrument_location: caller_locations(1..1).first)
203
+ end
204
+
197
205
  meta ||= {}
198
206
 
199
207
  instrumenter.extensions.process_instrument_options(opts, meta)
200
-
201
208
  instrumenter.instrument(category, title, desc, meta, &block)
202
209
  end
203
210
 
@@ -110,7 +110,8 @@ module Skylight
110
110
  -"HEROKU_DYNO_INFO_PATH" => :'heroku.dyno_info_path',
111
111
 
112
112
  # == Source Location ==
113
- -"SOURCE_LOCATION_IGNORED_GEMS" => :source_location_ignored_gems
113
+ -"SOURCE_LOCATION_IGNORED_GEMS" => :source_location_ignored_gems,
114
+ -"SOURCE_LOCATION_CACHE_SIZE" => :source_location_cache_size
114
115
  }.freeze
115
116
 
116
117
  KEY_TO_NATIVE_ENV = {
@@ -551,7 +552,7 @@ module Skylight
551
552
  when /^warn$/i then Logger::WARN
552
553
  when /^error$/i then Logger::ERROR
553
554
  when /^fatal$/i then Logger::FATAL
554
- else Logger::ERROR
555
+ else Logger::ERROR # rubocop:disable Lint/DuplicateBranch
555
556
  end
556
557
  end
557
558
  end
@@ -13,10 +13,10 @@ module Skylight
13
13
  end
14
14
 
15
15
  Skylight.module_eval <<-RUBY, __FILE__, __LINE__ + 1
16
- class #{name}Error < NativeError
17
- def self.code; #{code}; end
18
- def self.message; #{message.to_json}; end
19
- end
16
+ class #{name}Error < NativeError # class SqlLexError < NativeError
17
+ def self.code; #{code}; end # def self.code; 4; end
18
+ def self.message; #{message.to_json}; end # def self.message; "Failed to lex SQL query."; end
19
+ end # end
20
20
  RUBY
21
21
 
22
22
  klass = Skylight.const_get("#{name}Error")
@@ -11,11 +11,13 @@ module Skylight
11
11
  include Util::Logging
12
12
 
13
13
  META_KEYS = %i[source_location source_file source_line].freeze
14
+ MAX_CALLER_DEPTH = 75
14
15
 
15
16
  def initialize(*)
16
17
  super
17
- @caller_cache = Util::LruCache.new(100)
18
- @instance_method_source_location_cache = Util::LruCache.new(100)
18
+ cache_size = (config[:source_location_cache_size] || 1000).to_i
19
+ @caller_cache = Util::LruCache.new(cache_size)
20
+ @instance_method_source_location_cache = Util::LruCache.new(cache_size)
19
21
  gem_require_trie # memoize this at startup
20
22
  end
21
23
 
@@ -35,6 +37,7 @@ module Skylight
35
37
  source_line = opts[:source_line] || opts[:meta]&.[](:source_line)
36
38
  source_name_hint, const_name, method_name = opts[:source_location_hint] ||
37
39
  opts[:meta]&.[](:source_location_hint)
40
+ instrument_location = opts[:sk_instrument_location]
38
41
 
39
42
  if source_location
40
43
  meta[:source_location] = source_location
@@ -45,6 +48,9 @@ module Skylight
45
48
  elsif source_file
46
49
  meta[:source_file] = source_file
47
50
  meta[:source_line] = source_line
51
+ elsif instrument_location && project_path?(instrument_location.absolute_path)
52
+ meta[:source_file] = instrument_location.absolute_path
53
+ meta[:source_line] = instrument_location.lineno
48
54
  else
49
55
  warn "Ignoring source_line without source_file" if source_line
50
56
  if (location = find_caller(cache_key: opts.hash))
@@ -134,10 +140,14 @@ module Skylight
134
140
  end
135
141
 
136
142
  def find_caller(cache_key: nil)
143
+ # starting at 4 to skip Skylight extension processing logic
144
+ locations = ::Kernel.caller_locations(4..MAX_CALLER_DEPTH)
145
+
137
146
  if cache_key
138
- @caller_cache.fetch(cache_key) { find_caller_inner }
147
+ localized_cache_key = [cache_key, locations.map(&:lineno)].hash
148
+ @caller_cache.fetch(localized_cache_key) { find_caller_inner(locations) }
139
149
  else
140
- find_caller_inner
150
+ find_caller_inner(locations)
141
151
  end
142
152
  end
143
153
 
@@ -236,11 +246,12 @@ module Skylight
236
246
  nil
237
247
  end
238
248
 
239
- def find_caller_inner
249
+ def find_caller_inner(locations)
240
250
  # Start at file before this one
241
251
  # NOTE: We could start farther back now to avoid more Skylight files
242
- caller_locations(1).find do |l|
243
- find_source_gem(l.absolute_path) || project_path?(l.absolute_path)
252
+ locations.find do |l|
253
+ absolute_path = l.absolute_path
254
+ find_source_gem(absolute_path) || project_path?(absolute_path)
244
255
  end
245
256
  end
246
257
 
@@ -12,7 +12,8 @@ module Skylight
12
12
  # @return [Hash] a hash containing `:category`, `:title`, and `:annotations`
13
13
  def self.build_opts(method, _scheme, host, _port, _path, _query)
14
14
  { category: "api.http.#{method.downcase}",
15
- title: "#{method.upcase} #{host}" }
15
+ title: "#{method.upcase} #{host}",
16
+ internal: true }
16
17
  end
17
18
  end
18
19
  end
@@ -124,6 +124,8 @@ module Skylight
124
124
  # instrument_class_method :my_method, title: 'Expensive work'
125
125
  # end
126
126
  def instrument_class_method(name, opts = {})
127
+ # NOTE: If the class is defined anonymously and then assigned to a variable this code
128
+ # will not be aware of the updated name.
127
129
  title = "#{self}.#{name}"
128
130
  __sk_instrument_method_on(__sk_singleton_class, name, title, opts || {})
129
131
  end
@@ -144,32 +146,32 @@ module Skylight
144
146
  source_file, source_line = klass.instance_method(name).source_location
145
147
 
146
148
  klass.class_eval <<-RUBY, __FILE__, __LINE__ + 1
147
- alias_method :"before_instrument_#{name}", :"#{name}"
148
-
149
- def #{name}(*args, &blk)
150
- span = Skylight.instrument(
151
- category: :"#{category}",
152
- title: #{title.inspect},
153
- description: #{desc.inspect},
154
- source_file: #{source_file.inspect},
155
- source_line: #{source_line.inspect})
156
-
157
- meta = {}
158
- begin
159
- send(:before_instrument_#{name}, *args, &blk)
160
- rescue Exception => e
161
- meta[:exception_object] = e
162
- raise e
163
- ensure
164
- Skylight.done(span, meta) if span
165
- end
166
- end
167
-
168
- if protected_method_defined?(:"before_instrument_#{name}")
169
- protected :"#{name}"
170
- elsif private_method_defined?(:"before_instrument_#{name}")
171
- private :"#{name}"
172
- end
149
+ alias_method :"before_instrument_#{name}", :"#{name}" # alias_method :"before_instrument_process", :"process"
150
+ #
151
+ def #{name}(*args, &blk) # def process(*args, &blk)
152
+ span = Skylight.instrument( # span = Skylight.instrument(
153
+ category: :"#{category}", # category: :"app.method",
154
+ title: #{title.inspect}, # title: "process",
155
+ description: #{desc.inspect}, # description: "Process data",
156
+ source_file: #{source_file.inspect}, # source_file: "myapp/lib/processor.rb",
157
+ source_line: #{source_line.inspect}) # source_line: 123)
158
+ #
159
+ meta = {} # meta = {}
160
+ begin # begin
161
+ send(:before_instrument_#{name}, *args, &blk) # send(:before_instrument_process)
162
+ rescue Exception => e # rescue Exception => e
163
+ meta[:exception_object] = e # meta[:exception_object] = e
164
+ raise e # raise e
165
+ ensure # ensure
166
+ Skylight.done(span, meta) if span # Skylight.done(span, meta) if span
167
+ end # end
168
+ end # end
169
+ #
170
+ if protected_method_defined?(:"before_instrument_#{name}") # if protected_method_defined?(:"before_instrument_process")
171
+ protected :"#{name}" # protected :"process"
172
+ elsif private_method_defined?(:"before_instrument_#{name}") # elsif private_method_defined?(:"before_instrument_process")
173
+ private :"#{name}" # private :"process"
174
+ end # end
173
175
  RUBY
174
176
  end
175
177
 
@@ -10,7 +10,7 @@ module Skylight
10
10
  @closed = false
11
11
  end
12
12
 
13
- def respond_to_missing?(name, include_all = false) # rubocop:disable Lint/MissingSuper, Style/OptionalBooleanParameter
13
+ def respond_to_missing?(name, include_all = false) # rubocop:disable Lint/MissingSuper
14
14
  return false if name.to_s !~ /^to_ary$/
15
15
 
16
16
  @body.respond_to?(name, include_all)
@@ -101,7 +101,7 @@ module Skylight
101
101
 
102
102
  # @api private
103
103
  def self.check_install_errors(config)
104
- # Note: An unsupported arch doesn't count as an error.
104
+ # NOTE: An unsupported arch doesn't count as an error.
105
105
  install_log = File.expand_path("../../ext/install.log", __dir__)
106
106
 
107
107
  if File.exist?(install_log) && File.read(install_log) =~ /ERROR/
@@ -69,7 +69,8 @@ module Skylight
69
69
  return cat if cat == :skip
70
70
 
71
71
  meta ||= {}
72
- process_meta(trace, name, payload, meta, cache_key: ret.hash)
72
+ cache_key = ret.hash
73
+ process_meta(trace, name, payload, meta, cache_key: cache_key)
73
74
 
74
75
  [cat, title, desc, meta]
75
76
  end
@@ -18,7 +18,13 @@ module Skylight
18
18
  rescue
19
19
  block.call
20
20
  else
21
- Skylight.instrument(title: "Enqueue #{name}", category: CAT, description: desc, &block)
21
+ Skylight.instrument(
22
+ title: "Enqueue #{name}",
23
+ category: CAT,
24
+ description: desc,
25
+ internal: true,
26
+ &block
27
+ )
22
28
  end
23
29
 
24
30
  self.class.instance_eval do
@@ -85,7 +85,8 @@ module Skylight
85
85
  opts = {
86
86
  category: "app.delayed_job.job",
87
87
  title: format_source(*source_meta),
88
- meta: { source_location_hint: source_meta }
88
+ meta: { source_location_hint: source_meta },
89
+ internal: true
89
90
  }
90
91
 
91
92
  Skylight.instrument(opts) { __getobj__.perform }
@@ -6,7 +6,7 @@ module Skylight
6
6
  # Middleware for Excon that instruments requests
7
7
  class Middleware < ::Excon::Middleware::Base
8
8
  def initialize(*)
9
- @requests = {}
9
+ @requests = {}.compare_by_identity
10
10
  super
11
11
  end
12
12
 
@@ -38,19 +38,19 @@ module Skylight
38
38
  scheme = datum[:scheme]
39
39
  host = datum[:host]
40
40
  # TODO: Maybe don't show other default ports like 443
41
- port = datum[:port] != 80 ? datum[:port] : nil
41
+ port = datum[:port] == 80 ? nil : datum[:port]
42
42
  path = datum[:path]
43
43
  query = datum[:query]
44
44
 
45
45
  opts = Formatters::HTTP.build_opts(method, scheme, host, port, path, query)
46
46
 
47
- @requests[datum.object_id] = Skylight.instrument(opts)
47
+ @requests[datum] = Skylight.instrument(opts)
48
48
  rescue Exception => e
49
49
  Skylight.error "failed to begin instrumentation for Excon; msg=%s", e.message
50
50
  end
51
51
 
52
52
  def end_instrumentation(datum)
53
- if (request = @requests.delete(datum.object_id))
53
+ if (request = @requests.delete(datum))
54
54
  meta = {}
55
55
  if datum[:error].is_a?(Exception)
56
56
  meta[:exception_object] = datum[:error]
@@ -113,7 +113,8 @@ module Skylight
113
113
  category: CAT,
114
114
  title: title,
115
115
  description: payload.empty? ? nil : payload.to_json,
116
- meta: { database: event.database_name }
116
+ meta: { database: event.database_name },
117
+ internal: true
117
118
  }
118
119
 
119
120
  @events[event.operation_id] = Skylight.instrument(opts)
@@ -6,12 +6,14 @@ module Skylight
6
6
 
7
7
  PIPELINED_OPTS = {
8
8
  category: "db.redis.pipelined".freeze,
9
- title: "PIPELINE".freeze
9
+ title: "PIPELINE".freeze,
10
+ internal: true
10
11
  }.freeze
11
12
 
12
13
  MULTI_OPTS = {
13
14
  category: "db.redis.multi".freeze,
14
- title: "MULTI".freeze
15
+ title: "MULTI".freeze,
16
+ internal: true
15
17
  }.freeze
16
18
 
17
19
  module ClientInstrumentation
@@ -22,7 +24,8 @@ module Skylight
22
24
 
23
25
  opts = {
24
26
  category: "db.redis.command",
25
- title: command_name.upcase.to_s
27
+ title: command_name.upcase.to_s,
28
+ internal: true
26
29
  }
27
30
 
28
31
  Skylight.instrument(opts) { super }
@@ -6,7 +6,7 @@ module Skylight
6
6
  GC_CAT = "noise.gc".freeze
7
7
  SYNTHETIC = "<synthetic>".freeze
8
8
 
9
- META_KEYS = %i[mute_children].freeze
9
+ META_KEYS = %i[mute_children database].freeze
10
10
 
11
11
  include Util::Logging
12
12
 
@@ -340,8 +340,10 @@ module Skylight
340
340
  def validate_meta(meta)
341
341
  unknown_keys = meta.keys - allowed_meta_keys
342
342
  if unknown_keys.any?
343
- warn "Unknown meta keys will be ignored; keys=#{unknown_keys.inspect}"
344
- unknown_keys.each { |key| meta.delete(key) }
343
+ unknown_keys.each do |key|
344
+ maybe_warn("unknown_meta:#{key}", "Unknown meta key will be ignored; key=#{key.inspect}")
345
+ meta.delete(key)
346
+ end
345
347
  end
346
348
  end
347
349
 
@@ -192,7 +192,7 @@ module Skylight
192
192
  body.dig(*key.split(".")) if body.is_a?(Hash)
193
193
  end
194
194
 
195
- def respond_to_missing?(name, include_all = false) # rubocop:disable Style/OptionalBooleanParameter
195
+ def respond_to_missing?(name, include_all = false)
196
196
  super || body.respond_to?(name, include_all)
197
197
  end
198
198
 
@@ -4,20 +4,20 @@ module Skylight
4
4
  def instrumenter_method(name, block: false)
5
5
  if block
6
6
  module_eval <<-RUBY, __FILE__, __LINE__ + 1
7
- def #{name}(*args)
8
- unless instrumenter
9
- return yield if block_given?
10
- return
11
- end
12
-
13
- instrumenter.#{name}(*args) { yield }
14
- end
7
+ def #{name}(*args) # def mute(*args)
8
+ unless instrumenter # unless instrumenter
9
+ return yield if block_given? # return yield if block_given?
10
+ return # return
11
+ end # end
12
+ #
13
+ instrumenter.#{name}(*args) { yield } # instrumenter.mute(*args) { yield }
14
+ end # end
15
15
  RUBY
16
16
  else
17
17
  module_eval <<-RUBY, __FILE__, __LINE__ + 1
18
- def #{name}(*args)
19
- instrumenter&.#{name}(*args)
20
- end
18
+ def #{name}(*args) # def config(*args)
19
+ instrumenter&.#{name}(*args) # instrumenter&.config(*args)
20
+ end # end
21
21
  RUBY
22
22
  end
23
23
  end
@@ -13,7 +13,7 @@ module Skylight
13
13
 
14
14
  # Try to avoid writing to STDOUT/STDERR twice
15
15
  logger_logdev = @logger.instance_variable_get(:@logdev)
16
- logger_out = logger_logdev&.respond_to?(:dev) ? logger_logdev.dev : nil
16
+ logger_out = logger_logdev.respond_to?(:dev) ? logger_logdev.dev : nil
17
17
  if logger_out != $stdout && logger_out != $stderr
18
18
  @logger.<<(*args)
19
19
  end
@@ -114,10 +114,10 @@ module Skylight
114
114
 
115
115
  if logger
116
116
  if logger.respond_to?(level)
117
- if !args.empty?
118
- logger.send level, format(msg, *args)
119
- else
117
+ if args.empty?
120
118
  logger.send level, msg
119
+ else
120
+ logger.send level, format(msg, *args)
121
121
  end
122
122
  return # rubocop:disable Style/RedundantReturn
123
123
  else
@@ -56,7 +56,7 @@ module Skylight
56
56
  "so"
57
57
  when /windows|cygwin/
58
58
  "dll"
59
- else
59
+ else # rubocop:disable Lint/DuplicateBranch
60
60
  "so"
61
61
  end
62
62
 
@@ -3,5 +3,5 @@ module Skylight
3
3
  # for compatibility with semver when it is parsed by the rust agent.
4
4
  # This string will be transformed in the gemspec to "5.0.0.alpha"
5
5
  # to conform with rubygems.
6
- VERSION = "5.0.0-beta2".freeze
6
+ VERSION = "5.0.0-beta3".freeze
7
7
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: skylight
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.0.0.beta2
4
+ version: 5.0.0.beta3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tilde, Inc.
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-10-26 00:00:00.000000000 Z
11
+ date: 2020-11-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -142,14 +142,14 @@ dependencies:
142
142
  requirements:
143
143
  - - "~>"
144
144
  - !ruby/object:Gem::Version
145
- version: 0.79.0
145
+ version: 1.3.1
146
146
  type: :development
147
147
  prerelease: false
148
148
  version_requirements: !ruby/object:Gem::Requirement
149
149
  requirements:
150
150
  - - "~>"
151
151
  - !ruby/object:Gem::Version
152
- version: 0.79.0
152
+ version: 1.3.1
153
153
  - !ruby/object:Gem::Dependency
154
154
  name: timecop
155
155
  requirement: !ruby/object:Gem::Requirement
@@ -367,7 +367,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
367
367
  - !ruby/object:Gem::Version
368
368
  version: 1.3.1
369
369
  requirements: []
370
- rubygems_version: 3.1.2
370
+ rubygems_version: 3.1.4
371
371
  signing_key:
372
372
  specification_version: 4
373
373
  summary: Skylight is a smart profiler for Rails, Sinatra, and other Ruby apps.