skylight 4.2.3 → 5.3.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 (123) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +420 -331
  3. data/CLA.md +1 -1
  4. data/CONTRIBUTING.md +2 -8
  5. data/ERRORS.md +3 -0
  6. data/LICENSE.md +7 -17
  7. data/README.md +1 -1
  8. data/ext/extconf.rb +61 -56
  9. data/ext/libskylight.yml +8 -6
  10. data/ext/skylight_native.c +26 -100
  11. data/lib/skylight/api.rb +32 -21
  12. data/lib/skylight/cli/doctor.rb +64 -65
  13. data/lib/skylight/cli/helpers.rb +19 -19
  14. data/lib/skylight/cli/merger.rb +142 -138
  15. data/lib/skylight/cli.rb +48 -46
  16. data/lib/skylight/config.rb +640 -201
  17. data/lib/skylight/data/cacert.pem +730 -1023
  18. data/lib/skylight/deprecation.rb +17 -0
  19. data/lib/skylight/errors.rb +26 -9
  20. data/lib/skylight/extensions/source_location.rb +291 -0
  21. data/lib/skylight/extensions.rb +95 -0
  22. data/lib/skylight/formatters/http.rb +18 -0
  23. data/lib/skylight/gc.rb +99 -0
  24. data/lib/skylight/helpers.rb +81 -36
  25. data/lib/skylight/instrumenter.rb +336 -18
  26. data/lib/skylight/middleware.rb +147 -1
  27. data/lib/skylight/native.rb +60 -12
  28. data/lib/skylight/native_ext_fetcher.rb +13 -14
  29. data/lib/skylight/normalizers/action_controller/process_action.rb +68 -0
  30. data/lib/skylight/normalizers/action_controller/send_file.rb +51 -0
  31. data/lib/skylight/normalizers/action_dispatch/process_middleware.rb +22 -0
  32. data/lib/skylight/normalizers/action_dispatch/route_set.rb +27 -0
  33. data/lib/skylight/normalizers/action_view/render_collection.rb +24 -0
  34. data/lib/skylight/normalizers/action_view/render_layout.rb +25 -0
  35. data/lib/skylight/normalizers/action_view/render_partial.rb +23 -0
  36. data/lib/skylight/normalizers/action_view/render_template.rb +23 -0
  37. data/lib/skylight/normalizers/active_job/perform.rb +87 -0
  38. data/lib/skylight/normalizers/active_model_serializers/render.rb +32 -0
  39. data/lib/skylight/normalizers/active_record/instantiation.rb +16 -0
  40. data/lib/skylight/normalizers/active_record/sql.rb +20 -0
  41. data/lib/skylight/normalizers/active_storage.rb +28 -0
  42. data/lib/skylight/normalizers/active_support/cache.rb +11 -0
  43. data/lib/skylight/normalizers/active_support/cache_clear.rb +16 -0
  44. data/lib/skylight/normalizers/active_support/cache_decrement.rb +16 -0
  45. data/lib/skylight/normalizers/active_support/cache_delete.rb +16 -0
  46. data/lib/skylight/normalizers/active_support/cache_exist.rb +16 -0
  47. data/lib/skylight/normalizers/active_support/cache_fetch_hit.rb +16 -0
  48. data/lib/skylight/normalizers/active_support/cache_generate.rb +16 -0
  49. data/lib/skylight/normalizers/active_support/cache_increment.rb +16 -0
  50. data/lib/skylight/normalizers/active_support/cache_read.rb +16 -0
  51. data/lib/skylight/normalizers/active_support/cache_read_multi.rb +16 -0
  52. data/lib/skylight/normalizers/active_support/cache_write.rb +16 -0
  53. data/lib/skylight/normalizers/coach/handler_finish.rb +44 -0
  54. data/lib/skylight/normalizers/coach/middleware_finish.rb +33 -0
  55. data/lib/skylight/normalizers/couch_potato/query.rb +20 -0
  56. data/lib/skylight/normalizers/data_mapper/sql.rb +12 -0
  57. data/lib/skylight/normalizers/default.rb +24 -0
  58. data/lib/skylight/normalizers/elasticsearch/request.rb +20 -0
  59. data/lib/skylight/normalizers/faraday/request.rb +38 -0
  60. data/lib/skylight/normalizers/grape/endpoint.rb +28 -0
  61. data/lib/skylight/normalizers/grape/endpoint_render.rb +25 -0
  62. data/lib/skylight/normalizers/grape/endpoint_run.rb +39 -0
  63. data/lib/skylight/normalizers/grape/endpoint_run_filters.rb +20 -0
  64. data/lib/skylight/normalizers/grape/format_response.rb +20 -0
  65. data/lib/skylight/normalizers/graphiti/render.rb +22 -0
  66. data/lib/skylight/normalizers/graphiti/resolve.rb +31 -0
  67. data/lib/skylight/normalizers/graphql/base.rb +127 -0
  68. data/lib/skylight/normalizers/render.rb +79 -0
  69. data/lib/skylight/normalizers/sequel/sql.rb +12 -0
  70. data/lib/skylight/normalizers/shrine.rb +32 -0
  71. data/lib/skylight/normalizers/sql.rb +41 -0
  72. data/lib/skylight/normalizers.rb +157 -0
  73. data/lib/skylight/probes/action_controller.rb +52 -0
  74. data/lib/skylight/probes/action_dispatch/request_id.rb +33 -0
  75. data/lib/skylight/probes/action_dispatch/routing/route_set.rb +30 -0
  76. data/lib/skylight/probes/action_dispatch.rb +2 -0
  77. data/lib/skylight/probes/action_view.rb +42 -0
  78. data/lib/skylight/probes/active_job.rb +27 -0
  79. data/lib/skylight/probes/active_job_enqueue.rb +35 -0
  80. data/lib/skylight/probes/active_model_serializers.rb +50 -0
  81. data/lib/skylight/probes/active_record_async.rb +96 -0
  82. data/lib/skylight/probes/delayed_job.rb +144 -0
  83. data/lib/skylight/probes/elasticsearch.rb +36 -0
  84. data/lib/skylight/probes/excon/middleware.rb +65 -0
  85. data/lib/skylight/probes/excon.rb +25 -0
  86. data/lib/skylight/probes/faraday.rb +23 -0
  87. data/lib/skylight/probes/graphql.rb +38 -0
  88. data/lib/skylight/probes/httpclient.rb +44 -0
  89. data/lib/skylight/probes/middleware.rb +135 -0
  90. data/lib/skylight/probes/mongo.rb +156 -0
  91. data/lib/skylight/probes/mongoid.rb +13 -0
  92. data/lib/skylight/probes/net_http.rb +54 -0
  93. data/lib/skylight/probes/rack_builder.rb +37 -0
  94. data/lib/skylight/probes/redis.rb +51 -0
  95. data/lib/skylight/probes/sequel.rb +29 -0
  96. data/lib/skylight/probes/sinatra.rb +66 -0
  97. data/lib/skylight/probes/sinatra_add_middleware.rb +10 -10
  98. data/lib/skylight/probes/tilt.rb +25 -0
  99. data/lib/skylight/probes.rb +173 -0
  100. data/lib/skylight/railtie.rb +166 -28
  101. data/lib/skylight/sidekiq.rb +47 -0
  102. data/lib/skylight/sinatra.rb +1 -1
  103. data/lib/skylight/subscriber.rb +130 -0
  104. data/lib/skylight/test.rb +147 -0
  105. data/lib/skylight/trace.rb +325 -22
  106. data/lib/skylight/user_config.rb +58 -0
  107. data/lib/skylight/util/allocation_free.rb +26 -0
  108. data/lib/skylight/util/clock.rb +57 -0
  109. data/lib/skylight/util/component.rb +22 -22
  110. data/lib/skylight/util/deploy.rb +19 -24
  111. data/lib/skylight/util/gzip.rb +20 -0
  112. data/lib/skylight/util/http.rb +106 -113
  113. data/lib/skylight/util/instrumenter_method.rb +26 -0
  114. data/lib/skylight/util/logging.rb +136 -0
  115. data/lib/skylight/util/lru_cache.rb +36 -0
  116. data/lib/skylight/util/platform.rb +3 -7
  117. data/lib/skylight/util/ssl.rb +1 -25
  118. data/lib/skylight/util.rb +12 -0
  119. data/lib/skylight/vendor/cli/thor/rake_compat.rb +1 -1
  120. data/lib/skylight/version.rb +5 -1
  121. data/lib/skylight/vm/gc.rb +60 -0
  122. data/lib/skylight.rb +201 -14
  123. metadata +134 -18
@@ -1,6 +1,55 @@
1
1
  require "skylight/util/platform"
2
2
 
3
3
  module Skylight
4
+ # Some methods exepected to be defined by the native code (OUTDATED)
5
+ #
6
+ # * Skylight::Util::Clock#native_hrtime
7
+ # - returns current time in nanoseconds
8
+ # * Skylight::Trace#native_new(start, uuid, endpoint)
9
+ # - start is milliseconds
10
+ # - uuid is currently unused
11
+ # - endpoint is the endpoint name
12
+ # - returns an instance of Trace
13
+ # * Skylight::Trace#native_get_started_at
14
+ # - returns the start time
15
+ # * Skylight::Trace#native_get_endpoint
16
+ # - returns the endpoint name
17
+ # * Skylight::Trace#native_set_endpoint(endpoint)
18
+ # - returns nil
19
+ # * Skylight::Trace#native_get_uuid
20
+ # - returns the uuid
21
+ # * Skylight::Trace#native_start_span(time, category)
22
+ # - time is milliseconds
23
+ # - category is a string
24
+ # - returns a numeric span id
25
+ # * Skylight::Trace#native_stop_span(span, time)
26
+ # - span is the span id
27
+ # - time is milliseconds
28
+ # - returns nil
29
+ # * Skylight::Trace#native_span_set_title(span, title)
30
+ # - span is the span id
31
+ # - title is a string
32
+ # - returns nil
33
+ # * Skylight::Trace#native_span_set_description(span, desc)
34
+ # - span is the span id
35
+ # - desc is a string
36
+ # - returns nil
37
+ # * Skylight::Instrumenter#native_new(env)
38
+ # - env is the config converted to a flattened array of ENV style values
39
+ # e.g. `["SKYLIGHT_AUTHENTICATION", "abc123", ...]
40
+ # - returns a new Instrumenter instance
41
+ # * Skylight::Instrumenter#native_start()
42
+ # - returns a truthy value if successful
43
+ # * Skylight::Instrumenter#native_stop()
44
+ # - returns nil
45
+ # * Skylight::Instrumenter#native_submit_trace(trace)
46
+ # - trace is a Trace instance
47
+ # - returns nil
48
+ # * Skylight::Instrumenter#native_track_desc(endpoint, description)
49
+ # - endpoint is a string
50
+ # - description is a string
51
+ # - returns truthy unless uniqueness cap exceeded
52
+
4
53
  # @api private
5
54
  # Whether or not the native extension is present
6
55
  @has_native_ext = false
@@ -40,7 +89,8 @@ module Skylight
40
89
  end
41
90
 
42
91
  if Skylight.native?
43
- Skylight::Core::Util::Clock.use_native!
92
+ require "skylight/util/clock"
93
+ Util::Clock.use_native!
44
94
  else
45
95
  class Instrumenter
46
96
  def self.native_new(*_args)
@@ -51,24 +101,22 @@ module Skylight
51
101
 
52
102
  # @api private
53
103
  def self.check_install_errors(config)
54
- # Note: An unsupported arch doesn't count as an error.
104
+ # NOTE: An unsupported arch doesn't count as an error.
55
105
  install_log = File.expand_path("../../ext/install.log", __dir__)
56
106
 
57
107
  if File.exist?(install_log) && File.read(install_log) =~ /ERROR/
58
- config.alert_logger.error \
59
- "[SKYLIGHT] [#{Skylight::VERSION}] The Skylight native extension failed to install. " \
60
- "Please check #{install_log} and notify support@skylight.io. " \
61
- "The missing extension will not affect the functioning of your application."
108
+ config.alert_logger.error "[SKYLIGHT] [#{Skylight::VERSION}] The Skylight native extension failed to install. " \
109
+ "Please check #{install_log} and notify support@skylight.io. " \
110
+ "The missing extension will not affect the functioning of your application."
62
111
  end
63
112
  end
64
113
 
65
114
  # @api private
66
115
  def self.warn_skylight_native_missing(config)
67
- config.alert_logger.error \
68
- "[SKYLIGHT] [#{Skylight::VERSION}] The Skylight native extension for " \
69
- "your platform wasn't found. Supported operating systems are " \
70
- "Linux 2.6.18+ and Mac OS X 10.8+. The missing extension will not " \
71
- "affect the functioning of your application. If you are on a " \
72
- "supported platform, please contact support at support@skylight.io."
116
+ config.alert_logger.error "[SKYLIGHT] [#{Skylight::VERSION}] The Skylight native extension for " \
117
+ "your platform wasn't found. Supported operating systems are " \
118
+ "Linux 2.6.18+ and Mac OS X 10.8+. The missing extension will not " \
119
+ "affect the functioning of your application. If you are on a " \
120
+ "supported platform, please contact support at support@skylight.io."
73
121
  end
74
122
  end
@@ -17,13 +17,14 @@ module Skylight
17
17
 
18
18
  include FileUtils
19
19
 
20
- class FetchError < StandardError; end
20
+ class FetchError < StandardError
21
+ end
21
22
 
22
23
  # Creates a new fetcher and fetches
23
24
  # @param opts [Hash]
24
25
  def self.fetch(**args)
25
26
  args[:source] ||= BASE_URL
26
- args[:logger] ||= Logger.new(STDOUT)
27
+ args[:logger] ||= Logger.new($stdout)
27
28
  new(**args).fetch
28
29
  end
29
30
 
@@ -35,7 +36,7 @@ module Skylight
35
36
  # @param required [Boolean] whether the download is required to be successful
36
37
  # @param platform
37
38
  # @param log [Logger]
38
- def initialize(source:, target:, version:, checksum:, arch:, required: false, platform: nil, logger:)
39
+ def initialize(source:, target:, version:, checksum:, arch:, logger:, required: false, platform: nil)
39
40
  raise "source required" unless source
40
41
  raise "target required" unless target
41
42
  raise "checksum required" unless checksum
@@ -56,7 +57,7 @@ module Skylight
56
57
  # @return [String] the inflated archive
57
58
  def fetch
58
59
  log "fetching native ext; curr-platform=#{@platform}; " \
59
- "requested-arch=#{@arch}; version=#{@version}"
60
+ "requested-arch=#{@arch}; version=#{@version}"
60
61
 
61
62
  tar_gz = "#{@target}/#{basename}"
62
63
 
@@ -109,10 +110,12 @@ module Skylight
109
110
  next
110
111
  end
111
112
  end
112
- rescue => e
113
+ rescue StandardError => e
113
114
  remaining_attempts -= 1
114
115
 
115
- error "failed to fetch native extension; uri=#{uri}; msg=#{e.message}; remaining-attempts=#{remaining_attempts}", e
116
+ error "failed to fetch native extension; uri=#{uri}; msg=#{e.message}; " \
117
+ "remaining-attempts=#{remaining_attempts}",
118
+ e
116
119
 
117
120
  if remaining_attempts > 0
118
121
  sleep 2
@@ -148,9 +151,7 @@ module Skylight
148
151
  opts = {}
149
152
  opts[:use_ssl] = use_ssl
150
153
 
151
- if use_ssl
152
- opts[:ca_file] = Util::SSL.ca_cert_file_or_default
153
- end
154
+ opts[:ca_file] = Util::SSL.ca_cert_file_or_default if use_ssl
154
155
 
155
156
  Net::HTTP.start(host, port, p_host, p_port, p_user, p_pass, use_ssl: use_ssl) do |http|
156
157
  http.request_get path do |resp|
@@ -163,13 +164,13 @@ module Skylight
163
164
  out.write chunk
164
165
  end
165
166
 
166
- return [:success, digest.hexdigest]
167
+ return :success, digest.hexdigest
167
168
  when Net::HTTPRedirection
168
169
  unless (location = resp["location"])
169
170
  raise "received redirect but no location"
170
171
  end
171
172
 
172
- return [:redirect, location]
173
+ return :redirect, location
173
174
  else
174
175
  raise "received HTTP status code #{resp.code}"
175
176
  end
@@ -220,9 +221,7 @@ module Skylight
220
221
  def maybe_raise(err)
221
222
  error err
222
223
 
223
- if @required
224
- raise err
225
- end
224
+ raise err if @required
226
225
  end
227
226
 
228
227
  # Log an `info` to the `logger`
@@ -0,0 +1,68 @@
1
+ module Skylight
2
+ module Normalizers
3
+ module ActionController
4
+ # Normalizer for processing a Rails controller action
5
+ class ProcessAction < Normalizer
6
+ register "process_action.action_controller"
7
+
8
+ CAT = "app.controller.request".freeze
9
+
10
+ # Payload Keys: controller, action, params, format, method, path
11
+ # Additional keys available in `normalize_after`: status, view_runtime
12
+ # Along with ones added by probe: variant
13
+
14
+ # @param trace [Skylight::Messages::Trace::Builder]
15
+ # @param name [String] ignored, only present to match API
16
+ # @param payload [Hash]
17
+ # @option payload [String] :controller Controller name
18
+ # @option payload [String] :action Action name
19
+ # @return [Array]
20
+ def normalize(trace, _name, payload)
21
+ trace.endpoint = controller_action(payload)
22
+ [CAT, trace.endpoint, nil]
23
+ end
24
+
25
+ def normalize_after(trace, _span, _name, payload)
26
+ return unless config.enable_segments?
27
+
28
+ if (segment = segment_from_payload(payload))
29
+ trace.segment = segment
30
+ end
31
+ end
32
+
33
+ private
34
+
35
+ def controller_action(payload)
36
+ "#{payload[:controller]}##{payload[:action]}"
37
+ end
38
+
39
+ def process_meta_options(payload)
40
+ # provide hints to override default source_location behavior
41
+ super.merge(source_location_hint: [:instance_method, payload[:controller], payload[:action]])
42
+ end
43
+
44
+ def segment_from_payload(payload)
45
+ # Show 'error' if there's an unhandled exception or if the status is 4xx or 5xx
46
+ return "error" if payload[:exception] || payload[:exception_object]
47
+
48
+ segment_from_status(payload[:status]) || if payload[:sk_rendered_format]
49
+ # We only show the variant if we actually have a format
50
+ # We won't have a sk_rendered_format if it's a `head` outside of a `respond_to` block.
51
+ [payload[:sk_rendered_format], payload[:sk_variant]].compact.flatten.join("+")
52
+ end
53
+ end
54
+
55
+ def segment_from_status(status)
56
+ case status
57
+ when 304
58
+ "not modified"
59
+ when (300..399)
60
+ "redirect"
61
+ when (400..599)
62
+ "error"
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,51 @@
1
+ module Skylight
2
+ module Normalizers
3
+ module ActionController
4
+ enabled = true
5
+
6
+ # Temporary hacks
7
+ begin
8
+ require "action_dispatch/http/mime_type"
9
+ require "action_dispatch/http/mime_types"
10
+ require "rack/utils"
11
+ rescue LoadError
12
+ enabled = false
13
+ end
14
+
15
+ if enabled
16
+ class SendFile < Normalizer
17
+ register "send_file.action_controller"
18
+
19
+ CAT = "app.controller.send_file".freeze
20
+ TITLE = "send file".freeze
21
+
22
+ def normalize(_trace, _name, _payload)
23
+ title = TITLE
24
+
25
+ # depending on normalization, we probably want this to eventually
26
+ # include the full path, but we need to make sure we have a good
27
+ # deduping strategy first.
28
+ desc = nil
29
+
30
+ [CAT, title, desc]
31
+ end
32
+
33
+ private
34
+
35
+ OCTET_STREAM = "application/octet-stream".freeze
36
+ ATTACHMENT = "attachment".freeze
37
+
38
+ def initialize(*)
39
+ super
40
+
41
+ @mimes =
42
+ Mime::SET.each_with_object({}) do |mime, hash|
43
+ hash[mime.symbol] = mime.to_s.dup.freeze
44
+ hash
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Skylight
4
+ module Normalizers
5
+ module ActionDispatch
6
+ class ProcessMiddleware < Normalizer
7
+ register "process_middleware.action_dispatch"
8
+
9
+ CAT = "rack.middleware"
10
+ ANONYMOUS_MIDDLEWARE = "Anonymous Middleware"
11
+ ANONYMOUS = /\A#<(Class|Module|Proc):/.freeze
12
+
13
+ def normalize(trace, _name, payload)
14
+ name = payload[:middleware].to_s
15
+ name = ANONYMOUS_MIDDLEWARE if name[ANONYMOUS]
16
+ trace.endpoint = name
17
+ [CAT, name, nil]
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,27 @@
1
+ module Skylight
2
+ module Normalizers
3
+ module ActionDispatch
4
+ class RouteSet < Normalizer
5
+ register "route_set.action_dispatch"
6
+
7
+ CAT = "rack.app".freeze
8
+
9
+ def normalize(trace, _name, _payload)
10
+ trace.endpoint = router_class_name
11
+ [CAT, trace.endpoint, nil]
12
+ end
13
+
14
+ private
15
+
16
+ def router_class_name
17
+ "ActionDispatch::Routing::RouteSet"
18
+ end
19
+
20
+ def process_meta_options(_payload)
21
+ # provide hints to override default source_location behavior
22
+ super.merge(source_location_hint: [:own_instance_method, router_class_name, "call"])
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,24 @@
1
+ require "skylight/normalizers/render"
2
+
3
+ module Skylight
4
+ module Normalizers
5
+ module ActionView
6
+ # Normalizer for Rails collection rendering
7
+ class RenderCollection < RenderNormalizer
8
+ register "render_collection.action_view"
9
+
10
+ CAT = "view.render.collection".freeze
11
+
12
+ # @param trace [Skylight::Messages::Trace::Builder] ignored, only present to match API
13
+ # @param name [String] ignored, only present to match API
14
+ # @param payload (see RenderNormalizer#normalize_render)
15
+ # @option payload (see RenderNormalizer#normalize_render)
16
+ # @option payload [Integer] :count
17
+ # @return (see RenderNormalizer#normalize_render)
18
+ def normalize(_trace, _name, payload)
19
+ normalize_render(CAT, payload)
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "skylight/normalizers/render"
4
+
5
+ module Skylight
6
+ module Normalizers
7
+ module ActionView
8
+ # Normalizer for Rails layout rendering
9
+ class RenderLayout < RenderNormalizer
10
+ register "render_layout.action_view"
11
+
12
+ CAT = "view.render.layout"
13
+
14
+ # @param trace [Skylight::Messages::Trace::Builder] ignored, only present to match API
15
+ # @param name [String] ignored, only present to match API
16
+ # @param payload (see RenderNormalizer#normalize_render)
17
+ # @option payload (see RenderNormalizer#normalize_render)
18
+ # @return (see RenderNormalizer#normalize_render)
19
+ def normalize(_trace, _name, payload)
20
+ normalize_render(CAT, payload)
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,23 @@
1
+ require "skylight/normalizers/render"
2
+
3
+ module Skylight
4
+ module Normalizers
5
+ module ActionView
6
+ # Normalizer for Rails partial rendering
7
+ class RenderPartial < RenderNormalizer
8
+ register "render_partial.action_view"
9
+
10
+ CAT = "view.render.template".freeze
11
+
12
+ # @param trace [Skylight::Messages::Trace::Builder] ignored, only present to match API
13
+ # @param name [String] ignored, only present to match API
14
+ # @param payload (see RenderNormalizer#normalize_render)
15
+ # @option payload (see RenderNormalizer#normalize_render)
16
+ # @return (see RenderNormalizer#normalize_render)
17
+ def normalize(_trace, _name, payload)
18
+ normalize_render(CAT, payload)
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,23 @@
1
+ require "skylight/normalizers/render"
2
+
3
+ module Skylight
4
+ module Normalizers
5
+ module ActionView
6
+ # Normalizer for Rails template rendering
7
+ class RenderTemplate < RenderNormalizer
8
+ register "render_template.action_view"
9
+
10
+ CAT = "view.render.template".freeze
11
+
12
+ # @param trace [Skylight::Messages::Trace::Builder] ignored, only present to match API
13
+ # @param name [String] ignored, only present to match API
14
+ # @param payload (see RenderNormalizer#normalize_render)
15
+ # @option payload (see RenderNormalizer#normalize_render)
16
+ # @return (see RenderNormalizer#normalize_render)
17
+ def normalize(_trace, _name, payload)
18
+ normalize_render(CAT, payload)
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,87 @@
1
+ module Skylight
2
+ module Normalizers
3
+ module ActiveJob
4
+ class Perform < Normalizer
5
+ register "perform.active_job"
6
+
7
+ DELIVERY_JOB = /\AActionMailer::(Mail)?DeliveryJob\Z/.freeze
8
+ DELAYED_JOB_WRAPPER = "ActiveJob::QueueAdapters::DelayedJobAdapter::JobWrapper".freeze
9
+
10
+ def self.normalize_title(job_instance)
11
+ job_instance
12
+ .class
13
+ .name
14
+ .to_s
15
+ .tap do |str|
16
+ if str.match(DELIVERY_JOB)
17
+ mailer_class, mailer_method, * = job_instance.arguments
18
+ return "#{mailer_class}##{mailer_method}", str if mailer_class && mailer_method
19
+ end
20
+ end
21
+ end
22
+
23
+ CAT = "app.job.perform".freeze
24
+
25
+ def normalize(trace, _name, payload)
26
+ title = payload[:job].class.to_s
27
+ adapter_name = normalize_adapter_name(payload[:adapter])
28
+ desc = "{ adapter: '#{adapter_name}', queue: '#{payload[:job].queue_name}' }"
29
+
30
+ maybe_set_endpoint(trace, payload)
31
+
32
+ [CAT, title, desc]
33
+ end
34
+
35
+ def normalize_after(trace, _span, _name, payload)
36
+ maybe_set_endpoint(trace, payload)
37
+ end
38
+
39
+ private
40
+
41
+ def process_meta_options(payload)
42
+ # provide hints to override default source_location behavior
43
+ super.merge(source_location_hint: [:instance_method, payload[:job].class.to_s, "perform"])
44
+ end
45
+
46
+ def normalize_adapter_name(adapter)
47
+ adapter_string = adapter.is_a?(Class) ? adapter.to_s : adapter.class.to_s
48
+ adapter_string[/ActiveJob::QueueAdapters::(\w+)Adapter/, 1].underscore
49
+ rescue StandardError
50
+ "active_job"
51
+ end
52
+
53
+ def maybe_set_endpoint(trace, payload)
54
+ endpoint = normalize_title(payload[:job])
55
+
56
+ # Always assign the endpoint if it has not yet been assigned by the ActiveJob probe.
57
+ if !trace.endpoint ||
58
+ (defined?(Skylight::Probes::ActiveJob::TITLE) && trace.endpoint == Skylight::Probes::ActiveJob::TITLE) ||
59
+ (
60
+ defined?(Skylight::Probes::DelayedJob::Probe::UNKNOWN) &&
61
+ trace.endpoint == Skylight::Probes::DelayedJob::Probe::UNKNOWN
62
+ ) ||
63
+ # If a job is called using #perform_now inside a controller action
64
+ # or within another job's #perform method, we do not want this to
65
+ # overwrite the existing endpoint name (unless it is the default from ActiveJob).
66
+ #
67
+ # If the current endpoint name matches this payload, return true to allow the
68
+ # segment to be assigned by normalize_after.
69
+ trace.endpoint =~ DELIVERY_JOB ||
70
+ # This adapter wrapper needs to be handled specifically due to interactions with the
71
+ # standalone Delayed::Job probe, as there is no consistent way to get the wrapped
72
+ # job name among all Delayed::Job backends.
73
+ trace.endpoint == DELAYED_JOB_WRAPPER
74
+ trace.endpoint = endpoint
75
+ end
76
+
77
+ trace.segment = payload[:job].queue_name if trace.endpoint == endpoint && config.enable_segments?
78
+ end
79
+
80
+ def normalize_title(job_instance)
81
+ title, * = self.class.normalize_title(job_instance)
82
+ title
83
+ end
84
+ end
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,32 @@
1
+ module Skylight
2
+ module Normalizers
3
+ module ActiveModelSerializers
4
+ class Render < Normalizer
5
+ register "render.active_model_serializers"
6
+
7
+ CAT = "view.render.active_model_serializers".freeze
8
+ ANONYMOUS = "<Anonymous Serializer>".freeze
9
+
10
+ def normalize(_trace, _name, payload)
11
+ serializer_class = payload[:serializer]
12
+
13
+ title = serializer_class.name || ANONYMOUS
14
+ title = title.sub(/^ActiveModel::(Serializer::)?/, "")
15
+
16
+ if (adapter_instance = payload[:adapter])
17
+ adapter_name =
18
+ adapter_instance
19
+ .class
20
+ .name
21
+ .to_s
22
+ .sub(/^ActiveModel::Serializer::Adapter::/, "")
23
+ .sub(/^ActiveModelSerializers::Adapter::/, "")
24
+ desc = "Adapter: #{adapter_name}"
25
+ end
26
+
27
+ [CAT, title, desc]
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,16 @@
1
+ module Skylight
2
+ module Normalizers
3
+ module ActiveRecord
4
+ class Instantiation < Normalizer
5
+ register "instantiation.active_record"
6
+
7
+ CAT = "db.active_record.instantiation".freeze
8
+
9
+ def normalize(_trace, _name, payload)
10
+ # Payload also includes `:record_count` but this will be variable
11
+ [CAT, "#{payload[:class_name]} Instantiation", nil]
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,20 @@
1
+ require "skylight/normalizers/sql"
2
+
3
+ module Skylight
4
+ module Normalizers
5
+ module ActiveRecord
6
+ # Normalizer for SQL requests
7
+ class SQL < Skylight::Normalizers::SQL
8
+ register "sql.active_record"
9
+ end
10
+
11
+ class FutureResult < Normalizer
12
+ register "future_result.active_record"
13
+
14
+ def normalize(_trace, _name, payload)
15
+ ["db.future_result", "Async #{payload[:args][1] || "Query"}"]
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,28 @@
1
+ module Skylight
2
+ module Normalizers
3
+ class ActiveStorage < Normalizer
4
+ TITLES = {
5
+ "preview.active_storage" => "Preview",
6
+ "transform.active_storage" => "Transform",
7
+ "service_download.active_storage" => "Download",
8
+ "service_upload.active_storage" => "Upload",
9
+ "service_streaming_download.active_storage" => "Streaming Download",
10
+ "service_download_chunk.active_storage" => "Download Chunk",
11
+ "service_delete.active_storage" => "Delete",
12
+ "service_delete_prefixed.active_storage" => "Delete Prefixed",
13
+ "service_exist.active_storage" => "Exist",
14
+ "service_url.active_storage" => "Url"
15
+ }.freeze
16
+
17
+ TITLES.each_key { |key| register key }
18
+
19
+ def normalize(_trace, name, _payload)
20
+ title = ["ActiveStorage", TITLES[name]].join(" ")
21
+
22
+ cat = "app.#{name.split(".").reverse.join(".")}"
23
+
24
+ [cat, title, nil]
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,11 @@
1
+ module Skylight
2
+ module Normalizers
3
+ module ActiveSupport
4
+ class Cache < Normalizer
5
+ %w[clear decrement delete exist fetch_hit generate increment read read_multi write].each do |type|
6
+ require "skylight/normalizers/active_support/cache_#{type}"
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,16 @@
1
+ module Skylight
2
+ module Normalizers
3
+ module ActiveSupport
4
+ class CacheClear < Cache
5
+ register "cache_clear.active_support"
6
+
7
+ CAT = "app.cache.clear".freeze
8
+ TITLE = "cache clear".freeze
9
+
10
+ def normalize(_trace, _name, _payload)
11
+ [CAT, TITLE, nil]
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end