skylight 4.2.3 → 5.3.0

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -0,0 +1,79 @@
1
+ module Skylight
2
+ module Normalizers
3
+ # Base Normalizer for Rails rendering
4
+ class RenderNormalizer < Normalizer
5
+ include Skylight::Util::AllocationFree
6
+
7
+ def setup
8
+ @paths = []
9
+
10
+ Gem.path.each do |path|
11
+ @paths << "#{path}/bundler/gems".freeze
12
+ @paths << "#{path}/gems".freeze
13
+ @paths << path
14
+ end
15
+
16
+ @paths.concat(Array(config["normalizers.render.view_paths"]))
17
+ end
18
+
19
+ # Generic normalizer for renders
20
+ # @param category [String]
21
+ # @param payload [Hash]
22
+ # @option payload [String] :identifier
23
+ # @return [Array]
24
+ def normalize_render(category, payload)
25
+ if (path = payload[:identifier])
26
+ title = relative_path(path)
27
+ end
28
+
29
+ [category, title, nil]
30
+ end
31
+
32
+ def relative_path(path)
33
+ return path if relative_path?(path)
34
+
35
+ if (root = array_find(@paths) { |p| path.start_with?(p) })
36
+ start = root.size
37
+ start += 1 if path.getbyte(start) == SEPARATOR_BYTE
38
+
39
+ path[start, path.size].sub(
40
+ # Matches a Gem Version or 12-digit hex (sha)
41
+ # that is preceeded by a `-` and followed by `/`
42
+ # Also matches 'app/views/' if it exists
43
+ %r{-(?:#{Gem::Version::VERSION_PATTERN}|[0-9a-f]{12})/(?:app/views/)*},
44
+ ": ".freeze
45
+ )
46
+ else
47
+ "Absolute Path".freeze
48
+ end
49
+ end
50
+
51
+ private
52
+
53
+ def relative_path?(path)
54
+ !absolute_path?(path)
55
+ end
56
+
57
+ SEPARATOR_BYTE = File::SEPARATOR.ord
58
+
59
+ if File.const_defined?(:NULL) ? File::NULL == "NUL" : RbConfig::CONFIG["host_os"] =~ /mingw|mswin32/
60
+ # This is a DOSish environment
61
+ ALT_SEPARATOR_BYTE = File::ALT_SEPARATOR&.ord
62
+ COLON_BYTE = ":".ord
63
+ SEPARATOR_BYTES = [SEPARATOR_BYTE, ALT_SEPARATOR_BYTE].freeze
64
+
65
+ def absolute_path?(path)
66
+ SEPARATOR_BYTES.include?(path.getbyte(2)) if alpha?(path.getbyte(0)) && path.getbyte(1) == COLON_BYTE
67
+ end
68
+
69
+ def alpha?(byte)
70
+ (byte >= 65 && byte <= 90) || (byte >= 97 && byte <= 122)
71
+ end
72
+ else
73
+ def absolute_path?(path)
74
+ path.getbyte(0) == SEPARATOR_BYTE
75
+ end
76
+ end
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,12 @@
1
+ require "skylight/normalizers/sql"
2
+
3
+ module Skylight
4
+ module Normalizers
5
+ module Sequel
6
+ # Normalizer for SQL requests
7
+ class SQL < Normalizers::SQL
8
+ register "sql.sequel"
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,32 @@
1
+ module Skylight
2
+ module Normalizers
3
+ class Shrine < Normalizer
4
+ TITLES = {
5
+ "upload.shrine" => "Upload",
6
+ "download.shrine" => "Download",
7
+ "open.shrine" => "Open",
8
+ "exists.shrine" => "Exists",
9
+ "delete.shrine" => "Delete",
10
+ "metadata.shrine" => "Metadata",
11
+ "mime_type.shrine" => "MIME Type",
12
+ "image_dimensions.shrine" => "Image Dimensions",
13
+ "signature.shrine" => "Signature",
14
+ "extension.shrine" => "Extension",
15
+ "derivation.shrine" => "Derivation",
16
+ "derivatives.shrine" => "Derivatives",
17
+ "data_uri.shrine" => "Data URI",
18
+ "remote_url.shrine" => "Remote URL"
19
+ }.freeze
20
+
21
+ TITLES.each_key { |key| register key }
22
+
23
+ def normalize(_trace, name, _payload)
24
+ title = ["Shrine", TITLES[name]].join(" ")
25
+
26
+ cat = "app.#{name.split(".").reverse.join(".")}"
27
+
28
+ [cat, title, nil]
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "json"
4
+
5
+ module Skylight
6
+ module Normalizers
7
+ # Normalizer for SQL requests
8
+ class SQL < Normalizer
9
+ CAT = "db.sql.query"
10
+
11
+ # @param trace [Skylight::Messages::Trace::Builder] ignored, only present to match API
12
+ # @param name [String] ignored, only present to match API
13
+ # @param payload [Hash]
14
+ # @option payload [String] [:name] The SQL operation
15
+ # @option payload [Hash] [:binds] The bound parameters
16
+ # @return [Array]
17
+ def normalize(_trace, _name, payload)
18
+ return :skip if payload[:name] == "SCHEMA" || payload[:name] == "CACHE"
19
+
20
+ title = payload[:name] || "SQL"
21
+
22
+ # We can only handle UTF-8 encoded strings.
23
+ # (Construction method here avoids extra allocations)
24
+ sql = String.new.concat("<sk-sql>", payload[:sql], "</sk-sql>").force_encoding(Encoding::UTF_8)
25
+
26
+ unless sql.valid_encoding?
27
+ if config[:log_sql_parse_errors]
28
+ config.logger.error "[#{Skylight::SqlLexError.formatted_code}] Unable to extract binds from non-UTF-8 " \
29
+ "query. " \
30
+ "encoding=#{payload[:sql].encoding.name} " \
31
+ "sql=#{payload[:sql].inspect} "
32
+ end
33
+
34
+ sql = nil
35
+ end
36
+
37
+ [CAT, title, sql]
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,157 @@
1
+ module Skylight
2
+ # @api private
3
+ # Convert AS::N events to Skylight events
4
+ module Normalizers
5
+ def self.registry
6
+ @registry ||= {}
7
+ end
8
+
9
+ def self.register(name, klass, opts = {})
10
+ enabled = opts[:enabled] != false
11
+ registry[name] = [klass, enabled]
12
+ end
13
+
14
+ def self.unregister(name)
15
+ @registry.delete(name)
16
+ end
17
+
18
+ def self.enable(*names, enabled: true)
19
+ names.each do |name|
20
+ matches = registry.select { |n, _| n =~ /(^|\.)#{name}$/ }
21
+ raise ArgumentError, "no normalizers match #{name}" if matches.empty?
22
+
23
+ matches.each_value { |v| v[1] = enabled }
24
+ end
25
+ end
26
+
27
+ def self.disable(*names)
28
+ enable(*names, enabled: false)
29
+ end
30
+
31
+ def self.build(config)
32
+ normalizers = {}
33
+
34
+ registry.each do |key, (klass, enabled)|
35
+ next unless enabled
36
+
37
+ unless klass.method_defined?(:normalize)
38
+ # TODO: Warn
39
+ next
40
+ end
41
+
42
+ normalizers[key] = klass.new(config)
43
+ end
44
+
45
+ Container.new(normalizers)
46
+ end
47
+
48
+ class Normalizer
49
+ def self.register(name, opts = {})
50
+ Normalizers.register(name, self, opts)
51
+ end
52
+
53
+ attr_reader :config
54
+
55
+ include Util::Logging
56
+
57
+ def initialize(config)
58
+ @config = config
59
+ setup if respond_to?(:setup)
60
+ end
61
+
62
+ def normalize(_trace, _name, _payload)
63
+ :skip
64
+ end
65
+
66
+ def normalize_with_meta(trace, name, payload)
67
+ # If we have a normal response but no meta, add it
68
+ cat, title, desc, meta = ret = normalize(trace, name, payload)
69
+ return cat if cat == :skip
70
+
71
+ meta ||= {}
72
+ cache_key = ret.hash
73
+ process_meta(trace, name, payload, meta, cache_key: cache_key)
74
+
75
+ [cat, title, desc, meta]
76
+ end
77
+
78
+ def normalize_after(trace, span, name, payload); end
79
+
80
+ private
81
+
82
+ def process_meta(trace, _name, payload, meta, cache_key: nil)
83
+ trace.instrumenter.extensions.process_normalizer_meta(
84
+ payload,
85
+ meta,
86
+ cache_key: cache_key,
87
+ **process_meta_options(payload)
88
+ )
89
+ end
90
+
91
+ def process_meta_options(_payload)
92
+ {}
93
+ end
94
+ end
95
+
96
+ require "skylight/normalizers/default"
97
+ DEFAULT = Default.new
98
+
99
+ class Container
100
+ def initialize(normalizers)
101
+ @normalizers = normalizers
102
+ end
103
+
104
+ def keys
105
+ @normalizers.keys
106
+ end
107
+
108
+ def each_key(&block)
109
+ @normalizers.each_key(&block)
110
+ end
111
+
112
+ def normalize(trace, name, payload)
113
+ normalizer_for(name).normalize_with_meta(trace, name, payload)
114
+ end
115
+
116
+ def normalize_after(trace, span, name, payload)
117
+ normalizer_for(name).normalize_after(trace, span, name, payload)
118
+ end
119
+
120
+ def normalizer_for(name)
121
+ # We never expect to hit the default case since we only register listeners
122
+ # for items that we know have normalizers. For now, though, we'll play it
123
+ # safe and provide a fallback.
124
+ @normalizers.fetch(name, DEFAULT)
125
+ end
126
+ end
127
+
128
+ %w[
129
+ action_controller/process_action
130
+ action_controller/send_file
131
+ action_dispatch/process_middleware
132
+ action_dispatch/route_set
133
+ action_view/render_collection
134
+ action_view/render_partial
135
+ action_view/render_template
136
+ action_view/render_layout
137
+ active_job/perform
138
+ active_model_serializers/render
139
+ active_record/instantiation
140
+ active_record/sql
141
+ active_storage
142
+ active_support/cache
143
+ coach/handler_finish
144
+ coach/middleware_finish
145
+ couch_potato/query
146
+ data_mapper/sql
147
+ elasticsearch/request
148
+ faraday/request
149
+ grape/endpoint
150
+ graphiti/resolve
151
+ graphiti/render
152
+ graphql/base
153
+ sequel/sql
154
+ shrine
155
+ ].each { |file| require "skylight/normalizers/#{file}" }
156
+ end
157
+ end
@@ -0,0 +1,52 @@
1
+ module Skylight
2
+ module Probes
3
+ module ActionController
4
+ class Probe
5
+ def install
6
+ # Prepending doesn't work here since this a module that's already been included
7
+ ::ActionController::Instrumentation.class_eval do
8
+ private
9
+
10
+ alias_method :append_info_to_payload_without_sk, :append_info_to_payload
11
+ def append_info_to_payload(payload)
12
+ append_info_to_payload_without_sk(payload)
13
+
14
+ payload[:sk_rendered_format] = sk_rendered_mime.try(:ref)
15
+ payload[:sk_variant] = request.respond_to?(:variant) ? request.variant : nil
16
+ end
17
+
18
+ def sk_rendered_mime
19
+ if respond_to?(:media_type)
20
+ mt = media_type
21
+ return mt && Mime::Type.lookup(mt)
22
+ end
23
+
24
+ if content_type.is_a?(Mime::Type)
25
+ content_type
26
+ elsif content_type.respond_to?(:to_s)
27
+ type_str = content_type.to_s.split(";").first
28
+ Mime::Type.lookup(type_str) unless type_str.blank?
29
+ elsif respond_to?(:rendered_format) && rendered_format
30
+ rendered_format
31
+ end
32
+ rescue StandardError
33
+ # There are cases in which actionpack can return
34
+ # a stringified representation of a Mime::NullType instance,
35
+ # which is invalid for a number of reasons. This string raises
36
+ # errors when piped through Mime::Type.lookup, so it's probably
37
+ # best to just return nil in those cases.
38
+ nil
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
44
+
45
+ register(
46
+ :action_controller,
47
+ "ActionController::Instrumentation",
48
+ "action_controller/metal/instrumentation",
49
+ ActionController::Probe.new
50
+ )
51
+ end
52
+ end
@@ -0,0 +1,33 @@
1
+ module Skylight
2
+ module Probes
3
+ module ActionDispatch
4
+ module RequestId
5
+ module Instrumentation
6
+ def call(env)
7
+ @skylight_request_id = env["skylight.request_id"]
8
+ super
9
+ end
10
+
11
+ private
12
+
13
+ def internal_request_id
14
+ @skylight_request_id || super
15
+ end
16
+ end
17
+
18
+ class Probe
19
+ def install
20
+ ::ActionDispatch::RequestId.prepend(Instrumentation)
21
+ end
22
+ end
23
+ end
24
+ end
25
+
26
+ register(
27
+ :action_dispatch,
28
+ "ActionDispatch::RequestId",
29
+ "action_dispatch/middleware/request_id",
30
+ ActionDispatch::RequestId::Probe.new
31
+ )
32
+ end
33
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Skylight
4
+ module Probes
5
+ module ActionDispatch
6
+ module Routing
7
+ module RouteSet
8
+ module Instrumentation
9
+ def call(env)
10
+ ActiveSupport::Notifications.instrument("route_set.action_dispatch") { super }
11
+ end
12
+ end
13
+
14
+ class Probe
15
+ def install
16
+ ::ActionDispatch::Routing::RouteSet.prepend(Instrumentation)
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
22
+
23
+ register(
24
+ :rails_router,
25
+ "ActionDispatch::Routing::RouteSet",
26
+ "action_dispatch/routing/route_set",
27
+ ActionDispatch::Routing::RouteSet::Probe.new
28
+ )
29
+ end
30
+ end
@@ -0,0 +1,2 @@
1
+ Skylight.probe("action_dispatch/request_id")
2
+ Skylight.probe("action_dispatch/routing/route_set")
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Skylight
4
+ module Probes
5
+ module ActionView
6
+ module Instrumentation
7
+ def render_with_layout(*args) #:nodoc:
8
+ path, locals =
9
+ case args.length
10
+ when 2
11
+ args
12
+ when 4
13
+ # Rails > 6.0.0.beta3 arguments are (view, template, path, locals)
14
+ [args[2], args[3]]
15
+ end
16
+
17
+ layout = nil
18
+
19
+ layout = find_layout(path, locals.keys, [formats.first]) if path
20
+
21
+ if layout
22
+ ActiveSupport::Notifications.instrument("render_template.action_view", identifier: layout.identifier) do
23
+ super
24
+ end
25
+ else
26
+ super
27
+ end
28
+ end
29
+ end
30
+
31
+ class Probe
32
+ def install
33
+ return if ::ActionView.gem_version >= Gem::Version.new("6.1.0.alpha")
34
+
35
+ ::ActionView::TemplateRenderer.prepend(Instrumentation)
36
+ end
37
+ end
38
+ end
39
+
40
+ register(:action_view, "ActionView::TemplateRenderer", "action_view", ActionView::Probe.new)
41
+ end
42
+ end
@@ -0,0 +1,27 @@
1
+ module Skylight
2
+ module Probes
3
+ module ActiveJob
4
+ TITLE = "ActiveJob.execute".freeze
5
+
6
+ module Instrumentation
7
+ def execute(*)
8
+ Skylight.trace(TITLE, "app.job.execute", component: :worker) do |trace|
9
+ # See normalizers/active_job/perform for endpoint/segment assignment
10
+ super
11
+ rescue Exception
12
+ trace.segment = "error" if trace
13
+ raise
14
+ end
15
+ end
16
+ end
17
+
18
+ class Probe
19
+ def install
20
+ ::ActiveJob::Base.singleton_class.prepend(Instrumentation)
21
+ end
22
+ end
23
+ end
24
+
25
+ register(:active_job, "ActiveJob::Base", "active_job/base", ActiveJob::Probe.new)
26
+ end
27
+ end
@@ -0,0 +1,35 @@
1
+ module Skylight
2
+ module Probes
3
+ module ActiveJob
4
+ class EnqueueProbe
5
+ CAT = "other.active_job.enqueue".freeze
6
+
7
+ def install
8
+ ::ActiveJob::Base.around_enqueue do |job, block|
9
+ job_class = job.class
10
+ adapter_name = EnqueueProbe.normalize_adapter_name(job_class)
11
+
12
+ # If this is an ActionMailer::DeliveryJob, we'll report this as the mailer title
13
+ # and include ActionMailer::DeliveryJob in the description.
14
+ name, job_class_name = Normalizers::ActiveJob::Perform.normalize_title(job)
15
+ descriptors = ["adapter: '#{adapter_name}'", "queue: '#{job.queue_name}'"]
16
+ descriptors << "job: '#{job_class_name}'" if job_class_name
17
+ desc = "{ #{descriptors.join(", ")} }"
18
+ rescue StandardError
19
+ block.call
20
+ else
21
+ Skylight.instrument(title: "Enqueue #{name}", category: CAT, description: desc, internal: true, &block)
22
+ end
23
+
24
+ self.class.instance_eval do
25
+ def normalize_adapter_name(job_class)
26
+ job_class.queue_adapter_name
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+
33
+ register(:active_job_enqueue, "ActiveJob::Base", "active_job/base", ActiveJob::EnqueueProbe.new)
34
+ end
35
+ end
@@ -0,0 +1,50 @@
1
+ module Skylight
2
+ module Probes
3
+ module ActiveModelSerializers
4
+ module Instrumentation
5
+ def as_json(*)
6
+ payload = { serializer: self.class }
7
+ ActiveSupport::Notifications.instrument("render.active_model_serializers", payload) { super }
8
+ end
9
+ end
10
+
11
+ class Probe
12
+ def install
13
+ version = nil
14
+
15
+ # File moved location between version
16
+ %w[serializer serializers].each do |dir|
17
+ require "active_model/#{dir}/version"
18
+ rescue LoadError # rubocop:disable Lint/SuppressedException
19
+ end
20
+
21
+ version = Gem.loaded_specs["active_model_serializers"].version if Gem.loaded_specs["active_model_serializers"]
22
+
23
+ if !version || version < Gem::Version.new("0.5.0")
24
+ Skylight.error "Instrumention is only available for ActiveModelSerializers version 0.5.0 and greater."
25
+ return
26
+ end
27
+
28
+ # We don't actually support the RCs correctly, requires
29
+ # a release after 0.10.0.rc3
30
+ if version >= Gem::Version.new("0.10.0.rc1")
31
+ # AS::N is built in to newer versions
32
+ return
33
+ end
34
+
35
+ # End users could override as_json without calling super, but it's likely safer
36
+ # than overriding serializable_array/hash/object.
37
+
38
+ [::ActiveModel::Serializer, ::ActiveModel::ArraySerializer].each { |klass| klass.prepend(Instrumentation) }
39
+ end
40
+ end
41
+ end
42
+
43
+ register(
44
+ :active_model_serializers,
45
+ "ActiveModel::Serializer",
46
+ "active_model/serializer",
47
+ ActiveModelSerializers::Probe.new
48
+ )
49
+ end
50
+ end