skylight 3.1.4 → 5.3.4
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 +4 -4
- data/CHANGELOG.md +465 -294
- data/CLA.md +1 -1
- data/CONTRIBUTING.md +11 -3
- data/ERRORS.md +3 -0
- data/LICENSE.md +8 -18
- data/README.md +1 -2
- data/bin/skylight +1 -1
- data/ext/extconf.rb +118 -122
- data/ext/libskylight.yml +8 -6
- data/ext/skylight_native.c +56 -100
- data/lib/skylight/api.rb +41 -27
- data/lib/skylight/cli/doctor.rb +68 -70
- data/lib/skylight/cli/helpers.rb +3 -5
- data/lib/skylight/cli/merger.rb +99 -92
- data/lib/skylight/cli.rb +40 -43
- data/lib/skylight/config.rb +656 -201
- data/lib/skylight/data/cacert.pem +730 -1023
- data/lib/skylight/deprecation.rb +17 -0
- data/lib/skylight/errors.rb +34 -16
- data/lib/skylight/extensions/source_location.rb +291 -0
- data/lib/skylight/extensions.rb +95 -0
- data/lib/skylight/formatters/http.rb +18 -0
- data/lib/skylight/gc.rb +99 -0
- data/lib/skylight/helpers.rb +82 -39
- data/lib/skylight/instrumenter.rb +339 -9
- data/lib/skylight/middleware.rb +147 -1
- data/lib/skylight/native.rb +71 -23
- data/lib/skylight/native_ext_fetcher.rb +39 -47
- data/lib/skylight/normalizers/action_controller/process_action.rb +68 -0
- data/lib/skylight/normalizers/action_controller/send_file.rb +51 -0
- data/lib/skylight/normalizers/action_dispatch/process_middleware.rb +22 -0
- data/lib/skylight/normalizers/action_dispatch/route_set.rb +27 -0
- data/lib/skylight/normalizers/action_view/render_collection.rb +24 -0
- data/lib/skylight/normalizers/action_view/render_layout.rb +25 -0
- data/lib/skylight/normalizers/action_view/render_partial.rb +23 -0
- data/lib/skylight/normalizers/action_view/render_template.rb +23 -0
- data/lib/skylight/normalizers/active_job/perform.rb +87 -0
- data/lib/skylight/normalizers/active_model_serializers/render.rb +32 -0
- data/lib/skylight/normalizers/active_record/instantiation.rb +16 -0
- data/lib/skylight/normalizers/active_record/sql.rb +20 -0
- data/lib/skylight/normalizers/active_storage.rb +28 -0
- data/lib/skylight/normalizers/active_support/cache.rb +11 -0
- data/lib/skylight/normalizers/active_support/cache_clear.rb +16 -0
- data/lib/skylight/normalizers/active_support/cache_decrement.rb +16 -0
- data/lib/skylight/normalizers/active_support/cache_delete.rb +16 -0
- data/lib/skylight/normalizers/active_support/cache_exist.rb +16 -0
- data/lib/skylight/normalizers/active_support/cache_fetch_hit.rb +16 -0
- data/lib/skylight/normalizers/active_support/cache_generate.rb +16 -0
- data/lib/skylight/normalizers/active_support/cache_increment.rb +16 -0
- data/lib/skylight/normalizers/active_support/cache_read.rb +16 -0
- data/lib/skylight/normalizers/active_support/cache_read_multi.rb +16 -0
- data/lib/skylight/normalizers/active_support/cache_write.rb +16 -0
- data/lib/skylight/normalizers/coach/handler_finish.rb +44 -0
- data/lib/skylight/normalizers/coach/middleware_finish.rb +33 -0
- data/lib/skylight/normalizers/couch_potato/query.rb +20 -0
- data/lib/skylight/normalizers/data_mapper/sql.rb +12 -0
- data/lib/skylight/normalizers/default.rb +24 -0
- data/lib/skylight/normalizers/elasticsearch/request.rb +20 -0
- data/lib/skylight/normalizers/faraday/request.rb +38 -0
- data/lib/skylight/normalizers/grape/endpoint.rb +28 -0
- data/lib/skylight/normalizers/grape/endpoint_render.rb +25 -0
- data/lib/skylight/normalizers/grape/endpoint_run.rb +39 -0
- data/lib/skylight/normalizers/grape/endpoint_run_filters.rb +20 -0
- data/lib/skylight/normalizers/grape/format_response.rb +20 -0
- data/lib/skylight/normalizers/graphiti/render.rb +22 -0
- data/lib/skylight/normalizers/graphiti/resolve.rb +31 -0
- data/lib/skylight/normalizers/graphql/base.rb +127 -0
- data/lib/skylight/normalizers/render.rb +79 -0
- data/lib/skylight/normalizers/sequel/sql.rb +12 -0
- data/lib/skylight/normalizers/shrine.rb +32 -0
- data/lib/skylight/normalizers/sql.rb +41 -0
- data/lib/skylight/normalizers.rb +157 -0
- data/lib/skylight/probes/action_controller.rb +52 -0
- data/lib/skylight/probes/action_dispatch/request_id.rb +33 -0
- data/lib/skylight/probes/action_dispatch/routing/route_set.rb +30 -0
- data/lib/skylight/probes/action_dispatch.rb +2 -0
- data/lib/skylight/probes/action_view.rb +42 -0
- data/lib/skylight/probes/active_job.rb +27 -0
- data/lib/skylight/probes/active_job_enqueue.rb +35 -0
- data/lib/skylight/probes/active_model_serializers.rb +50 -0
- data/lib/skylight/probes/active_record_async.rb +96 -0
- data/lib/skylight/probes/delayed_job.rb +144 -0
- data/lib/skylight/probes/elasticsearch.rb +45 -0
- data/lib/skylight/probes/excon/middleware.rb +65 -0
- data/lib/skylight/probes/excon.rb +25 -0
- data/lib/skylight/probes/faraday.rb +23 -0
- data/lib/skylight/probes/graphql.rb +38 -0
- data/lib/skylight/probes/httpclient.rb +44 -0
- data/lib/skylight/probes/middleware.rb +135 -0
- data/lib/skylight/probes/mongo.rb +169 -0
- data/lib/skylight/probes/mongoid.rb +6 -0
- data/lib/skylight/probes/net_http.rb +54 -0
- data/lib/skylight/probes/rack_builder.rb +37 -0
- data/lib/skylight/probes/redis.rb +68 -0
- data/lib/skylight/probes/sequel.rb +29 -0
- data/lib/skylight/probes/sinatra.rb +66 -0
- data/lib/skylight/probes/sinatra_add_middleware.rb +10 -10
- data/lib/skylight/probes/tilt.rb +25 -0
- data/lib/skylight/probes.rb +172 -0
- data/lib/skylight/railtie.rb +172 -15
- data/lib/skylight/sidekiq.rb +47 -0
- data/lib/skylight/sinatra.rb +2 -2
- data/lib/skylight/subscriber.rb +130 -0
- data/lib/skylight/test.rb +147 -0
- data/lib/skylight/trace.rb +331 -15
- data/lib/skylight/user_config.rb +60 -0
- data/lib/skylight/util/allocation_free.rb +26 -0
- data/lib/skylight/util/clock.rb +57 -0
- data/lib/skylight/util/component.rb +47 -9
- data/lib/skylight/util/deploy.rb +24 -40
- data/lib/skylight/util/gzip.rb +20 -0
- data/lib/skylight/util/hostname.rb +4 -4
- data/lib/skylight/util/http.rb +62 -71
- data/lib/skylight/util/instrumenter_method.rb +26 -0
- data/lib/skylight/util/logging.rb +136 -0
- data/lib/skylight/util/lru_cache.rb +36 -0
- data/lib/skylight/util/platform.rb +74 -0
- data/lib/skylight/util/proxy.rb +13 -0
- data/lib/skylight/util/ssl.rb +4 -28
- data/lib/skylight/util.rb +12 -0
- data/lib/skylight/vendor/cli/thor/rake_compat.rb +1 -1
- data/lib/skylight/version.rb +5 -1
- data/lib/skylight/vm/gc.rb +60 -0
- data/lib/skylight.rb +213 -24
- 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
|
data/lib/skylight/util/ssl.rb
CHANGED
|
@@ -1,54 +1,30 @@
|
|
|
1
|
-
require
|
|
1
|
+
require "openssl"
|
|
2
2
|
|
|
3
3
|
module Skylight
|
|
4
4
|
module Util
|
|
5
5
|
class SSL
|
|
6
|
-
DEFAULT_CA_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[
|
|
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
|
data/lib/skylight/version.rb
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
1
|
module Skylight
|
|
2
|
-
|
|
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
|
|
2
|
-
require
|
|
3
|
-
require
|
|
4
|
-
require
|
|
5
|
-
require
|
|
6
|
-
require
|
|
7
|
-
require
|
|
8
|
-
require
|
|
9
|
-
require
|
|
10
|
-
require
|
|
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,
|
|
30
|
+
autoload :CLI, "skylight/cli"
|
|
15
31
|
|
|
16
|
-
#
|
|
17
|
-
|
|
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
|
-
|
|
35
|
+
extend Util::Logging
|
|
23
36
|
|
|
24
|
-
|
|
25
|
-
Instrumenter
|
|
26
|
-
end
|
|
37
|
+
LOCK = Mutex.new
|
|
27
38
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
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
|
-
|
|
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
|