Module: Skylight

Extended by:
Util::InstrumenterMethod, Util::Logging
Defined in:
lib/skylight/probes/tilt.rb,
lib/skylight.rb,
lib/skylight/gc.rb,
lib/skylight/api.rb,
lib/skylight/cli.rb,
lib/skylight/test.rb,
lib/skylight/util.rb,
lib/skylight/trace.rb,
lib/skylight/vm/gc.rb,
lib/skylight/config.rb,
lib/skylight/errors.rb,
lib/skylight/native.rb,
lib/skylight/probes.rb,
lib/skylight/helpers.rb,
lib/skylight/railtie.rb,
lib/skylight/sidekiq.rb,
lib/skylight/version.rb,
lib/skylight/util/ssl.rb,
lib/skylight/util/gzip.rb,
lib/skylight/util/http.rb,
lib/skylight/cli/doctor.rb,
lib/skylight/cli/merger.rb,
lib/skylight/extensions.rb,
lib/skylight/middleware.rb,
lib/skylight/subscriber.rb,
lib/skylight/util/clock.rb,
lib/skylight/util/proxy.rb,
lib/skylight/cli/helpers.rb,
lib/skylight/deprecation.rb,
lib/skylight/normalizers.rb,
lib/skylight/user_config.rb,
lib/skylight/util/deploy.rb,
lib/skylight/instrumenter.rb,
lib/skylight/probes/excon.rb,
lib/skylight/probes/mongo.rb,
lib/skylight/probes/redis.rb,
lib/skylight/util/logging.rb,
lib/skylight/probes/lambda.rb,
lib/skylight/probes/sequel.rb,
lib/skylight/util/hostname.rb,
lib/skylight/util/platform.rb,
lib/skylight/probes/faraday.rb,
lib/skylight/probes/graphql.rb,
lib/skylight/probes/sinatra.rb,
lib/skylight/util/component.rb,
lib/skylight/util/lru_cache.rb,
lib/skylight/formatters/http.rb,
lib/skylight/normalizers/sql.rb,
lib/skylight/probes/net_http.rb,
lib/skylight/probes/active_job.rb,
lib/skylight/probes/httpclient.rb,
lib/skylight/probes/middleware.rb,
lib/skylight/native_ext_fetcher.rb,
lib/skylight/normalizers/render.rb,
lib/skylight/normalizers/shrine.rb,
lib/skylight/probes/action_view.rb,
lib/skylight/probes/delayed_job.rb,
lib/skylight/normalizers/default.rb,
lib/skylight/probes/rack_builder.rb,
lib/skylight/probes/elasticsearch.rb,
lib/skylight/util/allocation_free.rb,
lib/skylight/normalizers/sequel/sql.rb,
lib/skylight/probes/excon/middleware.rb,
lib/skylight/probes/action_controller.rb,
lib/skylight/util/instrumenter_method.rb,
lib/skylight/probes/active_job_enqueue.rb,
lib/skylight/extensions/source_location.rb,
lib/skylight/normalizers/active_storage.rb,
lib/skylight/normalizers/grape/endpoint.rb,
lib/skylight/probes/active_record_async.rb,
lib/skylight/normalizers/data_mapper/sql.rb,
lib/skylight/normalizers/faraday/request.rb,
lib/skylight/normalizers/graphiti/render.rb,
lib/skylight/normalizers/graphiti/resolve.rb,
lib/skylight/normalizers/active_record/sql.rb,
lib/skylight/probes/sinatra_add_middleware.rb,
lib/skylight/normalizers/active_job/perform.rb,
lib/skylight/normalizers/couch_potato/query.rb,
lib/skylight/normalizers/grape/endpoint_run.rb,
lib/skylight/probes/active_model_serializers.rb,
lib/skylight/normalizers/active_support/cache.rb,
lib/skylight/normalizers/coach/handler_finish.rb,
lib/skylight/normalizers/elasticsearch/request.rb,
lib/skylight/normalizers/grape/endpoint_render.rb,
lib/skylight/normalizers/grape/format_response.rb,
lib/skylight/probes/action_dispatch/request_id.rb,
lib/skylight/normalizers/coach/middleware_finish.rb,
lib/skylight/normalizers/action_dispatch/route_set.rb,
lib/skylight/normalizers/action_view/render_layout.rb,
lib/skylight/normalizers/active_support/cache_read.rb,
lib/skylight/normalizers/action_view/render_partial.rb,
lib/skylight/normalizers/active_support/cache_clear.rb,
lib/skylight/normalizers/active_support/cache_exist.rb,
lib/skylight/normalizers/active_support/cache_write.rb,
lib/skylight/normalizers/grape/endpoint_run_filters.rb,
lib/skylight/probes/action_dispatch/show_exceptions.rb,
lib/skylight/normalizers/action_controller/send_file.rb,
lib/skylight/normalizers/action_view/render_template.rb,
lib/skylight/normalizers/active_record/instantiation.rb,
lib/skylight/normalizers/active_support/cache_delete.rb,
lib/skylight/probes/action_dispatch/routing/route_set.rb,
lib/skylight/normalizers/action_view/render_collection.rb,
lib/skylight/normalizers/active_support/cache_generate.rb,
lib/skylight/normalizers/active_support/cache_decrement.rb,
lib/skylight/normalizers/active_support/cache_fetch_hit.rb,
lib/skylight/normalizers/active_support/cache_increment.rb,
lib/skylight/normalizers/active_model_serializers/render.rb,
lib/skylight/normalizers/active_support/cache_read_multi.rb,
lib/skylight/normalizers/action_controller/process_action.rb,
lib/skylight/normalizers/action_dispatch/process_middleware.rb,
ext/skylight_native.c

Overview

Used from extconf.rb

Defined Under Namespace

Modules: CLI, Extensions, Formatters, Helpers, Normalizers, Probes, Sidekiq, Test, Util, VM Classes: Api, Config, ConfigError, Deprecation, GC, Instrumenter, Middleware, NativeError, NativeExtFetcher, Railtie, Subscriber, Trace, UserConfig

Constant Summary collapse

LOCK =
Mutex.new
TIERS =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

%w[rack api app view db noise other].freeze
TIER_REGEX =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

/^(?:#{TIERS.join("|")})(?:\.|$)/u.freeze
CATEGORY_REGEX =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

/^[a-z0-9_-]+(?:\.[a-z0-9_-]+)*$/iu.freeze
DEFAULT_CATEGORY =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

"app.block".freeze
DEFAULT_OPTIONS =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

{ category: DEFAULT_CATEGORY }.freeze
VERSION =

pre-release versions should be given here as “5.0.0-alpha” for compatibility with semver when it is parsed by the rust agent. This string will be transformed in the gemspec to “5.0.0.alpha” to conform with rubygems.

"7.1.1".freeze
SKYLIGHT_GEM_ROOT =
"#{File.expand_path("../..", __dir__)}/"
DEPRECATOR =
Deprecation.new("6.0", "skylight")

Class Method Summary collapse

Methods included from Util::Logging

config_for_logging, debug, error, fmt, info, log, log_context, raise_on_error?, t, trace, trace?, warn

Methods included from Util::InstrumenterMethod

instrumenter_method

Class Method Details

.check_install_errors(config) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



103
104
105
106
107
108
109
110
111
112
# File 'lib/skylight/native.rb', line 103

def self.check_install_errors(config)
  # NOTE: An unsupported arch doesn't count as an error.
  install_log = File.expand_path("../../ext/install.log", __dir__)

  if File.exist?(install_log) && File.read(install_log) =~ /ERROR/
    config.alert_logger.error "[SKYLIGHT] [#{Skylight::VERSION}] The Skylight native extension failed to install. " \
                                "Please check #{install_log} and notify support@skylight.io. " \
                                "The missing extension will not affect the functioning of your application."
  end
end

.enable_normalizer(*names) ⇒ Object



67
68
69
# File 'lib/skylight.rb', line 67

def enable_normalizer(*names)
  Normalizers.enable(*names)
end

.instrument(opts) ⇒ Object .instrument(title) ⇒ Object

Overloads:

  • .instrument(opts) ⇒ Object

    Parameters:

    • opts (Hash)

      the options for instrumentation.

    Options Hash (opts):

    • :category (String) — default: `DEFAULT_CATEGORY`

      The category

    • :title (String)

      The title

    • :description (String)

      The description

    • :meta (Hash)

      The meta

    • :source_location (String)

      The source location

    • :source_file (String)

      The source file. (Will be sanitized.)

    • :source_line (String)

      The source line.

  • .instrument(title) ⇒ Object

    Instrument with the specified title and the default category

    Parameters:

    • title (String)

      The title



169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
# File 'lib/skylight.rb', line 169

def instrument(opts = DEFAULT_OPTIONS, &block)
  unless instrumenter
    return yield if block_given?

    return
  end

  if opts.is_a?(Hash)
    category = opts[:category] || DEFAULT_CATEGORY
    title = opts[:title]
    desc = opts[:description]
    meta = opts[:meta]
  else
    category = DEFAULT_CATEGORY
    title = opts.to_s
    desc = nil
    meta = nil
    opts = {}
  end

  # NOTE: unless we have `:internal` (indicating a built-in Skylight instrument block),
  # or we already have a `source_file` or `source_line` (probably set by `instrument_method`),
  # we set the caller location to the second item on the stack
  # (immediate caller of the `instrument` method).
  unless opts[:source_file] || opts[:source_line] || opts[:internal]
    opts = opts.merge(sk_instrument_location: caller_locations(1..1).first)
  end

  meta ||= {}

  instrumenter.extensions.process_instrument_options(opts, meta)
  instrumenter.instrument(category, title, desc, meta, &block)
end

.instrumenterObject



59
60
61
# File 'lib/skylight.rb', line 59

def instrumenter
  defined?(@instrumenter) && @instrumenter
end

.libskylight_pathObject



61
62
63
# File 'lib/skylight/native.rb', line 61

def self.libskylight_path
  ENV.fetch("SKYLIGHT_LIB_PATH") { File.expand_path("../native/#{Util::Platform.tuple}", __FILE__) }
end

.load_libskylight(path) ⇒ Object



143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
# File 'ext/skylight_native.c', line 143

static VALUE
load_libskylight(VALUE klass, VALUE path) {
  int res;

  UNUSED(klass);
  CHECK_TYPE(path, T_STRING);

  // Already loaded
  if (sky_hrtime != 0) {
    return Qnil;
  }

  res = sky_load_libskylight(StringValueCStr(path));

  if (res < 0) {
    rb_raise(rb_eRuntimeError, "[SKYLIGHT] dlerror; msg=%s", dlerror());
    return Qnil;
  }

  return Qnil;
}

.native?Boolean

Returns:

  • (Boolean)


57
58
59
# File 'lib/skylight/native.rb', line 57

def self.native?
  @has_native_ext
end

.probe(*args) ⇒ Object



63
64
65
# File 'lib/skylight.rb', line 63

def probe(*args)
  Probes.probe(*args)
end

.spawn_shutdown_thread!Object

Runs the shutdown procedure in the background. This should do little more than unsubscribe from all ActiveSupport::Notifications



220
221
222
# File 'lib/skylight.rb', line 220

def spawn_shutdown_thread!
  @shutdown_thread || const_get(:LOCK).synchronize { @shutdown_thread ||= Thread.new { @instrumenter&.shutdown } }
end

.start!(config = nil) ⇒ Object

Start instrumenting



72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
# File 'lib/skylight.rb', line 72

def start!(config = nil)
  return instrumenter if instrumenter

  const_get(:LOCK).synchronize do
    return instrumenter if instrumenter

    config ||= {}
    config = Config.load(config) unless config.is_a?(Config)

    Probes.install!

    @instrumenter = Instrumenter.new(config).start!
  end
rescue StandardError => e
  level, message =
    if e.is_a?(ConfigError)
      [:warn, format("Unable to start Instrumenter due to a configuration error: %<message>s", message: e.message)]
    else
      [
        :error,
        format("Unable to start Instrumenter; msg=%<message>s; class=%<klass>s", message: e.message, klass: e.class)
      ]
    end

  if config.respond_to?("log_#{level}") && config.respond_to?(:log_trace)
    config.send("log_#{level}", message)
    config.log_trace e.backtrace.join("\n")
  else
    warn "[#{name.upcase}] #{message}"
  end
  false
end

.started?Boolean

Returns:

  • (Boolean)


105
106
107
# File 'lib/skylight.rb', line 105

def started?
  !!instrumenter
end

.stop!Object

Stop instrumenting



110
111
112
113
114
115
116
117
118
119
120
121
122
123
# File 'lib/skylight.rb', line 110

def stop!
  t { "stop!" }

  const_get(:LOCK).synchronize do
    t { "stop! synchronized" }
    return unless instrumenter

    # This is only really helpful for getting specs to pass.
    @instrumenter.current_trace = nil

    @instrumenter.shutdown
    @instrumenter = nil
  end
end

.trace(endpoint = nil, cat = nil, title = nil, desc = nil, meta: nil, segment: nil, component: nil) ⇒ Object

Start a trace



132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
# File 'lib/skylight.rb', line 132

def trace(endpoint = nil, cat = nil, title = nil, desc = nil, meta: nil, segment: nil, component: nil)
  unless instrumenter
    return yield if block_given?

    return
  end

  if instrumenter.poisoned?
    spawn_shutdown_thread!
    return yield if block_given?

    return
  end

  cat ||= DEFAULT_CATEGORY

  if block_given?
    instrumenter.trace(endpoint, cat, title, desc, meta: meta, segment: segment, component: component) do |tr|
      yield tr
    end
  else
    instrumenter.trace(endpoint, cat, title, desc, meta: meta, segment: segment, component: component)
  end
end

.tracing?Boolean

Check tracing

Returns:

  • (Boolean)


126
127
128
129
# File 'lib/skylight.rb', line 126

def tracing?
  t { "checking tracing?; thread=#{Thread.current.object_id}" }
  instrumenter&.current_trace
end

.warn_skylight_native_missing(config) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



115
116
117
118
119
120
121
# File 'lib/skylight/native.rb', line 115

def self.warn_skylight_native_missing(config)
  config.alert_logger.error "[SKYLIGHT] [#{Skylight::VERSION}] The Skylight native extension for " \
                              "your platform wasn't found. Supported operating systems are " \
                              "Linux 2.6.18+ and Mac OS X 10.8+. The missing extension will not " \
                              "affect the functioning of your application. If you are on a " \
                              "supported platform, please contact support at support@skylight.io."
end