sentry-ruby 5.23.0 → 5.24.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/background_worker.rb +2 -3
- data/lib/sentry/backpressure_monitor.rb +1 -1
- data/lib/sentry/breadcrumb.rb +5 -4
- data/lib/sentry/check_in_event.rb +2 -1
- data/lib/sentry/client.rb +39 -4
- data/lib/sentry/configuration.rb +27 -2
- data/lib/sentry/envelope/item.rb +1 -1
- data/lib/sentry/event.rb +2 -1
- data/lib/sentry/hub.rb +10 -0
- data/lib/sentry/interfaces/request.rb +1 -1
- data/lib/sentry/log_event.rb +159 -0
- data/lib/sentry/log_event_buffer.rb +97 -0
- data/lib/sentry/metrics/aggregator.rb +1 -1
- data/lib/sentry/profiler.rb +3 -2
- data/lib/sentry/propagation_context.rb +4 -4
- data/lib/sentry/scope.rb +1 -1
- data/lib/sentry/session_flusher.rb +1 -1
- data/lib/sentry/span.rb +3 -2
- data/lib/sentry/structured_logger.rb +138 -0
- data/lib/sentry/test_helper.rb +7 -0
- data/lib/sentry/threaded_periodic_worker.rb +3 -3
- data/lib/sentry/transaction.rb +1 -7
- data/lib/sentry/transport.rb +16 -8
- data/lib/sentry/utils/logging_helper.rb +10 -3
- data/lib/sentry/utils/uuid.rb +13 -0
- data/lib/sentry/vernier/profiler.rb +3 -2
- data/lib/sentry/version.rb +1 -1
- data/lib/sentry-ruby.rb +62 -4
- metadata +13 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 724630875bf8195cd594f3e761794886520b8eb95c13bf9a82642cdaf6f3ea94
|
4
|
+
data.tar.gz: c086418c80e60b60d1e099701fdb6b9ae1a9136bd464213dd9ff9cc17c582b75
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f8db6e3259785a16378f1a2f43f4dbb6e82be7f7eed84ba8f6a7ab8f1dc0f8ae4989a1d9fad5022361d756e0d8fd80d3cf16b6444933f10380e112e54afeaec1
|
7
|
+
data.tar.gz: 86ad04ab139eb703950d206a1a2a029f42da4fdf43896a342fa961ec8f7cd607de27270b49ec4ba7a635e2d34018387990e1a56d26287af39bf2708aee004a23
|
@@ -9,8 +9,7 @@ module Sentry
|
|
9
9
|
include LoggingHelper
|
10
10
|
|
11
11
|
attr_reader :max_queue, :number_of_threads
|
12
|
-
|
13
|
-
attr_reader :logger
|
12
|
+
|
14
13
|
attr_accessor :shutdown_timeout
|
15
14
|
|
16
15
|
DEFAULT_MAX_QUEUE = 30
|
@@ -19,7 +18,7 @@ module Sentry
|
|
19
18
|
@shutdown_timeout = 1
|
20
19
|
@number_of_threads = configuration.background_worker_threads
|
21
20
|
@max_queue = configuration.background_worker_max_queue
|
22
|
-
@
|
21
|
+
@sdk_logger = configuration.sdk_logger
|
23
22
|
@debug = configuration.debug
|
24
23
|
@shutdown_callback = nil
|
25
24
|
|
data/lib/sentry/breadcrumb.rb
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
module Sentry
|
4
4
|
class Breadcrumb
|
5
|
+
MAX_NESTING = 10
|
5
6
|
DATA_SERIALIZATION_ERROR_MESSAGE = "[data were removed due to serialization issues]"
|
6
7
|
|
7
8
|
# @return [String, nil]
|
@@ -47,7 +48,7 @@ module Sentry
|
|
47
48
|
# @param message [String]
|
48
49
|
# @return [void]
|
49
50
|
def message=(message)
|
50
|
-
@message = message ? message.byteslice(0..Event::MAX_MESSAGE_SIZE_IN_BYTES) : ""
|
51
|
+
@message = message && Utils::EncodingHelper.valid_utf_8?(message) ? message.byteslice(0..Event::MAX_MESSAGE_SIZE_IN_BYTES) : ""
|
51
52
|
end
|
52
53
|
|
53
54
|
# @param level [String]
|
@@ -60,16 +61,16 @@ module Sentry
|
|
60
61
|
|
61
62
|
def serialized_data
|
62
63
|
begin
|
63
|
-
::JSON.parse(::JSON.generate(@data))
|
64
|
+
::JSON.parse(::JSON.generate(@data, max_nesting: MAX_NESTING))
|
64
65
|
rescue Exception => e
|
65
|
-
Sentry.
|
66
|
+
Sentry.sdk_logger.debug(LOGGER_PROGNAME) do
|
66
67
|
<<~MSG
|
67
68
|
can't serialize breadcrumb data because of error: #{e}
|
68
69
|
data: #{@data}
|
69
70
|
MSG
|
70
71
|
end
|
71
72
|
|
72
|
-
DATA_SERIALIZATION_ERROR_MESSAGE
|
73
|
+
{ error: DATA_SERIALIZATION_ERROR_MESSAGE }
|
73
74
|
end
|
74
75
|
end
|
75
76
|
end
|
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
require "securerandom"
|
4
4
|
require "sentry/cron/monitor_config"
|
5
|
+
require "sentry/utils/uuid"
|
5
6
|
|
6
7
|
module Sentry
|
7
8
|
class CheckInEvent < Event
|
@@ -43,7 +44,7 @@ module Sentry
|
|
43
44
|
self.status = status
|
44
45
|
self.duration = duration
|
45
46
|
self.monitor_config = monitor_config
|
46
|
-
self.check_in_id = check_in_id ||
|
47
|
+
self.check_in_id = check_in_id || Utils.uuid
|
47
48
|
end
|
48
49
|
|
49
50
|
# @return [Hash]
|
data/lib/sentry/client.rb
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "sentry/transport"
|
4
|
+
require "sentry/log_event"
|
5
|
+
require "sentry/log_event_buffer"
|
4
6
|
|
5
7
|
module Sentry
|
6
8
|
class Client
|
@@ -14,16 +16,16 @@ module Sentry
|
|
14
16
|
# @return [SpotlightTransport, nil]
|
15
17
|
attr_reader :spotlight_transport
|
16
18
|
|
19
|
+
# @!visibility private
|
20
|
+
attr_reader :log_event_buffer
|
21
|
+
|
17
22
|
# @!macro configuration
|
18
23
|
attr_reader :configuration
|
19
24
|
|
20
|
-
# @deprecated Use Sentry.logger to retrieve the current logger instead.
|
21
|
-
attr_reader :logger
|
22
|
-
|
23
25
|
# @param configuration [Configuration]
|
24
26
|
def initialize(configuration)
|
25
27
|
@configuration = configuration
|
26
|
-
@
|
28
|
+
@sdk_logger = configuration.sdk_logger
|
27
29
|
|
28
30
|
if transport_class = configuration.transport.transport_class
|
29
31
|
@transport = transport_class.new(configuration)
|
@@ -38,6 +40,8 @@ module Sentry
|
|
38
40
|
end
|
39
41
|
|
40
42
|
@spotlight_transport = SpotlightTransport.new(configuration) if configuration.spotlight
|
43
|
+
|
44
|
+
@log_event_buffer = LogEventBuffer.new(configuration, self).start
|
41
45
|
end
|
42
46
|
|
43
47
|
# Applies the given scope's data to the event and sends it to Sentry.
|
@@ -88,6 +92,15 @@ module Sentry
|
|
88
92
|
nil
|
89
93
|
end
|
90
94
|
|
95
|
+
# Buffer a log event to be sent later with other logs in a single envelope
|
96
|
+
# @param event [LogEvent] the log event to be buffered
|
97
|
+
# @return [LogEvent]
|
98
|
+
def buffer_log_event(event, scope)
|
99
|
+
return unless event.is_a?(LogEvent)
|
100
|
+
@log_event_buffer.add_event(scope.apply_to_event(event))
|
101
|
+
event
|
102
|
+
end
|
103
|
+
|
91
104
|
# Capture an envelope directly.
|
92
105
|
# @param envelope [Envelope] the envelope to be captured.
|
93
106
|
# @return [void]
|
@@ -100,6 +113,7 @@ module Sentry
|
|
100
113
|
def flush
|
101
114
|
transport.flush if configuration.sending_to_dsn_allowed?
|
102
115
|
spotlight_transport.flush if spotlight_transport
|
116
|
+
@log_event_buffer.flush
|
103
117
|
end
|
104
118
|
|
105
119
|
# Initializes an Event object with the given exception. Returns `nil` if the exception's class is excluded from reporting.
|
@@ -167,6 +181,27 @@ module Sentry
|
|
167
181
|
)
|
168
182
|
end
|
169
183
|
|
184
|
+
# Initializes a LogEvent object with the given message and options
|
185
|
+
#
|
186
|
+
# @param message [String] the log message
|
187
|
+
# @param level [Symbol] the log level (:trace, :debug, :info, :warn, :error, :fatal)
|
188
|
+
# @param options [Hash] additional options
|
189
|
+
# @option options [Array] :parameters Array of values to replace template tokens in the message
|
190
|
+
#
|
191
|
+
# @return [LogEvent] the created log event
|
192
|
+
def event_from_log(message, level:, **options)
|
193
|
+
return unless configuration.sending_allowed?
|
194
|
+
|
195
|
+
attributes = options.reject { |k, _| k == :level || k == :severity }
|
196
|
+
|
197
|
+
LogEvent.new(
|
198
|
+
level: level,
|
199
|
+
body: message,
|
200
|
+
timestamp: Time.now.to_f,
|
201
|
+
attributes: attributes
|
202
|
+
)
|
203
|
+
end
|
204
|
+
|
170
205
|
# Initializes an Event object with the given Transaction object.
|
171
206
|
# @param transaction [Transaction] the transaction to be recorded.
|
172
207
|
# @return [TransactionEvent]
|
data/lib/sentry/configuration.rb
CHANGED
@@ -12,6 +12,8 @@ require "sentry/cron/configuration"
|
|
12
12
|
require "sentry/metrics/configuration"
|
13
13
|
require "sentry/linecache"
|
14
14
|
require "sentry/interfaces/stacktrace_builder"
|
15
|
+
require "sentry/logger"
|
16
|
+
require "sentry/log_event_buffer"
|
15
17
|
|
16
18
|
module Sentry
|
17
19
|
class Configuration
|
@@ -183,7 +185,19 @@ module Sentry
|
|
183
185
|
# Logger used by Sentry. In Rails, this is the Rails logger, otherwise
|
184
186
|
# Sentry provides its own Sentry::Logger.
|
185
187
|
# @return [Logger]
|
186
|
-
attr_accessor :
|
188
|
+
attr_accessor :sdk_logger
|
189
|
+
|
190
|
+
# @deprecated Use {#sdk_logger=} instead.
|
191
|
+
def logger=(logger)
|
192
|
+
warn "[sentry] `config.logger=` is deprecated. Please use `config.sdk_logger=` instead."
|
193
|
+
self.sdk_logger = logger
|
194
|
+
end
|
195
|
+
|
196
|
+
# @deprecated Use {#sdk_logger} instead.
|
197
|
+
def logger
|
198
|
+
warn "[sentry] `config.logger` is deprecated. Please use `config.sdk_logger` instead."
|
199
|
+
self.sdk_logger
|
200
|
+
end
|
187
201
|
|
188
202
|
# Project directory root for in_app detection. Could be Rails root, etc.
|
189
203
|
# Set automatically for Rails.
|
@@ -262,6 +276,10 @@ module Sentry
|
|
262
276
|
# @return [Proc]
|
263
277
|
attr_accessor :traces_sampler
|
264
278
|
|
279
|
+
# Enable Structured Logging
|
280
|
+
# @return [Boolean]
|
281
|
+
attr_accessor :enable_logs
|
282
|
+
|
265
283
|
# Easier way to use performance tracing
|
266
284
|
# If set to true, will set traces_sample_rate to 1.0
|
267
285
|
# @deprecated It will be removed in the next major release.
|
@@ -307,6 +325,10 @@ module Sentry
|
|
307
325
|
# @return [Array<Symbol>]
|
308
326
|
attr_accessor :enabled_patches
|
309
327
|
|
328
|
+
# Maximum number of log events to buffer before sending
|
329
|
+
# @return [Integer]
|
330
|
+
attr_accessor :max_log_events
|
331
|
+
|
310
332
|
# these are not config options
|
311
333
|
# @!visibility private
|
312
334
|
attr_reader :errors, :gem_specs
|
@@ -419,7 +441,7 @@ module Sentry
|
|
419
441
|
self.excluded_exceptions = IGNORE_DEFAULT + PUMA_IGNORE_DEFAULT
|
420
442
|
self.inspect_exception_causes_for_exclusion = true
|
421
443
|
self.linecache = ::Sentry::LineCache.new
|
422
|
-
self.
|
444
|
+
self.sdk_logger = ::Sentry::Logger.new(STDOUT)
|
423
445
|
self.project_root = Dir.pwd
|
424
446
|
self.propagate_traces = true
|
425
447
|
|
@@ -446,6 +468,7 @@ module Sentry
|
|
446
468
|
self.rack_env_whitelist = RACK_ENV_WHITELIST_DEFAULT
|
447
469
|
self.traces_sampler = nil
|
448
470
|
self.enable_tracing = nil
|
471
|
+
self.enable_logs = false
|
449
472
|
|
450
473
|
self.profiler_class = Sentry::Profiler
|
451
474
|
|
@@ -455,6 +478,8 @@ module Sentry
|
|
455
478
|
@gem_specs = Hash[Gem::Specification.map { |spec| [spec.name, spec.version.to_s] }] if Gem::Specification.respond_to?(:map)
|
456
479
|
|
457
480
|
run_post_initialization_callbacks
|
481
|
+
|
482
|
+
self.max_log_events = LogEventBuffer::DEFAULT_MAX_EVENTS
|
458
483
|
end
|
459
484
|
|
460
485
|
def validate
|
data/lib/sentry/envelope/item.rb
CHANGED
@@ -15,7 +15,7 @@ module Sentry
|
|
15
15
|
# rate limits and client reports use the data_category rather than envelope item type
|
16
16
|
def self.data_category(type)
|
17
17
|
case type
|
18
|
-
when "session", "attachment", "transaction", "profile", "span" then type
|
18
|
+
when "session", "attachment", "transaction", "profile", "span", "log" then type
|
19
19
|
when "sessions" then "session"
|
20
20
|
when "check_in" then "monitor"
|
21
21
|
when "statsd", "metric_meta" then "metric_bucket"
|
data/lib/sentry/event.rb
CHANGED
@@ -7,6 +7,7 @@ require "sentry/backtrace"
|
|
7
7
|
require "sentry/utils/real_ip"
|
8
8
|
require "sentry/utils/request_id"
|
9
9
|
require "sentry/utils/custom_inspection"
|
10
|
+
require "sentry/utils/uuid"
|
10
11
|
|
11
12
|
module Sentry
|
12
13
|
# This is an abstract class that defines the shared attributes of an event.
|
@@ -50,7 +51,7 @@ module Sentry
|
|
50
51
|
# @param message [String, nil]
|
51
52
|
def initialize(configuration:, integration_meta: nil, message: nil)
|
52
53
|
# Set some simple default values
|
53
|
-
@event_id =
|
54
|
+
@event_id = Utils.uuid
|
54
55
|
@timestamp = Sentry.utc_now.iso8601
|
55
56
|
@platform = :ruby
|
56
57
|
@type = self.class::TYPE
|
data/lib/sentry/hub.rb
CHANGED
@@ -216,6 +216,16 @@ module Sentry
|
|
216
216
|
event.check_in_id
|
217
217
|
end
|
218
218
|
|
219
|
+
def capture_log_event(message, **options)
|
220
|
+
return unless current_client
|
221
|
+
|
222
|
+
event = current_client.event_from_log(message, **options)
|
223
|
+
|
224
|
+
return unless event
|
225
|
+
|
226
|
+
current_client.buffer_log_event(event, current_scope)
|
227
|
+
end
|
228
|
+
|
219
229
|
def capture_event(event, **options, &block)
|
220
230
|
check_argument_type!(event, Sentry::Event)
|
221
231
|
|
@@ -99,7 +99,7 @@ module Sentry
|
|
99
99
|
# Rails adds objects to the Rack env that can sometimes raise exceptions
|
100
100
|
# when `to_s` is called.
|
101
101
|
# See: https://github.com/rails/rails/blob/master/actionpack/lib/action_dispatch/middleware/remote_ip.rb#L134
|
102
|
-
Sentry.
|
102
|
+
Sentry.sdk_logger.warn(LOGGER_PROGNAME) { "Error raised while formatting headers: #{e.message}" }
|
103
103
|
next
|
104
104
|
end
|
105
105
|
end
|
@@ -0,0 +1,159 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Sentry
|
4
|
+
# Event type that represents a log entry with its attributes
|
5
|
+
#
|
6
|
+
# @see https://develop.sentry.dev/sdk/telemetry/logs/#log-envelope-item-payload
|
7
|
+
class LogEvent < Event
|
8
|
+
TYPE = "log"
|
9
|
+
|
10
|
+
DEFAULT_PARAMETERS = [].freeze
|
11
|
+
DEFAULT_ATTRIBUTES = {}.freeze
|
12
|
+
DEFAULT_CONTEXT = {}.freeze
|
13
|
+
|
14
|
+
SERIALIZEABLE_ATTRIBUTES = %i[
|
15
|
+
level
|
16
|
+
body
|
17
|
+
timestamp
|
18
|
+
trace_id
|
19
|
+
attributes
|
20
|
+
]
|
21
|
+
|
22
|
+
SENTRY_ATTRIBUTES = {
|
23
|
+
"sentry.trace.parent_span_id" => :parent_span_id,
|
24
|
+
"sentry.environment" => :environment,
|
25
|
+
"sentry.release" => :release,
|
26
|
+
"sentry.address" => :server_name,
|
27
|
+
"sentry.sdk.name" => :sdk_name,
|
28
|
+
"sentry.sdk.version" => :sdk_version,
|
29
|
+
"sentry.message.template" => :template
|
30
|
+
}
|
31
|
+
|
32
|
+
LEVELS = %i[trace debug info warn error fatal].freeze
|
33
|
+
|
34
|
+
attr_accessor :level, :body, :template, :attributes
|
35
|
+
|
36
|
+
def initialize(configuration: Sentry.configuration, **options)
|
37
|
+
super(configuration: configuration)
|
38
|
+
|
39
|
+
@type = TYPE
|
40
|
+
@level = options.fetch(:level)
|
41
|
+
@body = options[:body]
|
42
|
+
@template = @body if is_template?
|
43
|
+
@attributes = options[:attributes] || DEFAULT_ATTRIBUTES
|
44
|
+
@contexts = DEFAULT_CONTEXT
|
45
|
+
end
|
46
|
+
|
47
|
+
def to_hash
|
48
|
+
SERIALIZEABLE_ATTRIBUTES.each_with_object({}) do |name, memo|
|
49
|
+
memo[name] = serialize(name)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
|
55
|
+
def serialize(name)
|
56
|
+
serializer = :"serialize_#{name}"
|
57
|
+
|
58
|
+
if respond_to?(serializer, true)
|
59
|
+
__send__(serializer)
|
60
|
+
else
|
61
|
+
public_send(name)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def serialize_level
|
66
|
+
level.to_s
|
67
|
+
end
|
68
|
+
|
69
|
+
def serialize_sdk_name
|
70
|
+
Sentry.sdk_meta["name"]
|
71
|
+
end
|
72
|
+
|
73
|
+
def serialize_sdk_version
|
74
|
+
Sentry.sdk_meta["version"]
|
75
|
+
end
|
76
|
+
|
77
|
+
def serialize_timestamp
|
78
|
+
Time.parse(timestamp).to_f
|
79
|
+
end
|
80
|
+
|
81
|
+
def serialize_trace_id
|
82
|
+
contexts.dig(:trace, :trace_id)
|
83
|
+
end
|
84
|
+
|
85
|
+
def serialize_parent_span_id
|
86
|
+
contexts.dig(:trace, :parent_span_id)
|
87
|
+
end
|
88
|
+
|
89
|
+
def serialize_body
|
90
|
+
if parameters.empty?
|
91
|
+
body
|
92
|
+
elsif parameters.is_a?(Hash)
|
93
|
+
body % parameters
|
94
|
+
else
|
95
|
+
sprintf(body, *parameters)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def serialize_attributes
|
100
|
+
hash = attributes.each_with_object({}) do |(key, value), memo|
|
101
|
+
memo[key] = attribute_hash(value)
|
102
|
+
end
|
103
|
+
|
104
|
+
SENTRY_ATTRIBUTES.each do |key, name|
|
105
|
+
if (value = serialize(name))
|
106
|
+
hash[key] = attribute_hash(value)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
hash
|
111
|
+
end
|
112
|
+
|
113
|
+
def attribute_hash(value)
|
114
|
+
{ value: value, type: value_type(value) }
|
115
|
+
end
|
116
|
+
|
117
|
+
def value_type(value)
|
118
|
+
case value
|
119
|
+
when Integer
|
120
|
+
"integer"
|
121
|
+
when TrueClass, FalseClass
|
122
|
+
"boolean"
|
123
|
+
when Float
|
124
|
+
"double"
|
125
|
+
else
|
126
|
+
"string"
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
def parameters
|
131
|
+
@parameters ||= begin
|
132
|
+
return DEFAULT_PARAMETERS unless template
|
133
|
+
|
134
|
+
parameters = template_tokens.empty? ?
|
135
|
+
attributes.fetch(:parameters, DEFAULT_PARAMETERS) : attributes.slice(*template_tokens)
|
136
|
+
|
137
|
+
if parameters.is_a?(Hash)
|
138
|
+
parameters.each do |key, value|
|
139
|
+
attributes["sentry.message.parameter.#{key}"] = value
|
140
|
+
end
|
141
|
+
else
|
142
|
+
parameters.each_with_index do |param, index|
|
143
|
+
attributes["sentry.message.parameter.#{index}"] = param
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
TOKEN_REGEXP = /%\{(\w+)\}/
|
150
|
+
|
151
|
+
def template_tokens
|
152
|
+
@template_tokens ||= body.scan(TOKEN_REGEXP).flatten.map(&:to_sym)
|
153
|
+
end
|
154
|
+
|
155
|
+
def is_template?
|
156
|
+
body.include?("%s") || TOKEN_REGEXP.match?(body)
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "sentry/threaded_periodic_worker"
|
4
|
+
|
5
|
+
module Sentry
|
6
|
+
# LogEventBuffer buffers log events and sends them to Sentry in a single envelope.
|
7
|
+
#
|
8
|
+
# This is used internally by the `Sentry::Client`.
|
9
|
+
#
|
10
|
+
# @!visibility private
|
11
|
+
class LogEventBuffer < ThreadedPeriodicWorker
|
12
|
+
FLUSH_INTERVAL = 5 # seconds
|
13
|
+
DEFAULT_MAX_EVENTS = 100
|
14
|
+
|
15
|
+
# @!visibility private
|
16
|
+
attr_reader :pending_events
|
17
|
+
|
18
|
+
def initialize(configuration, client)
|
19
|
+
super(configuration.sdk_logger, FLUSH_INTERVAL)
|
20
|
+
|
21
|
+
@client = client
|
22
|
+
@pending_events = []
|
23
|
+
@max_events = configuration.max_log_events || DEFAULT_MAX_EVENTS
|
24
|
+
@dsn = configuration.dsn
|
25
|
+
@sdk = Sentry.sdk_meta
|
26
|
+
@mutex = Mutex.new
|
27
|
+
|
28
|
+
log_debug("[Logging] Initialized buffer with max_events=#{@max_events}, flush_interval=#{FLUSH_INTERVAL}s")
|
29
|
+
end
|
30
|
+
|
31
|
+
def start
|
32
|
+
ensure_thread
|
33
|
+
self
|
34
|
+
end
|
35
|
+
|
36
|
+
def flush
|
37
|
+
@mutex.synchronize do
|
38
|
+
return if empty?
|
39
|
+
|
40
|
+
log_debug("[LogEventBuffer] flushing #{size} log events")
|
41
|
+
|
42
|
+
send_events
|
43
|
+
end
|
44
|
+
|
45
|
+
log_debug("[LogEventBuffer] flushed #{size} log events")
|
46
|
+
|
47
|
+
self
|
48
|
+
end
|
49
|
+
alias_method :run, :flush
|
50
|
+
|
51
|
+
def add_event(event)
|
52
|
+
raise ArgumentError, "expected a LogEvent, got #{event.class}" unless event.is_a?(LogEvent)
|
53
|
+
|
54
|
+
@mutex.synchronize do
|
55
|
+
@pending_events << event
|
56
|
+
send_events if size >= @max_events
|
57
|
+
end
|
58
|
+
|
59
|
+
self
|
60
|
+
end
|
61
|
+
|
62
|
+
def empty?
|
63
|
+
@pending_events.empty?
|
64
|
+
end
|
65
|
+
|
66
|
+
def size
|
67
|
+
@pending_events.size
|
68
|
+
end
|
69
|
+
|
70
|
+
private
|
71
|
+
|
72
|
+
def send_events
|
73
|
+
@client.send_envelope(to_envelope)
|
74
|
+
@pending_events.clear
|
75
|
+
end
|
76
|
+
|
77
|
+
def to_envelope
|
78
|
+
envelope = Envelope.new(
|
79
|
+
event_id: SecureRandom.uuid.delete("-"),
|
80
|
+
sent_at: Sentry.utc_now.iso8601,
|
81
|
+
dsn: @dsn,
|
82
|
+
sdk: @sdk
|
83
|
+
)
|
84
|
+
|
85
|
+
envelope.add_item(
|
86
|
+
{
|
87
|
+
type: "log",
|
88
|
+
item_count: size,
|
89
|
+
content_type: "application/vnd.sentry.items.log+json"
|
90
|
+
},
|
91
|
+
{ items: @pending_events.map(&:to_hash) }
|
92
|
+
)
|
93
|
+
|
94
|
+
envelope
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
@@ -34,7 +34,7 @@ module Sentry
|
|
34
34
|
attr_reader :client, :thread, :buckets, :flush_shift, :code_locations
|
35
35
|
|
36
36
|
def initialize(configuration, client)
|
37
|
-
super(configuration.
|
37
|
+
super(configuration.sdk_logger, FLUSH_INTERVAL)
|
38
38
|
@client = client
|
39
39
|
@before_emit = configuration.metrics.before_emit
|
40
40
|
@enable_code_locations = configuration.metrics.enable_code_locations
|
data/lib/sentry/profiler.rb
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
require "securerandom"
|
4
4
|
require_relative "profiler/helpers"
|
5
|
+
require "sentry/utils/uuid"
|
5
6
|
|
6
7
|
module Sentry
|
7
8
|
class Profiler
|
@@ -17,7 +18,7 @@ module Sentry
|
|
17
18
|
attr_reader :sampled, :started, :event_id
|
18
19
|
|
19
20
|
def initialize(configuration)
|
20
|
-
@event_id =
|
21
|
+
@event_id = Utils.uuid
|
21
22
|
@started = false
|
22
23
|
@sampled = nil
|
23
24
|
|
@@ -192,7 +193,7 @@ module Sentry
|
|
192
193
|
private
|
193
194
|
|
194
195
|
def log(message)
|
195
|
-
Sentry.
|
196
|
+
Sentry.sdk_logger.debug(LOGGER_PROGNAME) { "[Profiler] #{message}" }
|
196
197
|
end
|
197
198
|
|
198
199
|
def record_lost_event(reason)
|
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
require "securerandom"
|
4
4
|
require "sentry/baggage"
|
5
|
+
require "sentry/utils/uuid"
|
5
6
|
|
6
7
|
module Sentry
|
7
8
|
class PropagationContext
|
@@ -66,8 +67,8 @@ module Sentry
|
|
66
67
|
end
|
67
68
|
end
|
68
69
|
|
69
|
-
@trace_id ||=
|
70
|
-
@span_id =
|
70
|
+
@trace_id ||= Utils.uuid
|
71
|
+
@span_id = Utils.uuid.slice(0, 16)
|
71
72
|
end
|
72
73
|
|
73
74
|
# Extract the trace_id, parent_span_id and parent_sampled values from a sentry-trace header.
|
@@ -124,8 +125,7 @@ module Sentry
|
|
124
125
|
"trace_id" => trace_id,
|
125
126
|
"environment" => configuration.environment,
|
126
127
|
"release" => configuration.release,
|
127
|
-
"public_key" => configuration.dsn&.public_key
|
128
|
-
"user_segment" => @scope.user && @scope.user["segment"]
|
128
|
+
"public_key" => configuration.dsn&.public_key
|
129
129
|
}
|
130
130
|
|
131
131
|
items.compact!
|
data/lib/sentry/scope.rb
CHANGED
@@ -54,7 +54,7 @@ module Sentry
|
|
54
54
|
event.transaction = transaction_name if transaction_name
|
55
55
|
event.transaction_info = { source: transaction_source } if transaction_source
|
56
56
|
event.fingerprint = fingerprint
|
57
|
-
event.level = level
|
57
|
+
event.level = level unless event.is_a?(LogEvent)
|
58
58
|
event.breadcrumbs = breadcrumbs
|
59
59
|
event.rack_env = rack_env if rack_env
|
60
60
|
event.attachments = attachments
|
data/lib/sentry/span.rb
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
require "securerandom"
|
4
4
|
require "sentry/metrics/local_aggregator"
|
5
|
+
require "sentry/utils/uuid"
|
5
6
|
|
6
7
|
module Sentry
|
7
8
|
class Span
|
@@ -127,8 +128,8 @@ module Sentry
|
|
127
128
|
timestamp: nil,
|
128
129
|
origin: nil
|
129
130
|
)
|
130
|
-
@trace_id = trace_id ||
|
131
|
-
@span_id = span_id ||
|
131
|
+
@trace_id = trace_id || Utils.uuid
|
132
|
+
@span_id = span_id || Utils.uuid.slice(0, 16)
|
132
133
|
@parent_span_id = parent_span_id
|
133
134
|
@sampled = sampled
|
134
135
|
@start_timestamp = start_timestamp || Sentry.utc_now.to_f
|
@@ -0,0 +1,138 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Sentry
|
4
|
+
# The StructuredLogger class implements Sentry's SDK telemetry logs protocol.
|
5
|
+
# It provides methods for logging messages at different severity levels and
|
6
|
+
# sending them to Sentry with structured data.
|
7
|
+
#
|
8
|
+
# This class follows the Sentry Logs Protocol as defined in:
|
9
|
+
# https://develop.sentry.dev/sdk/telemetry/logs/
|
10
|
+
#
|
11
|
+
# @example Basic usage
|
12
|
+
# Sentry.logger.info("User logged in", user_id: 123)
|
13
|
+
#
|
14
|
+
# @example With structured data
|
15
|
+
# Sentry.logger.warn("API request failed",
|
16
|
+
# status_code: 404,
|
17
|
+
# endpoint: "/api/users",
|
18
|
+
# request_id: "abc-123"
|
19
|
+
# )
|
20
|
+
#
|
21
|
+
# @example With a message template
|
22
|
+
# # Using positional parameters
|
23
|
+
# Sentry.logger.info("User %s logged in", ["Jane Doe"])
|
24
|
+
#
|
25
|
+
# # Using hash parameters
|
26
|
+
# Sentry.logger.info("User %{name} logged in", name: "Jane Doe")
|
27
|
+
#
|
28
|
+
# # Using hash parameters and extra attributes
|
29
|
+
# Sentry.logger.info("User %{name} logged in", name: "Jane Doe", user_id: 312)
|
30
|
+
#
|
31
|
+
# @see https://develop.sentry.dev/sdk/telemetry/logs/ Sentry SDK Telemetry Logs Protocol
|
32
|
+
class StructuredLogger
|
33
|
+
# Severity number mapping for log levels according to the Sentry Logs Protocol
|
34
|
+
# @see https://develop.sentry.dev/sdk/telemetry/logs/#log-severity-number
|
35
|
+
LEVELS = {
|
36
|
+
trace: 1,
|
37
|
+
debug: 5,
|
38
|
+
info: 9,
|
39
|
+
warn: 13,
|
40
|
+
error: 17,
|
41
|
+
fatal: 21
|
42
|
+
}.freeze
|
43
|
+
|
44
|
+
# @return [Configuration] The Sentry configuration
|
45
|
+
# @!visibility private
|
46
|
+
attr_reader :config
|
47
|
+
|
48
|
+
# Initializes a new StructuredLogger instance
|
49
|
+
#
|
50
|
+
# @param config [Configuration] The Sentry configuration
|
51
|
+
def initialize(config)
|
52
|
+
@config = config
|
53
|
+
end
|
54
|
+
|
55
|
+
# Logs a message at TRACE level
|
56
|
+
#
|
57
|
+
# @param message [String] The log message
|
58
|
+
# @param parameters [Array] Array of values to replace template parameters in the message
|
59
|
+
# @param attributes [Hash] Additional attributes to include with the log
|
60
|
+
#
|
61
|
+
# @return [LogEvent, nil] The created log event or nil if logging is disabled
|
62
|
+
def trace(message, parameters = [], **attributes)
|
63
|
+
log(__method__, message, parameters: parameters, **attributes)
|
64
|
+
end
|
65
|
+
|
66
|
+
# Logs a message at DEBUG level
|
67
|
+
#
|
68
|
+
# @param message [String] The log message
|
69
|
+
# @param parameters [Array] Array of values to replace template parameters in the message
|
70
|
+
# @param attributes [Hash] Additional attributes to include with the log
|
71
|
+
#
|
72
|
+
# @return [LogEvent, nil] The created log event or nil if logging is disabled
|
73
|
+
def debug(message, parameters = [], **attributes)
|
74
|
+
log(__method__, message, parameters: parameters, **attributes)
|
75
|
+
end
|
76
|
+
|
77
|
+
# Logs a message at INFO level
|
78
|
+
#
|
79
|
+
# @param message [String] The log message
|
80
|
+
# @param parameters [Array] Array of values to replace template parameters in the message
|
81
|
+
# @param attributes [Hash] Additional attributes to include with the log
|
82
|
+
#
|
83
|
+
# @return [LogEvent, nil] The created log event or nil if logging is disabled
|
84
|
+
def info(message, parameters = [], **attributes)
|
85
|
+
log(__method__, message, parameters: parameters, **attributes)
|
86
|
+
end
|
87
|
+
|
88
|
+
# Logs a message at WARN level
|
89
|
+
#
|
90
|
+
# @param message [String] The log message
|
91
|
+
# @param parameters [Array] Array of values to replace template parameters in the message
|
92
|
+
# @param attributes [Hash] Additional attributes to include with the log
|
93
|
+
#
|
94
|
+
# @return [LogEvent, nil] The created log event or nil if logging is disabled
|
95
|
+
def warn(message, parameters = [], **attributes)
|
96
|
+
log(__method__, message, parameters: parameters, **attributes)
|
97
|
+
end
|
98
|
+
|
99
|
+
# Logs a message at ERROR level
|
100
|
+
#
|
101
|
+
# @param message [String] The log message
|
102
|
+
# @param parameters [Array] Array of values to replace template parameters in the message
|
103
|
+
# @param attributes [Hash] Additional attributes to include with the log
|
104
|
+
#
|
105
|
+
# @return [LogEvent, nil] The created log event or nil if logging is disabled
|
106
|
+
def error(message, parameters = [], **attributes)
|
107
|
+
log(__method__, message, parameters: parameters, **attributes)
|
108
|
+
end
|
109
|
+
|
110
|
+
# Logs a message at FATAL level
|
111
|
+
#
|
112
|
+
# @param message [String] The log message
|
113
|
+
# @param parameters [Array] Array of values to replace template parameters in the message
|
114
|
+
# @param attributes [Hash] Additional attributes to include with the log
|
115
|
+
#
|
116
|
+
# @return [LogEvent, nil] The created log event or nil if logging is disabled
|
117
|
+
def fatal(message, parameters = [], **attributes)
|
118
|
+
log(__method__, message, parameters: parameters, **attributes)
|
119
|
+
end
|
120
|
+
|
121
|
+
# Logs a message at the specified level
|
122
|
+
#
|
123
|
+
# @param level [Symbol] The log level (:trace, :debug, :info, :warn, :error, :fatal)
|
124
|
+
# @param message [String] The log message
|
125
|
+
# @param parameters [Array, Hash] Array or Hash of values to replace template parameters in the message
|
126
|
+
# @param attributes [Hash] Additional attributes to include with the log
|
127
|
+
#
|
128
|
+
# @return [LogEvent, nil] The created log event or nil if logging is disabled
|
129
|
+
def log(level, message, parameters:, **attributes)
|
130
|
+
case parameters
|
131
|
+
when Array then
|
132
|
+
Sentry.capture_log(message, level: level, severity: LEVELS[level], parameters: parameters, **attributes)
|
133
|
+
else
|
134
|
+
Sentry.capture_log(message, level: level, severity: LEVELS[level], **parameters)
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
data/lib/sentry/test_helper.rb
CHANGED
@@ -72,6 +72,13 @@ module Sentry
|
|
72
72
|
sentry_transport.envelopes
|
73
73
|
end
|
74
74
|
|
75
|
+
def sentry_logs
|
76
|
+
sentry_envelopes
|
77
|
+
.flat_map(&:items)
|
78
|
+
.select { |item| item.headers[:type] == "log" }
|
79
|
+
.flat_map { |item| item.payload[:items] }
|
80
|
+
end
|
81
|
+
|
75
82
|
# Returns the last captured event object.
|
76
83
|
# @return [Event, nil]
|
77
84
|
def last_sentry_event
|
@@ -4,11 +4,11 @@ module Sentry
|
|
4
4
|
class ThreadedPeriodicWorker
|
5
5
|
include LoggingHelper
|
6
6
|
|
7
|
-
def initialize(
|
7
|
+
def initialize(sdk_logger, interval)
|
8
8
|
@thread = nil
|
9
9
|
@exited = false
|
10
|
-
@interval =
|
11
|
-
@
|
10
|
+
@interval = interval
|
11
|
+
@sdk_logger = sdk_logger
|
12
12
|
end
|
13
13
|
|
14
14
|
def ensure_thread
|
data/lib/sentry/transaction.rb
CHANGED
@@ -45,9 +45,6 @@ module Sentry
|
|
45
45
|
# @deprecated Use Sentry.configuration instead.
|
46
46
|
attr_reader :configuration
|
47
47
|
|
48
|
-
# @deprecated Use Sentry.logger instead.
|
49
|
-
attr_reader :logger
|
50
|
-
|
51
48
|
# The effective sample rate at which this transaction was sampled.
|
52
49
|
# @return [Float, nil]
|
53
50
|
attr_reader :effective_sample_rate
|
@@ -78,7 +75,7 @@ module Sentry
|
|
78
75
|
@tracing_enabled = hub.configuration.tracing_enabled?
|
79
76
|
@traces_sampler = hub.configuration.traces_sampler
|
80
77
|
@traces_sample_rate = hub.configuration.traces_sample_rate
|
81
|
-
@
|
78
|
+
@sdk_logger = hub.configuration.sdk_logger
|
82
79
|
@release = hub.configuration.release
|
83
80
|
@environment = hub.configuration.environment
|
84
81
|
@dsn = hub.configuration.dsn
|
@@ -342,9 +339,6 @@ module Sentry
|
|
342
339
|
|
343
340
|
items["transaction"] = name unless source_low_quality?
|
344
341
|
|
345
|
-
user = @hub.current_scope&.user
|
346
|
-
items["user_segment"] = user["segment"] if user && user["segment"]
|
347
|
-
|
348
342
|
items.compact!
|
349
343
|
@baggage = Baggage.new(items, mutable: false)
|
350
344
|
end
|
data/lib/sentry/transport.rb
CHANGED
@@ -26,11 +26,8 @@ module Sentry
|
|
26
26
|
|
27
27
|
attr_reader :rate_limits, :discarded_events, :last_client_report_sent
|
28
28
|
|
29
|
-
# @deprecated Use Sentry.logger to retrieve the current logger instead.
|
30
|
-
attr_reader :logger
|
31
|
-
|
32
29
|
def initialize(configuration)
|
33
|
-
@
|
30
|
+
@sdk_logger = configuration.sdk_logger
|
34
31
|
@transport_configuration = configuration.transport
|
35
32
|
@dsn = configuration.dsn
|
36
33
|
@rate_limits = {}
|
@@ -133,10 +130,21 @@ module Sentry
|
|
133
130
|
|
134
131
|
envelope = Envelope.new(envelope_headers)
|
135
132
|
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
133
|
+
if event.is_a?(LogEvent)
|
134
|
+
envelope.add_item(
|
135
|
+
{
|
136
|
+
type: "log",
|
137
|
+
item_count: 1,
|
138
|
+
content_type: "application/vnd.sentry.items.log+json"
|
139
|
+
},
|
140
|
+
{ items: [event_payload] }
|
141
|
+
)
|
142
|
+
else
|
143
|
+
envelope.add_item(
|
144
|
+
{ type: item_type, content_type: "application/json" },
|
145
|
+
event_payload
|
146
|
+
)
|
147
|
+
end
|
140
148
|
|
141
149
|
if event.is_a?(TransactionEvent) && event.profile
|
142
150
|
envelope.add_item(
|
@@ -1,22 +1,29 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Sentry
|
4
|
+
# @private
|
4
5
|
module LoggingHelper
|
6
|
+
# @!visibility private
|
7
|
+
attr_reader :sdk_logger
|
8
|
+
|
9
|
+
# @!visibility private
|
5
10
|
def log_error(message, exception, debug: false)
|
6
11
|
message = "#{message}: #{exception.message}"
|
7
12
|
message += "\n#{exception.backtrace.join("\n")}" if debug
|
8
13
|
|
9
|
-
|
14
|
+
sdk_logger.error(LOGGER_PROGNAME) do
|
10
15
|
message
|
11
16
|
end
|
12
17
|
end
|
13
18
|
|
19
|
+
# @!visibility private
|
14
20
|
def log_debug(message)
|
15
|
-
|
21
|
+
sdk_logger.debug(LOGGER_PROGNAME) { message }
|
16
22
|
end
|
17
23
|
|
24
|
+
# @!visibility private
|
18
25
|
def log_warn(message)
|
19
|
-
|
26
|
+
sdk_logger.warn(LOGGER_PROGNAME) { message }
|
20
27
|
end
|
21
28
|
end
|
22
29
|
end
|
@@ -3,6 +3,7 @@
|
|
3
3
|
require "securerandom"
|
4
4
|
require_relative "../profiler/helpers"
|
5
5
|
require_relative "output"
|
6
|
+
require "sentry/utils/uuid"
|
6
7
|
|
7
8
|
module Sentry
|
8
9
|
module Vernier
|
@@ -12,7 +13,7 @@ module Sentry
|
|
12
13
|
attr_reader :started, :event_id, :result
|
13
14
|
|
14
15
|
def initialize(configuration)
|
15
|
-
@event_id =
|
16
|
+
@event_id = Utils.uuid
|
16
17
|
|
17
18
|
@started = false
|
18
19
|
@sampled = nil
|
@@ -103,7 +104,7 @@ module Sentry
|
|
103
104
|
private
|
104
105
|
|
105
106
|
def log(message)
|
106
|
-
Sentry.
|
107
|
+
Sentry.sdk_logger.debug(LOGGER_PROGNAME) { "[Profiler::Vernier] #{message}" }
|
107
108
|
end
|
108
109
|
|
109
110
|
def record_lost_event(reason)
|
data/lib/sentry/version.rb
CHANGED
data/lib/sentry-ruby.rb
CHANGED
@@ -11,7 +11,7 @@ require "sentry/utils/argument_checking_helper"
|
|
11
11
|
require "sentry/utils/encoding_helper"
|
12
12
|
require "sentry/utils/logging_helper"
|
13
13
|
require "sentry/configuration"
|
14
|
-
require "sentry/
|
14
|
+
require "sentry/structured_logger"
|
15
15
|
require "sentry/event"
|
16
16
|
require "sentry/error_event"
|
17
17
|
require "sentry/transaction_event"
|
@@ -54,6 +54,7 @@ module Sentry
|
|
54
54
|
|
55
55
|
GLOBALS = %i[
|
56
56
|
main_hub
|
57
|
+
logger
|
57
58
|
session_flusher
|
58
59
|
backpressure_monitor
|
59
60
|
metrics_aggregator
|
@@ -138,7 +139,7 @@ module Sentry
|
|
138
139
|
# @param version [String] version of the integration
|
139
140
|
def register_integration(name, version)
|
140
141
|
if initialized?
|
141
|
-
|
142
|
+
sdk_logger.warn(LOGGER_PROGNAME) do
|
142
143
|
<<~MSG
|
143
144
|
Integration '#{name}' is loaded after the SDK is initialized, which can cause unexpected behavior. Please make sure all integrations are loaded before SDK initialization.
|
144
145
|
MSG
|
@@ -238,6 +239,7 @@ module Sentry
|
|
238
239
|
def init(&block)
|
239
240
|
config = Configuration.new
|
240
241
|
yield(config) if block_given?
|
242
|
+
|
241
243
|
config.detect_release
|
242
244
|
apply_patches(config)
|
243
245
|
config.validate
|
@@ -489,6 +491,25 @@ module Sentry
|
|
489
491
|
get_current_hub.capture_check_in(slug, status, **options)
|
490
492
|
end
|
491
493
|
|
494
|
+
# Captures a log event and sends it to Sentry via the currently active hub.
|
495
|
+
# This is the underlying method used by the StructuredLogger class.
|
496
|
+
#
|
497
|
+
# @param message [String] the log message
|
498
|
+
# @param [Hash] options Extra log event options
|
499
|
+
# @option options [Symbol] level The log level (:trace, :debug, :info, :warn, :error, :fatal)
|
500
|
+
# @option options [Integer] severity The severity number according to the Sentry Logs Protocol
|
501
|
+
# @option options [Hash] Additional attributes to include with the log
|
502
|
+
#
|
503
|
+
# @example Direct usage (prefer using Sentry.logger instead)
|
504
|
+
# Sentry.capture_log("User logged in", level: :info, user_id: 123)
|
505
|
+
#
|
506
|
+
# @see https://develop.sentry.dev/sdk/telemetry/logs/ Sentry SDK Telemetry Logs Protocol
|
507
|
+
# @return [LogEvent, nil] The created log event or nil if logging is disabled
|
508
|
+
def capture_log(message, **options)
|
509
|
+
return unless initialized?
|
510
|
+
get_current_hub.capture_log_event(message, **options)
|
511
|
+
end
|
512
|
+
|
492
513
|
# Takes or initializes a new Sentry::Transaction and makes a sampling decision for it.
|
493
514
|
#
|
494
515
|
# @return [Transaction, nil]
|
@@ -593,6 +614,43 @@ module Sentry
|
|
593
614
|
get_current_hub.continue_trace(env, **options)
|
594
615
|
end
|
595
616
|
|
617
|
+
# Returns the structured logger instance that implements Sentry's SDK telemetry logs protocol.
|
618
|
+
#
|
619
|
+
# This logger is only available when logs are enabled in the configuration.
|
620
|
+
#
|
621
|
+
# @example Enable logs in configuration
|
622
|
+
# Sentry.init do |config|
|
623
|
+
# config.dsn = "YOUR_DSN"
|
624
|
+
# config.enable_logs = true
|
625
|
+
# end
|
626
|
+
#
|
627
|
+
# @example Basic usage
|
628
|
+
# Sentry.logger.info("User logged in successfully", user_id: 123)
|
629
|
+
# Sentry.logger.error("Failed to process payment",
|
630
|
+
# transaction_id: "tx_123",
|
631
|
+
# error_code: "PAYMENT_FAILED"
|
632
|
+
# )
|
633
|
+
#
|
634
|
+
# @see https://develop.sentry.dev/sdk/telemetry/logs/ Sentry SDK Telemetry Logs Protocol
|
635
|
+
#
|
636
|
+
# @return [StructuredLogger, nil] The structured logger instance or nil if logs are disabled
|
637
|
+
def logger
|
638
|
+
@logger ||=
|
639
|
+
if configuration.enable_logs
|
640
|
+
# Initialize the public-facing Structured Logger if logs are enabled
|
641
|
+
# This creates a StructuredLogger instance that implements Sentry's SDK telemetry logs protocol
|
642
|
+
# @see https://develop.sentry.dev/sdk/telemetry/logs/
|
643
|
+
StructuredLogger.new(configuration)
|
644
|
+
else
|
645
|
+
warn <<~STR
|
646
|
+
[sentry] `Sentry.logger` will no longer be used as internal SDK logger when `enable_logs` feature is turned on.
|
647
|
+
Use Sentry.configuration.sdk_logger for SDK-specific logging needs."
|
648
|
+
STR
|
649
|
+
|
650
|
+
configuration.sdk_logger
|
651
|
+
end
|
652
|
+
end
|
653
|
+
|
596
654
|
##### Helpers #####
|
597
655
|
|
598
656
|
# @!visibility private
|
@@ -604,8 +662,8 @@ module Sentry
|
|
604
662
|
end
|
605
663
|
|
606
664
|
# @!visibility private
|
607
|
-
def
|
608
|
-
configuration.
|
665
|
+
def sdk_logger
|
666
|
+
configuration.sdk_logger
|
609
667
|
end
|
610
668
|
|
611
669
|
# @!visibility private
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sentry-ruby
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 5.
|
4
|
+
version: 5.24.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sentry Team
|
8
8
|
bindir: bin
|
9
9
|
cert_chain: []
|
10
|
-
date:
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
11
11
|
dependencies:
|
12
12
|
- !ruby/object:Gem::Dependency
|
13
13
|
name: concurrent-ruby
|
@@ -48,8 +48,8 @@ email: accounts@sentry.io
|
|
48
48
|
executables: []
|
49
49
|
extensions: []
|
50
50
|
extra_rdoc_files:
|
51
|
-
- README.md
|
52
51
|
- LICENSE.txt
|
52
|
+
- README.md
|
53
53
|
files:
|
54
54
|
- ".gitignore"
|
55
55
|
- ".rspec"
|
@@ -101,6 +101,8 @@ files:
|
|
101
101
|
- lib/sentry/interfaces/stacktrace_builder.rb
|
102
102
|
- lib/sentry/interfaces/threads.rb
|
103
103
|
- lib/sentry/linecache.rb
|
104
|
+
- lib/sentry/log_event.rb
|
105
|
+
- lib/sentry/log_event_buffer.rb
|
104
106
|
- lib/sentry/logger.rb
|
105
107
|
- lib/sentry/metrics.rb
|
106
108
|
- lib/sentry/metrics/aggregator.rb
|
@@ -127,6 +129,7 @@ files:
|
|
127
129
|
- lib/sentry/session.rb
|
128
130
|
- lib/sentry/session_flusher.rb
|
129
131
|
- lib/sentry/span.rb
|
132
|
+
- lib/sentry/structured_logger.rb
|
130
133
|
- lib/sentry/test_helper.rb
|
131
134
|
- lib/sentry/threaded_periodic_worker.rb
|
132
135
|
- lib/sentry/transaction.rb
|
@@ -145,20 +148,21 @@ files:
|
|
145
148
|
- lib/sentry/utils/logging_helper.rb
|
146
149
|
- lib/sentry/utils/real_ip.rb
|
147
150
|
- lib/sentry/utils/request_id.rb
|
151
|
+
- lib/sentry/utils/uuid.rb
|
148
152
|
- lib/sentry/vernier/output.rb
|
149
153
|
- lib/sentry/vernier/profiler.rb
|
150
154
|
- lib/sentry/version.rb
|
151
155
|
- sentry-ruby-core.gemspec
|
152
156
|
- sentry-ruby.gemspec
|
153
|
-
homepage: https://github.com/getsentry/sentry-ruby/tree/5.
|
157
|
+
homepage: https://github.com/getsentry/sentry-ruby/tree/5.24.0/sentry-ruby
|
154
158
|
licenses:
|
155
159
|
- MIT
|
156
160
|
metadata:
|
157
|
-
homepage_uri: https://github.com/getsentry/sentry-ruby/tree/5.
|
158
|
-
source_code_uri: https://github.com/getsentry/sentry-ruby/tree/5.
|
159
|
-
changelog_uri: https://github.com/getsentry/sentry-ruby/blob/5.
|
161
|
+
homepage_uri: https://github.com/getsentry/sentry-ruby/tree/5.24.0/sentry-ruby
|
162
|
+
source_code_uri: https://github.com/getsentry/sentry-ruby/tree/5.24.0/sentry-ruby
|
163
|
+
changelog_uri: https://github.com/getsentry/sentry-ruby/blob/5.24.0/CHANGELOG.md
|
160
164
|
bug_tracker_uri: https://github.com/getsentry/sentry-ruby/issues
|
161
|
-
documentation_uri: http://www.rubydoc.info/gems/sentry-ruby/5.
|
165
|
+
documentation_uri: http://www.rubydoc.info/gems/sentry-ruby/5.24.0
|
162
166
|
rdoc_options: []
|
163
167
|
require_paths:
|
164
168
|
- lib
|
@@ -173,7 +177,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
173
177
|
- !ruby/object:Gem::Version
|
174
178
|
version: '0'
|
175
179
|
requirements: []
|
176
|
-
rubygems_version: 3.6.
|
180
|
+
rubygems_version: 3.6.7
|
177
181
|
specification_version: 4
|
178
182
|
summary: A gem that provides a client interface for the Sentry error logger
|
179
183
|
test_files: []
|