sentry-ruby-core 5.19.0 → 5.20.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.
- checksums.yaml +4 -4
- data/lib/sentry/attachment.rb +3 -5
- data/lib/sentry/backtrace.rb +1 -3
- data/lib/sentry/baggage.rb +6 -6
- data/lib/sentry/breadcrumb/sentry_logger.rb +6 -6
- data/lib/sentry/check_in_event.rb +4 -4
- data/lib/sentry/client.rb +9 -9
- data/lib/sentry/configuration.rb +28 -13
- data/lib/sentry/core_ext/object/deep_dup.rb +1 -1
- data/lib/sentry/cron/monitor_check_ins.rb +1 -1
- data/lib/sentry/cron/monitor_config.rb +1 -1
- data/lib/sentry/dsn.rb +3 -3
- data/lib/sentry/envelope.rb +8 -8
- data/lib/sentry/event.rb +7 -7
- data/lib/sentry/graphql.rb +1 -1
- data/lib/sentry/hub.rb +8 -1
- data/lib/sentry/interfaces/mechanism.rb +1 -1
- data/lib/sentry/interfaces/request.rb +5 -5
- data/lib/sentry/interfaces/single_exception.rb +1 -1
- data/lib/sentry/interfaces/stacktrace.rb +3 -1
- data/lib/sentry/interfaces/stacktrace_builder.rb +15 -2
- data/lib/sentry/logger.rb +1 -1
- data/lib/sentry/metrics/aggregator.rb +12 -12
- data/lib/sentry/metrics/set_metric.rb +2 -2
- data/lib/sentry/metrics.rb +15 -15
- data/lib/sentry/net/http.rb +1 -1
- data/lib/sentry/profiler.rb +19 -20
- data/lib/sentry/propagation_context.rb +1 -1
- data/lib/sentry/rack/capture_exceptions.rb +1 -1
- data/lib/sentry/rack.rb +2 -2
- data/lib/sentry/rake.rb +2 -2
- data/lib/sentry/release_detector.rb +4 -4
- data/lib/sentry/scope.rb +1 -0
- data/lib/sentry/session_flusher.rb +1 -1
- data/lib/sentry/span.rb +6 -0
- data/lib/sentry/test_helper.rb +1 -1
- data/lib/sentry/transaction.rb +2 -2
- data/lib/sentry/transaction_event.rb +1 -1
- data/lib/sentry/transport/http_transport.rb +12 -12
- data/lib/sentry/transport.rb +4 -4
- data/lib/sentry/utils/env_helper.rb +21 -0
- data/lib/sentry/utils/real_ip.rb +1 -1
- data/lib/sentry/version.rb +1 -1
- data/lib/sentry-ruby.rb +1 -1
- metadata +6 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 58924eaaabcd9af00039a761dc76db3fdbfdad597ac5ec274cf5b09121706ffe
|
4
|
+
data.tar.gz: 931128e011f2b359bb00ff3a55e6924dc06cd083fb8944c278a2bac6186af767
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b1a1aa47dcc33056a50e76faaee84a299093441a7994b9f377135a1a172a40f4c581a31ed553873c8ac960eff88d61303c22b98c07772590f36bedd4711b28be
|
7
|
+
data.tar.gz: 86ebfa52b4ddadeb7307985c4312b9ada2c0180be8ff65e2cf3af3eae3b6416403269642fdb4f502baa2f56ebd4e3f63b681e9e47de8b483db460d6f232d43ee
|
data/lib/sentry/attachment.rb
CHANGED
@@ -8,13 +8,13 @@ module Sentry
|
|
8
8
|
|
9
9
|
def initialize(bytes: nil, filename: nil, content_type: nil, path: nil)
|
10
10
|
@bytes = bytes
|
11
|
-
@filename = infer_filename(
|
11
|
+
@filename = filename || infer_filename(path)
|
12
12
|
@path = path
|
13
13
|
@content_type = content_type
|
14
14
|
end
|
15
15
|
|
16
16
|
def to_envelope_headers
|
17
|
-
{ type:
|
17
|
+
{ type: "attachment", filename: filename, content_type: content_type, length: payload.bytesize }
|
18
18
|
end
|
19
19
|
|
20
20
|
def payload
|
@@ -29,9 +29,7 @@ module Sentry
|
|
29
29
|
|
30
30
|
private
|
31
31
|
|
32
|
-
def infer_filename(
|
33
|
-
return filename if filename
|
34
|
-
|
32
|
+
def infer_filename(path)
|
35
33
|
if path
|
36
34
|
File.basename(path)
|
37
35
|
else
|
data/lib/sentry/backtrace.rb
CHANGED
@@ -80,8 +80,6 @@ module Sentry
|
|
80
80
|
end
|
81
81
|
end
|
82
82
|
|
83
|
-
APP_DIRS_PATTERN = /(bin|exe|app|config|lib|test|spec)/.freeze
|
84
|
-
|
85
83
|
# holder for an Array of Backtrace::Line instances
|
86
84
|
attr_reader :lines
|
87
85
|
|
@@ -91,7 +89,7 @@ module Sentry
|
|
91
89
|
ruby_lines = backtrace_cleanup_callback.call(ruby_lines) if backtrace_cleanup_callback
|
92
90
|
|
93
91
|
in_app_pattern ||= begin
|
94
|
-
Regexp.new("^(#{project_root}/)?#{app_dirs_pattern
|
92
|
+
Regexp.new("^(#{project_root}/)?#{app_dirs_pattern}")
|
95
93
|
end
|
96
94
|
|
97
95
|
lines = ruby_lines.to_a.map do |unparsed_line|
|
data/lib/sentry/baggage.rb
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
3
|
+
require "cgi"
|
4
4
|
|
5
5
|
module Sentry
|
6
6
|
# A {https://www.w3.org/TR/baggage W3C Baggage Header} implementation.
|
7
7
|
class Baggage
|
8
|
-
SENTRY_PREFIX =
|
8
|
+
SENTRY_PREFIX = "sentry-"
|
9
9
|
SENTRY_PREFIX_REGEX = /^sentry-/.freeze
|
10
10
|
|
11
11
|
# @return [Hash]
|
@@ -30,14 +30,14 @@ module Sentry
|
|
30
30
|
items = {}
|
31
31
|
mutable = true
|
32
32
|
|
33
|
-
header.split(
|
33
|
+
header.split(",").each do |item|
|
34
34
|
item = item.strip
|
35
|
-
key, val = item.split(
|
35
|
+
key, val = item.split("=")
|
36
36
|
|
37
37
|
next unless key && val
|
38
38
|
next unless key =~ SENTRY_PREFIX_REGEX
|
39
39
|
|
40
|
-
baggage_key = key.split(
|
40
|
+
baggage_key = key.split("-")[1]
|
41
41
|
next unless baggage_key
|
42
42
|
|
43
43
|
items[CGI.unescape(baggage_key)] = CGI.unescape(val)
|
@@ -64,7 +64,7 @@ module Sentry
|
|
64
64
|
# @return [String]
|
65
65
|
def serialize
|
66
66
|
items = @items.map { |k, v| "#{SENTRY_PREFIX}#{CGI.escape(k)}=#{CGI.escape(v)}" }
|
67
|
-
items.join(
|
67
|
+
items.join(",")
|
68
68
|
end
|
69
69
|
end
|
70
70
|
end
|
@@ -1,16 +1,16 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
3
|
+
require "logger"
|
4
4
|
|
5
5
|
module Sentry
|
6
6
|
class Breadcrumb
|
7
7
|
module SentryLogger
|
8
8
|
LEVELS = {
|
9
|
-
::Logger::DEBUG =>
|
10
|
-
::Logger::INFO =>
|
11
|
-
::Logger::WARN =>
|
12
|
-
::Logger::ERROR =>
|
13
|
-
::Logger::FATAL =>
|
9
|
+
::Logger::DEBUG => "debug",
|
10
|
+
::Logger::INFO => "info",
|
11
|
+
::Logger::WARN => "warn",
|
12
|
+
::Logger::ERROR => "error",
|
13
|
+
::Logger::FATAL => "fatal"
|
14
14
|
}.freeze
|
15
15
|
|
16
16
|
def add(*args, &block)
|
@@ -1,11 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
3
|
+
require "securerandom"
|
4
|
+
require "sentry/cron/monitor_config"
|
5
5
|
|
6
6
|
module Sentry
|
7
7
|
class CheckInEvent < Event
|
8
|
-
TYPE =
|
8
|
+
TYPE = "check_in"
|
9
9
|
|
10
10
|
# uuid to identify this check-in.
|
11
11
|
# @return [String]
|
@@ -43,7 +43,7 @@ module Sentry
|
|
43
43
|
self.status = status
|
44
44
|
self.duration = duration
|
45
45
|
self.monitor_config = monitor_config
|
46
|
-
self.check_in_id = check_in_id || SecureRandom.uuid.delete(
|
46
|
+
self.check_in_id = check_in_id || SecureRandom.uuid.delete("-")
|
47
47
|
end
|
48
48
|
|
49
49
|
# @return [Hash]
|
data/lib/sentry/client.rb
CHANGED
@@ -30,7 +30,7 @@ module Sentry
|
|
30
30
|
else
|
31
31
|
@transport =
|
32
32
|
case configuration.dsn&.scheme
|
33
|
-
when
|
33
|
+
when "http", "https"
|
34
34
|
HTTPTransport.new(configuration)
|
35
35
|
else
|
36
36
|
DummyTransport.new(configuration)
|
@@ -49,7 +49,7 @@ module Sentry
|
|
49
49
|
return unless configuration.sending_allowed?
|
50
50
|
|
51
51
|
if event.is_a?(ErrorEvent) && !configuration.sample_allowed?
|
52
|
-
transport.record_lost_event(:sample_rate,
|
52
|
+
transport.record_lost_event(:sample_rate, "error")
|
53
53
|
return
|
54
54
|
end
|
55
55
|
|
@@ -64,11 +64,11 @@ module Sentry
|
|
64
64
|
if event.nil?
|
65
65
|
log_debug("Discarded event because one of the event processors returned nil")
|
66
66
|
transport.record_lost_event(:event_processor, data_category)
|
67
|
-
transport.record_lost_event(:event_processor,
|
67
|
+
transport.record_lost_event(:event_processor, "span", num: spans_before + 1) if is_transaction
|
68
68
|
return
|
69
69
|
elsif is_transaction
|
70
70
|
spans_delta = spans_before - event.spans.size
|
71
|
-
transport.record_lost_event(:event_processor,
|
71
|
+
transport.record_lost_event(:event_processor, "span", num: spans_delta) if spans_delta > 0
|
72
72
|
end
|
73
73
|
|
74
74
|
if async_block = configuration.async
|
@@ -76,7 +76,7 @@ module Sentry
|
|
76
76
|
elsif configuration.background_worker_threads != 0 && hint.fetch(:background, true)
|
77
77
|
unless dispatch_background_event(event, hint)
|
78
78
|
transport.record_lost_event(:queue_overflow, data_category)
|
79
|
-
transport.record_lost_event(:queue_overflow,
|
79
|
+
transport.record_lost_event(:queue_overflow, "span", num: spans_before + 1) if is_transaction
|
80
80
|
end
|
81
81
|
else
|
82
82
|
send_event(event, hint)
|
@@ -195,13 +195,13 @@ module Sentry
|
|
195
195
|
|
196
196
|
if event.nil?
|
197
197
|
log_debug("Discarded event because before_send_transaction returned nil")
|
198
|
-
transport.record_lost_event(:before_send,
|
199
|
-
transport.record_lost_event(:before_send,
|
198
|
+
transport.record_lost_event(:before_send, "transaction")
|
199
|
+
transport.record_lost_event(:before_send, "span", num: spans_before + 1)
|
200
200
|
return
|
201
201
|
else
|
202
202
|
spans_after = event.is_a?(TransactionEvent) ? event.spans.size : 0
|
203
203
|
spans_delta = spans_before - spans_after
|
204
|
-
transport.record_lost_event(:before_send,
|
204
|
+
transport.record_lost_event(:before_send, "span", num: spans_delta) if spans_delta > 0
|
205
205
|
end
|
206
206
|
end
|
207
207
|
|
@@ -212,7 +212,7 @@ module Sentry
|
|
212
212
|
rescue => e
|
213
213
|
log_error("Event sending failed", e, debug: configuration.debug)
|
214
214
|
transport.record_lost_event(:network_error, data_category)
|
215
|
-
transport.record_lost_event(:network_error,
|
215
|
+
transport.record_lost_event(:network_error, "span", num: spans_before + 1) if event.is_a?(TransactionEvent)
|
216
216
|
raise
|
217
217
|
end
|
218
218
|
|
data/lib/sentry/configuration.rb
CHANGED
@@ -4,6 +4,7 @@ require "concurrent/utility/processor_counter"
|
|
4
4
|
|
5
5
|
require "sentry/utils/exception_cause_chain"
|
6
6
|
require 'sentry/utils/custom_inspection'
|
7
|
+
require 'sentry/utils/env_helper'
|
7
8
|
require "sentry/dsn"
|
8
9
|
require "sentry/release_detector"
|
9
10
|
require "sentry/transport/configuration"
|
@@ -22,6 +23,8 @@ module Sentry
|
|
22
23
|
# have an `engines` dir at the root of your project, you may want
|
23
24
|
# to set this to something like /(app|config|engines|lib)/
|
24
25
|
#
|
26
|
+
# The default is value is /(bin|exe|app|config|lib|test|spec)/
|
27
|
+
#
|
25
28
|
# @return [Regexp, nil]
|
26
29
|
attr_accessor :app_dirs_pattern
|
27
30
|
|
@@ -187,6 +190,11 @@ module Sentry
|
|
187
190
|
# @return [String]
|
188
191
|
attr_accessor :project_root
|
189
192
|
|
193
|
+
# Whether to strip the load path while constructing the backtrace frame filename.
|
194
|
+
# Defaults to true.
|
195
|
+
# @return [Boolean]
|
196
|
+
attr_accessor :strip_backtrace_load_path
|
197
|
+
|
190
198
|
# Insert sentry-trace to outgoing requests' headers
|
191
199
|
# @return [Boolean]
|
192
200
|
attr_accessor :propagate_traces
|
@@ -302,18 +310,18 @@ module Sentry
|
|
302
310
|
# But they are mostly considered as noise and should be ignored by default
|
303
311
|
# Please see https://github.com/getsentry/sentry-ruby/pull/2026 for more information
|
304
312
|
PUMA_IGNORE_DEFAULT = [
|
305
|
-
|
306
|
-
|
307
|
-
|
313
|
+
"Puma::MiniSSL::SSLError",
|
314
|
+
"Puma::HttpParserError",
|
315
|
+
"Puma::HttpParserError501"
|
308
316
|
].freeze
|
309
317
|
|
310
318
|
# Most of these errors generate 4XX responses. In general, Sentry clients
|
311
319
|
# only automatically report 5xx responses.
|
312
320
|
IGNORE_DEFAULT = [
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
321
|
+
"Mongoid::Errors::DocumentNotFound",
|
322
|
+
"Rack::QueryParser::InvalidParameterError",
|
323
|
+
"Rack::QueryParser::ParameterTypeError",
|
324
|
+
"Sinatra::NotFound"
|
317
325
|
].freeze
|
318
326
|
|
319
327
|
RACK_ENV_WHITELIST_DEFAULT = %w[
|
@@ -335,6 +343,8 @@ module Sentry
|
|
335
343
|
|
336
344
|
DEFAULT_PATCHES = %i[redis puma http].freeze
|
337
345
|
|
346
|
+
APP_DIRS_PATTERN = /(bin|exe|app|config|lib|test|spec)/.freeze
|
347
|
+
|
338
348
|
class << self
|
339
349
|
# Post initialization callbacks are called at the end of initialization process
|
340
350
|
# allowing extending the configuration of sentry-ruby by multiple extensions
|
@@ -349,11 +359,12 @@ module Sentry
|
|
349
359
|
end
|
350
360
|
|
351
361
|
def initialize
|
352
|
-
self.app_dirs_pattern =
|
353
|
-
self.debug =
|
362
|
+
self.app_dirs_pattern = APP_DIRS_PATTERN
|
363
|
+
self.debug = Sentry::Utils::EnvHelper.env_to_bool(ENV["SENTRY_DEBUG"])
|
354
364
|
self.background_worker_threads = (processor_count / 2.0).ceil
|
355
365
|
self.background_worker_max_queue = BackgroundWorker::DEFAULT_MAX_QUEUE
|
356
366
|
self.backtrace_cleanup_callback = nil
|
367
|
+
self.strip_backtrace_load_path = true
|
357
368
|
self.max_breadcrumbs = BreadcrumbBuffer::DEFAULT_SIZE
|
358
369
|
self.breadcrumbs_logger = []
|
359
370
|
self.context_lines = 3
|
@@ -377,7 +388,10 @@ module Sentry
|
|
377
388
|
self.enable_backpressure_handling = false
|
378
389
|
self.trusted_proxies = []
|
379
390
|
self.dsn = ENV['SENTRY_DSN']
|
380
|
-
|
391
|
+
|
392
|
+
spotlight_env = ENV['SENTRY_SPOTLIGHT']
|
393
|
+
spotlight_bool = Sentry::Utils::EnvHelper.env_to_bool(spotlight_env, strict: true)
|
394
|
+
self.spotlight = spotlight_bool.nil? ? (spotlight_env || false) : spotlight_bool
|
381
395
|
self.server_name = server_name_from_env
|
382
396
|
self.instrumenter = :sentry
|
383
397
|
self.trace_propagation_targets = [PROPAGATION_TARGETS_MATCH_ALL]
|
@@ -555,7 +569,8 @@ module Sentry
|
|
555
569
|
app_dirs_pattern: @app_dirs_pattern,
|
556
570
|
linecache: @linecache,
|
557
571
|
context_lines: @context_lines,
|
558
|
-
backtrace_cleanup_callback: @backtrace_cleanup_callback
|
572
|
+
backtrace_cleanup_callback: @backtrace_cleanup_callback,
|
573
|
+
strip_backtrace_load_path: @strip_backtrace_load_path
|
559
574
|
)
|
560
575
|
end
|
561
576
|
|
@@ -632,12 +647,12 @@ module Sentry
|
|
632
647
|
end
|
633
648
|
|
634
649
|
def environment_from_env
|
635
|
-
ENV[
|
650
|
+
ENV["SENTRY_CURRENT_ENV"] || ENV["SENTRY_ENVIRONMENT"] || ENV["RAILS_ENV"] || ENV["RACK_ENV"] || "development"
|
636
651
|
end
|
637
652
|
|
638
653
|
def server_name_from_env
|
639
654
|
if running_on_heroku?
|
640
|
-
ENV[
|
655
|
+
ENV["DYNO"]
|
641
656
|
else
|
642
657
|
# Try to resolve the hostname to an FQDN, but fall back to whatever
|
643
658
|
# the load name is.
|
data/lib/sentry/dsn.rb
CHANGED
@@ -4,7 +4,7 @@ require "uri"
|
|
4
4
|
|
5
5
|
module Sentry
|
6
6
|
class DSN
|
7
|
-
PORT_MAP = {
|
7
|
+
PORT_MAP = { "http" => 80, "https" => 443 }.freeze
|
8
8
|
REQUIRED_ATTRIBUTES = %w[host path public_key project_id].freeze
|
9
9
|
|
10
10
|
attr_reader :scheme, :secret_key, :port, *REQUIRED_ATTRIBUTES
|
@@ -13,7 +13,7 @@ module Sentry
|
|
13
13
|
@raw_value = dsn_string
|
14
14
|
|
15
15
|
uri = URI.parse(dsn_string)
|
16
|
-
uri_path = uri.path.split(
|
16
|
+
uri_path = uri.path.split("/")
|
17
17
|
|
18
18
|
if uri.user
|
19
19
|
# DSN-style string
|
@@ -25,7 +25,7 @@ module Sentry
|
|
25
25
|
@scheme = uri.scheme
|
26
26
|
@host = uri.host
|
27
27
|
@port = uri.port if uri.port
|
28
|
-
@path = uri_path.join(
|
28
|
+
@path = uri_path.join("/")
|
29
29
|
end
|
30
30
|
|
31
31
|
def valid?
|
data/lib/sentry/envelope.rb
CHANGED
@@ -15,19 +15,19 @@ module Sentry
|
|
15
15
|
end
|
16
16
|
|
17
17
|
def type
|
18
|
-
@headers[:type] ||
|
18
|
+
@headers[:type] || "event"
|
19
19
|
end
|
20
20
|
|
21
21
|
# rate limits and client reports use the data_category rather than envelope item type
|
22
22
|
def self.data_category(type)
|
23
23
|
case type
|
24
|
-
when
|
25
|
-
when
|
26
|
-
when
|
27
|
-
when
|
28
|
-
when
|
29
|
-
when
|
30
|
-
else
|
24
|
+
when "session", "attachment", "transaction", "profile", "span" then type
|
25
|
+
when "sessions" then "session"
|
26
|
+
when "check_in" then "monitor"
|
27
|
+
when "statsd", "metric_meta" then "metric_bucket"
|
28
|
+
when "event" then "error"
|
29
|
+
when "client_report" then "internal"
|
30
|
+
else "default"
|
31
31
|
end
|
32
32
|
end
|
33
33
|
|
data/lib/sentry/event.rb
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
6
|
-
require
|
7
|
-
require
|
8
|
-
require
|
9
|
-
require
|
3
|
+
require "socket"
|
4
|
+
require "securerandom"
|
5
|
+
require "sentry/interface"
|
6
|
+
require "sentry/backtrace"
|
7
|
+
require "sentry/utils/real_ip"
|
8
|
+
require "sentry/utils/request_id"
|
9
|
+
require "sentry/utils/custom_inspection"
|
10
10
|
|
11
11
|
module Sentry
|
12
12
|
# This is an abstract class that defines the shared attributes of an event.
|
data/lib/sentry/graphql.rb
CHANGED
@@ -4,6 +4,6 @@ Sentry.register_patch(:graphql) do |config|
|
|
4
4
|
if defined?(::GraphQL::Schema) && defined?(::GraphQL::Tracing::SentryTrace) && ::GraphQL::Schema.respond_to?(:trace_with)
|
5
5
|
::GraphQL::Schema.trace_with(::GraphQL::Tracing::SentryTrace, set_transaction_name: true)
|
6
6
|
else
|
7
|
-
config.logger.warn(Sentry::LOGGER_PROGNAME) {
|
7
|
+
config.logger.warn(Sentry::LOGGER_PROGNAME) { "You tried to enable the GraphQL integration but no GraphQL gem was detected. Make sure you have the `graphql` gem (>= 2.2.6) in your Gemfile." }
|
8
8
|
end
|
9
9
|
end
|
data/lib/sentry/hub.rb
CHANGED
@@ -73,7 +73,13 @@ module Sentry
|
|
73
73
|
end
|
74
74
|
|
75
75
|
def pop_scope
|
76
|
-
@stack.
|
76
|
+
if @stack.size > 1
|
77
|
+
@stack.pop
|
78
|
+
else
|
79
|
+
# We never want to enter a situation where we have no scope and no client
|
80
|
+
client = current_client
|
81
|
+
@stack = [Layer.new(client, Scope.new)]
|
82
|
+
end
|
77
83
|
end
|
78
84
|
|
79
85
|
def start_transaction(transaction: nil, custom_sampling_context: {}, instrumenter: :sentry, **options)
|
@@ -214,6 +220,7 @@ module Sentry
|
|
214
220
|
end
|
215
221
|
|
216
222
|
def add_breadcrumb(breadcrumb, hint: {})
|
223
|
+
return unless current_client
|
217
224
|
return unless configuration.enabled_in_current_env?
|
218
225
|
|
219
226
|
if before_breadcrumb = current_client.configuration.before_breadcrumb
|
@@ -59,7 +59,7 @@ module Sentry
|
|
59
59
|
self.query_string = request.query_string
|
60
60
|
end
|
61
61
|
|
62
|
-
self.url = request.scheme && request.url.split(
|
62
|
+
self.url = request.scheme && request.url.split("?").first
|
63
63
|
self.method = request.request_method
|
64
64
|
|
65
65
|
self.headers = filter_and_format_headers(env, send_default_pii)
|
@@ -85,14 +85,14 @@ module Sentry
|
|
85
85
|
env.each_with_object({}) do |(key, value), memo|
|
86
86
|
begin
|
87
87
|
key = key.to_s # rack env can contain symbols
|
88
|
-
next memo[
|
88
|
+
next memo["X-Request-Id"] ||= Utils::RequestId.read_from(env) if Utils::RequestId::REQUEST_ID_HEADERS.include?(key)
|
89
89
|
next if is_server_protocol?(key, value, env["SERVER_PROTOCOL"])
|
90
90
|
next if is_skippable_header?(key)
|
91
91
|
next if key == "HTTP_AUTHORIZATION" && !send_default_pii
|
92
92
|
|
93
93
|
# Rack stores headers as HTTP_WHAT_EVER, we need What-Ever
|
94
94
|
key = key.sub(/^HTTP_/, "")
|
95
|
-
key = key.split(
|
95
|
+
key = key.split("_").map(&:capitalize).join("-")
|
96
96
|
|
97
97
|
memo[key] = Utils::EncodingHelper.encode_to_utf_8(value.to_s)
|
98
98
|
rescue StandardError => e
|
@@ -108,7 +108,7 @@ module Sentry
|
|
108
108
|
def is_skippable_header?(key)
|
109
109
|
key.upcase != key || # lower-case envs aren't real http headers
|
110
110
|
key == "HTTP_COOKIE" || # Cookies don't go here, they go somewhere else
|
111
|
-
!(key.start_with?(
|
111
|
+
!(key.start_with?("HTTP_") || CONTENT_HEADERS.include?(key))
|
112
112
|
end
|
113
113
|
|
114
114
|
# In versions < 3, Rack adds in an incorrect HTTP_VERSION key, which causes downstream
|
@@ -120,7 +120,7 @@ module Sentry
|
|
120
120
|
rack_version = Gem::Version.new(::Rack.release)
|
121
121
|
return false if rack_version >= Gem::Version.new("3.0")
|
122
122
|
|
123
|
-
key ==
|
123
|
+
key == "HTTP_VERSION" && value == protocol_version
|
124
124
|
end
|
125
125
|
|
126
126
|
def filter_and_format_env(env, rack_env_whitelist)
|
@@ -26,7 +26,7 @@ module Sentry
|
|
26
26
|
|
27
27
|
@value = Utils::EncodingHelper.encode_to_utf_8(exception_message.byteslice(0..Event::MAX_MESSAGE_SIZE_IN_BYTES))
|
28
28
|
|
29
|
-
@module = exception.class.to_s.split(
|
29
|
+
@module = exception.class.to_s.split("::")[0...-1].join("::")
|
30
30
|
@thread_id = Thread.current.object_id
|
31
31
|
@stacktrace = stacktrace
|
32
32
|
@mechanism = mechanism
|
@@ -27,8 +27,9 @@ module Sentry
|
|
27
27
|
attr_accessor :abs_path, :context_line, :function, :in_app, :filename,
|
28
28
|
:lineno, :module, :pre_context, :post_context, :vars
|
29
29
|
|
30
|
-
def initialize(project_root, line)
|
30
|
+
def initialize(project_root, line, strip_backtrace_load_path = true)
|
31
31
|
@project_root = project_root
|
32
|
+
@strip_backtrace_load_path = strip_backtrace_load_path
|
32
33
|
|
33
34
|
@abs_path = line.file
|
34
35
|
@function = line.method if line.method
|
@@ -44,6 +45,7 @@ module Sentry
|
|
44
45
|
|
45
46
|
def compute_filename
|
46
47
|
return if abs_path.nil?
|
48
|
+
return abs_path unless @strip_backtrace_load_path
|
47
49
|
|
48
50
|
prefix =
|
49
51
|
if under_project_root? && in_app
|
@@ -17,22 +17,35 @@ module Sentry
|
|
17
17
|
# @return [Proc, nil]
|
18
18
|
attr_reader :backtrace_cleanup_callback
|
19
19
|
|
20
|
+
# @return [Boolean]
|
21
|
+
attr_reader :strip_backtrace_load_path
|
22
|
+
|
20
23
|
# @param project_root [String]
|
21
24
|
# @param app_dirs_pattern [Regexp, nil]
|
22
25
|
# @param linecache [LineCache]
|
23
26
|
# @param context_lines [Integer, nil]
|
24
27
|
# @param backtrace_cleanup_callback [Proc, nil]
|
28
|
+
# @param strip_backtrace_load_path [Boolean]
|
25
29
|
# @see Configuration#project_root
|
26
30
|
# @see Configuration#app_dirs_pattern
|
27
31
|
# @see Configuration#linecache
|
28
32
|
# @see Configuration#context_lines
|
29
33
|
# @see Configuration#backtrace_cleanup_callback
|
30
|
-
|
34
|
+
# @see Configuration#strip_backtrace_load_path
|
35
|
+
def initialize(
|
36
|
+
project_root:,
|
37
|
+
app_dirs_pattern:,
|
38
|
+
linecache:,
|
39
|
+
context_lines:,
|
40
|
+
backtrace_cleanup_callback: nil,
|
41
|
+
strip_backtrace_load_path: true
|
42
|
+
)
|
31
43
|
@project_root = project_root
|
32
44
|
@app_dirs_pattern = app_dirs_pattern
|
33
45
|
@linecache = linecache
|
34
46
|
@context_lines = context_lines
|
35
47
|
@backtrace_cleanup_callback = backtrace_cleanup_callback
|
48
|
+
@strip_backtrace_load_path = strip_backtrace_load_path
|
36
49
|
end
|
37
50
|
|
38
51
|
# Generates a StacktraceInterface with the given backtrace.
|
@@ -73,7 +86,7 @@ module Sentry
|
|
73
86
|
private
|
74
87
|
|
75
88
|
def convert_parsed_line_into_frame(line)
|
76
|
-
frame = StacktraceInterface::Frame.new(project_root, line)
|
89
|
+
frame = StacktraceInterface::Frame.new(project_root, line, strip_backtrace_load_path)
|
77
90
|
frame.set_context(linecache, context_lines) if context_lines
|
78
91
|
frame
|
79
92
|
end
|
data/lib/sentry/logger.rb
CHANGED
@@ -41,8 +41,8 @@ module Sentry
|
|
41
41
|
@stacktrace_builder = configuration.stacktrace_builder
|
42
42
|
|
43
43
|
@default_tags = {}
|
44
|
-
@default_tags[
|
45
|
-
@default_tags[
|
44
|
+
@default_tags["release"] = configuration.release if configuration.release
|
45
|
+
@default_tags["environment"] = configuration.environment if configuration.environment
|
46
46
|
|
47
47
|
@mutex = Mutex.new
|
48
48
|
|
@@ -59,7 +59,7 @@ module Sentry
|
|
59
59
|
def add(type,
|
60
60
|
key,
|
61
61
|
value,
|
62
|
-
unit:
|
62
|
+
unit: "none",
|
63
63
|
tags: {},
|
64
64
|
timestamp: nil,
|
65
65
|
stacklevel: nil)
|
@@ -98,7 +98,7 @@ module Sentry
|
|
98
98
|
unless flushable_buckets.empty?
|
99
99
|
payload = serialize_buckets(flushable_buckets)
|
100
100
|
envelope.add_item(
|
101
|
-
{ type:
|
101
|
+
{ type: "statsd", length: payload.bytesize },
|
102
102
|
payload
|
103
103
|
)
|
104
104
|
end
|
@@ -107,7 +107,7 @@ module Sentry
|
|
107
107
|
code_locations.each do |timestamp, locations|
|
108
108
|
payload = serialize_locations(timestamp, locations)
|
109
109
|
envelope.add_item(
|
110
|
-
{ type:
|
110
|
+
{ type: "metric_meta", content_type: "application/json" },
|
111
111
|
payload
|
112
112
|
)
|
113
113
|
end
|
@@ -161,8 +161,8 @@ module Sentry
|
|
161
161
|
buckets.map do |timestamp, timestamp_buckets|
|
162
162
|
timestamp_buckets.map do |metric_key, metric|
|
163
163
|
type, key, unit, tags = metric_key
|
164
|
-
values = metric.serialize.join(
|
165
|
-
sanitized_tags = tags.map { |k, v| "#{sanitize_tag_key(k)}:#{sanitize_tag_value(v)}" }.join(
|
164
|
+
values = metric.serialize.join(":")
|
165
|
+
sanitized_tags = tags.map { |k, v| "#{sanitize_tag_key(k)}:#{sanitize_tag_value(v)}" }.join(",")
|
166
166
|
|
167
167
|
"#{sanitize_key(key)}@#{sanitize_unit(unit)}:#{values}|#{type}|\##{sanitized_tags}|T#{timestamp}"
|
168
168
|
end
|
@@ -175,22 +175,22 @@ module Sentry
|
|
175
175
|
mri = "#{type}:#{sanitize_key(key)}@#{sanitize_unit(unit)}"
|
176
176
|
|
177
177
|
# note this needs to be an array but it really doesn't serve a purpose right now
|
178
|
-
[mri, [location.merge(type:
|
178
|
+
[mri, [location.merge(type: "location")]]
|
179
179
|
end.to_h
|
180
180
|
|
181
181
|
{ timestamp: timestamp, mapping: mapping }
|
182
182
|
end
|
183
183
|
|
184
184
|
def sanitize_key(key)
|
185
|
-
key.gsub(KEY_SANITIZATION_REGEX,
|
185
|
+
key.gsub(KEY_SANITIZATION_REGEX, "_")
|
186
186
|
end
|
187
187
|
|
188
188
|
def sanitize_unit(unit)
|
189
|
-
unit.gsub(UNIT_SANITIZATION_REGEX,
|
189
|
+
unit.gsub(UNIT_SANITIZATION_REGEX, "")
|
190
190
|
end
|
191
191
|
|
192
192
|
def sanitize_tag_key(key)
|
193
|
-
key.gsub(TAG_KEY_SANITIZATION_REGEX,
|
193
|
+
key.gsub(TAG_KEY_SANITIZATION_REGEX, "")
|
194
194
|
end
|
195
195
|
|
196
196
|
def sanitize_tag_value(value)
|
@@ -209,7 +209,7 @@ module Sentry
|
|
209
209
|
updated_tags = @default_tags.merge(tags)
|
210
210
|
|
211
211
|
transaction_name = get_transaction_name
|
212
|
-
updated_tags[
|
212
|
+
updated_tags["transaction"] = transaction_name if transaction_name
|
213
213
|
|
214
214
|
updated_tags
|
215
215
|
end
|
data/lib/sentry/metrics.rb
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
6
|
-
require
|
7
|
-
require
|
8
|
-
require
|
9
|
-
require
|
3
|
+
require "sentry/metrics/metric"
|
4
|
+
require "sentry/metrics/counter_metric"
|
5
|
+
require "sentry/metrics/distribution_metric"
|
6
|
+
require "sentry/metrics/gauge_metric"
|
7
|
+
require "sentry/metrics/set_metric"
|
8
|
+
require "sentry/metrics/timing"
|
9
|
+
require "sentry/metrics/aggregator"
|
10
10
|
|
11
11
|
module Sentry
|
12
12
|
module Metrics
|
@@ -14,32 +14,32 @@ module Sentry
|
|
14
14
|
INFORMATION_UNITS = %w[bit byte kilobyte kibibyte megabyte mebibyte gigabyte gibibyte terabyte tebibyte petabyte pebibyte exabyte exbibyte]
|
15
15
|
FRACTIONAL_UNITS = %w[ratio percent]
|
16
16
|
|
17
|
-
OP_NAME =
|
18
|
-
SPAN_ORIGIN =
|
17
|
+
OP_NAME = "metric.timing"
|
18
|
+
SPAN_ORIGIN = "auto.metric.timing"
|
19
19
|
|
20
20
|
class << self
|
21
|
-
def increment(key, value = 1.0, unit:
|
21
|
+
def increment(key, value = 1.0, unit: "none", tags: {}, timestamp: nil)
|
22
22
|
Sentry.metrics_aggregator&.add(:c, key, value, unit: unit, tags: tags, timestamp: timestamp)
|
23
23
|
end
|
24
24
|
|
25
|
-
def distribution(key, value, unit:
|
25
|
+
def distribution(key, value, unit: "none", tags: {}, timestamp: nil)
|
26
26
|
Sentry.metrics_aggregator&.add(:d, key, value, unit: unit, tags: tags, timestamp: timestamp)
|
27
27
|
end
|
28
28
|
|
29
|
-
def set(key, value, unit:
|
29
|
+
def set(key, value, unit: "none", tags: {}, timestamp: nil)
|
30
30
|
Sentry.metrics_aggregator&.add(:s, key, value, unit: unit, tags: tags, timestamp: timestamp)
|
31
31
|
end
|
32
32
|
|
33
|
-
def gauge(key, value, unit:
|
33
|
+
def gauge(key, value, unit: "none", tags: {}, timestamp: nil)
|
34
34
|
Sentry.metrics_aggregator&.add(:g, key, value, unit: unit, tags: tags, timestamp: timestamp)
|
35
35
|
end
|
36
36
|
|
37
|
-
def timing(key, unit:
|
37
|
+
def timing(key, unit: "second", tags: {}, timestamp: nil, &block)
|
38
38
|
return unless block_given?
|
39
39
|
return yield unless DURATION_UNITS.include?(unit)
|
40
40
|
|
41
41
|
result, value = Sentry.with_child_span(op: OP_NAME, description: key, origin: SPAN_ORIGIN) do |span|
|
42
|
-
tags.each { |k, v| span.set_tag(k, v.is_a?(Array) ? v.join(
|
42
|
+
tags.each { |k, v| span.set_tag(k, v.is_a?(Array) ? v.join(", ") : v.to_s) } if span
|
43
43
|
|
44
44
|
start = Timing.send(unit.to_sym)
|
45
45
|
result = yield
|
data/lib/sentry/net/http.rb
CHANGED
@@ -66,7 +66,7 @@ module Sentry
|
|
66
66
|
# IPv6 url could look like '::1/path', and that won't parse without
|
67
67
|
# wrapping it in square brackets.
|
68
68
|
hostname = address =~ Resolv::IPv6::Regex ? "[#{address}]" : address
|
69
|
-
uri = req.uri || URI.parse("#{use_ssl? ? 'https' : 'http'}://#{hostname}#{req.path}")
|
69
|
+
uri = req.uri || URI.parse(URI::DEFAULT_PARSER.escape("#{use_ssl? ? 'https' : 'http'}://#{hostname}#{req.path}"))
|
70
70
|
url = "#{uri.scheme}://#{uri.host}#{uri.path}" rescue uri.to_s
|
71
71
|
|
72
72
|
result = { method: req.method, url: url }
|
data/lib/sentry/profiler.rb
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
3
|
+
require "securerandom"
|
4
4
|
|
5
5
|
module Sentry
|
6
6
|
class Profiler
|
7
|
-
VERSION =
|
8
|
-
PLATFORM =
|
7
|
+
VERSION = "1"
|
8
|
+
PLATFORM = "ruby"
|
9
9
|
# 101 Hz in microseconds
|
10
10
|
DEFAULT_INTERVAL = 1e6 / 101
|
11
11
|
MICRO_TO_NANO_SECONDS = 1e3
|
@@ -14,14 +14,14 @@ module Sentry
|
|
14
14
|
attr_reader :sampled, :started, :event_id
|
15
15
|
|
16
16
|
def initialize(configuration)
|
17
|
-
@event_id = SecureRandom.uuid.delete(
|
17
|
+
@event_id = SecureRandom.uuid.delete("-")
|
18
18
|
@started = false
|
19
19
|
@sampled = nil
|
20
20
|
|
21
21
|
@profiling_enabled = defined?(StackProf) && configuration.profiling_enabled?
|
22
22
|
@profiles_sample_rate = configuration.profiles_sample_rate
|
23
23
|
@project_root = configuration.project_root
|
24
|
-
@app_dirs_pattern = configuration.app_dirs_pattern
|
24
|
+
@app_dirs_pattern = configuration.app_dirs_pattern
|
25
25
|
@in_app_pattern = Regexp.new("^(#{@project_root}/)?#{@app_dirs_pattern}")
|
26
26
|
end
|
27
27
|
|
@@ -33,7 +33,7 @@ module Sentry
|
|
33
33
|
raw: true,
|
34
34
|
aggregate: false)
|
35
35
|
|
36
|
-
@started ? log(
|
36
|
+
@started ? log("Started") : log("Not started since running elsewhere")
|
37
37
|
end
|
38
38
|
|
39
39
|
def stop
|
@@ -41,7 +41,7 @@ module Sentry
|
|
41
41
|
return unless @started
|
42
42
|
|
43
43
|
StackProf.stop
|
44
|
-
log(
|
44
|
+
log("Stopped")
|
45
45
|
end
|
46
46
|
|
47
47
|
# Sets initial sampling decision of the profile.
|
@@ -54,14 +54,14 @@ module Sentry
|
|
54
54
|
|
55
55
|
unless transaction_sampled
|
56
56
|
@sampled = false
|
57
|
-
log(
|
57
|
+
log("Discarding profile because transaction not sampled")
|
58
58
|
return
|
59
59
|
end
|
60
60
|
|
61
61
|
case @profiles_sample_rate
|
62
62
|
when 0.0
|
63
63
|
@sampled = false
|
64
|
-
log(
|
64
|
+
log("Discarding profile because sample_rate is 0")
|
65
65
|
return
|
66
66
|
when 1.0
|
67
67
|
@sampled = true
|
@@ -70,7 +70,7 @@ module Sentry
|
|
70
70
|
@sampled = Random.rand < @profiles_sample_rate
|
71
71
|
end
|
72
72
|
|
73
|
-
log(
|
73
|
+
log("Discarding profile due to sampling decision") unless @sampled
|
74
74
|
end
|
75
75
|
|
76
76
|
def to_hash
|
@@ -90,13 +90,12 @@ module Sentry
|
|
90
90
|
|
91
91
|
frame_map = {}
|
92
92
|
|
93
|
-
frames = results[:frames].
|
94
|
-
frame_id, frame_data = frame
|
95
|
-
|
93
|
+
frames = results[:frames].map.with_index do |(frame_id, frame_data), idx|
|
96
94
|
# need to map over stackprof frame ids to ours
|
97
95
|
frame_map[frame_id] = idx
|
98
96
|
|
99
97
|
file_path = frame_data[:file]
|
98
|
+
lineno = frame_data[:line]
|
100
99
|
in_app = in_app?(file_path)
|
101
100
|
filename = compute_filename(file_path, in_app)
|
102
101
|
function, mod = split_module(frame_data[:name])
|
@@ -109,7 +108,7 @@ module Sentry
|
|
109
108
|
}
|
110
109
|
|
111
110
|
frame_hash[:module] = mod if mod
|
112
|
-
frame_hash[:lineno] =
|
111
|
+
frame_hash[:lineno] = lineno if lineno && lineno >= 0
|
113
112
|
|
114
113
|
frame_hash
|
115
114
|
end
|
@@ -130,7 +129,7 @@ module Sentry
|
|
130
129
|
num_seen << results[:raw][idx + len]
|
131
130
|
idx += len + 1
|
132
131
|
|
133
|
-
log(
|
132
|
+
log("Unknown frame in stack") if stack.size != len
|
134
133
|
end
|
135
134
|
|
136
135
|
idx = 0
|
@@ -155,16 +154,16 @@ module Sentry
|
|
155
154
|
# Till then, on multi-threaded servers like puma, we will get frames from other active threads when the one
|
156
155
|
# we're profiling is idle/sleeping/waiting for IO etc.
|
157
156
|
# https://bugs.ruby-lang.org/issues/10602
|
158
|
-
thread_id:
|
157
|
+
thread_id: "0",
|
159
158
|
elapsed_since_start_ns: elapsed_since_start_ns.to_s
|
160
159
|
}
|
161
160
|
end
|
162
161
|
end
|
163
162
|
|
164
|
-
log(
|
163
|
+
log("Some samples thrown away") if samples.size != results[:samples]
|
165
164
|
|
166
165
|
if samples.size <= MIN_SAMPLES_REQUIRED
|
167
|
-
log(
|
166
|
+
log("Not enough samples, discarding profiler")
|
168
167
|
record_lost_event(:insufficient_data)
|
169
168
|
return {}
|
170
169
|
end
|
@@ -219,7 +218,7 @@ module Sentry
|
|
219
218
|
|
220
219
|
def split_module(name)
|
221
220
|
# last module plus class/instance method
|
222
|
-
i = name.rindex(
|
221
|
+
i = name.rindex("::")
|
223
222
|
function = i ? name[(i + 2)..-1] : name
|
224
223
|
mod = i ? name[0...i] : nil
|
225
224
|
|
@@ -227,7 +226,7 @@ module Sentry
|
|
227
226
|
end
|
228
227
|
|
229
228
|
def record_lost_event(reason)
|
230
|
-
Sentry.get_current_client&.transport&.record_lost_event(reason,
|
229
|
+
Sentry.get_current_client&.transport&.record_lost_event(reason, "profile")
|
231
230
|
end
|
232
231
|
end
|
233
232
|
end
|
data/lib/sentry/rack.rb
CHANGED
data/lib/sentry/rake.rb
CHANGED
@@ -8,10 +8,10 @@ module Sentry
|
|
8
8
|
module Application
|
9
9
|
# @api private
|
10
10
|
def display_error_message(ex)
|
11
|
-
mechanism = Sentry::Mechanism.new(type:
|
11
|
+
mechanism = Sentry::Mechanism.new(type: "rake", handled: false)
|
12
12
|
|
13
13
|
Sentry.capture_exception(ex, hint: { mechanism: mechanism }) do |scope|
|
14
|
-
task_name = top_level_tasks.join(
|
14
|
+
task_name = top_level_tasks.join(" ")
|
15
15
|
scope.set_transaction_name(task_name, source: :task)
|
16
16
|
scope.set_tag("rake_task", task_name)
|
17
17
|
end if Sentry.initialized? && !Sentry.configuration.skip_rake_integration
|
@@ -13,12 +13,12 @@ module Sentry
|
|
13
13
|
|
14
14
|
def detect_release_from_heroku(running_on_heroku)
|
15
15
|
return unless running_on_heroku
|
16
|
-
ENV[
|
16
|
+
ENV["HEROKU_SLUG_COMMIT"]
|
17
17
|
end
|
18
18
|
|
19
19
|
def detect_release_from_capistrano(project_root)
|
20
|
-
revision_file = File.join(project_root,
|
21
|
-
revision_log = File.join(project_root,
|
20
|
+
revision_file = File.join(project_root, "REVISION")
|
21
|
+
revision_log = File.join(project_root, "..", "revisions.log")
|
22
22
|
|
23
23
|
if File.exist?(revision_file)
|
24
24
|
File.read(revision_file).strip
|
@@ -32,7 +32,7 @@ module Sentry
|
|
32
32
|
end
|
33
33
|
|
34
34
|
def detect_release_from_env
|
35
|
-
ENV[
|
35
|
+
ENV["SENTRY_RELEASE"]
|
36
36
|
end
|
37
37
|
end
|
38
38
|
end
|
data/lib/sentry/scope.rb
CHANGED
@@ -62,6 +62,7 @@ module Sentry
|
|
62
62
|
|
63
63
|
if span
|
64
64
|
event.contexts[:trace] ||= span.get_trace_context
|
65
|
+
event.dynamic_sampling_context ||= span.get_dynamic_sampling_context
|
65
66
|
else
|
66
67
|
event.contexts[:trace] ||= propagation_context.get_trace_context
|
67
68
|
event.dynamic_sampling_context ||= propagation_context.get_dynamic_sampling_context
|
data/lib/sentry/span.rb
CHANGED
@@ -160,6 +160,12 @@ module Sentry
|
|
160
160
|
transaction.get_baggage&.serialize
|
161
161
|
end
|
162
162
|
|
163
|
+
# Returns the Dynamic Sampling Context from the transaction baggage.
|
164
|
+
# @return [Hash, nil]
|
165
|
+
def get_dynamic_sampling_context
|
166
|
+
transaction.get_baggage&.dynamic_sampling_context
|
167
|
+
end
|
168
|
+
|
163
169
|
# @return [Hash]
|
164
170
|
def to_hash
|
165
171
|
hash = {
|
data/lib/sentry/test_helper.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
module Sentry
|
2
2
|
module TestHelper
|
3
|
-
DUMMY_DSN =
|
3
|
+
DUMMY_DSN = "http://12345:67890@sentry.localdomain/sentry/42"
|
4
4
|
|
5
5
|
# Alters the existing SDK configuration with test-suitable options. Mainly:
|
6
6
|
# - Sets a dummy DSN instead of `nil` or an actual DSN.
|
data/lib/sentry/transaction.rb
CHANGED
@@ -265,8 +265,8 @@ module Sentry
|
|
265
265
|
else
|
266
266
|
is_backpressure = Sentry.backpressure_monitor&.downsample_factor&.positive?
|
267
267
|
reason = is_backpressure ? :backpressure : :sample_rate
|
268
|
-
hub.current_client.transport.record_lost_event(reason,
|
269
|
-
hub.current_client.transport.record_lost_event(reason,
|
268
|
+
hub.current_client.transport.record_lost_event(reason, "transaction")
|
269
|
+
hub.current_client.transport.record_lost_event(reason, "span")
|
270
270
|
end
|
271
271
|
end
|
272
272
|
|
@@ -7,7 +7,7 @@ module Sentry
|
|
7
7
|
class HTTPTransport < Transport
|
8
8
|
GZIP_ENCODING = "gzip"
|
9
9
|
GZIP_THRESHOLD = 1024 * 30
|
10
|
-
CONTENT_TYPE =
|
10
|
+
CONTENT_TYPE = "application/x-sentry-envelope"
|
11
11
|
|
12
12
|
DEFAULT_DELAY = 60
|
13
13
|
RETRY_AFTER_HEADER = "retry-after"
|
@@ -38,13 +38,13 @@ module Sentry
|
|
38
38
|
end
|
39
39
|
|
40
40
|
headers = {
|
41
|
-
|
42
|
-
|
43
|
-
|
41
|
+
"Content-Type" => CONTENT_TYPE,
|
42
|
+
"Content-Encoding" => encoding,
|
43
|
+
"User-Agent" => USER_AGENT
|
44
44
|
}
|
45
45
|
|
46
46
|
auth_header = generate_auth_header
|
47
|
-
headers[
|
47
|
+
headers["X-Sentry-Auth"] = auth_header if auth_header
|
48
48
|
|
49
49
|
response = conn.start do |http|
|
50
50
|
request = ::Net::HTTP::Post.new(endpoint, headers)
|
@@ -60,7 +60,7 @@ module Sentry
|
|
60
60
|
else
|
61
61
|
error_info = "the server responded with status #{response.code}"
|
62
62
|
error_info += "\nbody: #{response.body}"
|
63
|
-
error_info += " Error in headers is: #{response['x-sentry-error']}" if response[
|
63
|
+
error_info += " Error in headers is: #{response['x-sentry-error']}" if response["x-sentry-error"]
|
64
64
|
|
65
65
|
raise Sentry::ExternalError, error_info
|
66
66
|
end
|
@@ -78,13 +78,13 @@ module Sentry
|
|
78
78
|
|
79
79
|
now = Sentry.utc_now.to_i
|
80
80
|
fields = {
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
81
|
+
"sentry_version" => PROTOCOL_VERSION,
|
82
|
+
"sentry_client" => USER_AGENT,
|
83
|
+
"sentry_timestamp" => now,
|
84
|
+
"sentry_key" => @dsn.public_key
|
85
85
|
}
|
86
|
-
fields[
|
87
|
-
|
86
|
+
fields["sentry_secret"] = @dsn.secret_key if @dsn.secret_key
|
87
|
+
"Sentry " + fields.map { |key, value| "#{key}=#{value}" }.join(", ")
|
88
88
|
end
|
89
89
|
|
90
90
|
def conn
|
data/lib/sentry/transport.rb
CHANGED
@@ -5,7 +5,7 @@ require "sentry/envelope"
|
|
5
5
|
|
6
6
|
module Sentry
|
7
7
|
class Transport
|
8
|
-
PROTOCOL_VERSION =
|
8
|
+
PROTOCOL_VERSION = "7"
|
9
9
|
USER_AGENT = "sentry-ruby/#{Sentry::VERSION}"
|
10
10
|
CLIENT_REPORT_INTERVAL = 30
|
11
11
|
|
@@ -134,13 +134,13 @@ module Sentry
|
|
134
134
|
envelope = Envelope.new(envelope_headers)
|
135
135
|
|
136
136
|
envelope.add_item(
|
137
|
-
{ type: item_type, content_type:
|
137
|
+
{ type: item_type, content_type: "application/json" },
|
138
138
|
event_payload
|
139
139
|
)
|
140
140
|
|
141
141
|
if event.is_a?(TransactionEvent) && event.profile
|
142
142
|
envelope.add_item(
|
143
|
-
{ type:
|
143
|
+
{ type: "profile", content_type: "application/json" },
|
144
144
|
event.profile
|
145
145
|
)
|
146
146
|
end
|
@@ -185,7 +185,7 @@ module Sentry
|
|
185
185
|
{ reason: reason, category: category, quantity: val }
|
186
186
|
end
|
187
187
|
|
188
|
-
item_header = { type:
|
188
|
+
item_header = { type: "client_report" }
|
189
189
|
item_payload = {
|
190
190
|
timestamp: Sentry.utc_now.iso8601,
|
191
191
|
discarded_events: discarded_events_hash
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Sentry
|
4
|
+
module Utils
|
5
|
+
module EnvHelper
|
6
|
+
TRUTHY_ENV_VALUES = %w[t true yes y 1 on].freeze
|
7
|
+
FALSY_ENV_VALUES = %w[f false no n 0 off].freeze
|
8
|
+
|
9
|
+
def self.env_to_bool(value, strict: false)
|
10
|
+
value = value.to_s
|
11
|
+
normalized = value.downcase
|
12
|
+
|
13
|
+
return false if FALSY_ENV_VALUES.include?(normalized)
|
14
|
+
|
15
|
+
return true if TRUTHY_ENV_VALUES.include?(normalized)
|
16
|
+
|
17
|
+
strict ? nil : !(value.nil? || value.empty?)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
data/lib/sentry/utils/real_ip.rb
CHANGED
data/lib/sentry/version.rb
CHANGED
data/lib/sentry-ruby.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sentry-ruby-core
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 5.
|
4
|
+
version: 5.20.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sentry Team
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-09-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: sentry-ruby
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - '='
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 5.
|
19
|
+
version: 5.20.0
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - '='
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 5.
|
26
|
+
version: 5.20.0
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: concurrent-ruby
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -129,6 +129,7 @@ files:
|
|
129
129
|
- lib/sentry/utils/argument_checking_helper.rb
|
130
130
|
- lib/sentry/utils/custom_inspection.rb
|
131
131
|
- lib/sentry/utils/encoding_helper.rb
|
132
|
+
- lib/sentry/utils/env_helper.rb
|
132
133
|
- lib/sentry/utils/exception_cause_chain.rb
|
133
134
|
- lib/sentry/utils/http_tracing.rb
|
134
135
|
- lib/sentry/utils/logging_helper.rb
|
@@ -159,7 +160,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
159
160
|
- !ruby/object:Gem::Version
|
160
161
|
version: '0'
|
161
162
|
requirements: []
|
162
|
-
rubygems_version: 3.5.
|
163
|
+
rubygems_version: 3.5.16
|
163
164
|
signing_key:
|
164
165
|
specification_version: 4
|
165
166
|
summary: A gem that provides a client interface for the Sentry error logger
|