skylight-core 4.2.0 → 4.3.1

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a473587df8be0c1cf35b0296875e2cbd3c47d678be913e61c770e7d29d30756a
4
- data.tar.gz: d637956868b2c614225343bf10a063038778df91418053222d7a5e5038fcaa69
3
+ metadata.gz: 2443077b98bc42af5683f82aac17e192670026cbd6bdfa9a940caff2237860a0
4
+ data.tar.gz: e0dc413f3f0d0827f4b064b8fdfbac13f607357113ed50a223f9522e5775b5e0
5
5
  SHA512:
6
- metadata.gz: 91aebd0cfa951251a62903542df63949db425718233e178d362318bce81e4ccd865372e4d1cd9891d1adc09d87d8ac182daf5e5c6c7ded5b81f800ba1faa3374
7
- data.tar.gz: 4d442162789bcbd47ae5bc37fabdaf49650c0fb4f7fc8b50c6a4c2c63cfe6271cd66191db27114d9985ffdcaf5a82effad58984065411b469d9cafa064f3ed63
6
+ metadata.gz: e3ae4c018808967cf5b0cec1fb9056c037f37c2cd60b1790759755d1d9e05cba3f400a790502110fa5723541ad03f0fcf50eeb0d3ebc546d9ff19eb3c8d00309
7
+ data.tar.gz: ca5ca4747d2ec5a578f830dc5ee1ef818a651ca9a9f95ad069cfd26849014279f9aa4f9d3f2040eaf6de8ea64501959fbab005800c96107d17fe9f92b572517c
@@ -44,17 +44,31 @@ module Skylight::Core
44
44
  end
45
45
  end
46
46
 
47
- def self.with_after_close(resp, &block)
47
+ def self.with_after_close(resp, debug_identifier: "unknown", &block)
48
48
  # Responses should be arrays but in some situations they aren't
49
49
  # e.g. https://github.com/ruby-grape/grape/issues/1041
50
- # The safest approach seems to be to rely on implicit destructuring
51
- # since that is currently what Rack::Lint does.
52
50
  # See also https://github.com/rack/rack/issues/1239
53
- status, headers, body = resp
54
51
 
52
+ unless resp.respond_to?(:to_ary)
53
+ if resp.respond_to?(:to_a)
54
+ log_target.warn("Rack response from \"#{debug_identifier}\" cannot be implicitly converted to an array. This is in violation of "\
55
+ "the Rack SPEC and will raise an error in future versions.")
56
+ resp = resp.to_a
57
+ else
58
+ log_target.error("Rack response from \"#{debug_identifier}\" cannot be converted to an array. This is in violation of the Rack SPEC "\
59
+ "and may cause problems with Skylight operation.")
60
+ return resp
61
+ end
62
+ end
63
+
64
+ status, headers, body = resp
55
65
  [status, headers, BodyProxy.new(body, &block)]
56
66
  end
57
67
 
68
+ def self.log_target
69
+ @log_target ||= (Skylight::Core::Fanout.registered.first&.config || Logger.new(STDERR))
70
+ end
71
+
58
72
  include Util::Logging
59
73
 
60
74
  # For Util::Logging
@@ -84,7 +98,7 @@ module Skylight::Core
84
98
  resp = @app.call(env)
85
99
 
86
100
  if trace
87
- Middleware.with_after_close(resp) { trace.submit }
101
+ Middleware.with_after_close(resp, debug_identifier: "Rack App: #{@app.class}") { trace.submit }
88
102
  else
89
103
  resp
90
104
  end
@@ -4,12 +4,12 @@ module Skylight::Core
4
4
  class Perform < Normalizer
5
5
  register "perform.active_job"
6
6
 
7
- DELIVERY_JOB = "ActionMailer::DeliveryJob".freeze
7
+ DELIVERY_JOB = /\AActionMailer::(Mail)?DeliveryJob\Z/.freeze
8
8
  DELAYED_JOB_WRAPPER = "ActiveJob::QueueAdapters::DelayedJobAdapter::JobWrapper".freeze
9
9
 
10
10
  def self.normalize_title(job_instance)
11
11
  job_instance.class.name.to_s.tap do |str|
12
- if str == DELIVERY_JOB
12
+ if str.match(DELIVERY_JOB)
13
13
  mailer_class, mailer_method, * = job_instance.arguments
14
14
  return ["#{mailer_class}##{mailer_method}", str]
15
15
  end
@@ -25,7 +25,8 @@ module Skylight::Core
25
25
  end
26
26
 
27
27
  def get_namespace(endpoint)
28
- ::Grape::Namespace.joined_space(endpoint.namespace_stackable(:namespace))
28
+ # slice off preceding slash for data continuity
29
+ ::Grape::Namespace.joined_space_path(endpoint.namespace_stackable(:namespace)).to_s[1..-1]
29
30
  end
30
31
  end
31
32
  end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "active_support/inflector"
4
+
3
5
  module Skylight::Core::Normalizers::GraphQL
4
6
  # Some AS::N events in GraphQL are not super useful.
5
7
  # We are purposefully ignoring the following keys (and you probably shouldn't add them):
@@ -11,25 +13,61 @@ module Skylight::Core::Normalizers::GraphQL
11
13
  ANONYMOUS = "[anonymous]".freeze
12
14
  CAT = "app.graphql".freeze
13
15
 
14
- def normalize(_trace, name, _payload)
15
- [CAT, name, nil]
16
+ if defined?(::GraphQL::VERSION) && Gem::Version.new(::GraphQL::VERSION) >= Gem::Version.new("1.10")
17
+ def self.register_graphql
18
+ register("#{key}.graphql")
19
+ end
20
+ else
21
+ def self.register_graphql
22
+ register("graphql.#{key}")
23
+ end
24
+ end
25
+
26
+ def self.inherited(klass)
27
+ klass.const_set(
28
+ :KEY,
29
+ ActiveSupport::Inflector.underscore(
30
+ ActiveSupport::Inflector.demodulize(klass.name)
31
+ ).freeze
32
+ )
33
+ end
34
+
35
+ def self.key
36
+ self::KEY
16
37
  end
38
+
39
+ def normalize(_trace, _name, _payload)
40
+ [CAT, "graphql.#{key}", nil]
41
+ end
42
+
43
+ private
44
+
45
+ def key
46
+ self.class.key
47
+ end
48
+
49
+ def extract_query_name(query)
50
+ query&.context&.[](:skylight_endpoint) ||
51
+ query&.operation_name ||
52
+ ANONYMOUS
53
+ end
17
54
  end
18
55
 
19
56
  class Lex < Base
20
- register "graphql.lex"
57
+ register_graphql
21
58
  end
22
59
 
23
60
  class Parse < Base
24
- register "graphql.parse"
61
+ register_graphql
25
62
  end
26
63
 
27
64
  class Validate < Base
28
- register "graphql.validate"
65
+ register_graphql
29
66
  end
30
67
 
31
68
  class ExecuteMultiplex < Base
32
- register "graphql.execute_multiplex"
69
+ register_graphql
70
+
33
71
  def normalize_after(trace, _span, _name, payload)
34
72
  # This is in normalize_after because the queries may not have
35
73
  # an assigned operation name before they are executed.
@@ -44,7 +82,7 @@ module Skylight::Core::Normalizers::GraphQL
44
82
  # has not been done yet at the point where execute_multiplex starts.
45
83
  # [1] https://graphql.org/learn/serving-over-http/#post-request
46
84
  queries, has_errors = payload[:multiplex].queries.each_with_object([Set.new, Set.new]) do |query, (names, errors)|
47
- names << (query.operation_name || ANONYMOUS)
85
+ names << extract_query_name(query)
48
86
  errors << query.static_errors.any?
49
87
  end
50
88
 
@@ -58,14 +96,14 @@ module Skylight::Core::Normalizers::GraphQL
58
96
  end
59
97
 
60
98
  class AnalyzeQuery < Base
61
- register "graphql.analyze_query"
99
+ register_graphql
62
100
  end
63
101
 
64
102
  class ExecuteQuery < Base
65
- register "graphql.execute_query"
103
+ register_graphql
66
104
 
67
- def normalize(trace, name, payload)
68
- query_name = payload[:query]&.operation_name || ANONYMOUS
105
+ def normalize(trace, _name, payload)
106
+ query_name = extract_query_name(payload[:query])
69
107
 
70
108
  if query_name == ANONYMOUS
71
109
  meta = { mute_children: true }
@@ -75,18 +113,18 @@ module Skylight::Core::Normalizers::GraphQL
75
113
  # but in the case of a single query, it will be the same value anyway.
76
114
  trace.endpoint = "graphql:#{query_name}"
77
115
 
78
- [CAT, "#{name}: #{query_name}", nil, meta]
116
+ [CAT, "graphql.#{key}: #{query_name}", nil, meta]
79
117
  end
80
118
  end
81
119
 
82
120
  class ExecuteQueryLazy < ExecuteQuery
83
- register "graphql.execute_query_lazy"
121
+ register_graphql
84
122
 
85
- def normalize(trace, name, payload)
123
+ def normalize(trace, _name, payload)
86
124
  if payload[:query]
87
125
  super
88
126
  elsif payload[:multiplex]
89
- [CAT, "#{name}.multiplex", nil]
127
+ [CAT, "graphql.#{key}.multiplex", nil]
90
128
  end
91
129
  end
92
130
  end
@@ -27,6 +27,13 @@ module Skylight::Core
27
27
  elsif respond_to?(:rendered_format) && rendered_format
28
28
  rendered_format
29
29
  end
30
+ rescue
31
+ # There are cases in which actionpack can return
32
+ # a stringified representation of a Mime::NullType instance,
33
+ # which is invalid for a number of reasons. This string raises
34
+ # errors when piped through Mime::Type.lookup, so it's probably
35
+ # best to just return nil in those cases.
36
+ nil
30
37
  end
31
38
  end
32
39
  end
@@ -3,35 +3,36 @@
3
3
  module Skylight::Core
4
4
  module Probes
5
5
  module GraphQL
6
+ module Instrumentation
7
+ def initialize(*, **)
8
+ super
9
+
10
+ return unless defined?(@tracers)
11
+
12
+ unless @tracers.include?(::GraphQL::Tracing::ActiveSupportNotificationsTracing)
13
+ @tracers << ::GraphQL::Tracing::ActiveSupportNotificationsTracing
14
+ end
15
+ end
16
+ end
17
+
6
18
  class Probe
7
19
  def install
8
- ::GraphQL::Schema.class_eval do
9
- alias_method :multiplex_without_sk, :multiplex
10
-
11
- # Schema#execute also delegates to multiplex, so this is the only method
12
- # we need to override.
13
- def multiplex(*args, &block)
14
- sk_add_tracer
15
- multiplex_without_sk(*args, &block)
16
- end
17
-
18
- def sk_add_tracer
19
- Skylight::Core::Config::MUTEX.synchronize do
20
- graphql_tracer = ::GraphQL::Tracing::ActiveSupportNotificationsTracing
21
- unless tracers.include?(graphql_tracer)
22
- $stdout.puts "[SKYLIGHT::CORE] Adding tracer 'GraphQL::Tracing::ActiveSupportNotificationsTracing' to schema"
23
- tracers << graphql_tracer
24
- end
25
-
26
- class << self
27
- # Remove the probe and reset multiplex/execute to original version
28
- # after the tracer has been added
29
- alias_method :multiplex, :multiplex_without_sk
30
- end
31
- end
32
- end
20
+ tracing_klass_name = "::GraphQL::Tracing::ActiveSupportNotificationsTracing"
21
+ klasses_to_probe = %w(
22
+ ::GraphQL::Execution::Multiplex
23
+ ::GraphQL::Query
24
+ )
25
+
26
+ return unless ([tracing_klass_name] + klasses_to_probe).all?(&method(:safe_constantize))
27
+
28
+ klasses_to_probe.each do |klass_name|
29
+ safe_constantize(klass_name).prepend(Instrumentation)
33
30
  end
34
31
  end
32
+
33
+ def safe_constantize(klass_name)
34
+ Skylight::Core::Util::Inflector.safe_constantize(klass_name)
35
+ end
35
36
  end
36
37
  end
37
38
 
@@ -33,7 +33,7 @@ module Skylight::Core
33
33
  spans = Skylight::Core::Fanout.instrument(title: name, category: "#{category}")
34
34
  resp = call_without_sk(*args, &block)
35
35
 
36
- proxied_response = Skylight::Core::Middleware.with_after_close(resp) do
36
+ proxied_response = Skylight::Core::Middleware.with_after_close(resp, debug_identifier: "Middleware: #{name}") do
37
37
  Skylight::Core::Fanout.done(spans)
38
38
  end
39
39
  rescue Exception => err
@@ -1,5 +1,5 @@
1
1
  module Skylight
2
2
  module Core
3
- VERSION = "4.2.0".freeze
3
+ VERSION = "4.3.1".freeze
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: skylight-core
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.2.0
4
+ version: 4.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tilde, Inc.
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-10-30 00:00:00.000000000 Z
11
+ date: 2020-06-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -269,8 +269,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
269
269
  - !ruby/object:Gem::Version
270
270
  version: '0'
271
271
  requirements: []
272
- rubyforge_project:
273
- rubygems_version: 2.7.6
272
+ rubygems_version: 3.1.2
274
273
  signing_key:
275
274
  specification_version: 4
276
275
  summary: The core methods of the Skylight profiler.