sentry-ruby 5.23.0 → 5.27.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/.rspec +3 -1
- data/Gemfile +1 -3
- data/README.md +11 -6
- data/Rakefile +7 -11
- 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 +84 -4
- data/lib/sentry/configuration.rb +63 -2
- data/lib/sentry/debug_structured_logger.rb +94 -0
- data/lib/sentry/dsn.rb +32 -0
- data/lib/sentry/envelope/item.rb +1 -1
- data/lib/sentry/event.rb +2 -1
- data/lib/sentry/hub.rb +13 -1
- data/lib/sentry/interfaces/request.rb +1 -1
- data/lib/sentry/log_event.rb +206 -0
- data/lib/sentry/log_event_buffer.rb +75 -0
- data/lib/sentry/metrics/aggregator.rb +1 -1
- data/lib/sentry/profiler.rb +3 -2
- data/lib/sentry/propagation_context.rb +59 -22
- data/lib/sentry/scope.rb +13 -3
- data/lib/sentry/session_flusher.rb +1 -1
- data/lib/sentry/span.rb +4 -3
- data/lib/sentry/std_lib_logger.rb +50 -0
- data/lib/sentry/structured_logger.rb +138 -0
- data/lib/sentry/test_helper.rb +29 -0
- data/lib/sentry/threaded_periodic_worker.rb +3 -3
- data/lib/sentry/transaction.rb +30 -8
- 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 +17 -8
- data/lib/sentry/utils/logging_helper.rb +10 -3
- data/lib/sentry/utils/sample_rand.rb +97 -0
- 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 +67 -4
- metadata +17 -9
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)
|
@@ -216,6 +217,16 @@ module Sentry
|
|
216
217
|
event.check_in_id
|
217
218
|
end
|
218
219
|
|
220
|
+
def capture_log_event(message, **options)
|
221
|
+
return unless current_client
|
222
|
+
|
223
|
+
event = current_client.event_from_log(message, **options)
|
224
|
+
|
225
|
+
return unless event
|
226
|
+
|
227
|
+
current_client.buffer_log_event(event, current_scope)
|
228
|
+
end
|
229
|
+
|
219
230
|
def capture_event(event, **options, &block)
|
220
231
|
check_argument_type!(event, Sentry::Event)
|
221
232
|
|
@@ -347,6 +358,7 @@ module Sentry
|
|
347
358
|
parent_span_id: propagation_context.parent_span_id,
|
348
359
|
parent_sampled: propagation_context.parent_sampled,
|
349
360
|
baggage: propagation_context.baggage,
|
361
|
+
sample_rand: propagation_context.sample_rand,
|
350
362
|
**options
|
351
363
|
)
|
352
364
|
end
|
@@ -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,206 @@
|
|
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
|
8
|
+
TYPE = "log"
|
9
|
+
|
10
|
+
DEFAULT_PARAMETERS = [].freeze
|
11
|
+
DEFAULT_ATTRIBUTES = {}.freeze
|
12
|
+
|
13
|
+
SERIALIZEABLE_ATTRIBUTES = %i[
|
14
|
+
level
|
15
|
+
body
|
16
|
+
timestamp
|
17
|
+
environment
|
18
|
+
release
|
19
|
+
server_name
|
20
|
+
trace_id
|
21
|
+
attributes
|
22
|
+
contexts
|
23
|
+
]
|
24
|
+
|
25
|
+
SENTRY_ATTRIBUTES = {
|
26
|
+
"sentry.trace.parent_span_id" => :parent_span_id,
|
27
|
+
"sentry.environment" => :environment,
|
28
|
+
"sentry.release" => :release,
|
29
|
+
"sentry.address" => :server_name,
|
30
|
+
"sentry.sdk.name" => :sdk_name,
|
31
|
+
"sentry.sdk.version" => :sdk_version,
|
32
|
+
"sentry.message.template" => :template
|
33
|
+
}
|
34
|
+
|
35
|
+
USER_ATTRIBUTES = {
|
36
|
+
"user.id" => :user_id,
|
37
|
+
"user.name" => :user_username,
|
38
|
+
"user.email" => :user_email
|
39
|
+
}
|
40
|
+
|
41
|
+
LEVELS = %i[trace debug info warn error fatal].freeze
|
42
|
+
|
43
|
+
attr_accessor :level, :body, :template, :attributes, :user
|
44
|
+
|
45
|
+
attr_reader :configuration, *(SERIALIZEABLE_ATTRIBUTES - %i[level body attributes])
|
46
|
+
|
47
|
+
SERIALIZERS = %i[
|
48
|
+
attributes
|
49
|
+
body
|
50
|
+
level
|
51
|
+
parent_span_id
|
52
|
+
sdk_name
|
53
|
+
sdk_version
|
54
|
+
timestamp
|
55
|
+
trace_id
|
56
|
+
user_id
|
57
|
+
user_username
|
58
|
+
user_email
|
59
|
+
].map { |name| [name, :"serialize_#{name}"] }.to_h
|
60
|
+
|
61
|
+
VALUE_TYPES = Hash.new("string").merge!({
|
62
|
+
TrueClass => "boolean",
|
63
|
+
FalseClass => "boolean",
|
64
|
+
Integer => "integer",
|
65
|
+
Float => "double"
|
66
|
+
}).freeze
|
67
|
+
|
68
|
+
TOKEN_REGEXP = /%\{(\w+)\}/
|
69
|
+
|
70
|
+
def initialize(configuration: Sentry.configuration, **options)
|
71
|
+
@configuration = configuration
|
72
|
+
@type = TYPE
|
73
|
+
@server_name = configuration.server_name
|
74
|
+
@environment = configuration.environment
|
75
|
+
@release = configuration.release
|
76
|
+
@timestamp = Sentry.utc_now
|
77
|
+
@level = options.fetch(:level)
|
78
|
+
@body = options[:body]
|
79
|
+
@template = @body if is_template?
|
80
|
+
@attributes = options[:attributes] || DEFAULT_ATTRIBUTES
|
81
|
+
@user = options[:user] || {}
|
82
|
+
@contexts = {}
|
83
|
+
end
|
84
|
+
|
85
|
+
def to_hash
|
86
|
+
SERIALIZEABLE_ATTRIBUTES.each_with_object({}) do |name, memo|
|
87
|
+
memo[name] = serialize(name)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
private
|
92
|
+
|
93
|
+
def serialize(name)
|
94
|
+
serializer = SERIALIZERS[name]
|
95
|
+
|
96
|
+
if serializer
|
97
|
+
__send__(serializer)
|
98
|
+
else
|
99
|
+
public_send(name)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def serialize_level
|
104
|
+
level.to_s
|
105
|
+
end
|
106
|
+
|
107
|
+
def serialize_sdk_name
|
108
|
+
Sentry.sdk_meta["name"]
|
109
|
+
end
|
110
|
+
|
111
|
+
def serialize_sdk_version
|
112
|
+
Sentry.sdk_meta["version"]
|
113
|
+
end
|
114
|
+
|
115
|
+
def serialize_timestamp
|
116
|
+
timestamp.to_f
|
117
|
+
end
|
118
|
+
|
119
|
+
def serialize_trace_id
|
120
|
+
contexts.dig(:trace, :trace_id)
|
121
|
+
end
|
122
|
+
|
123
|
+
def serialize_parent_span_id
|
124
|
+
contexts.dig(:trace, :parent_span_id)
|
125
|
+
end
|
126
|
+
|
127
|
+
def serialize_body
|
128
|
+
if parameters.empty?
|
129
|
+
body
|
130
|
+
elsif parameters.is_a?(Hash)
|
131
|
+
body % parameters
|
132
|
+
else
|
133
|
+
sprintf(body, *parameters)
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
def serialize_user_id
|
138
|
+
user[:id]
|
139
|
+
end
|
140
|
+
|
141
|
+
def serialize_user_username
|
142
|
+
user[:username]
|
143
|
+
end
|
144
|
+
|
145
|
+
def serialize_user_email
|
146
|
+
user[:email]
|
147
|
+
end
|
148
|
+
|
149
|
+
def serialize_attributes
|
150
|
+
hash = {}
|
151
|
+
|
152
|
+
attributes.each do |key, value|
|
153
|
+
hash[key] = attribute_hash(value)
|
154
|
+
end
|
155
|
+
|
156
|
+
SENTRY_ATTRIBUTES.each do |key, name|
|
157
|
+
if (value = serialize(name))
|
158
|
+
hash[key] = attribute_hash(value)
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
USER_ATTRIBUTES.each do |key, name|
|
163
|
+
if (value = serialize(name))
|
164
|
+
hash[key] = value
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
hash
|
169
|
+
end
|
170
|
+
|
171
|
+
def attribute_hash(value)
|
172
|
+
{ value: value, type: value_type(value) }
|
173
|
+
end
|
174
|
+
|
175
|
+
def value_type(value)
|
176
|
+
VALUE_TYPES[value.class]
|
177
|
+
end
|
178
|
+
|
179
|
+
def parameters
|
180
|
+
@parameters ||= begin
|
181
|
+
return DEFAULT_PARAMETERS unless template
|
182
|
+
|
183
|
+
parameters = template_tokens.empty? ?
|
184
|
+
attributes.fetch(:parameters, DEFAULT_PARAMETERS) : attributes.slice(*template_tokens)
|
185
|
+
|
186
|
+
if parameters.is_a?(Hash)
|
187
|
+
parameters.each do |key, value|
|
188
|
+
attributes["sentry.message.parameter.#{key}"] = value
|
189
|
+
end
|
190
|
+
else
|
191
|
+
parameters.each_with_index do |param, index|
|
192
|
+
attributes["sentry.message.parameter.#{index}"] = param
|
193
|
+
end
|
194
|
+
end
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
def template_tokens
|
199
|
+
@template_tokens ||= body.scan(TOKEN_REGEXP).flatten.map(&:to_sym)
|
200
|
+
end
|
201
|
+
|
202
|
+
def is_template?
|
203
|
+
body.include?("%s") || TOKEN_REGEXP.match?(body)
|
204
|
+
end
|
205
|
+
end
|
206
|
+
end
|
@@ -0,0 +1,75 @@
|
|
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
|
+
@mutex = Mutex.new
|
25
|
+
|
26
|
+
log_debug("[Logging] Initialized buffer with max_events=#{@max_events}, flush_interval=#{FLUSH_INTERVAL}s")
|
27
|
+
end
|
28
|
+
|
29
|
+
def start
|
30
|
+
ensure_thread
|
31
|
+
self
|
32
|
+
end
|
33
|
+
|
34
|
+
def flush
|
35
|
+
@mutex.synchronize do
|
36
|
+
return if empty?
|
37
|
+
|
38
|
+
log_debug("[LogEventBuffer] flushing #{size} log events")
|
39
|
+
|
40
|
+
send_events
|
41
|
+
end
|
42
|
+
|
43
|
+
log_debug("[LogEventBuffer] flushed #{size} log events")
|
44
|
+
|
45
|
+
self
|
46
|
+
end
|
47
|
+
alias_method :run, :flush
|
48
|
+
|
49
|
+
def add_event(event)
|
50
|
+
raise ArgumentError, "expected a LogEvent, got #{event.class}" unless event.is_a?(LogEvent)
|
51
|
+
|
52
|
+
@mutex.synchronize do
|
53
|
+
@pending_events << event
|
54
|
+
send_events if size >= @max_events
|
55
|
+
end
|
56
|
+
|
57
|
+
self
|
58
|
+
end
|
59
|
+
|
60
|
+
def empty?
|
61
|
+
@pending_events.empty?
|
62
|
+
end
|
63
|
+
|
64
|
+
def size
|
65
|
+
@pending_events.size
|
66
|
+
end
|
67
|
+
|
68
|
+
private
|
69
|
+
|
70
|
+
def send_events
|
71
|
+
@client.send_logs(@pending_events)
|
72
|
+
@pending_events.clear
|
73
|
+
end
|
74
|
+
end
|
75
|
+
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,15 +2,15 @@
|
|
2
2
|
|
3
3
|
require "securerandom"
|
4
4
|
require "sentry/baggage"
|
5
|
+
require "sentry/utils/uuid"
|
6
|
+
require "sentry/utils/sample_rand"
|
5
7
|
|
6
8
|
module Sentry
|
7
9
|
class PropagationContext
|
8
10
|
SENTRY_TRACE_REGEXP = Regexp.new(
|
9
|
-
"
|
10
|
-
"([0-9a-f]{32})?" + # trace_id
|
11
|
+
"\\A([0-9a-f]{32})?" + # trace_id
|
11
12
|
"-?([0-9a-f]{16})?" + # span_id
|
12
|
-
"-?([01])
|
13
|
-
"[ \t]*$" # whitespace
|
13
|
+
"-?([01])?\\z" # sampled
|
14
14
|
)
|
15
15
|
|
16
16
|
# An uuid that can be used to identify a trace.
|
@@ -32,6 +32,53 @@ module Sentry
|
|
32
32
|
# Please use the #get_baggage method for interfacing outside this class.
|
33
33
|
# @return [Baggage, nil]
|
34
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
|
35
82
|
|
36
83
|
def initialize(scope, env = nil)
|
37
84
|
@scope = scope
|
@@ -39,6 +86,7 @@ module Sentry
|
|
39
86
|
@parent_sampled = nil
|
40
87
|
@baggage = nil
|
41
88
|
@incoming_trace = false
|
89
|
+
@sample_rand = nil
|
42
90
|
|
43
91
|
if env
|
44
92
|
sentry_trace_header = env["HTTP_SENTRY_TRACE"] || env[SENTRY_TRACE_HEADER_NAME]
|
@@ -60,28 +108,17 @@ module Sentry
|
|
60
108
|
Baggage.new({})
|
61
109
|
end
|
62
110
|
|
111
|
+
@sample_rand = self.class.extract_sample_rand_from_baggage(@baggage, @trace_id)
|
112
|
+
|
63
113
|
@baggage.freeze!
|
64
114
|
@incoming_trace = true
|
65
115
|
end
|
66
116
|
end
|
67
117
|
end
|
68
118
|
|
69
|
-
@trace_id ||=
|
70
|
-
@span_id =
|
71
|
-
|
72
|
-
|
73
|
-
# Extract the trace_id, parent_span_id and parent_sampled values from a sentry-trace header.
|
74
|
-
#
|
75
|
-
# @param sentry_trace [String] the sentry-trace header value from the previous transaction.
|
76
|
-
# @return [Array, nil]
|
77
|
-
def self.extract_sentry_trace(sentry_trace)
|
78
|
-
match = SENTRY_TRACE_REGEXP.match(sentry_trace)
|
79
|
-
return nil if match.nil?
|
80
|
-
|
81
|
-
trace_id, parent_span_id, sampled_flag = match[1..3]
|
82
|
-
parent_sampled = sampled_flag.nil? ? nil : sampled_flag != "0"
|
83
|
-
|
84
|
-
[trace_id, parent_span_id, parent_sampled]
|
119
|
+
@trace_id ||= Utils.uuid
|
120
|
+
@span_id = Utils.uuid.slice(0, 16)
|
121
|
+
@sample_rand ||= self.class.generate_sample_rand(@baggage, @trace_id, @parent_sampled)
|
85
122
|
end
|
86
123
|
|
87
124
|
# Returns the trace context that can be used to embed in an Event.
|
@@ -122,10 +159,10 @@ module Sentry
|
|
122
159
|
|
123
160
|
items = {
|
124
161
|
"trace_id" => trace_id,
|
162
|
+
"sample_rand" => Utils::SampleRand.format(@sample_rand),
|
125
163
|
"environment" => configuration.environment,
|
126
164
|
"release" => configuration.release,
|
127
|
-
"public_key" => configuration.dsn&.public_key
|
128
|
-
"user_segment" => @scope.user && @scope.user["segment"]
|
165
|
+
"public_key" => configuration.dsn&.public_key
|
129
166
|
}
|
130
167
|
|
131
168
|
items.compact!
|
data/lib/sentry/scope.rb
CHANGED
@@ -46,7 +46,7 @@ module Sentry
|
|
46
46
|
# @param hint [Hash] the hint data that'll be passed to event processors.
|
47
47
|
# @return [Event]
|
48
48
|
def apply_to_event(event, hint = nil)
|
49
|
-
unless event.is_a?(CheckInEvent)
|
49
|
+
unless event.is_a?(CheckInEvent) || event.is_a?(LogEvent)
|
50
50
|
event.tags = tags.merge(event.tags)
|
51
51
|
event.user = user.merge(event.user)
|
52
52
|
event.extra = extra.merge(event.extra)
|
@@ -60,12 +60,22 @@ module Sentry
|
|
60
60
|
event.attachments = attachments
|
61
61
|
end
|
62
62
|
|
63
|
+
if event.is_a?(LogEvent)
|
64
|
+
event.user = user.merge(event.user)
|
65
|
+
end
|
66
|
+
|
63
67
|
if span
|
64
68
|
event.contexts[:trace] ||= span.get_trace_context
|
65
|
-
|
69
|
+
|
70
|
+
if event.respond_to?(:dynamic_sampling_context)
|
71
|
+
event.dynamic_sampling_context ||= span.get_dynamic_sampling_context
|
72
|
+
end
|
66
73
|
else
|
67
74
|
event.contexts[:trace] ||= propagation_context.get_trace_context
|
68
|
-
|
75
|
+
|
76
|
+
if event.respond_to?(:dynamic_sampling_context)
|
77
|
+
event.dynamic_sampling_context ||= propagation_context.get_dynamic_sampling_context
|
78
|
+
end
|
69
79
|
end
|
70
80
|
|
71
81
|
all_event_processors = self.class.global_event_processors + @event_processors
|
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
|
@@ -261,7 +262,7 @@ module Sentry
|
|
261
262
|
|
262
263
|
|
263
264
|
# Sets the span's status.
|
264
|
-
# @param
|
265
|
+
# @param status [String] status of the span.
|
265
266
|
def set_status(status)
|
266
267
|
@status = status
|
267
268
|
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Sentry
|
4
|
+
# Ruby Logger support Add commentMore actions
|
5
|
+
# intercepts any logger instance and send the log to Sentry too.
|
6
|
+
module StdLibLogger
|
7
|
+
SEVERITY_MAP = {
|
8
|
+
0 => :debug,
|
9
|
+
1 => :info,
|
10
|
+
2 => :warn,
|
11
|
+
3 => :error,
|
12
|
+
4 => :fatal
|
13
|
+
}.freeze
|
14
|
+
|
15
|
+
def add(severity, message = nil, progname = nil, &block)
|
16
|
+
result = super
|
17
|
+
|
18
|
+
return unless Sentry.initialized? && Sentry.get_current_hub
|
19
|
+
|
20
|
+
# exclude sentry SDK logs -- to prevent recursive log action,
|
21
|
+
# do not process internal logs again
|
22
|
+
if message.nil? && progname != Sentry::Logger::PROGNAME
|
23
|
+
|
24
|
+
# handle different nature of Ruby Logger class:
|
25
|
+
# inspo from Sentry::Breadcrumb::SentryLogger
|
26
|
+
if block_given?
|
27
|
+
message = yield
|
28
|
+
else
|
29
|
+
message = progname
|
30
|
+
end
|
31
|
+
|
32
|
+
message = message.to_s.strip
|
33
|
+
|
34
|
+
if !message.nil? && message != Sentry::Logger::PROGNAME && method = SEVERITY_MAP[severity]
|
35
|
+
Sentry.logger.send(method, message)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
result
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
Sentry.register_patch(:logger) do |config|
|
45
|
+
if config.enable_logs
|
46
|
+
::Logger.prepend(Sentry::StdLibLogger)
|
47
|
+
else
|
48
|
+
config.sdk_logger.warn(":logger patch enabled but `enable_logs` is turned off - skipping applying patch")
|
49
|
+
end
|
50
|
+
end
|