sentry-ruby-core 5.22.4 → 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/Gemfile +4 -3
- data/lib/sentry/background_worker.rb +2 -3
- data/lib/sentry/backpressure_monitor.rb +1 -1
- data/lib/sentry/backtrace.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 +34 -2
- data/lib/sentry/envelope/item.rb +1 -1
- data/lib/sentry/event.rb +2 -1
- data/lib/sentry/hub.rb +41 -1
- data/lib/sentry/interfaces/request.rb +1 -1
- data/lib/sentry/linecache.rb +3 -3
- 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 +20 -0
- data/lib/sentry/threaded_periodic_worker.rb +3 -3
- data/lib/sentry/transaction.rb +9 -9
- data/lib/sentry/transaction_event.rb +4 -1
- data/lib/sentry/transport/http_transport.rb +0 -1
- data/lib/sentry/transport.rb +16 -8
- data/lib/sentry/utils/http_tracing.rb +15 -1
- data/lib/sentry/utils/logging_helper.rb +10 -3
- data/lib/sentry/utils/uuid.rb +13 -0
- data/lib/sentry/vernier/profiler.rb +6 -4
- data/lib/sentry/version.rb +1 -1
- data/lib/sentry-ruby.rb +70 -4
- metadata +10 -6
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
|
@@ -83,5 +90,18 @@ module Sentry
|
|
83
90
|
def extract_sentry_exceptions(event)
|
84
91
|
event&.exception&.values || []
|
85
92
|
end
|
93
|
+
|
94
|
+
def reset_sentry_globals!
|
95
|
+
Sentry::MUTEX.synchronize do
|
96
|
+
# Don't check initialized? because sometimes we stub it in tests
|
97
|
+
if Sentry.instance_variable_defined?(:@main_hub)
|
98
|
+
Sentry::GLOBALS.each do |var|
|
99
|
+
Sentry.instance_variable_set(:"@#{var}", nil)
|
100
|
+
end
|
101
|
+
|
102
|
+
Thread.current.thread_variable_set(Sentry::THREAD_LOCAL, nil)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
86
106
|
end
|
87
107
|
end
|
@@ -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,14 +75,18 @@ 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
|
85
82
|
@effective_sample_rate = nil
|
86
83
|
@contexts = {}
|
87
84
|
@measurements = {}
|
88
|
-
|
85
|
+
|
86
|
+
unless @hub.profiler_running?
|
87
|
+
@profiler = @configuration.profiler_class.new(@configuration)
|
88
|
+
end
|
89
|
+
|
89
90
|
init_span_recorder
|
90
91
|
end
|
91
92
|
|
@@ -257,7 +258,7 @@ module Sentry
|
|
257
258
|
@name = UNLABELD_NAME
|
258
259
|
end
|
259
260
|
|
260
|
-
@
|
261
|
+
@hub.stop_profiler!(self)
|
261
262
|
|
262
263
|
if @sampled
|
263
264
|
event = hub.current_client.event_from_transaction(self)
|
@@ -299,6 +300,8 @@ module Sentry
|
|
299
300
|
# Start the profiler.
|
300
301
|
# @return [void]
|
301
302
|
def start_profiler!
|
303
|
+
return unless profiler
|
304
|
+
|
302
305
|
profiler.set_initial_sample_decision(sampled)
|
303
306
|
profiler.start
|
304
307
|
end
|
@@ -336,9 +339,6 @@ module Sentry
|
|
336
339
|
|
337
340
|
items["transaction"] = name unless source_low_quality?
|
338
341
|
|
339
|
-
user = @hub.current_scope&.user
|
340
|
-
items["user_segment"] = user["segment"] if user && user["segment"]
|
341
|
-
|
342
342
|
items.compact!
|
343
343
|
@baggage = Baggage.new(items, mutable: false)
|
344
344
|
end
|
@@ -59,8 +59,11 @@ module Sentry
|
|
59
59
|
|
60
60
|
private
|
61
61
|
|
62
|
+
EMPTY_PROFILE = {}.freeze
|
63
|
+
|
62
64
|
def populate_profile(transaction)
|
63
|
-
profile_hash = transaction.profiler
|
65
|
+
profile_hash = transaction.profiler&.to_hash || EMPTY_PROFILE
|
66
|
+
|
64
67
|
return if profile_hash.empty?
|
65
68
|
|
66
69
|
profile_hash.merge!(
|
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(
|
@@ -17,7 +17,7 @@ module Sentry
|
|
17
17
|
|
18
18
|
def record_sentry_breadcrumb(request_info, response_status)
|
19
19
|
crumb = Sentry::Breadcrumb.new(
|
20
|
-
level:
|
20
|
+
level: get_level(response_status),
|
21
21
|
category: self.class::BREADCRUMB_CATEGORY,
|
22
22
|
type: "info",
|
23
23
|
data: { status: response_status, **request_info }
|
@@ -55,6 +55,20 @@ module Sentry
|
|
55
55
|
"#{URI.encode_www_form_component(prefix)}=#{URI.encode_www_form_component(value)}"
|
56
56
|
end
|
57
57
|
end
|
58
|
+
|
59
|
+
private
|
60
|
+
|
61
|
+
def get_level(status)
|
62
|
+
return :info unless status && status.is_a?(Integer)
|
63
|
+
|
64
|
+
if status >= 500
|
65
|
+
:error
|
66
|
+
elsif status >= 400
|
67
|
+
:warning
|
68
|
+
else
|
69
|
+
:info
|
70
|
+
end
|
71
|
+
end
|
58
72
|
end
|
59
73
|
end
|
60
74
|
end
|
@@ -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
|
@@ -74,6 +75,7 @@ module Sentry
|
|
74
75
|
return unless @started
|
75
76
|
|
76
77
|
@result = ::Vernier.stop_profile
|
78
|
+
@started = false
|
77
79
|
|
78
80
|
log("Stopped")
|
79
81
|
rescue RuntimeError => e
|
@@ -89,20 +91,20 @@ module Sentry
|
|
89
91
|
end
|
90
92
|
|
91
93
|
def to_hash
|
92
|
-
return EMPTY_RESULT unless @started
|
93
|
-
|
94
94
|
unless @sampled
|
95
95
|
record_lost_event(:sample_rate)
|
96
96
|
return EMPTY_RESULT
|
97
97
|
end
|
98
98
|
|
99
|
+
return EMPTY_RESULT unless result
|
100
|
+
|
99
101
|
{ **profile_meta, profile: output.to_h }
|
100
102
|
end
|
101
103
|
|
102
104
|
private
|
103
105
|
|
104
106
|
def log(message)
|
105
|
-
Sentry.
|
107
|
+
Sentry.sdk_logger.debug(LOGGER_PROGNAME) { "[Profiler::Vernier] #{message}" }
|
106
108
|
end
|
107
109
|
|
108
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"
|
@@ -52,6 +52,15 @@ module Sentry
|
|
52
52
|
|
53
53
|
MUTEX = Mutex.new
|
54
54
|
|
55
|
+
GLOBALS = %i[
|
56
|
+
main_hub
|
57
|
+
logger
|
58
|
+
session_flusher
|
59
|
+
backpressure_monitor
|
60
|
+
metrics_aggregator
|
61
|
+
exception_locals_tp
|
62
|
+
].freeze
|
63
|
+
|
55
64
|
class << self
|
56
65
|
# @!visibility private
|
57
66
|
def exception_locals_tp
|
@@ -130,7 +139,7 @@ module Sentry
|
|
130
139
|
# @param version [String] version of the integration
|
131
140
|
def register_integration(name, version)
|
132
141
|
if initialized?
|
133
|
-
|
142
|
+
sdk_logger.warn(LOGGER_PROGNAME) do
|
134
143
|
<<~MSG
|
135
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.
|
136
145
|
MSG
|
@@ -230,6 +239,7 @@ module Sentry
|
|
230
239
|
def init(&block)
|
231
240
|
config = Configuration.new
|
232
241
|
yield(config) if block_given?
|
242
|
+
|
233
243
|
config.detect_release
|
234
244
|
apply_patches(config)
|
235
245
|
config.validate
|
@@ -481,6 +491,25 @@ module Sentry
|
|
481
491
|
get_current_hub.capture_check_in(slug, status, **options)
|
482
492
|
end
|
483
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
|
+
|
484
513
|
# Takes or initializes a new Sentry::Transaction and makes a sampling decision for it.
|
485
514
|
#
|
486
515
|
# @return [Transaction, nil]
|
@@ -585,6 +614,43 @@ module Sentry
|
|
585
614
|
get_current_hub.continue_trace(env, **options)
|
586
615
|
end
|
587
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
|
+
|
588
654
|
##### Helpers #####
|
589
655
|
|
590
656
|
# @!visibility private
|
@@ -596,8 +662,8 @@ module Sentry
|
|
596
662
|
end
|
597
663
|
|
598
664
|
# @!visibility private
|
599
|
-
def
|
600
|
-
configuration.
|
665
|
+
def sdk_logger
|
666
|
+
configuration.sdk_logger
|
601
667
|
end
|
602
668
|
|
603
669
|
# @!visibility private
|