sentry-ruby-core 5.17.3 → 5.18.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fe82a2b6001d48448ad45cfdfcf6eca4c99708b33ca289afc1777dac54dcd851
4
- data.tar.gz: db84b44742d0e847b6fd66dac5a3338e63d4497723979b7c71fbbea46eb50480
3
+ metadata.gz: 2ec8300501e7004bf7648188108874295436b1330cdf999edb35143d3b371461
4
+ data.tar.gz: 52508a18bfc34c68494b37abc4f9907bd18b46aebe32e4dba46e16a60a7c685b
5
5
  SHA512:
6
- metadata.gz: 0b5cd84206fa239965fdfddc7a9570c2ca8c490f61055ec7c4b919d5e9ab299accbb6b8588a939101e4c3605a043f2e33392baa14f11a8bf1868ed78bf0f8fb7
7
- data.tar.gz: 1348bd6636f8283af3d85934ffe414606072758939cc0027c70730f8711f933ab72d9ee23d49cd921ca3562dcd4a034f93255fe5f3eb257a0e4288815be840e5
6
+ metadata.gz: 7add2e138fa5efa7b0db55b90a94d4d0e06de39b8bacca0b39bef0f9496ab6793990e8ae909cb71465d19d07e29f6ef6bdb3e44a2b0f1b953dfe6a5c332caa1a
7
+ data.tar.gz: 0f5824802082fba7fa352ad86402e56a230a2daa0b2ffc894c0fb771da6b719e5ee6e3cb864a79f7d75bdcb8600310435ef4b5c97a8acb7504e6232a777f1314
data/Gemfile CHANGED
@@ -15,6 +15,8 @@ gem "puma"
15
15
  gem "timecop"
16
16
  gem "stackprof" unless RUBY_PLATFORM == "java"
17
17
 
18
+ gem "graphql", ">= 2.2.6" if RUBY_VERSION.to_f >= 2.7
19
+
18
20
  gem "benchmark-ips"
19
21
  gem "benchmark_driver"
20
22
  gem "benchmark-ipsa"
data/README.md CHANGED
@@ -13,14 +13,14 @@ _Bad software is everywhere, and we're tired of it. Sentry is on a mission to he
13
13
  Sentry SDK for Ruby
14
14
  ===========
15
15
 
16
- | current version | build | coverage | downloads |
17
- | --- | ----- | -------- | --------- |
18
- | [![Gem Version](https://img.shields.io/gem/v/sentry-ruby?label=sentry-ruby)](https://rubygems.org/gems/sentry-ruby) | [![Build Status](https://github.com/getsentry/sentry-ruby/actions/workflows/sentry_ruby_test.yml/badge.svg)](https://github.com/getsentry/sentry-ruby/actions/workflows/sentry_ruby_test.yml) | [![Coverage Status](https://img.shields.io/codecov/c/github/getsentry/sentry-ruby/master?logo=codecov)](https://codecov.io/gh/getsentry/sentry-ruby/branch/master) | [![Downloads](https://img.shields.io/gem/dt/sentry-ruby.svg)](https://rubygems.org/gems/sentry-ruby/) |
19
- | [![Gem Version](https://img.shields.io/gem/v/sentry-rails?label=sentry-rails)](https://rubygems.org/gems/sentry-rails) | [![Build Status](https://github.com/getsentry/sentry-ruby/actions/workflows/sentry_rails_test.yml/badge.svg)](https://github.com/getsentry/sentry-ruby/actions/workflows/sentry_rails_test.yml) | [![Coverage Status](https://img.shields.io/codecov/c/github/getsentry/sentry-ruby/master?logo=codecov)](https://codecov.io/gh/getsentry/sentry-ruby/branch/master) | [![Downloads](https://img.shields.io/gem/dt/sentry-rails.svg)](https://rubygems.org/gems/sentry-rails/) |
20
- | [![Gem Version](https://img.shields.io/gem/v/sentry-sidekiq?label=sentry-sidekiq)](https://rubygems.org/gems/sentry-sidekiq) | [![Build Status](https://github.com/getsentry/sentry-ruby/actions/workflows/sentry_sidekiq_test.yml/badge.svg)](https://github.com/getsentry/sentry-ruby/actions/workflows/sentry_sidekiq_test.yml) | [![Coverage Status](https://img.shields.io/codecov/c/github/getsentry/sentry-ruby/master?logo=codecov)](https://codecov.io/gh/getsentry/sentry-ruby/branch/master) | [![Downloads](https://img.shields.io/gem/dt/sentry-sidekiq.svg)](https://rubygems.org/gems/sentry-sidekiq/) |
21
- | [![Gem Version](https://img.shields.io/gem/v/sentry-delayed_job?label=sentry-delayed_job)](https://rubygems.org/gems/sentry-delayed_job) | [![Build Status](https://github.com/getsentry/sentry-ruby/actions/workflows/sentry_delayed_job_test.yml/badge.svg)](https://github.com/getsentry/sentry-ruby/actions/workflows/sentry_delayed_job_test.yml) | [![Coverage Status](https://img.shields.io/codecov/c/github/getsentry/sentry-ruby/master?logo=codecov)](https://codecov.io/gh/getsentry/sentry-ruby/branch/master) | [![Downloads](https://img.shields.io/gem/dt/sentry-delayed_job.svg)](https://rubygems.org/gems/sentry-delayed_job/) |
22
- | [![Gem Version](https://img.shields.io/gem/v/sentry-resque?label=sentry-resque)](https://rubygems.org/gems/sentry-resque) | [![Build Status](https://github.com/getsentry/sentry-ruby/actions/workflows/sentry_resque_test.yml/badge.svg)](https://github.com/getsentry/sentry-ruby/actions/workflows/sentry_resque_test.yml) | [![Coverage Status](https://img.shields.io/codecov/c/github/getsentry/sentry-ruby/master?logo=codecov)](https://codecov.io/gh/getsentry/sentry-ruby/branch/master) | [![Downloads](https://img.shields.io/gem/dt/sentry-resque.svg)](https://rubygems.org/gems/sentry-resque/) |
23
- | [![Gem Version](https://img.shields.io/gem/v/sentry-opentelemetry?label=sentry-opentelemetry)](https://rubygems.org/gems/sentry-opentelemetry) | [![Build Status](https://github.com/getsentry/sentry-ruby/actions/workflows/sentry_opentelemetry_test.yml/badge.svg)](https://github.com/getsentry/sentry-ruby/actions/workflows/sentry_opentelemetry_test.yml) | [![Coverage Status](https://img.shields.io/codecov/c/github/getsentry/sentry-ruby/master?logo=codecov)](https://codecov.io/gh/getsentry/sentry-ruby/branch/master) | [![Downloads](https://img.shields.io/gem/dt/sentry-opentelemetry.svg)](https://rubygems.org/gems/sentry-opentelemetry/) |
16
+ | Current version | Build | Coverage | API doc |
17
+ | ---------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------- |
18
+ | [![Gem Version](https://img.shields.io/gem/v/sentry-ruby?label=sentry-ruby)](https://rubygems.org/gems/sentry-ruby) | [![Build Status](https://github.com/getsentry/sentry-ruby/actions/workflows/sentry_ruby_test.yml/badge.svg)](https://github.com/getsentry/sentry-ruby/actions/workflows/sentry_ruby_test.yml) | [![Coverage Status](https://img.shields.io/codecov/c/github/getsentry/sentry-ruby/master?logo=codecov)](https://codecov.io/gh/getsentry/sentry-ruby/branch/master) | [![API doc](https://img.shields.io/badge/API%20doc-rubydoc.info-blue)](https://www.rubydoc.info/gems/sentry-ruby) |
19
+ | [![Gem Version](https://img.shields.io/gem/v/sentry-rails?label=sentry-rails)](https://rubygems.org/gems/sentry-rails) | [![Build Status](https://github.com/getsentry/sentry-ruby/actions/workflows/sentry_rails_test.yml/badge.svg)](https://github.com/getsentry/sentry-ruby/actions/workflows/sentry_rails_test.yml) | [![Coverage Status](https://img.shields.io/codecov/c/github/getsentry/sentry-ruby/master?logo=codecov)](https://codecov.io/gh/getsentry/sentry-ruby/branch/master) | [![API doc](https://img.shields.io/badge/API%20doc-rubydoc.info-blue)](https://www.rubydoc.info/gems/sentry-rails) |
20
+ | [![Gem Version](https://img.shields.io/gem/v/sentry-sidekiq?label=sentry-sidekiq)](https://rubygems.org/gems/sentry-sidekiq) | [![Build Status](https://github.com/getsentry/sentry-ruby/actions/workflows/sentry_sidekiq_test.yml/badge.svg)](https://github.com/getsentry/sentry-ruby/actions/workflows/sentry_sidekiq_test.yml) | [![Coverage Status](https://img.shields.io/codecov/c/github/getsentry/sentry-ruby/master?logo=codecov)](https://codecov.io/gh/getsentry/sentry-ruby/branch/master) | [![API doc](https://img.shields.io/badge/API%20doc-rubydoc.info-blue)](https://www.rubydoc.info/gems/sentry-sidekiq) |
21
+ | [![Gem Version](https://img.shields.io/gem/v/sentry-delayed_job?label=sentry-delayed_job)](https://rubygems.org/gems/sentry-delayed_job) | [![Build Status](https://github.com/getsentry/sentry-ruby/actions/workflows/sentry_delayed_job_test.yml/badge.svg)](https://github.com/getsentry/sentry-ruby/actions/workflows/sentry_delayed_job_test.yml) | [![Coverage Status](https://img.shields.io/codecov/c/github/getsentry/sentry-ruby/master?logo=codecov)](https://codecov.io/gh/getsentry/sentry-ruby/branch/master) | [![API doc](https://img.shields.io/badge/API%20doc-rubydoc.info-blue)](https://www.rubydoc.info/gems/sentry-delayed_job) |
22
+ | [![Gem Version](https://img.shields.io/gem/v/sentry-resque?label=sentry-resque)](https://rubygems.org/gems/sentry-resque) | [![Build Status](https://github.com/getsentry/sentry-ruby/actions/workflows/sentry_resque_test.yml/badge.svg)](https://github.com/getsentry/sentry-ruby/actions/workflows/sentry_resque_test.yml) | [![Coverage Status](https://img.shields.io/codecov/c/github/getsentry/sentry-ruby/master?logo=codecov)](https://codecov.io/gh/getsentry/sentry-ruby/branch/master) | [![API doc](https://img.shields.io/badge/API%20doc-rubydoc.info-blue)](https://www.rubydoc.info/gems/sentry-resque) |
23
+ | [![Gem Version](https://img.shields.io/gem/v/sentry-opentelemetry?label=sentry-opentelemetry)](https://rubygems.org/gems/sentry-opentelemetry) | [![Build Status](https://github.com/getsentry/sentry-ruby/actions/workflows/sentry_opentelemetry_test.yml/badge.svg)](https://github.com/getsentry/sentry-ruby/actions/workflows/sentry_opentelemetry_test.yml) | [![Coverage Status](https://img.shields.io/codecov/c/github/getsentry/sentry-ruby/master?logo=codecov)](https://codecov.io/gh/getsentry/sentry-ruby/branch/master) | [![API doc](https://img.shields.io/badge/API%20doc-rubydoc.info-blue)](https://www.rubydoc.info/gems/sentry-opentelemetry) |
24
24
 
25
25
 
26
26
 
@@ -103,6 +103,6 @@ To learn more about sampling transactions, please visit the [official documentat
103
103
 
104
104
  * [![Ruby docs](https://img.shields.io/badge/documentation-sentry.io-green.svg?label=ruby%20docs)](https://docs.sentry.io/platforms/ruby/)
105
105
  * [![Forum](https://img.shields.io/badge/forum-sentry-green.svg)](https://forum.sentry.io/c/sdks)
106
- * [![Discord Chat](https://img.shields.io/discord/621778831602221064?logo=discord&logoColor=ffffff&color=7389D8)](https://discord.gg/PXa5Apfe7K)
106
+ * [![Discord Chat](https://img.shields.io/discord/621778831602221064?logo=discord&logoColor=ffffff&color=7389D8)](https://discord.gg/PXa5Apfe7K)
107
107
  * [![Stack Overflow](https://img.shields.io/badge/stack%20overflow-sentry-green.svg)](https://stackoverflow.com/questions/tagged/sentry)
108
108
  * [![Twitter Follow](https://img.shields.io/twitter/follow/getsentry?label=getsentry&style=social)](https://twitter.com/intent/follow?screen_name=getsentry)
data/bin/console CHANGED
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
3
  require "bundler/setup"
4
+ require "debug"
4
5
  require "sentry-ruby"
5
6
 
6
7
  # You can add fixtures and/or initialization code here to make experimenting
@@ -1,19 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Sentry
4
- class BackpressureMonitor
5
- include LoggingHelper
6
-
4
+ class BackpressureMonitor < ThreadedPeriodicWorker
7
5
  DEFAULT_INTERVAL = 10
8
6
  MAX_DOWNSAMPLE_FACTOR = 10
9
7
 
10
8
  def initialize(configuration, client, interval: DEFAULT_INTERVAL)
11
- @interval = interval
9
+ super(configuration.logger, interval)
12
10
  @client = client
13
- @logger = configuration.logger
14
-
15
- @thread = nil
16
- @exited = false
17
11
 
18
12
  @healthy = true
19
13
  @downsample_factor = 0
@@ -47,29 +41,5 @@ module Sentry
47
41
  log_debug("[BackpressureMonitor] health check negative, downsampling with a factor of #{@downsample_factor}")
48
42
  end
49
43
  end
50
-
51
- def kill
52
- log_debug("[BackpressureMonitor] killing monitor")
53
-
54
- @exited = true
55
- @thread&.kill
56
- end
57
-
58
- private
59
-
60
- def ensure_thread
61
- return if @exited
62
- return if @thread&.alive?
63
-
64
- @thread = Thread.new do
65
- loop do
66
- sleep(@interval)
67
- run
68
- end
69
- end
70
- rescue ThreadError
71
- log_debug("[BackpressureMonitor] Thread creation failed")
72
- @exited = true
73
- end
74
44
  end
75
45
  end
@@ -351,7 +351,7 @@ module Sentry
351
351
  def initialize
352
352
  self.app_dirs_pattern = nil
353
353
  self.debug = false
354
- self.background_worker_threads = Concurrent.processor_count
354
+ self.background_worker_threads = (Concurrent.processor_count / 2.0).ceil
355
355
  self.background_worker_max_queue = BackgroundWorker::DEFAULT_MAX_QUEUE
356
356
  self.backtrace_cleanup_callback = nil
357
357
  self.max_breadcrumbs = BreadcrumbBuffer::DEFAULT_SIZE
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ Sentry.register_patch(:graphql) do |config|
4
+ if defined?(::GraphQL::Schema) && defined?(::GraphQL::Tracing::SentryTrace) && ::GraphQL::Schema.respond_to?(:trace_with)
5
+ ::GraphQL::Schema.trace_with(::GraphQL::Tracing::SentryTrace, set_transaction_name: true)
6
+ else
7
+ config.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
+ end
9
+ end
data/lib/sentry/hub.rb CHANGED
@@ -193,7 +193,12 @@ module Sentry
193
193
  elsif custom_scope = options[:scope]
194
194
  scope.update_from_scope(custom_scope)
195
195
  elsif !options.empty?
196
- scope.update_from_options(**options)
196
+ unsupported_option_keys = scope.update_from_options(**options)
197
+
198
+ configuration.log_debug <<~MSG
199
+ Options #{unsupported_option_keys} are not supported and will not be applied to the event.
200
+ You may want to set them under the `extra` option.
201
+ MSG
197
202
  end
198
203
 
199
204
  event = current_client.capture_event(event, scope, hint)
@@ -279,6 +284,12 @@ module Sentry
279
284
  headers
280
285
  end
281
286
 
287
+ def get_trace_propagation_meta
288
+ get_trace_propagation_headers.map do |k, v|
289
+ "<meta name=\"#{k}\" content=\"#{v}\">"
290
+ end.join("\n")
291
+ end
292
+
282
293
  def continue_trace(env, **options)
283
294
  configure_scope { |s| s.generate_propagation_context(env) }
284
295
 
@@ -2,9 +2,7 @@
2
2
 
3
3
  module Sentry
4
4
  module Metrics
5
- class Aggregator
6
- include LoggingHelper
7
-
5
+ class Aggregator < ThreadedPeriodicWorker
8
6
  FLUSH_INTERVAL = 5
9
7
  ROLLUP_IN_SECONDS = 10
10
8
 
@@ -36,8 +34,8 @@ module Sentry
36
34
  attr_reader :client, :thread, :buckets, :flush_shift, :code_locations
37
35
 
38
36
  def initialize(configuration, client)
37
+ super(configuration.logger, FLUSH_INTERVAL)
39
38
  @client = client
40
- @logger = configuration.logger
41
39
  @before_emit = configuration.metrics.before_emit
42
40
  @enable_code_locations = configuration.metrics.enable_code_locations
43
41
  @stacktrace_builder = configuration.stacktrace_builder
@@ -46,8 +44,6 @@ module Sentry
46
44
  @default_tags['release'] = configuration.release if configuration.release
47
45
  @default_tags['environment'] = configuration.environment if configuration.environment
48
46
 
49
- @thread = nil
50
- @exited = false
51
47
  @mutex = Mutex.new
52
48
 
53
49
  # a nested hash of timestamp -> bucket keys -> Metric instance
@@ -120,34 +116,10 @@ module Sentry
120
116
  @client.capture_envelope(envelope)
121
117
  end
122
118
 
123
- def kill
124
- log_debug('[Metrics::Aggregator] killing thread')
125
-
126
- @exited = true
127
- @thread&.kill
128
- end
119
+ alias_method :run, :flush
129
120
 
130
121
  private
131
122
 
132
- def ensure_thread
133
- return false if @exited
134
- return true if @thread&.alive?
135
-
136
- @thread = Thread.new do
137
- loop do
138
- # TODO-neel-metrics use event for force flush later
139
- sleep(FLUSH_INTERVAL)
140
- flush
141
- end
142
- end
143
-
144
- true
145
- rescue ThreadError
146
- log_debug('[Metrics::Aggregator] thread creation failed')
147
- @exited = true
148
- false
149
- end
150
-
151
123
  # important to sort for key consistency
152
124
  def serialize_tags(tags)
153
125
  tags.flat_map do |k, v|
@@ -15,6 +15,7 @@ module Sentry
15
15
  FRACTIONAL_UNITS = %w[ratio percent]
16
16
 
17
17
  OP_NAME = 'metric.timing'
18
+ SPAN_ORIGIN = 'auto.metric.timing'
18
19
 
19
20
  class << self
20
21
  def increment(key, value = 1.0, unit: 'none', tags: {}, timestamp: nil)
@@ -37,7 +38,7 @@ module Sentry
37
38
  return unless block_given?
38
39
  return yield unless DURATION_UNITS.include?(unit)
39
40
 
40
- result, value = Sentry.with_child_span(op: OP_NAME, description: key) do |span|
41
+ result, value = Sentry.with_child_span(op: OP_NAME, description: key, origin: SPAN_ORIGIN) do |span|
41
42
  tags.each { |k, v| span.set_tag(k, v.is_a?(Array) ? v.join(', ') : v.to_s) } if span
42
43
 
43
44
  start = Timing.send(unit.to_sym)
@@ -8,6 +8,7 @@ module Sentry
8
8
  module Net
9
9
  module HTTP
10
10
  OP_NAME = "http.client"
11
+ SPAN_ORIGIN = "auto.http.net_http"
11
12
  BREADCRUMB_CATEGORY = "net.http"
12
13
 
13
14
  # To explain how the entire thing works, we need to know how the original Net::HTTP#request works
@@ -30,7 +31,7 @@ module Sentry
30
31
  return super unless started? && Sentry.initialized?
31
32
  return super if from_sentry_sdk?
32
33
 
33
- Sentry.with_child_span(op: OP_NAME, start_timestamp: Sentry.utc_now.to_f) do |sentry_span|
34
+ Sentry.with_child_span(op: OP_NAME, start_timestamp: Sentry.utc_now.to_f, origin: SPAN_ORIGIN) do |sentry_span|
34
35
  request_info = extract_request_info(req)
35
36
 
36
37
  if propagate_trace?(request_info[:url], Sentry.configuration)
@@ -5,6 +5,7 @@ module Sentry
5
5
  class CaptureExceptions
6
6
  ERROR_EVENT_ID_KEY = "sentry.error_event_id"
7
7
  MECHANISM_TYPE = "rack"
8
+ SPAN_ORIGIN = "auto.http.rack"
8
9
 
9
10
  def initialize(app)
10
11
  @app = app
@@ -63,7 +64,13 @@ module Sentry
63
64
  end
64
65
 
65
66
  def start_transaction(env, scope)
66
- options = { name: scope.transaction_name, source: scope.transaction_source, op: transaction_op }
67
+ options = {
68
+ name: scope.transaction_name,
69
+ source: scope.transaction_source,
70
+ op: transaction_op,
71
+ origin: SPAN_ORIGIN
72
+ }
73
+
67
74
  transaction = Sentry.continue_trace(env, **options)
68
75
  Sentry.start_transaction(transaction: transaction, custom_sampling_context: { env: env }, **options)
69
76
  end
data/lib/sentry/redis.rb CHANGED
@@ -4,6 +4,7 @@ module Sentry
4
4
  # @api private
5
5
  class Redis
6
6
  OP_NAME = "db.redis"
7
+ SPAN_ORIGIN = "auto.db.redis"
7
8
  LOGGER_NAME = :redis_logger
8
9
 
9
10
  def initialize(commands, host, port, db)
@@ -13,7 +14,7 @@ module Sentry
13
14
  def instrument
14
15
  return yield unless Sentry.initialized?
15
16
 
16
- Sentry.with_child_span(op: OP_NAME, start_timestamp: Sentry.utc_now.to_f) do |span|
17
+ Sentry.with_child_span(op: OP_NAME, start_timestamp: Sentry.utc_now.to_f, origin: SPAN_ORIGIN) do |span|
17
18
  yield.tap do
18
19
  record_breadcrumb
19
20
 
data/lib/sentry/scope.rb CHANGED
@@ -9,8 +9,8 @@ module Sentry
9
9
  include ArgumentCheckingHelper
10
10
 
11
11
  ATTRIBUTES = [
12
- :transaction_names,
13
- :transaction_sources,
12
+ :transaction_name,
13
+ :transaction_source,
14
14
  :contexts,
15
15
  :extra,
16
16
  :tags,
@@ -96,8 +96,8 @@ module Sentry
96
96
  copy.extra = extra.deep_dup
97
97
  copy.tags = tags.deep_dup
98
98
  copy.user = user.deep_dup
99
- copy.transaction_names = transaction_names.dup
100
- copy.transaction_sources = transaction_sources.dup
99
+ copy.transaction_name = transaction_name.dup
100
+ copy.transaction_source = transaction_source.dup
101
101
  copy.fingerprint = fingerprint.deep_dup
102
102
  copy.span = span.deep_dup
103
103
  copy.session = session.deep_dup
@@ -114,8 +114,8 @@ module Sentry
114
114
  self.extra = scope.extra
115
115
  self.tags = scope.tags
116
116
  self.user = scope.user
117
- self.transaction_names = scope.transaction_names
118
- self.transaction_sources = scope.transaction_sources
117
+ self.transaction_name = scope.transaction_name
118
+ self.transaction_source = scope.transaction_source
119
119
  self.fingerprint = scope.fingerprint
120
120
  self.span = scope.span
121
121
  self.propagation_context = scope.propagation_context
@@ -128,14 +128,15 @@ module Sentry
128
128
  # @param user [Hash]
129
129
  # @param level [String, Symbol]
130
130
  # @param fingerprint [Array]
131
- # @return [void]
131
+ # @return [Array]
132
132
  def update_from_options(
133
133
  contexts: nil,
134
134
  extra: nil,
135
135
  tags: nil,
136
136
  user: nil,
137
137
  level: nil,
138
- fingerprint: nil
138
+ fingerprint: nil,
139
+ **options
139
140
  )
140
141
  self.contexts.merge!(contexts) if contexts
141
142
  self.extra.merge!(extra) if extra
@@ -143,6 +144,9 @@ module Sentry
143
144
  self.user = user if user
144
145
  self.level = level if level
145
146
  self.fingerprint = fingerprint if fingerprint
147
+
148
+ # Returns unsupported option keys so we can notify users.
149
+ options.keys
146
150
  end
147
151
 
148
152
  # Sets the scope's rack_env attribute.
@@ -227,8 +231,8 @@ module Sentry
227
231
  # @param transaction_name [String]
228
232
  # @return [void]
229
233
  def set_transaction_name(transaction_name, source: :custom)
230
- @transaction_names << transaction_name
231
- @transaction_sources << source
234
+ @transaction_name = transaction_name
235
+ @transaction_source = source
232
236
  end
233
237
 
234
238
  # Sets the currently active session on the scope.
@@ -238,20 +242,6 @@ module Sentry
238
242
  @session = session
239
243
  end
240
244
 
241
- # Returns current transaction name.
242
- # The "transaction" here does not refer to `Transaction` objects.
243
- # @return [String, nil]
244
- def transaction_name
245
- @transaction_names.last
246
- end
247
-
248
- # Returns current transaction source.
249
- # The "transaction" here does not refer to `Transaction` objects.
250
- # @return [String, nil]
251
- def transaction_source
252
- @transaction_sources.last
253
- end
254
-
255
245
  # These are high cardinality and thus bad.
256
246
  # @return [Boolean]
257
247
  def transaction_source_low_quality?
@@ -307,8 +297,8 @@ module Sentry
307
297
  @user = {}
308
298
  @level = :error
309
299
  @fingerprint = []
310
- @transaction_names = []
311
- @transaction_sources = []
300
+ @transaction_name = nil
301
+ @transaction_source = nil
312
302
  @event_processors = []
313
303
  @rack_env = {}
314
304
  @span = nil
@@ -1,19 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Sentry
4
- class SessionFlusher
5
- include LoggingHelper
6
-
4
+ class SessionFlusher < ThreadedPeriodicWorker
7
5
  FLUSH_INTERVAL = 60
8
6
 
9
7
  def initialize(configuration, client)
10
- @thread = nil
11
- @exited = false
8
+ super(configuration.logger, FLUSH_INTERVAL)
12
9
  @client = client
13
10
  @pending_aggregates = {}
14
11
  @release = configuration.release
15
12
  @environment = configuration.environment
16
- @logger = configuration.logger
17
13
 
18
14
  log_debug("[Sessions] Sessions won't be captured without a valid release") unless @release
19
15
  end
@@ -25,30 +21,18 @@ module Sentry
25
21
  @pending_aggregates = {}
26
22
  end
27
23
 
24
+ alias_method :run, :flush
25
+
28
26
  def add_session(session)
29
- return if @exited
30
27
  return unless @release
31
28
 
32
- begin
33
- ensure_thread
34
- rescue ThreadError
35
- log_debug("Session flusher thread creation failed")
36
- @exited = true
37
- return
38
- end
29
+ return unless ensure_thread
39
30
 
40
31
  return unless Session::AGGREGATE_STATUSES.include?(session.status)
41
32
  @pending_aggregates[session.aggregation_key] ||= init_aggregates(session.aggregation_key)
42
33
  @pending_aggregates[session.aggregation_key][session.status] += 1
43
34
  end
44
35
 
45
- def kill
46
- log_debug("Killing session flusher")
47
-
48
- @exited = true
49
- @thread&.kill
50
- end
51
-
52
36
  private
53
37
 
54
38
  def init_aggregates(aggregation_key)
@@ -70,16 +54,5 @@ module Sentry
70
54
  def attrs
71
55
  { release: @release, environment: @environment }
72
56
  end
73
-
74
- def ensure_thread
75
- return if @thread&.alive?
76
-
77
- @thread = Thread.new do
78
- loop do
79
- sleep(FLUSH_INTERVAL)
80
- flush
81
- end
82
- end
83
- end
84
57
  end
85
58
  end
data/lib/sentry/span.rb CHANGED
@@ -39,6 +39,11 @@ module Sentry
39
39
  # Recommended: If different than server.port.
40
40
  # Example: 16456
41
41
  SERVER_SOCKET_PORT = "server.socket.port"
42
+
43
+ FILEPATH = "code.filepath"
44
+ LINENO = "code.lineno"
45
+ FUNCTION = "code.function"
46
+ NAMESPACE = "code.namespace"
42
47
  end
43
48
 
44
49
  STATUS_MAP = {
@@ -55,6 +60,8 @@ module Sentry
55
60
  504 => "deadline_exceeded"
56
61
  }
57
62
 
63
+ DEFAULT_SPAN_ORIGIN = "manual"
64
+
58
65
  # An uuid that can be used to identify a trace.
59
66
  # @return [String]
60
67
  attr_reader :trace_id
@@ -88,6 +95,9 @@ module Sentry
88
95
  # Span data
89
96
  # @return [Hash]
90
97
  attr_reader :data
98
+ # Span origin that tracks what kind of instrumentation created a span
99
+ # @return [String]
100
+ attr_reader :origin
91
101
 
92
102
  # The SpanRecorder the current span belongs to.
93
103
  # SpanRecorder holds all spans under the same Transaction object (including the Transaction itself).
@@ -109,7 +119,8 @@ module Sentry
109
119
  parent_span_id: nil,
110
120
  sampled: nil,
111
121
  start_timestamp: nil,
112
- timestamp: nil
122
+ timestamp: nil,
123
+ origin: nil
113
124
  )
114
125
  @trace_id = trace_id || SecureRandom.uuid.delete("-")
115
126
  @span_id = span_id || SecureRandom.uuid.delete("-").slice(0, 16)
@@ -123,6 +134,7 @@ module Sentry
123
134
  @status = status
124
135
  @data = {}
125
136
  @tags = {}
137
+ @origin = origin || DEFAULT_SPAN_ORIGIN
126
138
  end
127
139
 
128
140
  # Finishes the span by adding a timestamp.
@@ -160,7 +172,8 @@ module Sentry
160
172
  op: @op,
161
173
  status: @status,
162
174
  tags: @tags,
163
- data: @data
175
+ data: @data,
176
+ origin: @origin
164
177
  }
165
178
 
166
179
  summary = metrics_summary
@@ -178,7 +191,8 @@ module Sentry
178
191
  parent_span_id: @parent_span_id,
179
192
  description: @description,
180
193
  op: @op,
181
- status: @status
194
+ status: @status,
195
+ origin: @origin
182
196
  }
183
197
  end
184
198
 
@@ -275,6 +289,12 @@ module Sentry
275
289
  @tags[key] = value
276
290
  end
277
291
 
292
+ # Sets the origin of the span.
293
+ # @param origin [String]
294
+ def set_origin(origin)
295
+ @origin = origin
296
+ end
297
+
278
298
  # Collects gauge metrics on the span for metric summaries.
279
299
  def metrics_local_aggregator
280
300
  @metrics_local_aggregator ||= Sentry::Metrics::LocalAggregator.new
@@ -20,7 +20,7 @@ module Sentry
20
20
  # set transport to DummyTransport, so we can easily intercept the captured events
21
21
  dummy_config.transport.transport_class = Sentry::DummyTransport
22
22
  # make sure SDK allows sending under the current environment
23
- dummy_config.enabled_environments << dummy_config.environment unless dummy_config.enabled_environments.include?(dummy_config.environment)
23
+ dummy_config.enabled_environments += [dummy_config.environment] unless dummy_config.enabled_environments.include?(dummy_config.environment)
24
24
  # disble async event sending
25
25
  dummy_config.background_worker_threads = 0
26
26
 
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sentry
4
+ class ThreadedPeriodicWorker
5
+ include LoggingHelper
6
+
7
+ def initialize(logger, internal)
8
+ @thread = nil
9
+ @exited = false
10
+ @interval = internal
11
+ @logger = logger
12
+ end
13
+
14
+ def ensure_thread
15
+ return false if @exited
16
+ return true if @thread&.alive?
17
+
18
+ @thread = Thread.new do
19
+ loop do
20
+ sleep(@interval)
21
+ run
22
+ end
23
+ end
24
+
25
+ true
26
+ rescue ThreadError
27
+ log_debug("[#{self.class.name}] thread creation failed")
28
+ @exited = true
29
+ false
30
+ end
31
+
32
+ def kill
33
+ log_debug("[#{self.class.name}] thread killed")
34
+
35
+ @exited = true
36
+ @thread&.kill
37
+ end
38
+ end
39
+ end
@@ -61,7 +61,7 @@ module Sentry
61
61
  data, serialized_items = serialize_envelope(envelope)
62
62
 
63
63
  if data
64
- log_info("[Transport] Sending envelope with items [#{serialized_items.map(&:type).join(', ')}] #{envelope.event_id} to Sentry")
64
+ log_debug("[Transport] Sending envelope with items [#{serialized_items.map(&:type).join(', ')}] #{envelope.event_id} to Sentry")
65
65
  send_data(data)
66
66
  end
67
67
  end
@@ -11,10 +11,6 @@ module Sentry
11
11
  end
12
12
  end
13
13
 
14
- def log_info(message)
15
- @logger.info(LOGGER_PROGNAME) { message }
16
- end
17
-
18
14
  def log_debug(message)
19
15
  @logger.debug(LOGGER_PROGNAME) { message }
20
16
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Sentry
4
- VERSION = "5.17.3"
4
+ VERSION = "5.18.1"
5
5
  end
data/lib/sentry-ruby.rb CHANGED
@@ -20,6 +20,7 @@ require "sentry/span"
20
20
  require "sentry/transaction"
21
21
  require "sentry/hub"
22
22
  require "sentry/background_worker"
23
+ require "sentry/threaded_periodic_worker"
23
24
  require "sentry/session_flusher"
24
25
  require "sentry/backpressure_monitor"
25
26
  require "sentry/cron/monitor_check_ins"
@@ -550,6 +551,15 @@ module Sentry
550
551
  get_current_hub.get_trace_propagation_headers
551
552
  end
552
553
 
554
+ # Returns the a Hash containing sentry-trace and baggage.
555
+ # Can be either from the currently active span or the propagation context.
556
+ #
557
+ # @return [String]
558
+ def get_trace_propagation_meta
559
+ return '' unless initialized?
560
+ get_current_hub.get_trace_propagation_meta
561
+ end
562
+
553
563
  # Continue an incoming trace from a rack env like hash.
554
564
  #
555
565
  # @param env [Hash]
@@ -590,3 +600,4 @@ end
590
600
  require "sentry/net/http"
591
601
  require "sentry/redis"
592
602
  require "sentry/puma"
603
+ require "sentry/graphql"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sentry-ruby-core
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.17.3
4
+ version: 5.18.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sentry Team
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-04-11 00:00:00.000000000 Z
11
+ date: 2024-07-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: sentry-ruby
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - '='
18
18
  - !ruby/object:Gem::Version
19
- version: 5.17.3
19
+ version: 5.18.1
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - '='
25
25
  - !ruby/object:Gem::Version
26
- version: 5.17.3
26
+ version: 5.18.1
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: concurrent-ruby
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -79,6 +79,7 @@ files:
79
79
  - lib/sentry/error_event.rb
80
80
  - lib/sentry/event.rb
81
81
  - lib/sentry/exceptions.rb
82
+ - lib/sentry/graphql.rb
82
83
  - lib/sentry/hub.rb
83
84
  - lib/sentry/integrable.rb
84
85
  - lib/sentry/interface.rb
@@ -115,6 +116,7 @@ files:
115
116
  - lib/sentry/session_flusher.rb
116
117
  - lib/sentry/span.rb
117
118
  - lib/sentry/test_helper.rb
119
+ - lib/sentry/threaded_periodic_worker.rb
118
120
  - lib/sentry/transaction.rb
119
121
  - lib/sentry/transaction_event.rb
120
122
  - lib/sentry/transport.rb
@@ -154,7 +156,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
154
156
  - !ruby/object:Gem::Version
155
157
  version: '0'
156
158
  requirements: []
157
- rubygems_version: 3.1.6
159
+ rubygems_version: 3.5.11
158
160
  signing_key:
159
161
  specification_version: 4
160
162
  summary: A gem that provides a client interface for the Sentry error logger