skylight 3.1.4 → 5.3.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (126) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +465 -294
  3. data/CLA.md +1 -1
  4. data/CONTRIBUTING.md +11 -3
  5. data/ERRORS.md +3 -0
  6. data/LICENSE.md +8 -18
  7. data/README.md +1 -2
  8. data/bin/skylight +1 -1
  9. data/ext/extconf.rb +118 -122
  10. data/ext/libskylight.yml +8 -6
  11. data/ext/skylight_native.c +56 -100
  12. data/lib/skylight/api.rb +41 -27
  13. data/lib/skylight/cli/doctor.rb +68 -70
  14. data/lib/skylight/cli/helpers.rb +3 -5
  15. data/lib/skylight/cli/merger.rb +99 -92
  16. data/lib/skylight/cli.rb +40 -43
  17. data/lib/skylight/config.rb +656 -201
  18. data/lib/skylight/data/cacert.pem +730 -1023
  19. data/lib/skylight/deprecation.rb +17 -0
  20. data/lib/skylight/errors.rb +34 -16
  21. data/lib/skylight/extensions/source_location.rb +291 -0
  22. data/lib/skylight/extensions.rb +95 -0
  23. data/lib/skylight/formatters/http.rb +18 -0
  24. data/lib/skylight/gc.rb +99 -0
  25. data/lib/skylight/helpers.rb +82 -39
  26. data/lib/skylight/instrumenter.rb +339 -9
  27. data/lib/skylight/middleware.rb +147 -1
  28. data/lib/skylight/native.rb +71 -23
  29. data/lib/skylight/native_ext_fetcher.rb +39 -47
  30. data/lib/skylight/normalizers/action_controller/process_action.rb +68 -0
  31. data/lib/skylight/normalizers/action_controller/send_file.rb +51 -0
  32. data/lib/skylight/normalizers/action_dispatch/process_middleware.rb +22 -0
  33. data/lib/skylight/normalizers/action_dispatch/route_set.rb +27 -0
  34. data/lib/skylight/normalizers/action_view/render_collection.rb +24 -0
  35. data/lib/skylight/normalizers/action_view/render_layout.rb +25 -0
  36. data/lib/skylight/normalizers/action_view/render_partial.rb +23 -0
  37. data/lib/skylight/normalizers/action_view/render_template.rb +23 -0
  38. data/lib/skylight/normalizers/active_job/perform.rb +87 -0
  39. data/lib/skylight/normalizers/active_model_serializers/render.rb +32 -0
  40. data/lib/skylight/normalizers/active_record/instantiation.rb +16 -0
  41. data/lib/skylight/normalizers/active_record/sql.rb +20 -0
  42. data/lib/skylight/normalizers/active_storage.rb +28 -0
  43. data/lib/skylight/normalizers/active_support/cache.rb +11 -0
  44. data/lib/skylight/normalizers/active_support/cache_clear.rb +16 -0
  45. data/lib/skylight/normalizers/active_support/cache_decrement.rb +16 -0
  46. data/lib/skylight/normalizers/active_support/cache_delete.rb +16 -0
  47. data/lib/skylight/normalizers/active_support/cache_exist.rb +16 -0
  48. data/lib/skylight/normalizers/active_support/cache_fetch_hit.rb +16 -0
  49. data/lib/skylight/normalizers/active_support/cache_generate.rb +16 -0
  50. data/lib/skylight/normalizers/active_support/cache_increment.rb +16 -0
  51. data/lib/skylight/normalizers/active_support/cache_read.rb +16 -0
  52. data/lib/skylight/normalizers/active_support/cache_read_multi.rb +16 -0
  53. data/lib/skylight/normalizers/active_support/cache_write.rb +16 -0
  54. data/lib/skylight/normalizers/coach/handler_finish.rb +44 -0
  55. data/lib/skylight/normalizers/coach/middleware_finish.rb +33 -0
  56. data/lib/skylight/normalizers/couch_potato/query.rb +20 -0
  57. data/lib/skylight/normalizers/data_mapper/sql.rb +12 -0
  58. data/lib/skylight/normalizers/default.rb +24 -0
  59. data/lib/skylight/normalizers/elasticsearch/request.rb +20 -0
  60. data/lib/skylight/normalizers/faraday/request.rb +38 -0
  61. data/lib/skylight/normalizers/grape/endpoint.rb +28 -0
  62. data/lib/skylight/normalizers/grape/endpoint_render.rb +25 -0
  63. data/lib/skylight/normalizers/grape/endpoint_run.rb +39 -0
  64. data/lib/skylight/normalizers/grape/endpoint_run_filters.rb +20 -0
  65. data/lib/skylight/normalizers/grape/format_response.rb +20 -0
  66. data/lib/skylight/normalizers/graphiti/render.rb +22 -0
  67. data/lib/skylight/normalizers/graphiti/resolve.rb +31 -0
  68. data/lib/skylight/normalizers/graphql/base.rb +127 -0
  69. data/lib/skylight/normalizers/render.rb +79 -0
  70. data/lib/skylight/normalizers/sequel/sql.rb +12 -0
  71. data/lib/skylight/normalizers/shrine.rb +32 -0
  72. data/lib/skylight/normalizers/sql.rb +41 -0
  73. data/lib/skylight/normalizers.rb +157 -0
  74. data/lib/skylight/probes/action_controller.rb +52 -0
  75. data/lib/skylight/probes/action_dispatch/request_id.rb +33 -0
  76. data/lib/skylight/probes/action_dispatch/routing/route_set.rb +30 -0
  77. data/lib/skylight/probes/action_dispatch.rb +2 -0
  78. data/lib/skylight/probes/action_view.rb +42 -0
  79. data/lib/skylight/probes/active_job.rb +27 -0
  80. data/lib/skylight/probes/active_job_enqueue.rb +35 -0
  81. data/lib/skylight/probes/active_model_serializers.rb +50 -0
  82. data/lib/skylight/probes/active_record_async.rb +96 -0
  83. data/lib/skylight/probes/delayed_job.rb +144 -0
  84. data/lib/skylight/probes/elasticsearch.rb +45 -0
  85. data/lib/skylight/probes/excon/middleware.rb +65 -0
  86. data/lib/skylight/probes/excon.rb +25 -0
  87. data/lib/skylight/probes/faraday.rb +23 -0
  88. data/lib/skylight/probes/graphql.rb +38 -0
  89. data/lib/skylight/probes/httpclient.rb +44 -0
  90. data/lib/skylight/probes/middleware.rb +135 -0
  91. data/lib/skylight/probes/mongo.rb +169 -0
  92. data/lib/skylight/probes/mongoid.rb +6 -0
  93. data/lib/skylight/probes/net_http.rb +54 -0
  94. data/lib/skylight/probes/rack_builder.rb +37 -0
  95. data/lib/skylight/probes/redis.rb +68 -0
  96. data/lib/skylight/probes/sequel.rb +29 -0
  97. data/lib/skylight/probes/sinatra.rb +66 -0
  98. data/lib/skylight/probes/sinatra_add_middleware.rb +10 -10
  99. data/lib/skylight/probes/tilt.rb +25 -0
  100. data/lib/skylight/probes.rb +172 -0
  101. data/lib/skylight/railtie.rb +172 -15
  102. data/lib/skylight/sidekiq.rb +47 -0
  103. data/lib/skylight/sinatra.rb +2 -2
  104. data/lib/skylight/subscriber.rb +130 -0
  105. data/lib/skylight/test.rb +147 -0
  106. data/lib/skylight/trace.rb +331 -15
  107. data/lib/skylight/user_config.rb +60 -0
  108. data/lib/skylight/util/allocation_free.rb +26 -0
  109. data/lib/skylight/util/clock.rb +57 -0
  110. data/lib/skylight/util/component.rb +47 -9
  111. data/lib/skylight/util/deploy.rb +24 -40
  112. data/lib/skylight/util/gzip.rb +20 -0
  113. data/lib/skylight/util/hostname.rb +4 -4
  114. data/lib/skylight/util/http.rb +62 -71
  115. data/lib/skylight/util/instrumenter_method.rb +26 -0
  116. data/lib/skylight/util/logging.rb +136 -0
  117. data/lib/skylight/util/lru_cache.rb +36 -0
  118. data/lib/skylight/util/platform.rb +74 -0
  119. data/lib/skylight/util/proxy.rb +13 -0
  120. data/lib/skylight/util/ssl.rb +4 -28
  121. data/lib/skylight/util.rb +12 -0
  122. data/lib/skylight/vendor/cli/thor/rake_compat.rb +1 -1
  123. data/lib/skylight/version.rb +5 -1
  124. data/lib/skylight/vm/gc.rb +60 -0
  125. data/lib/skylight.rb +213 -24
  126. metadata +171 -53
@@ -0,0 +1,36 @@
1
+ # Based on code by Sam Saffron: https://stackoverflow.com/a/16161783/181916
2
+ module Skylight
3
+ module Util
4
+ class LruCache
5
+ def initialize(max_size)
6
+ @max_size = max_size
7
+ @data = {}
8
+ end
9
+
10
+ def max_size=(size)
11
+ raise ArgumentError, :max_size if @max_size < 1
12
+
13
+ @max_size = size
14
+ @data.shift while @data.size > @max_size
15
+ end
16
+
17
+ # Individual hash operations here are atomic in MRI.
18
+ def fetch(key)
19
+ found = true
20
+ value = @data.delete(key) { found = false }
21
+
22
+ value = yield if !found && block_given?
23
+
24
+ @data[key] = value if value
25
+
26
+ @data.shift if !found && value && @data.length > @max_size
27
+
28
+ value
29
+ end
30
+
31
+ def clear
32
+ @data.clear
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,74 @@
1
+ require "rbconfig"
2
+
3
+ # Used from extconf and to load libskylight
4
+ module Skylight
5
+ module Util
6
+ module Platform
7
+ # Normalize the platform OS
8
+ OS =
9
+ case os = RbConfig::CONFIG["host_os"].downcase
10
+ when /linux/
11
+ # The official ruby-alpine Docker containers pre-build Ruby. As a result,
12
+ # Ruby doesn't know that it's on a musl-based platform. `ldd` is the
13
+ # only reliable way to detect musl that we've found.
14
+ # See https://github.com/skylightio/skylight-ruby/issues/92
15
+ ENV.fetch("SKYLIGHT_MUSL") { `ldd --version 2>&1` =~ /musl/ } ? "linux-musl" : "linux"
16
+ when /darwin/
17
+ "darwin"
18
+ when /freebsd/
19
+ "freebsd"
20
+ when /netbsd/
21
+ "netbsd"
22
+ when /openbsd/
23
+ "openbsd"
24
+ when /sunos|solaris/
25
+ "solaris"
26
+ when /mingw|mswin/
27
+ "windows"
28
+ else
29
+ os
30
+ end
31
+
32
+ # Normalize the platform CPU
33
+ ARCH =
34
+ case cpu = RbConfig::CONFIG["host_cpu"].downcase
35
+ when /amd64|x86_64/
36
+ "x86_64"
37
+ when /i?86|x86|i86pc/
38
+ "x86"
39
+ when /ppc|powerpc/
40
+ "powerpc"
41
+ when /arm64|aarch64/
42
+ "aarch64"
43
+ else
44
+ cpu
45
+ end
46
+
47
+ LIBEXT =
48
+ case OS
49
+ when /darwin/
50
+ "dylib"
51
+ when /linux|bsd|solaris/
52
+ "so"
53
+ when /windows|cygwin/
54
+ "dll"
55
+ else
56
+ "so"
57
+ end
58
+
59
+ TUPLE = "#{ARCH}-#{OS}".freeze
60
+
61
+ def self.tuple
62
+ TUPLE
63
+ end
64
+
65
+ def self.libext
66
+ LIBEXT
67
+ end
68
+
69
+ def self.dlext
70
+ RbConfig::CONFIG["DLEXT"]
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,13 @@
1
+ module Skylight
2
+ module Util
3
+ module Proxy
4
+ def self.detect_url(env)
5
+ u = env["HTTP_PROXY"] || env["http_proxy"]
6
+ if u && !u.empty?
7
+ u = "http://#{u}" unless u =~ %r{://}
8
+ u
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -1,54 +1,30 @@
1
- require 'openssl'
1
+ require "openssl"
2
2
 
3
3
  module Skylight
4
4
  module Util
5
5
  class SSL
6
- DEFAULT_CA_FILE = File.expand_path('../../data/cacert.pem', __FILE__)
6
+ DEFAULT_CA_FILE = File.expand_path("../data/cacert.pem", __dir__)
7
7
 
8
8
  def self.detect_ca_cert_file!
9
- return nil if ENV['SKYLIGHT_FORCE_OWN_CERTS']
9
+ return nil if ENV["SKYLIGHT_FORCE_OWN_CERTS"]
10
10
 
11
11
  @ca_cert_file = false
12
12
  if defined?(OpenSSL::X509::DEFAULT_CERT_FILE)
13
13
  f = OpenSSL::X509::DEFAULT_CERT_FILE
14
14
 
15
- if f && File.exist?(f)
16
- @ca_cert_file = f
17
- end
18
- end
19
- end
20
-
21
- def self.detect_ca_cert_dir!
22
- return nil if ENV['SKYLIGHT_FORCE_OWN_CERTS']
23
-
24
- @ca_cert_dir = false
25
- if defined?(OpenSSL::X509::DEFAULT_CERT_DIR)
26
- d = OpenSSL::X509::DEFAULT_CERT_DIR
27
-
28
- if d && File.exist?(d)
29
- @ca_cert_dir = d
30
- end
15
+ @ca_cert_file = f if f && File.exist?(f)
31
16
  end
32
17
  end
33
18
 
34
19
  detect_ca_cert_file!
35
- detect_ca_cert_dir!
36
20
 
37
21
  def self.ca_cert_file?
38
22
  !!@ca_cert_file
39
23
  end
40
24
 
41
- def self.ca_cert_dir?
42
- !!@ca_cert_dir
43
- end
44
-
45
25
  def self.ca_cert_file_or_default
46
26
  @ca_cert_file || DEFAULT_CA_FILE
47
27
  end
48
-
49
- def self.ca_cert_dir
50
- @ca_cert_dir
51
- end
52
28
  end
53
29
  end
54
30
  end
@@ -0,0 +1,12 @@
1
+ module Skylight
2
+ # @api private
3
+ module Util
4
+ # Used from the main lib
5
+ require "skylight/util/allocation_free"
6
+ require "skylight/util/clock"
7
+ require "skylight/util/instrumenter_method"
8
+
9
+ # Used from the CLI
10
+ autoload :Gzip, "skylight/util/gzip"
11
+ end
12
+ end
@@ -11,7 +11,7 @@ class Thor
11
11
  # class Default < Thor
12
12
  # include Thor::RakeCompat
13
13
  #
14
- # RSpec::Core::RakeTask.new(:spec) do |t|
14
+ # RSpec::RakeTask.new(:spec) do |t|
15
15
  # t.spec_opts = ['--options', "./.rspec"]
16
16
  # t.spec_files = FileList['spec/**/*_spec.rb']
17
17
  # end
@@ -1,3 +1,7 @@
1
1
  module Skylight
2
- VERSION = '3.1.4'
2
+ # pre-release versions should be given here as "5.0.0-alpha"
3
+ # for compatibility with semver when it is parsed by the rust agent.
4
+ # This string will be transformed in the gemspec to "5.0.0.alpha"
5
+ # to conform with rubygems.
6
+ VERSION = "5.3.4".freeze
3
7
  end
@@ -0,0 +1,60 @@
1
+ module Skylight
2
+ # @api private
3
+ module VM
4
+ if defined?(JRUBY_VERSION)
5
+ # This doesn't quite work as we would like it. I believe that the GC
6
+ # statistics includes time that is not stop-the-world, this does not
7
+ # necessarily take time away from the application.
8
+ #
9
+ # require 'java'
10
+ # class GC
11
+ # def initialize
12
+ # @factory = Java::JavaLangManagement::ManagementFactory
13
+ # end
14
+ #
15
+ # def enable
16
+ # end
17
+ #
18
+ # def total_time
19
+ # res = 0.0
20
+ #
21
+ # @factory.garbage_collector_mx_beans.each do |mx|
22
+ # res += (mx.collection_time.to_f / 1_000.0)
23
+ # end
24
+ #
25
+ # res
26
+ # end
27
+ # end
28
+ elsif defined?(::GC::Profiler)
29
+ class GC
30
+ def initialize
31
+ @total = 0
32
+ end
33
+
34
+ def enable
35
+ ::GC::Profiler.enable
36
+ end
37
+
38
+ def total_time
39
+ # Reported in seconds
40
+ run = (::GC::Profiler.total_time * 1_000_000).to_i
41
+
42
+ ::GC::Profiler.clear if run > 0
43
+
44
+ @total += run
45
+ end
46
+ end
47
+ end
48
+
49
+ # Fallback
50
+ unless defined?(VM::GC)
51
+ class GC
52
+ def enable; end
53
+
54
+ def total_time
55
+ 0
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
data/lib/skylight.rb CHANGED
@@ -1,34 +1,223 @@
1
- require 'skylight/version'
2
- require 'skylight/core'
3
- require 'skylight/trace'
4
- require 'skylight/instrumenter'
5
- require 'skylight/middleware'
6
- require 'skylight/api'
7
- require 'skylight/helpers'
8
- require 'skylight/config'
9
- require 'skylight/errors'
10
- require 'skylight/native'
1
+ require "skylight/version"
2
+ require "skylight/trace"
3
+ require "skylight/instrumenter"
4
+ require "skylight/middleware"
5
+ require "skylight/api"
6
+ require "skylight/helpers"
7
+ require "skylight/config"
8
+ require "skylight/user_config"
9
+ require "skylight/errors"
10
+ require "skylight/native"
11
+ require "skylight/gc"
12
+ require "skylight/vm/gc"
13
+ require "skylight/util"
14
+ require "skylight/deprecation"
15
+ require "skylight/subscriber"
16
+ require "skylight/sidekiq"
17
+ require "skylight/probes"
18
+
19
+ # For prettier global names
20
+ require "English"
21
+
22
+ require "active_support/notifications"
23
+
24
+ # Specifically check for Railtie since we've had at least one case of a
25
+ # customer having Rails defined without having all of Rails loaded.
26
+ require "skylight/railtie" if defined?(Rails::Railtie)
11
27
 
12
28
  module Skylight
13
29
  # Used from the CLI
14
- autoload :CLI, 'skylight/cli'
30
+ autoload :CLI, "skylight/cli"
15
31
 
16
- # Specifically check for Railtie since we've had at least one case of a
17
- # customer having Rails defined without having all of Rails loaded.
18
- if defined?(Rails::Railtie)
19
- require 'skylight/railtie'
20
- end
32
+ # Is this autoload even useful?
33
+ autoload :Normalizers, "skylight/normalizers"
21
34
 
22
- include Core::Instrumentable
35
+ extend Util::Logging
23
36
 
24
- def self.instrumenter_class
25
- Instrumenter
26
- end
37
+ LOCK = Mutex.new
27
38
 
28
- def self.config_class
29
- Config
30
- end
39
+ # @api private
40
+ TIERS = %w[rack api app view db noise other].freeze
41
+
42
+ # @api private
43
+ TIER_REGEX = /^(?:#{TIERS.join("|")})(?:\.|$)/u.freeze
44
+
45
+ # @api private
46
+ CATEGORY_REGEX = /^[a-z0-9_-]+(?:\.[a-z0-9_-]+)*$/iu.freeze
47
+
48
+ # @api private
49
+ DEFAULT_CATEGORY = "app.block".freeze
50
+
51
+ # @api private
52
+ DEFAULT_OPTIONS = { category: DEFAULT_CATEGORY }.freeze
53
+
54
+ at_exit { stop! }
55
+
56
+ class << self
57
+ extend Util::InstrumenterMethod
58
+
59
+ def instrumenter
60
+ defined?(@instrumenter) && @instrumenter
61
+ end
62
+
63
+ def probe(*args)
64
+ Probes.probe(*args)
65
+ end
66
+
67
+ def enable_normalizer(*names)
68
+ Normalizers.enable(*names)
69
+ end
70
+
71
+ # Start instrumenting
72
+ def start!(config = nil)
73
+ return instrumenter if instrumenter
74
+
75
+ const_get(:LOCK).synchronize do
76
+ return instrumenter if instrumenter
77
+
78
+ config ||= {}
79
+ config = Config.load(config) unless config.is_a?(Config)
80
+
81
+ Probes.install!
82
+
83
+ @instrumenter = Instrumenter.new(config).start!
84
+ end
85
+ rescue StandardError => e
86
+ level, message =
87
+ if e.is_a?(ConfigError)
88
+ [:warn, format("Unable to start Instrumenter due to a configuration error: %<message>s", message: e.message)]
89
+ else
90
+ [
91
+ :error,
92
+ format("Unable to start Instrumenter; msg=%<message>s; class=%<klass>s", message: e.message, klass: e.class)
93
+ ]
94
+ end
95
+
96
+ if config.respond_to?("log_#{level}") && config.respond_to?(:log_trace)
97
+ config.send("log_#{level}", message)
98
+ config.log_trace e.backtrace.join("\n")
99
+ else
100
+ warn "[#{name.upcase}] #{message}"
101
+ end
102
+ false
103
+ end
104
+
105
+ def started?
106
+ !!instrumenter
107
+ end
31
108
 
32
- Core::Probes.add_path(File.expand_path("skylight/probes", __dir__))
109
+ # Stop instrumenting
110
+ def stop!
111
+ t { "stop!" }
33
112
 
113
+ const_get(:LOCK).synchronize do
114
+ t { "stop! synchronized" }
115
+ return unless instrumenter
116
+
117
+ # This is only really helpful for getting specs to pass.
118
+ @instrumenter.current_trace = nil
119
+
120
+ @instrumenter.shutdown
121
+ @instrumenter = nil
122
+ end
123
+ end
124
+
125
+ # Check tracing
126
+ def tracing?
127
+ t { "checking tracing?; thread=#{Thread.current.object_id}" }
128
+ instrumenter&.current_trace
129
+ end
130
+
131
+ # Start a trace
132
+ def trace(endpoint = nil, cat = nil, title = nil, meta: nil, segment: nil, component: nil)
133
+ unless instrumenter
134
+ return yield if block_given?
135
+
136
+ return
137
+ end
138
+
139
+ if instrumenter.poisoned?
140
+ spawn_shutdown_thread!
141
+ return yield if block_given?
142
+
143
+ return
144
+ end
145
+
146
+ cat ||= DEFAULT_CATEGORY
147
+
148
+ if block_given?
149
+ instrumenter.trace(endpoint, cat, title, nil, meta: meta, segment: segment, component: component) do |tr|
150
+ yield tr
151
+ end
152
+ else
153
+ instrumenter.trace(endpoint, cat, title, nil, meta: meta, segment: segment, component: component)
154
+ end
155
+ end
156
+
157
+ # @overload instrument(opts)
158
+ # @param [Hash] opts the options for instrumentation.
159
+ # @option opts [String] :category (`DEFAULT_CATEGORY`) The category
160
+ # @option opts [String] :title The title
161
+ # @option opts [String] :description The description
162
+ # @option opts [Hash] :meta The meta
163
+ # @option opts [String] :source_location The source location
164
+ # @option opts [String] :source_file The source file. (Will be sanitized.)
165
+ # @option opts [String] :source_line The source line.
166
+ # @overload instrument(title)
167
+ # Instrument with the specified title and the default category
168
+ # @param [String] title The title
169
+ def instrument(opts = DEFAULT_OPTIONS, &block)
170
+ unless instrumenter
171
+ return yield if block_given?
172
+
173
+ return
174
+ end
175
+
176
+ if opts.is_a?(Hash)
177
+ category = opts[:category] || DEFAULT_CATEGORY
178
+ title = opts[:title]
179
+ desc = opts[:description]
180
+ meta = opts[:meta]
181
+ else
182
+ category = DEFAULT_CATEGORY
183
+ title = opts.to_s
184
+ desc = nil
185
+ meta = nil
186
+ opts = {}
187
+ end
188
+
189
+ # NOTE: unless we have `:internal` (indicating a built-in Skylight instrument block),
190
+ # or we already have a `source_file` or `source_line` (probably set by `instrument_method`),
191
+ # we set the caller location to the second item on the stack
192
+ # (immediate caller of the `instrument` method).
193
+ unless opts[:source_file] || opts[:source_line] || opts[:internal]
194
+ opts = opts.merge(sk_instrument_location: caller_locations(1..1).first)
195
+ end
196
+
197
+ meta ||= {}
198
+
199
+ instrumenter.extensions.process_instrument_options(opts, meta)
200
+ instrumenter.instrument(category, title, desc, meta, &block)
201
+ end
202
+
203
+ instrumenter_method :config
204
+
205
+ instrumenter_method :mute, block: true
206
+ instrumenter_method :unmute, block: true
207
+ instrumenter_method :muted?
208
+
209
+ # End a span
210
+ instrumenter_method :done
211
+
212
+ instrumenter_method :broken!
213
+
214
+ # Temporarily disable
215
+ instrumenter_method :disable, block: true
216
+
217
+ # Runs the shutdown procedure in the background.
218
+ # This should do little more than unsubscribe from all ActiveSupport::Notifications
219
+ def spawn_shutdown_thread!
220
+ @shutdown_thread || const_get(:LOCK).synchronize { @shutdown_thread ||= Thread.new { @instrumenter&.shutdown } }
221
+ end
222
+ end
34
223
  end