sentry-ruby 5.3.0 → 5.8.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.
Files changed (67) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +11 -0
  3. data/.rspec +2 -0
  4. data/.yardopts +2 -0
  5. data/CHANGELOG.md +313 -0
  6. data/CODE_OF_CONDUCT.md +74 -0
  7. data/Gemfile +31 -0
  8. data/Makefile +4 -0
  9. data/README.md +10 -6
  10. data/Rakefile +13 -0
  11. data/bin/console +18 -0
  12. data/bin/setup +8 -0
  13. data/lib/sentry/background_worker.rb +72 -0
  14. data/lib/sentry/backtrace.rb +124 -0
  15. data/lib/sentry/baggage.rb +81 -0
  16. data/lib/sentry/breadcrumb/sentry_logger.rb +90 -0
  17. data/lib/sentry/breadcrumb.rb +70 -0
  18. data/lib/sentry/breadcrumb_buffer.rb +64 -0
  19. data/lib/sentry/client.rb +207 -0
  20. data/lib/sentry/configuration.rb +543 -0
  21. data/lib/sentry/core_ext/object/deep_dup.rb +61 -0
  22. data/lib/sentry/core_ext/object/duplicable.rb +155 -0
  23. data/lib/sentry/dsn.rb +53 -0
  24. data/lib/sentry/envelope.rb +96 -0
  25. data/lib/sentry/error_event.rb +38 -0
  26. data/lib/sentry/event.rb +178 -0
  27. data/lib/sentry/exceptions.rb +9 -0
  28. data/lib/sentry/hub.rb +241 -0
  29. data/lib/sentry/integrable.rb +26 -0
  30. data/lib/sentry/interface.rb +16 -0
  31. data/lib/sentry/interfaces/exception.rb +43 -0
  32. data/lib/sentry/interfaces/request.rb +134 -0
  33. data/lib/sentry/interfaces/single_exception.rb +65 -0
  34. data/lib/sentry/interfaces/stacktrace.rb +87 -0
  35. data/lib/sentry/interfaces/stacktrace_builder.rb +79 -0
  36. data/lib/sentry/interfaces/threads.rb +42 -0
  37. data/lib/sentry/linecache.rb +47 -0
  38. data/lib/sentry/logger.rb +20 -0
  39. data/lib/sentry/net/http.rb +103 -0
  40. data/lib/sentry/rack/capture_exceptions.rb +82 -0
  41. data/lib/sentry/rack.rb +5 -0
  42. data/lib/sentry/rake.rb +41 -0
  43. data/lib/sentry/redis.rb +107 -0
  44. data/lib/sentry/release_detector.rb +39 -0
  45. data/lib/sentry/scope.rb +339 -0
  46. data/lib/sentry/session.rb +33 -0
  47. data/lib/sentry/session_flusher.rb +90 -0
  48. data/lib/sentry/span.rb +236 -0
  49. data/lib/sentry/test_helper.rb +78 -0
  50. data/lib/sentry/transaction.rb +345 -0
  51. data/lib/sentry/transaction_event.rb +53 -0
  52. data/lib/sentry/transport/configuration.rb +25 -0
  53. data/lib/sentry/transport/dummy_transport.rb +21 -0
  54. data/lib/sentry/transport/http_transport.rb +175 -0
  55. data/lib/sentry/transport.rb +214 -0
  56. data/lib/sentry/utils/argument_checking_helper.rb +13 -0
  57. data/lib/sentry/utils/custom_inspection.rb +14 -0
  58. data/lib/sentry/utils/encoding_helper.rb +22 -0
  59. data/lib/sentry/utils/exception_cause_chain.rb +20 -0
  60. data/lib/sentry/utils/logging_helper.rb +26 -0
  61. data/lib/sentry/utils/real_ip.rb +84 -0
  62. data/lib/sentry/utils/request_id.rb +18 -0
  63. data/lib/sentry/version.rb +5 -0
  64. data/lib/sentry-ruby.rb +511 -0
  65. data/sentry-ruby-core.gemspec +23 -0
  66. data/sentry-ruby.gemspec +24 -0
  67. metadata +66 -16
@@ -0,0 +1,339 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "sentry/breadcrumb_buffer"
4
+ require "etc"
5
+
6
+ module Sentry
7
+ class Scope
8
+ include ArgumentCheckingHelper
9
+
10
+ ATTRIBUTES = [
11
+ :transaction_names,
12
+ :transaction_sources,
13
+ :contexts,
14
+ :extra,
15
+ :tags,
16
+ :user,
17
+ :level,
18
+ :breadcrumbs,
19
+ :fingerprint,
20
+ :event_processors,
21
+ :rack_env,
22
+ :span,
23
+ :session
24
+ ]
25
+
26
+ attr_reader(*ATTRIBUTES)
27
+
28
+ # @param max_breadcrumbs [Integer] the maximum number of breadcrumbs to be stored in the scope.
29
+ def initialize(max_breadcrumbs: nil)
30
+ @max_breadcrumbs = max_breadcrumbs
31
+ set_default_value
32
+ end
33
+
34
+ # Resets the scope's attributes to defaults.
35
+ # @return [void]
36
+ def clear
37
+ set_default_value
38
+ end
39
+
40
+ # Applies stored attributes and event processors to the given event.
41
+ # @param event [Event]
42
+ # @param hint [Hash] the hint data that'll be passed to event processors.
43
+ # @return [Event]
44
+ def apply_to_event(event, hint = nil)
45
+ event.tags = tags.merge(event.tags)
46
+ event.user = user.merge(event.user)
47
+ event.extra = extra.merge(event.extra)
48
+ event.contexts = contexts.merge(event.contexts)
49
+ event.transaction = transaction_name if transaction_name
50
+ event.transaction_info = { source: transaction_source } if transaction_source
51
+
52
+ if span
53
+ event.contexts[:trace] = span.get_trace_context
54
+ end
55
+
56
+ event.fingerprint = fingerprint
57
+ event.level = level
58
+ event.breadcrumbs = breadcrumbs
59
+ event.rack_env = rack_env if rack_env
60
+
61
+ all_event_processors = self.class.global_event_processors + @event_processors
62
+
63
+ unless all_event_processors.empty?
64
+ all_event_processors.each do |processor_block|
65
+ event = processor_block.call(event, hint)
66
+ end
67
+ end
68
+
69
+ event
70
+ end
71
+
72
+ # Adds the breadcrumb to the scope's breadcrumbs buffer.
73
+ # @param breadcrumb [Breadcrumb]
74
+ # @return [void]
75
+ def add_breadcrumb(breadcrumb)
76
+ breadcrumbs.record(breadcrumb)
77
+ end
78
+
79
+ # Clears the scope's breadcrumbs buffer
80
+ # @return [void]
81
+ def clear_breadcrumbs
82
+ set_new_breadcrumb_buffer
83
+ end
84
+
85
+ # @return [Scope]
86
+ def dup
87
+ copy = super
88
+ copy.breadcrumbs = breadcrumbs.dup
89
+ copy.contexts = contexts.deep_dup
90
+ copy.extra = extra.deep_dup
91
+ copy.tags = tags.deep_dup
92
+ copy.user = user.deep_dup
93
+ copy.transaction_names = transaction_names.dup
94
+ copy.transaction_sources = transaction_sources.dup
95
+ copy.fingerprint = fingerprint.deep_dup
96
+ copy.span = span.deep_dup
97
+ copy.session = session.deep_dup
98
+ copy
99
+ end
100
+
101
+ # Updates the scope's data from a given scope.
102
+ # @param scope [Scope]
103
+ # @return [void]
104
+ def update_from_scope(scope)
105
+ self.breadcrumbs = scope.breadcrumbs
106
+ self.contexts = scope.contexts
107
+ self.extra = scope.extra
108
+ self.tags = scope.tags
109
+ self.user = scope.user
110
+ self.transaction_names = scope.transaction_names
111
+ self.transaction_sources = scope.transaction_sources
112
+ self.fingerprint = scope.fingerprint
113
+ self.span = scope.span
114
+ end
115
+
116
+ # Updates the scope's data from the given options.
117
+ # @param contexts [Hash]
118
+ # @param extras [Hash]
119
+ # @param tags [Hash]
120
+ # @param user [Hash]
121
+ # @param level [String, Symbol]
122
+ # @param fingerprint [Array]
123
+ # @return [void]
124
+ def update_from_options(
125
+ contexts: nil,
126
+ extra: nil,
127
+ tags: nil,
128
+ user: nil,
129
+ level: nil,
130
+ fingerprint: nil
131
+ )
132
+ self.contexts.merge!(contexts) if contexts
133
+ self.extra.merge!(extra) if extra
134
+ self.tags.merge!(tags) if tags
135
+ self.user = user if user
136
+ self.level = level if level
137
+ self.fingerprint = fingerprint if fingerprint
138
+ end
139
+
140
+ # Sets the scope's rack_env attribute.
141
+ # @param env [Hash]
142
+ # @return [Hash]
143
+ def set_rack_env(env)
144
+ env = env || {}
145
+ @rack_env = env
146
+ end
147
+
148
+ # Sets the scope's span attribute.
149
+ # @param span [Span]
150
+ # @return [Span]
151
+ def set_span(span)
152
+ check_argument_type!(span, Span)
153
+ @span = span
154
+ end
155
+
156
+ # @!macro set_user
157
+ def set_user(user_hash)
158
+ check_argument_type!(user_hash, Hash)
159
+ @user = user_hash
160
+ end
161
+
162
+ # @!macro set_extras
163
+ def set_extras(extras_hash)
164
+ check_argument_type!(extras_hash, Hash)
165
+ @extra.merge!(extras_hash)
166
+ end
167
+
168
+ # Adds a new key-value pair to current extras.
169
+ # @param key [String, Symbol]
170
+ # @param value [Object]
171
+ # @return [Hash]
172
+ def set_extra(key, value)
173
+ set_extras(key => value)
174
+ end
175
+
176
+ # @!macro set_tags
177
+ def set_tags(tags_hash)
178
+ check_argument_type!(tags_hash, Hash)
179
+ @tags.merge!(tags_hash)
180
+ end
181
+
182
+ # Adds a new key-value pair to current tags.
183
+ # @param key [String, Symbol]
184
+ # @param value [Object]
185
+ # @return [Hash]
186
+ def set_tag(key, value)
187
+ set_tags(key => value)
188
+ end
189
+
190
+ # Updates the scope's contexts attribute by merging with the old value.
191
+ # @param contexts [Hash]
192
+ # @return [Hash]
193
+ def set_contexts(contexts_hash)
194
+ check_argument_type!(contexts_hash, Hash)
195
+ @contexts.merge!(contexts_hash) do |key, old, new|
196
+ old.merge(new)
197
+ end
198
+ end
199
+
200
+ # @!macro set_context
201
+ def set_context(key, value)
202
+ check_argument_type!(value, Hash)
203
+ set_contexts(key => value)
204
+ end
205
+
206
+ # Sets the scope's level attribute.
207
+ # @param level [String, Symbol]
208
+ # @return [void]
209
+ def set_level(level)
210
+ @level = level
211
+ end
212
+
213
+ # Appends a new transaction name to the scope.
214
+ # The "transaction" here does not refer to `Transaction` objects.
215
+ # @param transaction_name [String]
216
+ # @return [void]
217
+ def set_transaction_name(transaction_name, source: :custom)
218
+ @transaction_names << transaction_name
219
+ @transaction_sources << source
220
+ end
221
+
222
+ # Sets the currently active session on the scope.
223
+ # @param session [Session, nil]
224
+ # @return [void]
225
+ def set_session(session)
226
+ @session = session
227
+ end
228
+
229
+ # Returns current transaction name.
230
+ # The "transaction" here does not refer to `Transaction` objects.
231
+ # @return [String, nil]
232
+ def transaction_name
233
+ @transaction_names.last
234
+ end
235
+
236
+ # Returns current transaction source.
237
+ # The "transaction" here does not refer to `Transaction` objects.
238
+ # @return [String, nil]
239
+ def transaction_source
240
+ @transaction_sources.last
241
+ end
242
+
243
+ # Returns the associated Transaction object.
244
+ # @return [Transaction, nil]
245
+ def get_transaction
246
+ span.transaction if span
247
+ end
248
+
249
+ # Returns the associated Span object.
250
+ # @return [Span, nil]
251
+ def get_span
252
+ span
253
+ end
254
+
255
+ # Sets the scope's fingerprint attribute.
256
+ # @param fingerprint [Array]
257
+ # @return [Array]
258
+ def set_fingerprint(fingerprint)
259
+ check_argument_type!(fingerprint, Array)
260
+
261
+ @fingerprint = fingerprint
262
+ end
263
+
264
+ # Adds a new event processor [Proc] to the scope.
265
+ # @param block [Proc]
266
+ # @return [void]
267
+ def add_event_processor(&block)
268
+ @event_processors << block
269
+ end
270
+
271
+ protected
272
+
273
+ # for duplicating scopes internally
274
+ attr_writer(*ATTRIBUTES)
275
+
276
+ private
277
+
278
+ def set_default_value
279
+ @contexts = { :os => self.class.os_context, :runtime => self.class.runtime_context }
280
+ @extra = {}
281
+ @tags = {}
282
+ @user = {}
283
+ @level = :error
284
+ @fingerprint = []
285
+ @transaction_names = []
286
+ @transaction_sources = []
287
+ @event_processors = []
288
+ @rack_env = {}
289
+ @span = nil
290
+ @session = nil
291
+ set_new_breadcrumb_buffer
292
+ end
293
+
294
+ def set_new_breadcrumb_buffer
295
+ @breadcrumbs = BreadcrumbBuffer.new(@max_breadcrumbs)
296
+ end
297
+
298
+ class << self
299
+ # @return [Hash]
300
+ def os_context
301
+ @os_context ||=
302
+ begin
303
+ uname = Etc.uname
304
+ {
305
+ name: uname[:sysname] || RbConfig::CONFIG["host_os"],
306
+ version: uname[:version],
307
+ build: uname[:release],
308
+ kernel_version: uname[:version]
309
+ }
310
+ end
311
+ end
312
+
313
+ # @return [Hash]
314
+ def runtime_context
315
+ @runtime_context ||= {
316
+ name: RbConfig::CONFIG["ruby_install_name"],
317
+ version: RUBY_DESCRIPTION || Sentry.sys_command("ruby -v")
318
+ }
319
+ end
320
+
321
+ # Returns the global event processors array.
322
+ # @return [Array<Proc>]
323
+ def global_event_processors
324
+ @global_event_processors ||= []
325
+ end
326
+
327
+ # Adds a new global event processor [Proc].
328
+ # Sometimes we need a global event processor without needing to configure scope.
329
+ # These run before scope event processors.
330
+ #
331
+ # @param block [Proc]
332
+ # @return [void]
333
+ def add_global_event_processor(&block)
334
+ global_event_processors << block
335
+ end
336
+ end
337
+
338
+ end
339
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sentry
4
+ class Session
5
+ attr_reader :started, :status, :aggregation_key
6
+
7
+ # TODO-neel add :crashed after adding handled mechanism
8
+ STATUSES = %i(ok errored exited)
9
+ AGGREGATE_STATUSES = %i(errored exited)
10
+
11
+ def initialize
12
+ @started = Sentry.utc_now
13
+ @status = :ok
14
+
15
+ # truncate seconds from the timestamp since we only care about
16
+ # minute level granularity for aggregation
17
+ @aggregation_key = Time.utc(@started.year, @started.month, @started.day, @started.hour, @started.min)
18
+ end
19
+
20
+ # TODO-neel add :crashed after adding handled mechanism
21
+ def update_from_exception(_exception = nil)
22
+ @status = :errored
23
+ end
24
+
25
+ def close
26
+ @status = :exited if @status == :ok
27
+ end
28
+
29
+ def deep_dup
30
+ dup
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,90 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sentry
4
+ class SessionFlusher
5
+ include LoggingHelper
6
+
7
+ FLUSH_INTERVAL = 60
8
+
9
+ def initialize(configuration, client)
10
+ @thread = nil
11
+ @exited = false
12
+ @client = client
13
+ @pending_aggregates = {}
14
+ @release = configuration.release
15
+ @environment = configuration.environment
16
+ @logger = configuration.logger
17
+
18
+ log_debug("[Sessions] Sessions won't be captured without a valid release") unless @release
19
+ end
20
+
21
+ def flush
22
+ return if @pending_aggregates.empty?
23
+ envelope = pending_envelope
24
+
25
+ Sentry.background_worker.perform do
26
+ @client.transport.send_envelope(envelope)
27
+ end
28
+
29
+ @pending_aggregates = {}
30
+ end
31
+
32
+ def add_session(session)
33
+ return if @exited
34
+ return unless @release
35
+
36
+ begin
37
+ ensure_thread
38
+ rescue ThreadError
39
+ log_debug("Session flusher thread creation failed")
40
+ @exited = true
41
+ return
42
+ end
43
+
44
+ return unless Session::AGGREGATE_STATUSES.include?(session.status)
45
+ @pending_aggregates[session.aggregation_key] ||= init_aggregates(session.aggregation_key)
46
+ @pending_aggregates[session.aggregation_key][session.status] += 1
47
+ end
48
+
49
+ def kill
50
+ log_debug("Killing session flusher")
51
+
52
+ @exited = true
53
+ @thread&.kill
54
+ end
55
+
56
+ private
57
+
58
+ def init_aggregates(aggregation_key)
59
+ aggregates = { started: aggregation_key.iso8601 }
60
+ Session::AGGREGATE_STATUSES.each { |k| aggregates[k] = 0 }
61
+ aggregates
62
+ end
63
+
64
+ def pending_envelope
65
+ envelope = Envelope.new
66
+
67
+ header = { type: 'sessions' }
68
+ payload = { attrs: attrs, aggregates: @pending_aggregates.values }
69
+
70
+ envelope.add_item(header, payload)
71
+ envelope
72
+ end
73
+
74
+ def attrs
75
+ { release: @release, environment: @environment }
76
+ end
77
+
78
+ def ensure_thread
79
+ return if @thread&.alive?
80
+
81
+ @thread = Thread.new do
82
+ loop do
83
+ sleep(FLUSH_INTERVAL)
84
+ flush
85
+ end
86
+ end
87
+ end
88
+
89
+ end
90
+ end
@@ -0,0 +1,236 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "securerandom"
4
+
5
+ module Sentry
6
+ class Span
7
+ STATUS_MAP = {
8
+ 400 => "invalid_argument",
9
+ 401 => "unauthenticated",
10
+ 403 => "permission_denied",
11
+ 404 => "not_found",
12
+ 409 => "already_exists",
13
+ 429 => "resource_exhausted",
14
+ 499 => "cancelled",
15
+ 500 => "internal_error",
16
+ 501 => "unimplemented",
17
+ 503 => "unavailable",
18
+ 504 => "deadline_exceeded"
19
+ }
20
+
21
+ # An uuid that can be used to identify a trace.
22
+ # @return [String]
23
+ attr_reader :trace_id
24
+ # An uuid that can be used to identify the span.
25
+ # @return [String]
26
+ attr_reader :span_id
27
+ # Span parent's span_id.
28
+ # @return [String]
29
+ attr_reader :parent_span_id
30
+ # Sampling result of the span.
31
+ # @return [Boolean, nil]
32
+ attr_reader :sampled
33
+ # Starting timestamp of the span.
34
+ # @return [Float]
35
+ attr_reader :start_timestamp
36
+ # Finishing timestamp of the span.
37
+ # @return [Float]
38
+ attr_reader :timestamp
39
+ # Span description
40
+ # @return [String]
41
+ attr_reader :description
42
+ # Span operation
43
+ # @return [String]
44
+ attr_reader :op
45
+ # Span status
46
+ # @return [String]
47
+ attr_reader :status
48
+ # Span tags
49
+ # @return [Hash]
50
+ attr_reader :tags
51
+ # Span data
52
+ # @return [Hash]
53
+ attr_reader :data
54
+
55
+ # The SpanRecorder the current span belongs to.
56
+ # SpanRecorder holds all spans under the same Transaction object (including the Transaction itself).
57
+ # @return [SpanRecorder]
58
+ attr_accessor :span_recorder
59
+
60
+ # The Transaction object the Span belongs to.
61
+ # Every span needs to be attached to a Transaction and their child spans will also inherit the same transaction.
62
+ # @return [Transaction]
63
+ attr_reader :transaction
64
+
65
+ def initialize(
66
+ transaction:,
67
+ description: nil,
68
+ op: nil,
69
+ status: nil,
70
+ trace_id: nil,
71
+ span_id: nil,
72
+ parent_span_id: nil,
73
+ sampled: nil,
74
+ start_timestamp: nil,
75
+ timestamp: nil
76
+ )
77
+ @trace_id = trace_id || SecureRandom.uuid.delete("-")
78
+ @span_id = span_id || SecureRandom.hex(8)
79
+ @parent_span_id = parent_span_id
80
+ @sampled = sampled
81
+ @start_timestamp = start_timestamp || Sentry.utc_now.to_f
82
+ @timestamp = timestamp
83
+ @description = description
84
+ @transaction = transaction
85
+ @op = op
86
+ @status = status
87
+ @data = {}
88
+ @tags = {}
89
+ end
90
+
91
+ # Finishes the span by adding a timestamp.
92
+ # @return [self]
93
+ def finish(end_timestamp: nil)
94
+ @timestamp = end_timestamp || @timestamp || Sentry.utc_now.to_f
95
+ self
96
+ end
97
+
98
+ # Generates a trace string that can be used to connect other transactions.
99
+ # @return [String]
100
+ def to_sentry_trace
101
+ sampled_flag = ""
102
+ sampled_flag = @sampled ? 1 : 0 unless @sampled.nil?
103
+
104
+ "#{@trace_id}-#{@span_id}-#{sampled_flag}"
105
+ end
106
+
107
+ # Generates a W3C Baggage header string for distributed tracing
108
+ # from the incoming baggage stored on the transaction.
109
+ # @return [String, nil]
110
+ def to_baggage
111
+ transaction.get_baggage&.serialize
112
+ end
113
+
114
+ # @return [Hash]
115
+ def to_hash
116
+ {
117
+ trace_id: @trace_id,
118
+ span_id: @span_id,
119
+ parent_span_id: @parent_span_id,
120
+ start_timestamp: @start_timestamp,
121
+ timestamp: @timestamp,
122
+ description: @description,
123
+ op: @op,
124
+ status: @status,
125
+ tags: @tags,
126
+ data: @data
127
+ }
128
+ end
129
+
130
+ # Returns the span's context that can be used to embed in an Event.
131
+ # @return [Hash]
132
+ def get_trace_context
133
+ {
134
+ trace_id: @trace_id,
135
+ span_id: @span_id,
136
+ parent_span_id: @parent_span_id,
137
+ description: @description,
138
+ op: @op,
139
+ status: @status
140
+ }
141
+ end
142
+
143
+ # Starts a child span with given attributes.
144
+ # @param attributes [Hash] the attributes for the child span.
145
+ def start_child(**attributes)
146
+ attributes = attributes.dup.merge(transaction: @transaction, trace_id: @trace_id, parent_span_id: @span_id, sampled: @sampled)
147
+ new_span = Span.new(**attributes)
148
+ new_span.span_recorder = span_recorder
149
+
150
+ if span_recorder
151
+ span_recorder.add(new_span)
152
+ end
153
+
154
+ new_span
155
+ end
156
+
157
+ # Starts a child span, yield it to the given block, and then finish the span after the block is executed.
158
+ # @example
159
+ # span.with_child_span do |child_span|
160
+ # # things happen here will be recorded in a child span
161
+ # end
162
+ #
163
+ # @param attributes [Hash] the attributes for the child span.
164
+ # @param block [Proc] the action to be recorded in the child span.
165
+ # @yieldparam child_span [Span]
166
+ def with_child_span(**attributes, &block)
167
+ child_span = start_child(**attributes)
168
+
169
+ yield(child_span)
170
+
171
+ child_span.finish
172
+ rescue
173
+ child_span.set_http_status(500)
174
+ child_span.finish
175
+ raise
176
+ end
177
+
178
+ def deep_dup
179
+ dup
180
+ end
181
+
182
+ # Sets the span's operation.
183
+ # @param op [String] operation of the span.
184
+ def set_op(op)
185
+ @op = op
186
+ end
187
+
188
+ # Sets the span's description.
189
+ # @param description [String] description of the span.
190
+ def set_description(description)
191
+ @description = description
192
+ end
193
+
194
+
195
+ # Sets the span's status.
196
+ # @param satus [String] status of the span.
197
+ def set_status(status)
198
+ @status = status
199
+ end
200
+
201
+ # Sets the span's finish timestamp.
202
+ # @param timestamp [Float] finished time in float format (most precise).
203
+ def set_timestamp(timestamp)
204
+ @timestamp = timestamp
205
+ end
206
+
207
+ # Sets the span's status with given http status code.
208
+ # @param status_code [String] example: "500".
209
+ def set_http_status(status_code)
210
+ status_code = status_code.to_i
211
+ set_data("status_code", status_code)
212
+
213
+ status =
214
+ if status_code >= 200 && status_code < 299
215
+ "ok"
216
+ else
217
+ STATUS_MAP[status_code]
218
+ end
219
+ set_status(status)
220
+ end
221
+
222
+ # Inserts a key-value pair to the span's data payload.
223
+ # @param key [String, Symbol]
224
+ # @param value [Object]
225
+ def set_data(key, value)
226
+ @data[key] = value
227
+ end
228
+
229
+ # Sets a tag to the span.
230
+ # @param key [String, Symbol]
231
+ # @param value [String]
232
+ def set_tag(key, value)
233
+ @tags[key] = value
234
+ end
235
+ end
236
+ end