sentry-ruby 5.26.0 → 6.3.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 +26 -4
- data/README.md +2 -2
- data/lib/sentry/background_worker.rb +1 -4
- data/lib/sentry/backtrace/line.rb +99 -0
- data/lib/sentry/backtrace.rb +44 -76
- data/lib/sentry/breadcrumb.rb +1 -1
- data/lib/sentry/breadcrumb_buffer.rb +2 -2
- data/lib/sentry/check_in_event.rb +2 -2
- data/lib/sentry/client.rb +59 -136
- data/lib/sentry/configuration.rb +168 -78
- data/lib/sentry/cron/monitor_check_ins.rb +3 -3
- data/lib/sentry/cron/monitor_config.rb +2 -2
- data/lib/sentry/cron/monitor_schedule.rb +2 -2
- data/lib/sentry/debug_structured_logger.rb +94 -0
- data/lib/sentry/dsn.rb +32 -0
- data/lib/sentry/envelope/item.rb +3 -3
- data/lib/sentry/error_event.rb +3 -3
- data/lib/sentry/event.rb +4 -10
- data/lib/sentry/graphql.rb +1 -1
- data/lib/sentry/hub.rb +29 -5
- data/lib/sentry/interface.rb +1 -1
- data/lib/sentry/interfaces/exception.rb +2 -2
- data/lib/sentry/interfaces/request.rb +2 -0
- data/lib/sentry/interfaces/single_exception.rb +4 -4
- data/lib/sentry/interfaces/stacktrace.rb +3 -3
- data/lib/sentry/interfaces/stacktrace_builder.rb +0 -8
- data/lib/sentry/interfaces/threads.rb +2 -2
- data/lib/sentry/log_event.rb +33 -138
- data/lib/sentry/log_event_buffer.rb +13 -60
- data/lib/sentry/metric_event.rb +49 -0
- data/lib/sentry/metric_event_buffer.rb +28 -0
- data/lib/sentry/metrics.rb +47 -42
- data/lib/sentry/profiler.rb +4 -5
- data/lib/sentry/propagation_context.rb +55 -18
- data/lib/sentry/rspec.rb +1 -1
- data/lib/sentry/scope.rb +32 -5
- data/lib/sentry/sequel.rb +35 -0
- data/lib/sentry/span.rb +2 -17
- data/lib/sentry/std_lib_logger.rb +10 -1
- data/lib/sentry/telemetry_event_buffer.rb +130 -0
- data/lib/sentry/test_helper.rb +30 -0
- data/lib/sentry/transaction.rb +72 -95
- data/lib/sentry/transaction_event.rb +4 -9
- 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 +3 -5
- data/lib/sentry/utils/encoding_helper.rb +6 -0
- data/lib/sentry/utils/logging_helper.rb +25 -9
- data/lib/sentry/utils/sample_rand.rb +97 -0
- data/lib/sentry/utils/telemetry_attributes.rb +30 -0
- data/lib/sentry/vernier/profiler.rb +4 -3
- data/lib/sentry/version.rb +1 -1
- data/lib/sentry-ruby.rb +25 -30
- data/sentry-ruby-core.gemspec +1 -1
- data/sentry-ruby.gemspec +1 -1
- metadata +17 -17
- data/lib/sentry/metrics/aggregator.rb +0 -248
- data/lib/sentry/metrics/configuration.rb +0 -47
- data/lib/sentry/metrics/counter_metric.rb +0 -25
- data/lib/sentry/metrics/distribution_metric.rb +0 -25
- data/lib/sentry/metrics/gauge_metric.rb +0 -35
- data/lib/sentry/metrics/local_aggregator.rb +0 -53
- data/lib/sentry/metrics/metric.rb +0 -19
- data/lib/sentry/metrics/set_metric.rb +0 -28
- data/lib/sentry/metrics/timing.rb +0 -51
data/lib/sentry/event.rb
CHANGED
|
@@ -81,12 +81,6 @@ module Sentry
|
|
|
81
81
|
@message = (message || "").byteslice(0..MAX_MESSAGE_SIZE_IN_BYTES)
|
|
82
82
|
end
|
|
83
83
|
|
|
84
|
-
# @deprecated This method will be removed in v5.0.0. Please just use Sentry.configuration
|
|
85
|
-
# @return [Configuration]
|
|
86
|
-
def configuration
|
|
87
|
-
Sentry.configuration
|
|
88
|
-
end
|
|
89
|
-
|
|
90
84
|
# Sets the event's timestamp.
|
|
91
85
|
# @param time [Time, Float]
|
|
92
86
|
# @return [void]
|
|
@@ -118,16 +112,16 @@ module Sentry
|
|
|
118
112
|
end
|
|
119
113
|
|
|
120
114
|
# @return [Hash]
|
|
121
|
-
def
|
|
115
|
+
def to_h
|
|
122
116
|
data = serialize_attributes
|
|
123
|
-
data[:breadcrumbs] = breadcrumbs.
|
|
124
|
-
data[:request] = request.
|
|
117
|
+
data[:breadcrumbs] = breadcrumbs.to_h if breadcrumbs
|
|
118
|
+
data[:request] = request.to_h if request
|
|
125
119
|
data
|
|
126
120
|
end
|
|
127
121
|
|
|
128
122
|
# @return [Hash]
|
|
129
123
|
def to_json_compatible
|
|
130
|
-
JSON.parse(JSON.generate(
|
|
124
|
+
JSON.parse(JSON.generate(to_h))
|
|
131
125
|
end
|
|
132
126
|
|
|
133
127
|
private
|
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
|
@@ -116,11 +116,12 @@ module Sentry
|
|
|
116
116
|
return unless configuration.tracing_enabled?
|
|
117
117
|
return unless instrumenter == configuration.instrumenter
|
|
118
118
|
|
|
119
|
-
transaction ||= Transaction.new(**options
|
|
119
|
+
transaction ||= Transaction.new(**options)
|
|
120
120
|
|
|
121
121
|
sampling_context = {
|
|
122
|
-
transaction_context: transaction.
|
|
123
|
-
parent_sampled: transaction.parent_sampled
|
|
122
|
+
transaction_context: transaction.to_h,
|
|
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)
|
|
@@ -217,7 +218,7 @@ module Sentry
|
|
|
217
218
|
end
|
|
218
219
|
|
|
219
220
|
def capture_log_event(message, **options)
|
|
220
|
-
return unless current_client
|
|
221
|
+
return unless current_client && current_client.configuration.enable_logs
|
|
221
222
|
|
|
222
223
|
event = current_client.event_from_log(message, **options)
|
|
223
224
|
|
|
@@ -226,6 +227,29 @@ module Sentry
|
|
|
226
227
|
current_client.buffer_log_event(event, current_scope)
|
|
227
228
|
end
|
|
228
229
|
|
|
230
|
+
# Captures a metric and sends it to Sentry
|
|
231
|
+
#
|
|
232
|
+
# @param name [String] the metric name
|
|
233
|
+
# @param type [Symbol] the metric type (:counter, :gauge, :distribution)
|
|
234
|
+
# @param value [Numeric] the metric value
|
|
235
|
+
# @param unit [String, nil] (optional) the metric unit
|
|
236
|
+
# @param attributes [Hash, nil] (optional) additional attributes for the metric
|
|
237
|
+
# @return [void]
|
|
238
|
+
def capture_metric(name:, type:, value:, unit: nil, attributes: nil)
|
|
239
|
+
return unless current_client&.configuration.enable_metrics
|
|
240
|
+
|
|
241
|
+
metric = MetricEvent.new(
|
|
242
|
+
name: name,
|
|
243
|
+
value: value,
|
|
244
|
+
type: type,
|
|
245
|
+
unit: unit,
|
|
246
|
+
attributes: attributes,
|
|
247
|
+
)
|
|
248
|
+
|
|
249
|
+
current_client.buffer_metric_event(metric, current_scope)
|
|
250
|
+
end
|
|
251
|
+
|
|
252
|
+
|
|
229
253
|
def capture_event(event, **options, &block)
|
|
230
254
|
check_argument_type!(event, Sentry::Event)
|
|
231
255
|
|
|
@@ -352,11 +376,11 @@ module Sentry
|
|
|
352
376
|
return nil unless propagation_context.incoming_trace
|
|
353
377
|
|
|
354
378
|
Transaction.new(
|
|
355
|
-
hub: self,
|
|
356
379
|
trace_id: propagation_context.trace_id,
|
|
357
380
|
parent_span_id: propagation_context.parent_span_id,
|
|
358
381
|
parent_sampled: propagation_context.parent_sampled,
|
|
359
382
|
baggage: propagation_context.baggage,
|
|
383
|
+
sample_rand: propagation_context.sample_rand,
|
|
360
384
|
**options
|
|
361
385
|
)
|
|
362
386
|
end
|
data/lib/sentry/interface.rb
CHANGED
|
@@ -32,10 +32,10 @@ module Sentry
|
|
|
32
32
|
@mechanism = mechanism
|
|
33
33
|
end
|
|
34
34
|
|
|
35
|
-
def
|
|
35
|
+
def to_h
|
|
36
36
|
data = super
|
|
37
|
-
data[:stacktrace] = data[:stacktrace].
|
|
38
|
-
data[:mechanism] = data[:mechanism].
|
|
37
|
+
data[:stacktrace] = data[:stacktrace].to_h if data[:stacktrace]
|
|
38
|
+
data[:mechanism] = data[:mechanism].to_h
|
|
39
39
|
data
|
|
40
40
|
end
|
|
41
41
|
|
|
@@ -60,7 +60,7 @@ module Sentry
|
|
|
60
60
|
end
|
|
61
61
|
end
|
|
62
62
|
|
|
63
|
-
stacktrace.frames.last
|
|
63
|
+
stacktrace.frames.last&.vars = locals
|
|
64
64
|
end
|
|
65
65
|
|
|
66
66
|
new(exception: exception, stacktrace: stacktrace, mechanism: mechanism)
|
|
@@ -11,8 +11,8 @@ module Sentry
|
|
|
11
11
|
end
|
|
12
12
|
|
|
13
13
|
# @return [Hash]
|
|
14
|
-
def
|
|
15
|
-
{ frames: @frames.map(&:
|
|
14
|
+
def to_h
|
|
15
|
+
{ frames: @frames.map(&:to_h) }
|
|
16
16
|
end
|
|
17
17
|
|
|
18
18
|
# @return [String]
|
|
@@ -66,7 +66,7 @@ module Sentry
|
|
|
66
66
|
linecache.get_file_context(abs_path, lineno, context_lines)
|
|
67
67
|
end
|
|
68
68
|
|
|
69
|
-
def
|
|
69
|
+
def to_h(*args)
|
|
70
70
|
data = super(*args)
|
|
71
71
|
data.delete(:vars) unless vars && !vars.empty?
|
|
72
72
|
data.delete(:pre_context) unless pre_context && !pre_context.empty?
|
|
@@ -75,14 +75,6 @@ module Sentry
|
|
|
75
75
|
StacktraceInterface.new(frames: frames)
|
|
76
76
|
end
|
|
77
77
|
|
|
78
|
-
# Get the code location hash for a single line for where metrics where added.
|
|
79
|
-
# @return [Hash]
|
|
80
|
-
def metrics_code_location(unparsed_line)
|
|
81
|
-
parsed_line = Backtrace::Line.parse(unparsed_line)
|
|
82
|
-
frame = convert_parsed_line_into_frame(parsed_line)
|
|
83
|
-
frame.to_hash.reject { |k, _| %i[project_root in_app].include?(k) }
|
|
84
|
-
end
|
|
85
|
-
|
|
86
78
|
private
|
|
87
79
|
|
|
88
80
|
def convert_parsed_line_into_frame(line)
|
|
@@ -13,7 +13,7 @@ module Sentry
|
|
|
13
13
|
end
|
|
14
14
|
|
|
15
15
|
# @return [Hash]
|
|
16
|
-
def
|
|
16
|
+
def to_h
|
|
17
17
|
{
|
|
18
18
|
values: [
|
|
19
19
|
{
|
|
@@ -21,7 +21,7 @@ module Sentry
|
|
|
21
21
|
name: @name,
|
|
22
22
|
crashed: @crashed,
|
|
23
23
|
current: @current,
|
|
24
|
-
stacktrace: @stacktrace&.
|
|
24
|
+
stacktrace: @stacktrace&.to_h
|
|
25
25
|
}
|
|
26
26
|
]
|
|
27
27
|
}
|
data/lib/sentry/log_event.rb
CHANGED
|
@@ -1,129 +1,52 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require "sentry/utils/telemetry_attributes"
|
|
4
|
+
|
|
3
5
|
module Sentry
|
|
4
6
|
# Event type that represents a log entry with its attributes
|
|
5
7
|
#
|
|
6
8
|
# @see https://develop.sentry.dev/sdk/telemetry/logs/#log-envelope-item-payload
|
|
7
9
|
class LogEvent
|
|
10
|
+
include Sentry::Utils::TelemetryAttributes
|
|
11
|
+
|
|
8
12
|
TYPE = "log"
|
|
9
13
|
|
|
10
14
|
DEFAULT_PARAMETERS = [].freeze
|
|
11
|
-
|
|
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
|
-
}
|
|
15
|
+
|
|
16
|
+
PARAMETER_PREFIX = "sentry.message.parameter"
|
|
40
17
|
|
|
41
18
|
LEVELS = %i[trace debug info warn error fatal].freeze
|
|
42
19
|
|
|
43
|
-
attr_accessor :level, :body, :template, :attributes, :
|
|
44
|
-
|
|
45
|
-
attr_reader :configuration, *SERIALIZEABLE_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
|
|
20
|
+
attr_accessor :level, :body, :template, :attributes, :origin, :trace_id, :span_id
|
|
21
|
+
attr_reader :timestamp
|
|
67
22
|
|
|
68
23
|
TOKEN_REGEXP = /%\{(\w+)\}/
|
|
69
24
|
|
|
70
|
-
def initialize(
|
|
71
|
-
@configuration = configuration
|
|
25
|
+
def initialize(**options)
|
|
72
26
|
@type = TYPE
|
|
73
|
-
@server_name = configuration.server_name
|
|
74
|
-
@environment = configuration.environment
|
|
75
|
-
@release = configuration.release
|
|
76
27
|
@timestamp = Sentry.utc_now
|
|
77
28
|
@level = options.fetch(:level)
|
|
78
29
|
@body = options[:body]
|
|
79
30
|
@template = @body if is_template?
|
|
80
|
-
@attributes = options[:attributes] ||
|
|
81
|
-
@
|
|
82
|
-
@
|
|
31
|
+
@attributes = options[:attributes] || {}
|
|
32
|
+
@origin = options[:origin]
|
|
33
|
+
@trace_id = nil
|
|
34
|
+
@span_id = nil
|
|
83
35
|
end
|
|
84
36
|
|
|
85
|
-
def
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
37
|
+
def to_h
|
|
38
|
+
{
|
|
39
|
+
level: level.to_s,
|
|
40
|
+
timestamp: timestamp.to_f,
|
|
41
|
+
trace_id: @trace_id,
|
|
42
|
+
span_id: @span_id,
|
|
43
|
+
body: serialize_body,
|
|
44
|
+
attributes: serialize_attributes
|
|
45
|
+
}.compact
|
|
89
46
|
end
|
|
90
47
|
|
|
91
48
|
private
|
|
92
49
|
|
|
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
50
|
def serialize_body
|
|
128
51
|
if parameters.empty?
|
|
129
52
|
body
|
|
@@ -134,46 +57,14 @@ module Sentry
|
|
|
134
57
|
end
|
|
135
58
|
end
|
|
136
59
|
|
|
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
60
|
def serialize_attributes
|
|
150
|
-
|
|
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) }
|
|
61
|
+
populate_sentry_attributes!
|
|
62
|
+
@attributes.transform_values! { |v| attribute_hash(v) }
|
|
173
63
|
end
|
|
174
64
|
|
|
175
|
-
def
|
|
176
|
-
|
|
65
|
+
def populate_sentry_attributes!
|
|
66
|
+
@attributes["sentry.origin"] ||= @origin if @origin
|
|
67
|
+
@attributes["sentry.message.template"] ||= template if has_parameters?
|
|
177
68
|
end
|
|
178
69
|
|
|
179
70
|
def parameters
|
|
@@ -185,11 +76,11 @@ module Sentry
|
|
|
185
76
|
|
|
186
77
|
if parameters.is_a?(Hash)
|
|
187
78
|
parameters.each do |key, value|
|
|
188
|
-
attributes["
|
|
79
|
+
attributes["#{PARAMETER_PREFIX}.#{key}"] = value
|
|
189
80
|
end
|
|
190
81
|
else
|
|
191
82
|
parameters.each_with_index do |param, index|
|
|
192
|
-
attributes["
|
|
83
|
+
attributes["#{PARAMETER_PREFIX}.#{index}"] = param
|
|
193
84
|
end
|
|
194
85
|
end
|
|
195
86
|
end
|
|
@@ -202,5 +93,9 @@ module Sentry
|
|
|
202
93
|
def is_template?
|
|
203
94
|
body.include?("%s") || TOKEN_REGEXP.match?(body)
|
|
204
95
|
end
|
|
96
|
+
|
|
97
|
+
def has_parameters?
|
|
98
|
+
attributes.keys.any? { |key| key.start_with?(PARAMETER_PREFIX) }
|
|
99
|
+
end
|
|
205
100
|
end
|
|
206
101
|
end
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require "sentry/
|
|
3
|
+
require "sentry/telemetry_event_buffer"
|
|
4
4
|
|
|
5
5
|
module Sentry
|
|
6
6
|
# LogEventBuffer buffers log events and sends them to Sentry in a single envelope.
|
|
@@ -8,68 +8,21 @@ module Sentry
|
|
|
8
8
|
# This is used internally by the `Sentry::Client`.
|
|
9
9
|
#
|
|
10
10
|
# @!visibility private
|
|
11
|
-
class LogEventBuffer <
|
|
12
|
-
FLUSH_INTERVAL = 5 # seconds
|
|
11
|
+
class LogEventBuffer < TelemetryEventBuffer
|
|
13
12
|
DEFAULT_MAX_EVENTS = 100
|
|
14
|
-
|
|
15
|
-
# @!visibility private
|
|
16
|
-
attr_reader :pending_events
|
|
13
|
+
MAX_EVENTS_BEFORE_DROP = 1000
|
|
17
14
|
|
|
18
15
|
def initialize(configuration, client)
|
|
19
|
-
super(
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
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
|
|
16
|
+
super(
|
|
17
|
+
configuration,
|
|
18
|
+
client,
|
|
19
|
+
event_class: LogEvent,
|
|
20
|
+
max_items: configuration.max_log_events || DEFAULT_MAX_EVENTS,
|
|
21
|
+
max_items_before_drop: MAX_EVENTS_BEFORE_DROP,
|
|
22
|
+
envelope_type: "log",
|
|
23
|
+
envelope_content_type: "application/vnd.sentry.items.log+json",
|
|
24
|
+
before_send: configuration.before_send_log
|
|
25
|
+
)
|
|
73
26
|
end
|
|
74
27
|
end
|
|
75
28
|
end
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "sentry/utils/telemetry_attributes"
|
|
4
|
+
|
|
5
|
+
module Sentry
|
|
6
|
+
class MetricEvent
|
|
7
|
+
include Sentry::Utils::TelemetryAttributes
|
|
8
|
+
|
|
9
|
+
attr_reader :name, :type, :value, :unit, :timestamp, :trace_id, :span_id, :attributes
|
|
10
|
+
attr_writer :trace_id, :span_id, :attributes
|
|
11
|
+
|
|
12
|
+
def initialize(
|
|
13
|
+
name:,
|
|
14
|
+
type:,
|
|
15
|
+
value:,
|
|
16
|
+
unit: nil,
|
|
17
|
+
attributes: nil
|
|
18
|
+
)
|
|
19
|
+
@name = name
|
|
20
|
+
@type = type
|
|
21
|
+
@value = value
|
|
22
|
+
@unit = unit
|
|
23
|
+
@attributes = attributes || {}
|
|
24
|
+
|
|
25
|
+
@timestamp = Sentry.utc_now
|
|
26
|
+
@trace_id = nil
|
|
27
|
+
@span_id = nil
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def to_h
|
|
31
|
+
{
|
|
32
|
+
name: @name,
|
|
33
|
+
type: @type,
|
|
34
|
+
value: @value,
|
|
35
|
+
unit: @unit,
|
|
36
|
+
timestamp: @timestamp,
|
|
37
|
+
trace_id: @trace_id,
|
|
38
|
+
span_id: @span_id,
|
|
39
|
+
attributes: serialize_attributes
|
|
40
|
+
}.compact
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
private
|
|
44
|
+
|
|
45
|
+
def serialize_attributes
|
|
46
|
+
@attributes.transform_values! { |v| attribute_hash(v) }
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "sentry/telemetry_event_buffer"
|
|
4
|
+
|
|
5
|
+
module Sentry
|
|
6
|
+
# MetricEventBuffer buffers metric 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 MetricEventBuffer < TelemetryEventBuffer
|
|
12
|
+
DEFAULT_MAX_METRICS = 1000
|
|
13
|
+
MAX_METRICS_BEFORE_DROP = 10_000
|
|
14
|
+
|
|
15
|
+
def initialize(configuration, client)
|
|
16
|
+
super(
|
|
17
|
+
configuration,
|
|
18
|
+
client,
|
|
19
|
+
event_class: MetricEvent,
|
|
20
|
+
max_items: configuration.max_metric_events || DEFAULT_MAX_METRICS,
|
|
21
|
+
max_items_before_drop: MAX_METRICS_BEFORE_DROP,
|
|
22
|
+
envelope_type: "trace_metric",
|
|
23
|
+
envelope_content_type: "application/vnd.sentry.items.trace-metric+json",
|
|
24
|
+
before_send: configuration.before_send_metric
|
|
25
|
+
)
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|