Skip to content

Commit 8057a97

Browse files
authored
Merge branch 'master' into sdk_logger_resiliency
2 parents be4cb34 + 854f4ca commit 8057a97

23 files changed

Lines changed: 1248 additions & 50 deletions

CHANGELOG.md

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,21 @@
22

33
### Features
44

5+
- Implement new `Sentry.metrics` functionality ([#2818](https://github.com/getsentry/sentry-ruby/pull/2818))
6+
7+
The SDK now supports Sentry's new [Trace Connected Metrics](https://docs.sentry.io/product/explore/metrics/) product.
8+
9+
```ruby
10+
Sentry.init do |config|
11+
# ...
12+
config.enable_metrics = true
13+
end
14+
15+
Sentry.metrics.count("button.click", 1, attributes: { button_id: "submit" })
16+
Sentry.metrics.distribution("response.time", 120.5, unit: "millisecond")
17+
Sentry.metrics.gauge("cpu.usage", 75.2, unit: "percent")
18+
```
19+
520
- Support for tracing `Sequel` queries ([#2814](https://github.com/getsentry/sentry-ruby/pull/2814))
621

722
```ruby
@@ -19,6 +34,11 @@
1934
### Bug Fixes
2035

2136
- Handle empty frames case gracefully with local vars ([#2807](https://github.com/getsentry/sentry-ruby/pull/2807))
37+
- Handle more extra attribute types when using `extra` attributes for structured logging ([#2815](https://github.com/getsentry/sentry-ruby/pull/2815))
38+
```ruby
39+
# This now works too and the nested hash is dumped to JSON string
40+
Sentry.logger.info("Hello World", extra: { today: Date.today, user_id: user.id })
41+
```
2242
- Prevent SDK crash when SDK logging fails ([#2817](https://github.com/getsentry/sentry-ruby/pull/2817))
2343

2444
## 6.2.0
@@ -530,7 +550,6 @@
530550
- Use `Concurrent.available_processor_count` instead of `Concurrent.usable_processor_count` ([#2358](https://github.com/getsentry/sentry-ruby/pull/2358))
531551

532552
- Support for tracing Faraday requests ([#2345](https://github.com/getsentry/sentry-ruby/pull/2345))
533-
534553
- Closes [#1795](https://github.com/getsentry/sentry-ruby/issues/1795)
535554
- Please note that the Faraday instrumentation has some limitations in case of async requests: <https://github.com/lostisland/faraday/issues/1381>
536555

@@ -553,7 +572,6 @@
553572
```
554573

555574
- Transaction data are now included in the context ([#2365](https://github.com/getsentry/sentry-ruby/pull/2365))
556-
557575
- Closes [#2363](https://github.com/getsentry/sentry-ruby/issues/2363)
558576

559577
- Inject Sentry meta tags in the Rails application layout automatically in the generator ([#2369](https://github.com/getsentry/sentry-ruby/pull/2369))
@@ -667,7 +685,6 @@
667685
- Fix warning about default gems on Ruby 3.3.0 ([#2225](https://github.com/getsentry/sentry-ruby/pull/2225))
668686
- Add `hint:` support to `Sentry::Rails::ErrorSubscriber` [#2235](https://github.com/getsentry/sentry-ruby/pull/2235)
669687
- Add [Metrics](https://docs.sentry.io/product/metrics/) support
670-
671688
- Add main APIs and `Aggregator` thread [#2247](https://github.com/getsentry/sentry-ruby/pull/2247)
672689
- Add `Sentry::Metrics.timing` API for measuring block duration [#2254](https://github.com/getsentry/sentry-ruby/pull/2254)
673690
- Add metric summaries on spans [#2255](https://github.com/getsentry/sentry-ruby/pull/2255)
@@ -827,7 +844,6 @@
827844
- Improve default slug generation for Crons [#2168](https://github.com/getsentry/sentry-ruby/pull/2168)
828845
- Change release name generator to use full SHA commit hash and align with `sentry-cli` and other Sentry SDKs [#2174](https://github.com/getsentry/sentry-ruby/pull/2174)
829846
- Automatic Crons support for scheduling gems
830-
831847
- Add support for [`sidekiq-cron`](https://github.com/sidekiq-cron/sidekiq-cron) [#2170](https://github.com/getsentry/sentry-ruby/pull/2170)
832848
833849
You can opt in to the `sidekiq-cron` patch and we will automatically monitor check-ins for all jobs listed in your `config/schedule.yml` file.
@@ -883,7 +899,6 @@
883899
- Adopt Rails 7.1's new BroadcastLogger [#2120](https://github.com/getsentry/sentry-ruby/pull/2120)
884900
- Support sending events after all retries were performed (sentry-resque) [#2087](https://github.com/getsentry/sentry-ruby/pull/2087)
885901
- Add [Cron Monitoring](https://docs.sentry.io/product/crons/) support
886-
887902
- Add `Sentry.capture_check_in` API for Cron Monitoring [#2117](https://github.com/getsentry/sentry-ruby/pull/2117)
888903
889904
You can now track progress of long running scheduled jobs.
@@ -966,7 +981,6 @@
966981
```
967982

968983
- Tracing without Performance
969-
970984
- Implement `PropagationContext` on `Scope` and add `Sentry.get_trace_propagation_headers` API [#2084](https://github.com/getsentry/sentry-ruby/pull/2084)
971985
- Implement `Sentry.continue_trace` API [#2089](https://github.com/getsentry/sentry-ruby/pull/2089)
972986

@@ -1053,7 +1067,6 @@
10531067
```
10541068

10551069
Some implementation caveats:
1056-
10571070
- Profiles are sampled **relative** to traces, so if both rates are 0.5, we will capture 0.25 of all requests.
10581071
- Profiles are only captured for code running within a transaction.
10591072
- Profiles for multi-threaded servers like `puma` might not capture frames correctly when async I/O is happening. This is a `stackprof` limitation.
@@ -1138,7 +1151,6 @@
11381151
- Expose `end_timestamp` in `Span#finish` and `Transaction#finish` [#1946](https://github.com/getsentry/sentry-ruby/pull/1946)
11391152
- Add `Transaction#set_context` api [#1947](https://github.com/getsentry/sentry-ruby/pull/1947)
11401153
- Add OpenTelemetry support with new `sentry-opentelemetry` gem
1141-
11421154
- Add `config.instrumenter` to switch between `:sentry` and `:otel` instrumentation [#1944](https://github.com/getsentry/sentry-ruby/pull/1944)
11431155

11441156
The new `sentry-opentelemetry` gem adds support to automatically integrate OpenTelemetry performance tracing with Sentry. [Give it a try](https://github.com/getsentry/sentry-ruby/tree/master/sentry-opentelemetry#getting-started) and let us know if you have any feedback or problems with using it.
@@ -1158,7 +1170,6 @@
11581170
```
11591171

11601172
- Use `Sentry.with_child_span` in redis and net/http instead of `span.start_child` [#1920](https://github.com/getsentry/sentry-ruby/pull/1920)
1161-
11621173
- This might change the nesting of some spans and make it more accurate
11631174
- Followup fix to set the sentry-trace header in the correct place [#1922](https://github.com/getsentry/sentry-ruby/pull/1922)
11641175

@@ -1187,14 +1198,12 @@
11871198
### Features
11881199

11891200
- Support rack 3 [#1884](https://github.com/getsentry/sentry-ruby/pull/1884)
1190-
11911201
- We no longer need the `HTTP_VERSION` check for ignoring the header
11921202

11931203
- Add [Dynamic Sampling](https://docs.sentry.io/product/sentry-basics/sampling/) support
11941204
The SDK now supports Sentry's Dynamic Sampling product.
11951205

11961206
Note that this is not supported for users still using the `config.async` option.
1197-
11981207
- Parse incoming [W3C Baggage Headers](https://www.w3.org/TR/baggage/) and propagate them to continue traces [#1869](https://github.com/getsentry/sentry-ruby/pull/1869)
11991208
- in all outgoing requests in our net/http patch
12001209
- in Sentry transactions as [Dynamic Sampling Context](https://develop.sentry.dev/sdk/performance/dynamic-sampling-context/)
@@ -1230,7 +1239,6 @@
12301239
- Expose `:values` in `ExceptionInterface`, so that it can be accessed in `before_send` under `event.exception.values` [#1843](https://github.com/getsentry/sentry-ruby/pull/1843)
12311240

12321241
- Add top level `Sentry.close` API [#1844](https://github.com/getsentry/sentry-ruby/pull/1844)
1233-
12341242
- Cleans up SDK state and sets it to uninitialized
12351243
- No-ops all SDK APIs and also disables the transport layer, so nothing will be sent to Sentry after closing the SDK
12361244

@@ -1392,7 +1400,6 @@ end
13921400
- Check envelope size before sending it [#1747](https://github.com/getsentry/sentry-ruby/pull/1747)
13931401

13941402
The SDK will now check if the envelope's event items are oversized before sending the envelope. It goes like this:
1395-
13961403
1. If an event is oversized (200kb), the SDK will remove its breadcrumbs (which in our experience is the most common cause).
13971404
2. If the event size now falls within the limit, it'll be sent.
13981405
3. Otherwise, the event will be thrown away. The SDK will also log a debug message about the event's attributes size (in bytes) breakdown. For example,
@@ -1711,7 +1718,6 @@ When `config.send_default_pii` is set as `true`, `:http_logger` will include que
17111718
### Features
17121719

17131720
- Support exception frame's local variable capturing
1714-
17151721
- [#1580](https://github.com/getsentry/sentry-ruby/pull/1580)
17161722
- [#1589](https://github.com/getsentry/sentry-ruby/pull/1589)
17171723

sentry-rails/spec/sentry/rails/log_subscribers/action_controller_subscriber_spec.rb

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434

3535
expect(log_event[:attributes][:method][:value]).to eq("GET")
3636
expect(log_event[:attributes][:path][:value]).to eq("/world")
37-
expect(log_event[:attributes][:format][:value]).to eq(:html)
37+
expect(log_event[:attributes][:format][:value]).to eq("\"html\"")
3838
expect(log_event[:attributes]["sentry.origin"][:value]).to eq("auto.log.rails.log_subscriber")
3939
end
4040

@@ -275,8 +275,10 @@
275275
log_event = sentry_logs.find { |log| log[:body] == "HelloController#world" }
276276
expect(log_event).not_to be_nil
277277
expect(log_event[:attributes][:params]).to be_present
278-
expect(log_event[:attributes][:params][:value]).to include("safe_param" => "value")
279-
expect(log_event[:attributes][:params][:value]).to include("password" => "[FILTERED]")
278+
279+
params = JSON.parse(log_event[:attributes][:params][:value])
280+
expect(params).to include("safe_param" => "value")
281+
expect(params).to include("password" => "[FILTERED]")
280282
end
281283

282284
it "filters sensitive parameter names" do
@@ -295,7 +297,7 @@
295297
log_event = sentry_logs.find { |log| log[:body] == "HelloController#world" }
296298
expect(log_event).not_to be_nil
297299

298-
params = log_event[:attributes][:params][:value]
300+
params = JSON.parse(log_event[:attributes][:params][:value])
299301
expect(params).to include("normal_param" => "value")
300302
expect(params).to include("password" => "[FILTERED]")
301303
expect(params).to include("api_key" => "[FILTERED]")
@@ -323,7 +325,7 @@
323325
log_event = sentry_logs.find { |log| log[:body] == "HelloController#world" }
324326
expect(log_event).not_to be_nil
325327

326-
params = log_event[:attributes][:params][:value]
328+
params = JSON.parse(log_event[:attributes][:params][:value])
327329
expect(params).to include("normal_param" => "value")
328330
expect(params["user"]).to include("name" => "John")
329331
expect(params["user"]).to include("password" => "[FILTERED]")

sentry-rails/spec/sentry/rails/log_subscribers/action_mailer_subscriber_spec.rb

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
expect(log_event[:attributes][:mailer][:value]).to eq("UserMailer")
3838
expect(log_event[:attributes][:duration_ms][:value]).to be > 0
3939
expect(log_event[:attributes][:perform_deliveries][:value]).to be true
40-
expect(log_event[:attributes][:delivery_method][:value]).to eq(:test)
40+
expect(log_event[:attributes][:delivery_method][:value]).to eq("\"test\"")
4141
expect(log_event[:attributes]["sentry.origin"][:value]).to eq("auto.log.rails.log_subscriber")
4242
expect(log_event[:attributes][:date]).to be_present
4343
end
@@ -76,7 +76,7 @@
7676

7777
log_event = sentry_logs.find { |log| log[:body] == "Email delivered via NotificationMailer" }
7878
expect(log_event).not_to be_nil
79-
expect(log_event[:attributes][:delivery_method][:value]).to eq(:smtp)
79+
expect(log_event[:attributes][:delivery_method][:value]).to eq("\"smtp\"")
8080
end
8181

8282
it "includes date when available" do
@@ -179,12 +179,12 @@
179179
expect(log_event).not_to be_nil
180180
expect(log_event[:attributes][:params]).to be_present
181181

182-
params = log_event[:attributes][:params][:value]
182+
params = JSON.parse(log_event[:attributes][:params][:value])
183183

184-
expect(params).to include(user_id: 123, safe_param: "value")
185-
expect(params[:password]).to eq("[FILTERED]")
186-
expect(params[:api_key]).to eq("[FILTERED]")
187-
expect(params).to include(email_address: "user@example.com", subject: "Welcome!")
184+
expect(params).to include("user_id" => 123, "safe_param" => "value")
185+
expect(params["password"]).to eq("[FILTERED]")
186+
expect(params["api_key"]).to eq("[FILTERED]")
187+
expect(params).to include("email_address" => "user@example.com", "subject" => "Welcome!")
188188
end
189189
end
190190

sentry-rails/spec/sentry/rails/log_subscribers/active_job_subscriber_spec.rb

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@
5757
expect(attributes[:job_id][:value]).to be_a(String)
5858
expect(attributes[:queue_name][:value]).to eq("default")
5959
expect(attributes[:executions][:value]).to eq(1)
60-
expect(attributes[:priority][:value]).to be_a(Integer).or be_nil
60+
expect(attributes[:priority][:value]).to be_a(Integer).or(eq("null")).or be_nil
6161
end
6262

6363
it "includes adapter information when available" do
@@ -122,8 +122,9 @@ def perform(*args, **kwargs)
122122
expect(log_event).not_to be_nil
123123

124124
attributes = log_event[:attributes]
125-
expect(attributes[:arguments][:value]).to be_a(Array)
126-
expect(attributes[:arguments][:value]).to include("safe_arg")
125+
arguments = JSON.parse(attributes[:arguments][:value])
126+
expect(arguments).to be_a(Array)
127+
expect(arguments).to include("safe_arg")
127128
end
128129

129130
it "filters sensitive arguments" do
@@ -147,11 +148,11 @@ def perform(password:, token:, safe_data:)
147148
expect(log_event).not_to be_nil
148149

149150
attributes = log_event[:attributes]
150-
arguments = attributes[:arguments][:value]
151+
arguments = JSON.parse(attributes[:arguments][:value])
151152

152-
expect(arguments.first).to include(safe_data: "public")
153-
expect(arguments.first).to include(password: "[FILTERED]")
154-
expect(arguments.first).to include(token: "[FILTERED]")
153+
expect(arguments.first).to include("safe_data" => "public")
154+
expect(arguments.first).to include("password" => "[FILTERED]")
155+
expect(arguments.first).to include("token" => "[FILTERED]")
155156

156157
Rails.application.config.filter_parameters = original_filter_params
157158
end
@@ -175,7 +176,7 @@ def perform(short_string, long_string)
175176
expect(log_event).not_to be_nil
176177

177178
attributes = log_event[:attributes]
178-
arguments = attributes[:arguments][:value]
179+
arguments = JSON.parse(attributes[:arguments][:value])
179180

180181
expect(arguments).to include("short")
181182
expect(arguments).to include("[FILTERED: 150 chars]")
@@ -204,11 +205,11 @@ def perform(string_arg, hash_arg, number_arg, array_arg)
204205
expect(log_event).not_to be_nil
205206

206207
attributes = log_event[:attributes]
207-
arguments = attributes[:arguments][:value]
208+
arguments = JSON.parse(attributes[:arguments][:value])
208209

209210
expect(arguments[0]).to eq("string_value")
210-
expect(arguments[1]).to include(safe_key: "value")
211-
expect(arguments[1]).to include(password: "[FILTERED]")
211+
expect(arguments[1]).to include("safe_key" => "value")
212+
expect(arguments[1]).to include("password" => "[FILTERED]")
212213
expect(arguments[2]).to eq(42)
213214
expect(arguments[3]).to eq([1, 2, 3])
214215
end

sentry-ruby/lib/sentry-ruby.rb

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
require "sentry/backpressure_monitor"
2828
require "sentry/cron/monitor_check_ins"
2929
require "sentry/vernier/profiler"
30+
require "sentry/metrics"
3031

3132
[
3233
"sentry/rake",
@@ -627,6 +628,24 @@ def logger
627628
@logger ||= configuration.structured_logging.logger_class.new(configuration)
628629
end
629630

631+
# Returns the metrics API for capturing custom metrics.
632+
#
633+
# @example Enable metrics
634+
# Sentry.init do |config|
635+
# config.dsn = "YOUR_DSN"
636+
# config.enable_metrics = true
637+
# end
638+
#
639+
# @example Usage
640+
# Sentry.metrics.count("button.click", 1, attributes: { button_id: "submit" })
641+
# Sentry.metrics.distribution("response.time", 120.5, unit: "millisecond")
642+
# Sentry.metrics.gauge("cpu.usage", 75.2, unit: "percent")
643+
#
644+
# @return [Metrics] The metrics API
645+
def metrics
646+
Metrics
647+
end
648+
630649
##### Helpers #####
631650

632651
# @!visibility private

0 commit comments

Comments
 (0)