sentry-ruby 5.26.0 → 5.28.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/Gemfile +1 -3
- data/lib/sentry/client.rb +3 -2
- data/lib/sentry/configuration.rb +54 -6
- data/lib/sentry/debug_structured_logger.rb +94 -0
- data/lib/sentry/dsn.rb +32 -0
- data/lib/sentry/graphql.rb +1 -1
- data/lib/sentry/hub.rb +3 -1
- data/lib/sentry/log_event.rb +18 -5
- data/lib/sentry/metrics/configuration.rb +12 -2
- data/lib/sentry/metrics.rb +12 -0
- data/lib/sentry/propagation_context.rb +55 -18
- data/lib/sentry/std_lib_logger.rb +6 -1
- data/lib/sentry/test_helper.rb +22 -0
- data/lib/sentry/transaction.rb +29 -1
- data/lib/sentry/transport/debug_transport.rb +70 -0
- data/lib/sentry/transport/dummy_transport.rb +1 -0
- data/lib/sentry/transport/http_transport.rb +9 -5
- data/lib/sentry/transport.rb +1 -0
- data/lib/sentry/utils/sample_rand.rb +97 -0
- data/lib/sentry/version.rb +1 -1
- data/lib/sentry-ruby.rb +8 -4
- metadata +10 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0a048bcf517a994eb2577cc8f9630e7771f0dbe9a80cff9a93e1d4d68186db49
|
4
|
+
data.tar.gz: 97d7489043a301a9fdfed0d9ca31d38156c5082a0a2e43e83592d86e9eba939d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 17466b57a83b0292b367b43dcf7c22128ae93822ab7481f3afb3459c52842c917c57d3b2274a3e377fcfd089ab10efa1e12bdd7401a991018387fb026e5fe014
|
7
|
+
data.tar.gz: cbea0779676929f05597e84da1e4cd7cc25fa0a6d383c8d08e6e26112e9bbe90403d14fdebaa8164a18d5db894ec286d22e5611da217a7bd5efb9279119ace33
|
data/Gemfile
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
source "https://rubygems.org"
|
4
4
|
git_source(:github) { |name| "https://github.com/#{name}.git" }
|
5
5
|
|
6
|
-
eval_gemfile "../Gemfile"
|
6
|
+
eval_gemfile "../Gemfile.dev"
|
7
7
|
|
8
8
|
gem "sentry-ruby", path: "./"
|
9
9
|
|
@@ -11,8 +11,6 @@ rack_version = ENV["RACK_VERSION"]
|
|
11
11
|
rack_version = "3.0.0" if rack_version.nil?
|
12
12
|
gem "rack", "~> #{Gem::Version.new(rack_version)}" unless rack_version == "0"
|
13
13
|
|
14
|
-
gem "ostruct" if RUBY_VERSION >= "3.4"
|
15
|
-
|
16
14
|
redis_rb_version = ENV.fetch("REDIS_RB_VERSION", "5.0")
|
17
15
|
gem "redis", "~> #{redis_rb_version}"
|
18
16
|
|
data/lib/sentry/client.rb
CHANGED
@@ -195,9 +195,10 @@ module Sentry
|
|
195
195
|
def event_from_log(message, level:, **options)
|
196
196
|
return unless configuration.sending_allowed?
|
197
197
|
|
198
|
-
attributes = options.reject { |k, _| k == :level || k == :severity }
|
198
|
+
attributes = options.reject { |k, _| k == :level || k == :severity || k == :origin }
|
199
|
+
origin = options[:origin]
|
199
200
|
|
200
|
-
LogEvent.new(level: level, body: message, attributes: attributes)
|
201
|
+
LogEvent.new(level: level, body: message, attributes: attributes, origin: origin)
|
201
202
|
end
|
202
203
|
|
203
204
|
# Initializes an Event object with the given Transaction object.
|
data/lib/sentry/configuration.rb
CHANGED
@@ -13,6 +13,7 @@ require "sentry/metrics/configuration"
|
|
13
13
|
require "sentry/linecache"
|
14
14
|
require "sentry/interfaces/stacktrace_builder"
|
15
15
|
require "sentry/logger"
|
16
|
+
require "sentry/structured_logger"
|
16
17
|
require "sentry/log_event_buffer"
|
17
18
|
|
18
19
|
module Sentry
|
@@ -196,6 +197,11 @@ module Sentry
|
|
196
197
|
# @return [Logger]
|
197
198
|
attr_accessor :sdk_logger
|
198
199
|
|
200
|
+
# File path for DebugTransport to log events to. If not set, defaults to a temporary file.
|
201
|
+
# This is useful for debugging and testing purposes.
|
202
|
+
# @return [String, nil]
|
203
|
+
attr_accessor :sdk_debug_transport_log_file
|
204
|
+
|
199
205
|
# @deprecated Use {#sdk_logger=} instead.
|
200
206
|
def logger=(logger)
|
201
207
|
warn "[sentry] `config.logger=` is deprecated. Please use `config.sdk_logger=` instead."
|
@@ -289,6 +295,10 @@ module Sentry
|
|
289
295
|
# @return [Boolean]
|
290
296
|
attr_accessor :enable_logs
|
291
297
|
|
298
|
+
# Structured logging configuration.
|
299
|
+
# @return [StructuredLoggingConfiguration]
|
300
|
+
attr_reader :structured_logging
|
301
|
+
|
292
302
|
# Easier way to use performance tracing
|
293
303
|
# If set to true, will set traces_sample_rate to 1.0
|
294
304
|
# @deprecated It will be removed in the next major release.
|
@@ -390,7 +400,23 @@ module Sentry
|
|
390
400
|
|
391
401
|
# allow extensions to add their hooks to the Configuration class
|
392
402
|
def add_post_initialization_callback(&block)
|
393
|
-
|
403
|
+
callbacks[:initialize][:after] << block
|
404
|
+
end
|
405
|
+
|
406
|
+
def before(event, &block)
|
407
|
+
callbacks[event.to_sym][:before] << block
|
408
|
+
end
|
409
|
+
|
410
|
+
def after(event, &block)
|
411
|
+
callbacks[event.to_sym][:after] << block
|
412
|
+
end
|
413
|
+
|
414
|
+
# @!visibility private
|
415
|
+
def callbacks
|
416
|
+
@callbacks ||= {
|
417
|
+
initialize: { before: [], after: [] },
|
418
|
+
configured: { before: [], after: [] }
|
419
|
+
}
|
394
420
|
end
|
395
421
|
|
396
422
|
def validations
|
@@ -434,6 +460,8 @@ module Sentry
|
|
434
460
|
validate :profiles_sample_rate, optional: true, type: :numeric
|
435
461
|
|
436
462
|
def initialize
|
463
|
+
run_callbacks(:before, :initialize)
|
464
|
+
|
437
465
|
self.app_dirs_pattern = APP_DIRS_PATTERN
|
438
466
|
self.debug = Sentry::Utils::EnvHelper.env_to_bool(ENV["SENTRY_DEBUG"])
|
439
467
|
self.background_worker_threads = (processor_count / 2.0).ceil
|
@@ -484,12 +512,17 @@ module Sentry
|
|
484
512
|
|
485
513
|
@transport = Transport::Configuration.new
|
486
514
|
@cron = Cron::Configuration.new
|
487
|
-
@metrics = Metrics::Configuration.new
|
515
|
+
@metrics = Metrics::Configuration.new(self.sdk_logger)
|
516
|
+
@structured_logging = StructuredLoggingConfiguration.new
|
488
517
|
@gem_specs = Hash[Gem::Specification.map { |spec| [spec.name, spec.version.to_s] }] if Gem::Specification.respond_to?(:map)
|
489
518
|
|
490
|
-
run_post_initialization_callbacks
|
491
|
-
|
492
519
|
self.max_log_events = LogEventBuffer::DEFAULT_MAX_EVENTS
|
520
|
+
|
521
|
+
run_callbacks(:after, :initialize)
|
522
|
+
|
523
|
+
yield(self) if block_given?
|
524
|
+
|
525
|
+
run_callbacks(:after, :configured)
|
493
526
|
end
|
494
527
|
|
495
528
|
def validate
|
@@ -773,8 +806,8 @@ module Sentry
|
|
773
806
|
File.directory?("/etc/heroku") && !ENV["CI"]
|
774
807
|
end
|
775
808
|
|
776
|
-
def
|
777
|
-
self.class.
|
809
|
+
def run_callbacks(hook, event)
|
810
|
+
self.class.callbacks[event][hook].each do |hook|
|
778
811
|
instance_eval(&hook)
|
779
812
|
end
|
780
813
|
end
|
@@ -784,4 +817,19 @@ module Sentry
|
|
784
817
|
available_processor_count || Concurrent.processor_count
|
785
818
|
end
|
786
819
|
end
|
820
|
+
|
821
|
+
class StructuredLoggingConfiguration
|
822
|
+
# File path for DebugStructuredLogger to log events to
|
823
|
+
# @return [String, Pathname, nil]
|
824
|
+
attr_accessor :file_path
|
825
|
+
|
826
|
+
# The class to use as a structured logger.
|
827
|
+
# @return [Class]
|
828
|
+
attr_accessor :logger_class
|
829
|
+
|
830
|
+
def initialize
|
831
|
+
@file_path = nil
|
832
|
+
@logger_class = Sentry::StructuredLogger
|
833
|
+
end
|
834
|
+
end
|
787
835
|
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "json"
|
4
|
+
require "fileutils"
|
5
|
+
require "pathname"
|
6
|
+
require "delegate"
|
7
|
+
|
8
|
+
module Sentry
|
9
|
+
# DebugStructuredLogger is a logger that captures structured log events to a file for debugging purposes.
|
10
|
+
#
|
11
|
+
# It can optionally also send log events to Sentry via the normal structured logger if logging
|
12
|
+
# is enabled.
|
13
|
+
class DebugStructuredLogger < SimpleDelegator
|
14
|
+
DEFAULT_LOG_FILE_PATH = File.join("log", "sentry_debug_logs.log")
|
15
|
+
|
16
|
+
attr_reader :log_file, :backend
|
17
|
+
|
18
|
+
def initialize(configuration)
|
19
|
+
@log_file = initialize_log_file(
|
20
|
+
configuration.structured_logging.file_path || DEFAULT_LOG_FILE_PATH
|
21
|
+
)
|
22
|
+
@backend = initialize_backend(configuration)
|
23
|
+
|
24
|
+
super(@backend)
|
25
|
+
end
|
26
|
+
|
27
|
+
# Override all log level methods to capture events
|
28
|
+
%i[trace debug info warn error fatal].each do |level|
|
29
|
+
define_method(level) do |message, parameters = [], **attributes|
|
30
|
+
log_event = capture_log_event(level, message, parameters, **attributes)
|
31
|
+
backend.public_send(level, message, parameters, **attributes)
|
32
|
+
log_event
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def log(level, message, parameters:, **attributes)
|
37
|
+
log_event = capture_log_event(level, message, parameters, **attributes)
|
38
|
+
backend.log(level, message, parameters: parameters, **attributes)
|
39
|
+
log_event
|
40
|
+
end
|
41
|
+
|
42
|
+
def capture_log_event(level, message, parameters, **attributes)
|
43
|
+
log_event_json = {
|
44
|
+
timestamp: Time.now.utc.iso8601,
|
45
|
+
level: level.to_s,
|
46
|
+
message: message,
|
47
|
+
parameters: parameters,
|
48
|
+
attributes: attributes
|
49
|
+
}
|
50
|
+
|
51
|
+
File.open(log_file, "a") { |file| file << JSON.dump(log_event_json) << "\n" }
|
52
|
+
log_event_json
|
53
|
+
end
|
54
|
+
|
55
|
+
def logged_events
|
56
|
+
File.readlines(log_file).map do |line|
|
57
|
+
JSON.parse(line)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def clear
|
62
|
+
File.write(log_file, "")
|
63
|
+
if backend.respond_to?(:config)
|
64
|
+
backend.config.sdk_logger.debug("DebugStructuredLogger: Cleared events from #{log_file}")
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
private
|
69
|
+
|
70
|
+
def initialize_backend(configuration)
|
71
|
+
if configuration.enable_logs
|
72
|
+
StructuredLogger.new(configuration)
|
73
|
+
else
|
74
|
+
# Create a no-op logger if logging is disabled
|
75
|
+
NoOpLogger.new
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def initialize_log_file(log_file_path)
|
80
|
+
log_file = Pathname(log_file_path)
|
81
|
+
|
82
|
+
FileUtils.mkdir_p(log_file.dirname) unless log_file.dirname.exist?
|
83
|
+
|
84
|
+
log_file
|
85
|
+
end
|
86
|
+
|
87
|
+
# No-op logger for when structured logging is disabled
|
88
|
+
class NoOpLogger
|
89
|
+
%i[trace debug info warn error fatal log].each do |method|
|
90
|
+
define_method(method) { |*args, **kwargs| nil }
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
data/lib/sentry/dsn.rb
CHANGED
@@ -1,11 +1,15 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "uri"
|
4
|
+
require "ipaddr"
|
5
|
+
require "resolv"
|
4
6
|
|
5
7
|
module Sentry
|
6
8
|
class DSN
|
7
9
|
PORT_MAP = { "http" => 80, "https" => 443 }.freeze
|
8
10
|
REQUIRED_ATTRIBUTES = %w[host path public_key project_id].freeze
|
11
|
+
LOCALHOST_NAMES = %w[localhost 127.0.0.1 ::1 [::1]].freeze
|
12
|
+
LOCALHOST_PATTERN = /\.local(host|domain)?$/i
|
9
13
|
|
10
14
|
attr_reader :scheme, :secret_key, :port, *REQUIRED_ATTRIBUTES
|
11
15
|
|
@@ -49,5 +53,33 @@ module Sentry
|
|
49
53
|
def envelope_endpoint
|
50
54
|
"#{path}/api/#{project_id}/envelope/"
|
51
55
|
end
|
56
|
+
|
57
|
+
def local?
|
58
|
+
@local ||= (localhost? || private_ip? || resolved_ips_private?)
|
59
|
+
end
|
60
|
+
|
61
|
+
def localhost?
|
62
|
+
LOCALHOST_NAMES.include?(host.downcase) || LOCALHOST_PATTERN.match?(host)
|
63
|
+
end
|
64
|
+
|
65
|
+
def private_ip?
|
66
|
+
@private_ip ||= begin
|
67
|
+
begin
|
68
|
+
IPAddr.new(host).private?
|
69
|
+
rescue IPAddr::InvalidAddressError
|
70
|
+
false
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def resolved_ips_private?
|
76
|
+
@resolved_ips_private ||= begin
|
77
|
+
begin
|
78
|
+
Resolv.getaddresses(host).any? { |ip| IPAddr.new(ip).private? }
|
79
|
+
rescue Resolv::ResolvError, IPAddr::InvalidAddressError
|
80
|
+
false
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
52
84
|
end
|
53
85
|
end
|
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.
|
7
|
+
config.sdk_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
@@ -120,7 +120,8 @@ module Sentry
|
|
120
120
|
|
121
121
|
sampling_context = {
|
122
122
|
transaction_context: transaction.to_hash,
|
123
|
-
parent_sampled: transaction.parent_sampled
|
123
|
+
parent_sampled: transaction.parent_sampled,
|
124
|
+
parent_sample_rate: transaction.parent_sample_rate
|
124
125
|
}
|
125
126
|
|
126
127
|
sampling_context.merge!(custom_sampling_context)
|
@@ -357,6 +358,7 @@ module Sentry
|
|
357
358
|
parent_span_id: propagation_context.parent_span_id,
|
358
359
|
parent_sampled: propagation_context.parent_sampled,
|
359
360
|
baggage: propagation_context.baggage,
|
361
|
+
sample_rand: propagation_context.sample_rand,
|
360
362
|
**options
|
361
363
|
)
|
362
364
|
end
|
data/lib/sentry/log_event.rb
CHANGED
@@ -29,9 +29,12 @@ module Sentry
|
|
29
29
|
"sentry.address" => :server_name,
|
30
30
|
"sentry.sdk.name" => :sdk_name,
|
31
31
|
"sentry.sdk.version" => :sdk_version,
|
32
|
-
"sentry.message.template" => :template
|
32
|
+
"sentry.message.template" => :template,
|
33
|
+
"sentry.origin" => :origin
|
33
34
|
}
|
34
35
|
|
36
|
+
PARAMETER_PREFIX = "sentry.message.parameter"
|
37
|
+
|
35
38
|
USER_ATTRIBUTES = {
|
36
39
|
"user.id" => :user_id,
|
37
40
|
"user.name" => :user_username,
|
@@ -40,9 +43,9 @@ module Sentry
|
|
40
43
|
|
41
44
|
LEVELS = %i[trace debug info warn error fatal].freeze
|
42
45
|
|
43
|
-
attr_accessor :level, :body, :template, :attributes, :user
|
46
|
+
attr_accessor :level, :body, :template, :attributes, :user, :origin
|
44
47
|
|
45
|
-
attr_reader :configuration, *SERIALIZEABLE_ATTRIBUTES
|
48
|
+
attr_reader :configuration, *(SERIALIZEABLE_ATTRIBUTES - %i[level body attributes])
|
46
49
|
|
47
50
|
SERIALIZERS = %i[
|
48
51
|
attributes
|
@@ -51,6 +54,7 @@ module Sentry
|
|
51
54
|
parent_span_id
|
52
55
|
sdk_name
|
53
56
|
sdk_version
|
57
|
+
template
|
54
58
|
timestamp
|
55
59
|
trace_id
|
56
60
|
user_id
|
@@ -79,6 +83,7 @@ module Sentry
|
|
79
83
|
@template = @body if is_template?
|
80
84
|
@attributes = options[:attributes] || DEFAULT_ATTRIBUTES
|
81
85
|
@user = options[:user] || {}
|
86
|
+
@origin = options[:origin]
|
82
87
|
@contexts = {}
|
83
88
|
end
|
84
89
|
|
@@ -146,6 +151,10 @@ module Sentry
|
|
146
151
|
user[:email]
|
147
152
|
end
|
148
153
|
|
154
|
+
def serialize_template
|
155
|
+
template if has_parameters?
|
156
|
+
end
|
157
|
+
|
149
158
|
def serialize_attributes
|
150
159
|
hash = {}
|
151
160
|
|
@@ -185,11 +194,11 @@ module Sentry
|
|
185
194
|
|
186
195
|
if parameters.is_a?(Hash)
|
187
196
|
parameters.each do |key, value|
|
188
|
-
attributes["
|
197
|
+
attributes["#{PARAMETER_PREFIX}.#{key}"] = value
|
189
198
|
end
|
190
199
|
else
|
191
200
|
parameters.each_with_index do |param, index|
|
192
|
-
attributes["
|
201
|
+
attributes["#{PARAMETER_PREFIX}.#{index}"] = param
|
193
202
|
end
|
194
203
|
end
|
195
204
|
end
|
@@ -202,5 +211,9 @@ module Sentry
|
|
202
211
|
def is_template?
|
203
212
|
body.include?("%s") || TOKEN_REGEXP.match?(body)
|
204
213
|
end
|
214
|
+
|
215
|
+
def has_parameters?
|
216
|
+
attributes.keys.any? { |key| key.start_with?(PARAMETER_PREFIX) }
|
217
|
+
end
|
205
218
|
end
|
206
219
|
end
|
@@ -4,12 +4,13 @@ module Sentry
|
|
4
4
|
module Metrics
|
5
5
|
class Configuration
|
6
6
|
include ArgumentCheckingHelper
|
7
|
+
include LoggingHelper
|
7
8
|
|
8
9
|
# Enable metrics usage.
|
9
10
|
# Starts a new {Sentry::Metrics::Aggregator} instance to aggregate metrics
|
10
11
|
# and a thread to aggregate flush every 5 seconds.
|
11
12
|
# @return [Boolean]
|
12
|
-
|
13
|
+
attr_reader :enabled
|
13
14
|
|
14
15
|
# Enable code location reporting.
|
15
16
|
# Will be sent once per day.
|
@@ -32,11 +33,20 @@ module Sentry
|
|
32
33
|
# @return [Proc, nil]
|
33
34
|
attr_reader :before_emit
|
34
35
|
|
35
|
-
def initialize
|
36
|
+
def initialize(sdk_logger)
|
37
|
+
@sdk_logger = sdk_logger
|
36
38
|
@enabled = false
|
37
39
|
@enable_code_locations = true
|
38
40
|
end
|
39
41
|
|
42
|
+
def enabled=(value)
|
43
|
+
log_warn <<~MSG
|
44
|
+
`config.metrics` is now deprecated and will be removed in the next major.
|
45
|
+
MSG
|
46
|
+
|
47
|
+
@enabled = value
|
48
|
+
end
|
49
|
+
|
40
50
|
def before_emit=(value)
|
41
51
|
check_callable!("metrics.before_emit", value)
|
42
52
|
|
data/lib/sentry/metrics.rb
CHANGED
@@ -19,22 +19,28 @@ module Sentry
|
|
19
19
|
|
20
20
|
class << self
|
21
21
|
def increment(key, value = 1.0, unit: "none", tags: {}, timestamp: nil)
|
22
|
+
log_deprecation
|
22
23
|
Sentry.metrics_aggregator&.add(:c, key, value, unit: unit, tags: tags, timestamp: timestamp)
|
23
24
|
end
|
24
25
|
|
25
26
|
def distribution(key, value, unit: "none", tags: {}, timestamp: nil)
|
27
|
+
log_deprecation
|
26
28
|
Sentry.metrics_aggregator&.add(:d, key, value, unit: unit, tags: tags, timestamp: timestamp)
|
27
29
|
end
|
28
30
|
|
29
31
|
def set(key, value, unit: "none", tags: {}, timestamp: nil)
|
32
|
+
log_deprecation
|
30
33
|
Sentry.metrics_aggregator&.add(:s, key, value, unit: unit, tags: tags, timestamp: timestamp)
|
31
34
|
end
|
32
35
|
|
33
36
|
def gauge(key, value, unit: "none", tags: {}, timestamp: nil)
|
37
|
+
log_deprecation
|
34
38
|
Sentry.metrics_aggregator&.add(:g, key, value, unit: unit, tags: tags, timestamp: timestamp)
|
35
39
|
end
|
36
40
|
|
37
41
|
def timing(key, unit: "second", tags: {}, timestamp: nil, &block)
|
42
|
+
log_deprecation
|
43
|
+
|
38
44
|
return unless block_given?
|
39
45
|
return yield unless DURATION_UNITS.include?(unit)
|
40
46
|
|
@@ -51,6 +57,12 @@ module Sentry
|
|
51
57
|
Sentry.metrics_aggregator&.add(:d, key, value, unit: unit, tags: tags, timestamp: timestamp)
|
52
58
|
result
|
53
59
|
end
|
60
|
+
|
61
|
+
def log_deprecation
|
62
|
+
Sentry.sdk_logger.warn(LOGGER_PROGNAME) do
|
63
|
+
"`Sentry::Metrics` is now deprecated and will be removed in the next major."
|
64
|
+
end
|
65
|
+
end
|
54
66
|
end
|
55
67
|
end
|
56
68
|
end
|
@@ -3,15 +3,14 @@
|
|
3
3
|
require "securerandom"
|
4
4
|
require "sentry/baggage"
|
5
5
|
require "sentry/utils/uuid"
|
6
|
+
require "sentry/utils/sample_rand"
|
6
7
|
|
7
8
|
module Sentry
|
8
9
|
class PropagationContext
|
9
10
|
SENTRY_TRACE_REGEXP = Regexp.new(
|
10
|
-
"
|
11
|
-
"([0-9a-f]{32})?" + # trace_id
|
11
|
+
"\\A([0-9a-f]{32})?" + # trace_id
|
12
12
|
"-?([0-9a-f]{16})?" + # span_id
|
13
|
-
"-?([01])
|
14
|
-
"[ \t]*$" # whitespace
|
13
|
+
"-?([01])?\\z" # sampled
|
15
14
|
)
|
16
15
|
|
17
16
|
# An uuid that can be used to identify a trace.
|
@@ -33,6 +32,53 @@ module Sentry
|
|
33
32
|
# Please use the #get_baggage method for interfacing outside this class.
|
34
33
|
# @return [Baggage, nil]
|
35
34
|
attr_reader :baggage
|
35
|
+
# The propagated random value used for sampling decisions.
|
36
|
+
# @return [Float, nil]
|
37
|
+
attr_reader :sample_rand
|
38
|
+
|
39
|
+
# Extract the trace_id, parent_span_id and parent_sampled values from a sentry-trace header.
|
40
|
+
#
|
41
|
+
# @param sentry_trace [String] the sentry-trace header value from the previous transaction.
|
42
|
+
# @return [Array, nil]
|
43
|
+
def self.extract_sentry_trace(sentry_trace)
|
44
|
+
value = sentry_trace.to_s.strip
|
45
|
+
return if value.empty?
|
46
|
+
|
47
|
+
match = SENTRY_TRACE_REGEXP.match(value)
|
48
|
+
return if match.nil?
|
49
|
+
|
50
|
+
trace_id, parent_span_id, sampled_flag = match[1..3]
|
51
|
+
parent_sampled = sampled_flag.nil? ? nil : sampled_flag != "0"
|
52
|
+
|
53
|
+
[trace_id, parent_span_id, parent_sampled]
|
54
|
+
end
|
55
|
+
|
56
|
+
def self.extract_sample_rand_from_baggage(baggage, trace_id = nil)
|
57
|
+
return unless baggage&.items
|
58
|
+
|
59
|
+
sample_rand_str = baggage.items["sample_rand"]
|
60
|
+
return unless sample_rand_str
|
61
|
+
|
62
|
+
generator = Utils::SampleRand.new(trace_id: trace_id)
|
63
|
+
generator.generate_from_value(sample_rand_str)
|
64
|
+
end
|
65
|
+
|
66
|
+
def self.generate_sample_rand(baggage, trace_id, parent_sampled)
|
67
|
+
generator = Utils::SampleRand.new(trace_id: trace_id)
|
68
|
+
|
69
|
+
if baggage&.items && !parent_sampled.nil?
|
70
|
+
sample_rate_str = baggage.items["sample_rate"]
|
71
|
+
sample_rate = sample_rate_str&.to_f
|
72
|
+
|
73
|
+
if sample_rate && !parent_sampled.nil?
|
74
|
+
generator.generate_from_sampling_decision(parent_sampled, sample_rate)
|
75
|
+
else
|
76
|
+
generator.generate_from_trace_id
|
77
|
+
end
|
78
|
+
else
|
79
|
+
generator.generate_from_trace_id
|
80
|
+
end
|
81
|
+
end
|
36
82
|
|
37
83
|
def initialize(scope, env = nil)
|
38
84
|
@scope = scope
|
@@ -40,6 +86,7 @@ module Sentry
|
|
40
86
|
@parent_sampled = nil
|
41
87
|
@baggage = nil
|
42
88
|
@incoming_trace = false
|
89
|
+
@sample_rand = nil
|
43
90
|
|
44
91
|
if env
|
45
92
|
sentry_trace_header = env["HTTP_SENTRY_TRACE"] || env[SENTRY_TRACE_HEADER_NAME]
|
@@ -61,6 +108,8 @@ module Sentry
|
|
61
108
|
Baggage.new({})
|
62
109
|
end
|
63
110
|
|
111
|
+
@sample_rand = self.class.extract_sample_rand_from_baggage(@baggage, @trace_id)
|
112
|
+
|
64
113
|
@baggage.freeze!
|
65
114
|
@incoming_trace = true
|
66
115
|
end
|
@@ -69,20 +118,7 @@ module Sentry
|
|
69
118
|
|
70
119
|
@trace_id ||= Utils.uuid
|
71
120
|
@span_id = Utils.uuid.slice(0, 16)
|
72
|
-
|
73
|
-
|
74
|
-
# Extract the trace_id, parent_span_id and parent_sampled values from a sentry-trace header.
|
75
|
-
#
|
76
|
-
# @param sentry_trace [String] the sentry-trace header value from the previous transaction.
|
77
|
-
# @return [Array, nil]
|
78
|
-
def self.extract_sentry_trace(sentry_trace)
|
79
|
-
match = SENTRY_TRACE_REGEXP.match(sentry_trace)
|
80
|
-
return nil if match.nil?
|
81
|
-
|
82
|
-
trace_id, parent_span_id, sampled_flag = match[1..3]
|
83
|
-
parent_sampled = sampled_flag.nil? ? nil : sampled_flag != "0"
|
84
|
-
|
85
|
-
[trace_id, parent_span_id, parent_sampled]
|
121
|
+
@sample_rand ||= self.class.generate_sample_rand(@baggage, @trace_id, @parent_sampled)
|
86
122
|
end
|
87
123
|
|
88
124
|
# Returns the trace context that can be used to embed in an Event.
|
@@ -123,6 +159,7 @@ module Sentry
|
|
123
159
|
|
124
160
|
items = {
|
125
161
|
"trace_id" => trace_id,
|
162
|
+
"sample_rand" => Utils::SampleRand.format(@sample_rand),
|
126
163
|
"environment" => configuration.environment,
|
127
164
|
"release" => configuration.release,
|
128
165
|
"public_key" => configuration.dsn&.public_key
|
@@ -12,11 +12,16 @@ module Sentry
|
|
12
12
|
4 => :fatal
|
13
13
|
}.freeze
|
14
14
|
|
15
|
+
ORIGIN = "auto.logger.ruby.std_logger"
|
16
|
+
|
15
17
|
def add(severity, message = nil, progname = nil, &block)
|
16
18
|
result = super
|
17
19
|
|
18
20
|
return unless Sentry.initialized? && Sentry.get_current_hub
|
19
21
|
|
22
|
+
# Only process logs that meet or exceed the logger's level
|
23
|
+
return result if severity < level
|
24
|
+
|
20
25
|
# exclude sentry SDK logs -- to prevent recursive log action,
|
21
26
|
# do not process internal logs again
|
22
27
|
if message.nil? && progname != Sentry::Logger::PROGNAME
|
@@ -32,7 +37,7 @@ module Sentry
|
|
32
37
|
message = message.to_s.strip
|
33
38
|
|
34
39
|
if !message.nil? && message != Sentry::Logger::PROGNAME && method = SEVERITY_MAP[severity]
|
35
|
-
Sentry.logger.send(method, message)
|
40
|
+
Sentry.logger.send(method, message, origin: ORIGIN)
|
36
41
|
end
|
37
42
|
end
|
38
43
|
|
data/lib/sentry/test_helper.rb
CHANGED
@@ -2,8 +2,13 @@
|
|
2
2
|
|
3
3
|
module Sentry
|
4
4
|
module TestHelper
|
5
|
+
module_function
|
6
|
+
|
5
7
|
DUMMY_DSN = "http://12345:67890@sentry.localdomain/sentry/42"
|
6
8
|
|
9
|
+
# Not really real, but it will be resolved as a non-local for testing needs
|
10
|
+
REAL_DSN = "https://user:pass@getsentry.io/project/42"
|
11
|
+
|
7
12
|
# Alters the existing SDK configuration with test-suitable options. Mainly:
|
8
13
|
# - Sets a dummy DSN instead of `nil` or an actual DSN.
|
9
14
|
# - Sets the transport to DummyTransport, which allows easy access to the captured events.
|
@@ -46,6 +51,8 @@ module Sentry
|
|
46
51
|
def teardown_sentry_test
|
47
52
|
return unless Sentry.initialized?
|
48
53
|
|
54
|
+
clear_sentry_events
|
55
|
+
|
49
56
|
# pop testing layer created by `setup_sentry_test`
|
50
57
|
# but keep the base layer to avoid nil-pointer errors
|
51
58
|
# TODO: find a way to notify users if they somehow popped the test layer before calling this method
|
@@ -55,6 +62,21 @@ module Sentry
|
|
55
62
|
Sentry::Scope.global_event_processors.clear
|
56
63
|
end
|
57
64
|
|
65
|
+
def clear_sentry_events
|
66
|
+
return unless Sentry.initialized?
|
67
|
+
|
68
|
+
sentry_transport.clear if sentry_transport.respond_to?(:clear)
|
69
|
+
|
70
|
+
if Sentry.configuration.enable_logs && sentry_logger.respond_to?(:clear)
|
71
|
+
sentry_logger.clear
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
# @return [Sentry::StructuredLogger, Sentry::DebugStructuredLogger]
|
76
|
+
def sentry_logger
|
77
|
+
Sentry.logger
|
78
|
+
end
|
79
|
+
|
58
80
|
# @return [Transport]
|
59
81
|
def sentry_transport
|
60
82
|
Sentry.get_current_client.transport
|
data/lib/sentry/transaction.rb
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
require "sentry/baggage"
|
4
4
|
require "sentry/profiler"
|
5
|
+
require "sentry/utils/sample_rand"
|
5
6
|
require "sentry/propagation_context"
|
6
7
|
|
7
8
|
module Sentry
|
@@ -57,12 +58,17 @@ module Sentry
|
|
57
58
|
# @return [Profiler]
|
58
59
|
attr_reader :profiler
|
59
60
|
|
61
|
+
# Sample rand value generated from trace_id
|
62
|
+
# @return [String]
|
63
|
+
attr_reader :sample_rand
|
64
|
+
|
60
65
|
def initialize(
|
61
66
|
hub:,
|
62
67
|
name: nil,
|
63
68
|
source: :custom,
|
64
69
|
parent_sampled: nil,
|
65
70
|
baggage: nil,
|
71
|
+
sample_rand: nil,
|
66
72
|
**options
|
67
73
|
)
|
68
74
|
super(transaction: self, **options)
|
@@ -82,12 +88,18 @@ module Sentry
|
|
82
88
|
@effective_sample_rate = nil
|
83
89
|
@contexts = {}
|
84
90
|
@measurements = {}
|
91
|
+
@sample_rand = sample_rand
|
85
92
|
|
86
93
|
unless @hub.profiler_running?
|
87
94
|
@profiler = @configuration.profiler_class.new(@configuration)
|
88
95
|
end
|
89
96
|
|
90
97
|
init_span_recorder
|
98
|
+
|
99
|
+
unless @sample_rand
|
100
|
+
generator = Utils::SampleRand.new(trace_id: @trace_id)
|
101
|
+
@sample_rand = generator.generate_from_trace_id
|
102
|
+
end
|
91
103
|
end
|
92
104
|
|
93
105
|
# @deprecated use Sentry.continue_trace instead.
|
@@ -123,12 +135,15 @@ module Sentry
|
|
123
135
|
|
124
136
|
baggage.freeze!
|
125
137
|
|
138
|
+
sample_rand = extract_sample_rand_from_baggage(baggage, trace_id, parent_sampled)
|
139
|
+
|
126
140
|
new(
|
127
141
|
trace_id: trace_id,
|
128
142
|
parent_span_id: parent_span_id,
|
129
143
|
parent_sampled: parent_sampled,
|
130
144
|
hub: hub,
|
131
145
|
baggage: baggage,
|
146
|
+
sample_rand: sample_rand,
|
132
147
|
**options
|
133
148
|
)
|
134
149
|
end
|
@@ -139,6 +154,11 @@ module Sentry
|
|
139
154
|
PropagationContext.extract_sentry_trace(sentry_trace)
|
140
155
|
end
|
141
156
|
|
157
|
+
def self.extract_sample_rand_from_baggage(baggage, trace_id, parent_sampled)
|
158
|
+
PropagationContext.extract_sample_rand_from_baggage(baggage, trace_id) ||
|
159
|
+
PropagationContext.generate_sample_rand(baggage, trace_id, parent_sampled)
|
160
|
+
end
|
161
|
+
|
142
162
|
# @return [Hash]
|
143
163
|
def to_hash
|
144
164
|
hash = super
|
@@ -153,6 +173,13 @@ module Sentry
|
|
153
173
|
hash
|
154
174
|
end
|
155
175
|
|
176
|
+
def parent_sample_rate
|
177
|
+
return unless @baggage&.items
|
178
|
+
|
179
|
+
sample_rate_str = @baggage.items["sample_rate"]
|
180
|
+
sample_rate_str&.to_f
|
181
|
+
end
|
182
|
+
|
156
183
|
# @return [Transaction]
|
157
184
|
def deep_dup
|
158
185
|
copy = super
|
@@ -225,7 +252,7 @@ module Sentry
|
|
225
252
|
@effective_sample_rate /= 2**factor
|
226
253
|
end
|
227
254
|
|
228
|
-
@sampled =
|
255
|
+
@sampled = @sample_rand < @effective_sample_rate
|
229
256
|
end
|
230
257
|
|
231
258
|
if @sampled
|
@@ -331,6 +358,7 @@ module Sentry
|
|
331
358
|
items = {
|
332
359
|
"trace_id" => trace_id,
|
333
360
|
"sample_rate" => effective_sample_rate&.to_s,
|
361
|
+
"sample_rand" => Utils::SampleRand.format(@sample_rand),
|
334
362
|
"sampled" => sampled&.to_s,
|
335
363
|
"environment" => @environment,
|
336
364
|
"release" => @release,
|
@@ -0,0 +1,70 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "json"
|
4
|
+
require "fileutils"
|
5
|
+
require "pathname"
|
6
|
+
require "delegate"
|
7
|
+
|
8
|
+
module Sentry
|
9
|
+
# DebugTransport is a transport that logs events to a file for debugging purposes.
|
10
|
+
#
|
11
|
+
# It can optionally also send events to Sentry via HTTP transport if a real DSN
|
12
|
+
# is provided.
|
13
|
+
class DebugTransport < SimpleDelegator
|
14
|
+
DEFAULT_LOG_FILE_PATH = File.join("log", "sentry_debug_events.log")
|
15
|
+
|
16
|
+
attr_reader :log_file, :backend
|
17
|
+
|
18
|
+
def initialize(configuration)
|
19
|
+
@log_file = initialize_log_file(configuration)
|
20
|
+
@backend = initialize_backend(configuration)
|
21
|
+
|
22
|
+
super(@backend)
|
23
|
+
end
|
24
|
+
|
25
|
+
def send_event(event)
|
26
|
+
log_envelope(envelope_from_event(event))
|
27
|
+
backend.send_event(event)
|
28
|
+
end
|
29
|
+
|
30
|
+
def log_envelope(envelope)
|
31
|
+
envelope_json = {
|
32
|
+
timestamp: Time.now.utc.iso8601,
|
33
|
+
envelope_headers: envelope.headers,
|
34
|
+
items: envelope.items.map do |item|
|
35
|
+
{ headers: item.headers, payload: item.payload }
|
36
|
+
end
|
37
|
+
}
|
38
|
+
|
39
|
+
File.open(log_file, "a") { |file| file << JSON.dump(envelope_json) << "\n" }
|
40
|
+
end
|
41
|
+
|
42
|
+
def logged_envelopes
|
43
|
+
return [] unless File.exist?(log_file)
|
44
|
+
|
45
|
+
File.readlines(log_file).map do |line|
|
46
|
+
JSON.parse(line)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def clear
|
51
|
+
File.write(log_file, "")
|
52
|
+
log_debug("DebugTransport: Cleared events from #{log_file}")
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
|
57
|
+
def initialize_backend(configuration)
|
58
|
+
backend = configuration.dsn.local? ? DummyTransport : HTTPTransport
|
59
|
+
backend.new(configuration)
|
60
|
+
end
|
61
|
+
|
62
|
+
def initialize_log_file(configuration)
|
63
|
+
log_file = Pathname(configuration.sdk_debug_transport_log_file || DEFAULT_LOG_FILE_PATH)
|
64
|
+
|
65
|
+
FileUtils.mkdir_p(log_file.dirname) unless log_file.dirname.exist?
|
66
|
+
|
67
|
+
log_file
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -45,11 +45,7 @@ module Sentry
|
|
45
45
|
auth_header = generate_auth_header
|
46
46
|
headers["X-Sentry-Auth"] = auth_header if auth_header
|
47
47
|
|
48
|
-
response =
|
49
|
-
request = ::Net::HTTP::Post.new(endpoint, headers)
|
50
|
-
request.body = data
|
51
|
-
http.request(request)
|
52
|
-
end
|
48
|
+
response = do_request(endpoint, headers, data)
|
53
49
|
|
54
50
|
if response.code.match?(/\A2\d{2}/)
|
55
51
|
handle_rate_limited_response(response) if has_rate_limited_header?(response)
|
@@ -111,6 +107,14 @@ module Sentry
|
|
111
107
|
connection
|
112
108
|
end
|
113
109
|
|
110
|
+
def do_request(endpoint, headers, body)
|
111
|
+
conn.start do |http|
|
112
|
+
request = ::Net::HTTP::Post.new(endpoint, headers)
|
113
|
+
request.body = body
|
114
|
+
http.request(request)
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
114
118
|
private
|
115
119
|
|
116
120
|
def has_rate_limited_header?(headers)
|
data/lib/sentry/transport.rb
CHANGED
@@ -0,0 +1,97 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Sentry
|
4
|
+
module Utils
|
5
|
+
class SampleRand
|
6
|
+
PRECISION = 1_000_000.0
|
7
|
+
FORMAT_PRECISION = 6
|
8
|
+
|
9
|
+
attr_reader :trace_id
|
10
|
+
|
11
|
+
def self.valid?(value)
|
12
|
+
return false unless value
|
13
|
+
value >= 0.0 && value < 1.0
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.format(value)
|
17
|
+
return unless value
|
18
|
+
|
19
|
+
truncated = (value * PRECISION).floor / PRECISION
|
20
|
+
"%.#{FORMAT_PRECISION}f" % truncated
|
21
|
+
end
|
22
|
+
|
23
|
+
def initialize(trace_id: nil)
|
24
|
+
@trace_id = trace_id
|
25
|
+
end
|
26
|
+
|
27
|
+
def generate_from_trace_id
|
28
|
+
(random_from_trace_id * PRECISION).floor / PRECISION
|
29
|
+
end
|
30
|
+
|
31
|
+
def generate_from_sampling_decision(sampled, sample_rate)
|
32
|
+
if invalid_sample_rate?(sample_rate)
|
33
|
+
fallback_generation
|
34
|
+
else
|
35
|
+
generate_based_on_sampling(sampled, sample_rate)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def generate_from_value(sample_rand_value)
|
40
|
+
parsed_value = parse_value(sample_rand_value)
|
41
|
+
|
42
|
+
if self.class.valid?(parsed_value)
|
43
|
+
parsed_value
|
44
|
+
else
|
45
|
+
fallback_generation
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
def random_from_trace_id
|
52
|
+
if @trace_id
|
53
|
+
Random.new(@trace_id[0, 16].to_i(16))
|
54
|
+
else
|
55
|
+
Random.new
|
56
|
+
end.rand(1.0)
|
57
|
+
end
|
58
|
+
|
59
|
+
def invalid_sample_rate?(sample_rate)
|
60
|
+
sample_rate.nil? || sample_rate <= 0.0 || sample_rate > 1.0
|
61
|
+
end
|
62
|
+
|
63
|
+
def fallback_generation
|
64
|
+
if @trace_id
|
65
|
+
(random_from_trace_id * PRECISION).floor / PRECISION
|
66
|
+
else
|
67
|
+
format_random(Random.rand(1.0))
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def generate_based_on_sampling(sampled, sample_rate)
|
72
|
+
random = random_from_trace_id
|
73
|
+
|
74
|
+
result = if sampled
|
75
|
+
random * sample_rate
|
76
|
+
elsif sample_rate == 1.0
|
77
|
+
random
|
78
|
+
else
|
79
|
+
sample_rate + random * (1.0 - sample_rate)
|
80
|
+
end
|
81
|
+
|
82
|
+
format_random(result)
|
83
|
+
end
|
84
|
+
|
85
|
+
def format_random(value)
|
86
|
+
truncated = (value * PRECISION).floor / PRECISION
|
87
|
+
("%.#{FORMAT_PRECISION}f" % truncated).to_f
|
88
|
+
end
|
89
|
+
|
90
|
+
def parse_value(sample_rand_value)
|
91
|
+
Float(sample_rand_value)
|
92
|
+
rescue ArgumentError
|
93
|
+
nil
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
data/lib/sentry/version.rb
CHANGED
data/lib/sentry-ruby.rb
CHANGED
@@ -10,8 +10,10 @@ require "sentry/core_ext/object/deep_dup"
|
|
10
10
|
require "sentry/utils/argument_checking_helper"
|
11
11
|
require "sentry/utils/encoding_helper"
|
12
12
|
require "sentry/utils/logging_helper"
|
13
|
+
require "sentry/utils/sample_rand"
|
13
14
|
require "sentry/configuration"
|
14
15
|
require "sentry/structured_logger"
|
16
|
+
require "sentry/debug_structured_logger"
|
15
17
|
require "sentry/event"
|
16
18
|
require "sentry/error_event"
|
17
19
|
require "sentry/transaction_event"
|
@@ -237,8 +239,7 @@ module Sentry
|
|
237
239
|
# @yieldparam config [Configuration]
|
238
240
|
# @return [void]
|
239
241
|
def init(&block)
|
240
|
-
config = Configuration.new
|
241
|
-
yield(config) if block_given?
|
242
|
+
config = Configuration.new(&block)
|
242
243
|
|
243
244
|
config.detect_release
|
244
245
|
apply_patches(config)
|
@@ -498,6 +499,7 @@ module Sentry
|
|
498
499
|
# @param [Hash] options Extra log event options
|
499
500
|
# @option options [Symbol] level The log level (:trace, :debug, :info, :warn, :error, :fatal)
|
500
501
|
# @option options [Integer] severity The severity number according to the Sentry Logs Protocol
|
502
|
+
# @option options [String] origin The origin of the log event (e.g., "auto.db.rails", "manual")
|
501
503
|
# @option options [Hash] Additional attributes to include with the log
|
502
504
|
#
|
503
505
|
# @example Direct usage (prefer using Sentry.logger instead)
|
@@ -638,13 +640,15 @@ module Sentry
|
|
638
640
|
@logger ||=
|
639
641
|
if configuration.enable_logs
|
640
642
|
# Initialize the public-facing Structured Logger if logs are enabled
|
641
|
-
#
|
643
|
+
# Use configured structured logger class or default to StructuredLogger
|
642
644
|
# @see https://develop.sentry.dev/sdk/telemetry/logs/
|
643
|
-
|
645
|
+
configuration.structured_logging.logger_class.new(configuration)
|
644
646
|
else
|
645
647
|
warn <<~STR
|
646
648
|
[sentry] `Sentry.logger` will no longer be used as internal SDK logger when `enable_logs` feature is turned on.
|
647
649
|
Use Sentry.configuration.sdk_logger for SDK-specific logging needs."
|
650
|
+
|
651
|
+
Caller: #{caller.first}
|
648
652
|
STR
|
649
653
|
|
650
654
|
configuration.sdk_logger
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sentry-ruby
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 5.
|
4
|
+
version: 5.28.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sentry Team
|
@@ -80,6 +80,7 @@ files:
|
|
80
80
|
- lib/sentry/cron/monitor_check_ins.rb
|
81
81
|
- lib/sentry/cron/monitor_config.rb
|
82
82
|
- lib/sentry/cron/monitor_schedule.rb
|
83
|
+
- lib/sentry/debug_structured_logger.rb
|
83
84
|
- lib/sentry/dsn.rb
|
84
85
|
- lib/sentry/envelope.rb
|
85
86
|
- lib/sentry/envelope/item.rb
|
@@ -137,6 +138,7 @@ files:
|
|
137
138
|
- lib/sentry/transaction_event.rb
|
138
139
|
- lib/sentry/transport.rb
|
139
140
|
- lib/sentry/transport/configuration.rb
|
141
|
+
- lib/sentry/transport/debug_transport.rb
|
140
142
|
- lib/sentry/transport/dummy_transport.rb
|
141
143
|
- lib/sentry/transport/http_transport.rb
|
142
144
|
- lib/sentry/transport/spotlight_transport.rb
|
@@ -149,21 +151,22 @@ files:
|
|
149
151
|
- lib/sentry/utils/logging_helper.rb
|
150
152
|
- lib/sentry/utils/real_ip.rb
|
151
153
|
- lib/sentry/utils/request_id.rb
|
154
|
+
- lib/sentry/utils/sample_rand.rb
|
152
155
|
- lib/sentry/utils/uuid.rb
|
153
156
|
- lib/sentry/vernier/output.rb
|
154
157
|
- lib/sentry/vernier/profiler.rb
|
155
158
|
- lib/sentry/version.rb
|
156
159
|
- sentry-ruby-core.gemspec
|
157
160
|
- sentry-ruby.gemspec
|
158
|
-
homepage: https://github.com/getsentry/sentry-ruby/tree/5.
|
161
|
+
homepage: https://github.com/getsentry/sentry-ruby/tree/5.28.0/sentry-ruby
|
159
162
|
licenses:
|
160
163
|
- MIT
|
161
164
|
metadata:
|
162
|
-
homepage_uri: https://github.com/getsentry/sentry-ruby/tree/5.
|
163
|
-
source_code_uri: https://github.com/getsentry/sentry-ruby/tree/5.
|
164
|
-
changelog_uri: https://github.com/getsentry/sentry-ruby/blob/5.
|
165
|
+
homepage_uri: https://github.com/getsentry/sentry-ruby/tree/5.28.0/sentry-ruby
|
166
|
+
source_code_uri: https://github.com/getsentry/sentry-ruby/tree/5.28.0/sentry-ruby
|
167
|
+
changelog_uri: https://github.com/getsentry/sentry-ruby/blob/5.28.0/CHANGELOG.md
|
165
168
|
bug_tracker_uri: https://github.com/getsentry/sentry-ruby/issues
|
166
|
-
documentation_uri: http://www.rubydoc.info/gems/sentry-ruby/5.
|
169
|
+
documentation_uri: http://www.rubydoc.info/gems/sentry-ruby/5.28.0
|
167
170
|
rdoc_options: []
|
168
171
|
require_paths:
|
169
172
|
- lib
|
@@ -178,7 +181,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
178
181
|
- !ruby/object:Gem::Version
|
179
182
|
version: '0'
|
180
183
|
requirements: []
|
181
|
-
rubygems_version: 3.6.
|
184
|
+
rubygems_version: 3.6.9
|
182
185
|
specification_version: 4
|
183
186
|
summary: A gem that provides a client interface for the Sentry error logger
|
184
187
|
test_files: []
|