Skip to content

Commit 1ad61e4

Browse files
authored
fix(rails): better logs docs (#15226)
<!-- Use this checklist to make sure your PR is ready for merge. You may delete any sections you don't need. --> ## DESCRIBE YOUR PR Improves the flow and adds info about `before_send_log` option in the Rails' `Logs` section. I tried to make it flow similarly to how we have Laravel structured. --- Fixes getsentry/sentry-ruby#2738 ## Preview https://sentry-docs-git-rails-improve-logs-docs.sentry.dev/platforms/ruby/guides/rails/logs/ ## IS YOUR CHANGE URGENT? Help us prioritize incoming PRs by letting us know when the change needs to go live. - [ ] Urgent deadline (GA date, etc.): <!-- ENTER DATE HERE --> - [ ] Other deadline: <!-- ENTER DATE HERE --> - [x] None: Not urgent, can wait up to 1 week+ ## SLA - Teamwork makes the dream work, so please add a reviewer to your PRs. - Please give the docs team up to 1 week to review your PR unless you've added an urgent due date to it. Thanks in advance for your help! ## PRE-MERGE CHECKLIST *Make sure you've checked the following before merging your changes:* - [ ] Checked Vercel preview for correctness, including links - [ ] PR was reviewed and approved by any necessary SMEs (subject matter experts) - [ ] PR was reviewed and approved by a member of the [Sentry docs team](https://github.com/orgs/getsentry/teams/docs) ## LEGAL BOILERPLATE <!-- Sentry employees and contractors can delete or ignore this section. --> Look, I get it. The entity doing business as "Sentry" was incorporated in the State of Delaware in 2015 as Functional Software, Inc. and is gonna need some rights from me in order to utilize my contributions in this here PR. So here's the deal: I retain all rights, title and interest in and to my contributions, and by keeping this boilerplate intact I confirm that Sentry can use, modify, copy, and redistribute my contributions, under Sentry's choice of terms. ## EXTRA RESOURCES - [Sentry Docs contributor guide](https://docs.sentry.io/contributing/)
1 parent 678770f commit 1ad61e4

File tree

6 files changed

+115
-172
lines changed

6 files changed

+115
-172
lines changed

docs/platforms/ruby/common/configuration/options.mdx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,14 @@ Provides a lambda or proc that's called with an SDK-specific transaction event o
342342

343343
</SdkOption>
344344

345+
<SdkOption name="before_send_log" type="lambda | proc">
346+
347+
Provides a lambda or proc that's called with an SDK-specific log object, and can return a modified log object, or `nil` to skip reporting the log. This can be used to filter logs before they are sent to Sentry.
348+
349+
<PlatformContent includePath="configuration/before-send-log/" />
350+
351+
</SdkOption>
352+
345353
<SdkOption name="backtrace_cleanup_callback" type="lambda">
346354

347355
If you want to clean up the backtrace of an exception before it's sent to Sentry, you can specify a callback with `backtrace_cleanup_callback`, for example:

docs/platforms/ruby/guides/rails/logs/index.mdx

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,28 @@ With Sentry Structured Logs, you can send text-based log information from your R
2626
## Default Attributes
2727

2828
<PlatformContent includePath="logs/default-attributes" />
29+
30+
## Troubleshooting
31+
32+
If logs aren't appearing in Sentry:
33+
34+
**Verify configuration:**
35+
```ruby
36+
Sentry.init do |config|
37+
config.enable_logs = true # Must be set
38+
end
39+
```
40+
41+
**Test your setup:**
42+
43+
```ruby
44+
Sentry.logger.info("Test log message")
45+
Sentry.get_current_client.flush
46+
```
47+
48+
Then verify if the log appears in Sentry.
49+
50+
**Enable debug mode:**
51+
```ruby
52+
config.debug = true # See SDK diagnostic output
53+
```
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
```ruby
2+
Sentry.init do |config|
3+
config.dsn = "___PUBLIC_DSN___"
4+
config.enable_logs = true
5+
6+
config.before_send_log = lambda do |log|
7+
# Skip info logs
8+
return if log.level == :info
9+
10+
log
11+
end
12+
end
13+
```
14+
Lines changed: 52 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,28 @@
1-
### Available Built-in Subscribers
1+
### before_send_log
22

3-
The Rails SDK includes several built-in log subscribers that you can enable:
3+
To filter logs before they are sent to Sentry, use the `before_send_log` callback. Return `nil` to skip a log, or return the log object to send it.
44

5-
#### Default Subscribers (enabled automatically)
6-
- **ActiveRecord**: Database queries with SQL, duration, connection info, and caching status
7-
- **ActionController**: HTTP requests with controller, action, parameters, response status, and timing
5+
<PlatformContent includePath="configuration/before-send-log" />
86

9-
#### Additional Subscribers (opt-in)
10-
- **ActiveJob**: Background job execution (`perform`), enqueueing (`enqueue`), retry failures (`retry_stopped`), and job discarding (`discard`)
11-
- **ActionMailer**: Email delivery (`deliver`) and processing (`process`) events
7+
### Structured Logging Subscribers
128

13-
### Custom Subscriber Configuration
9+
Structured logging is enabled by default when you set `enable_logs = true`. You can customize which Rails events are captured.
1410

15-
You can customize which subscribers are active:
11+
**Default subscribers (enabled automatically):**
12+
- `active_record` - Database queries
13+
- `action_controller` - HTTP requests
1614

17-
```ruby
18-
Sentry.init do |config|
19-
config.dsn = "___PUBLIC_DSN___"
15+
**Additional subscribers (opt-in):**
16+
- `active_job` - Background jobs
17+
- `action_mailer` - Email delivery
2018

21-
config.enable_logs = true
22-
23-
config.rails.structured_logging.enabled = true
24-
25-
config.rails.structured_logging.subscribers = {
26-
active_record: Sentry::Rails::LogSubscribers::ActiveRecordSubscriber,
27-
action_controller: Sentry::Rails::LogSubscribers::ActionControllerSubscriber
28-
}
29-
end
30-
```
31-
32-
To enable additional subscribers, add them to the configuration:
19+
**Enable additional subscribers:**
3320

3421
```ruby
3522
Sentry.init do |config|
3623
config.dsn = "___PUBLIC_DSN___"
37-
3824
config.enable_logs = true
3925

40-
config.rails.structured_logging.enabled = true
41-
4226
config.rails.structured_logging.subscribers = {
4327
active_record: Sentry::Rails::LogSubscribers::ActiveRecordSubscriber,
4428
action_controller: Sentry::Rails::LogSubscribers::ActionControllerSubscriber,
@@ -48,30 +32,37 @@ Sentry.init do |config|
4832
end
4933
```
5034

51-
To disable specific subscribers:
35+
**Disable default subscribers:**
5236

5337
```ruby
54-
Sentry.init do |config|
55-
config.dsn = "___PUBLIC_DSN___"
38+
config.rails.structured_logging.subscribers = {
39+
active_record: Sentry::Rails::LogSubscribers::ActiveRecordSubscriber
40+
# ActionController disabled
41+
}
42+
```
5643

57-
config.enable_logs = true
44+
**Disable structured logging entirely:**
45+
46+
```ruby
47+
config.rails.structured_logging.enabled = false
48+
```
5849

59-
config.rails.structured_logging.enabled = true
50+
### Sensitive Data Filtering
6051

61-
config.rails.structured_logging.subscribers = {
62-
active_record: Sentry::Rails::LogSubscribers::ActiveRecordSubscriber
63-
# ActionController subscriber disabled
64-
}
65-
end
52+
Structured logging automatically respects Rails' parameter filtering:
53+
54+
```ruby {filename:config/application.rb}
55+
config.filter_parameters += [:password, :credit_card, :ssn]
6656
```
6757

68-
### Creating Custom Log Subscribers
58+
This filters sensitive data from ActionController parameters, ActiveJob arguments, and ActionMailer parameters.
6959

70-
You can create custom log subscribers by extending the base class:
60+
### Custom Log Subscribers
61+
62+
You can create custom subscribers to capture your own Rails instrumentation events:
7163

7264
```ruby
7365
class MyCustomSubscriber < Sentry::Rails::LogSubscriber
74-
# Attach to your component's instrumentation events
7566
attach_to :my_component
7667

7768
def my_event(event)
@@ -80,48 +71,41 @@ class MyCustomSubscriber < Sentry::Rails::LogSubscriber
8071
level: :info,
8172
attributes: {
8273
duration_ms: event.duration,
83-
custom_data: event.payload[:custom_data],
8474
user_id: event.payload[:user_id]
8575
}
8676
)
8777
end
88-
89-
def another_event(event)
90-
log_structured_event(
91-
message: "Another custom event",
92-
level: :warn,
93-
attributes: {
94-
event_type: event.payload[:type],
95-
metadata: event.payload[:metadata]
96-
}
97-
)
98-
end
9978
end
10079
```
10180

102-
Then register your custom subscriber:
81+
Register it in your configuration:
10382

10483
```ruby
105-
Sentry.init do |config|
106-
config.dsn = "___PUBLIC_DSN___"
84+
config.rails.structured_logging.subscribers = {
85+
active_record: Sentry::Rails::LogSubscribers::ActiveRecordSubscriber,
86+
my_component: MyCustomSubscriber
87+
}
88+
```
10789

108-
config.enable_logs = true
90+
### Using `Rails.logger`
10991

110-
config.rails.structured_logging.enabled = true
92+
If you want all Rails logs to go to Sentry, you can enable the `:logger` patch:
11193

112-
config.rails.structured_logging.subscribers = {
113-
active_record: Sentry::Rails::LogSubscribers::ActiveRecordSubscriber,
114-
action_controller: Sentry::Rails::LogSubscribers::ActionControllerSubscriber,
115-
my_component: MyCustomSubscriber
116-
}
94+
```ruby
95+
Sentry.init do |config|
96+
config.dsn = "___PUBLIC_DSN___"
97+
config.enable_logs = true
98+
config.enabled_patches = [:logger]
11799
end
118100
```
119101

120-
### Sensitive Data Filtering
121-
122-
Log subscribers automatically respect Rails' parameter filtering configuration. Sensitive parameters defined in `config.filter_parameters` will be filtered from structured logs:
102+
This will send all `Rails.logger` calls to Sentry:
123103

124104
```ruby
125-
# config/application.rb
126-
config.filter_parameters += [:password, :credit_card, :ssn]
105+
Rails.logger.info("Processing user request")
106+
Rails.logger.error("Failed to save record")
127107
```
108+
109+
<Alert level="warning">
110+
This captures ALL Rails framework logs as well as ANY OTHER logs produced by instances of the `Logger` class and this can be very noisy. We recommend using `Sentry.logger` for better control over what gets logged.
111+
</Alert>
Lines changed: 5 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
To enable logging, you need to initialize the SDK with the `enable_logs` option set to `true`.
1+
To enable logging, initialize the SDK with `enable_logs` set to `true`:
22

33
```ruby
44
Sentry.init do |config|
@@ -7,60 +7,8 @@ Sentry.init do |config|
77
end
88
```
99

10-
### Structured Logging with Log Subscribers
10+
This enables:
11+
- The `Sentry.logger` API for explicit logging
12+
- Automatic structured logging of Rails framework events (ActiveRecord queries, controller actions, etc.)
1113

12-
<Alert level="info" title="Note on structured logging">
13-
Structured logging with Log Subscribers provides rich context and metadata compared to plain logger messages. This enables better filtering, searching, and analysis of your application's behavior in Sentry.
14-
</Alert>
15-
16-
Rails applications can benefit from structured logging using ActiveSupport's Log Subscribers. This feature captures Rails instrumentation events and sends them as structured logs to Sentry with relevant context and metadata.
17-
18-
#### Default Setup
19-
20-
To enable structured logging with default subscribers:
21-
22-
```ruby
23-
Sentry.init do |config|
24-
config.dsn = "___PUBLIC_DSN___"
25-
config.enable_logs = true
26-
config.rails.structured_logging.enabled = true
27-
end
28-
```
29-
30-
By default, this enables structured logging for:
31-
32-
- **ActiveRecord**: Database queries with SQL, duration, connection info, and caching status
33-
- **ActionController**: HTTP requests with controller, action, parameters, response status, and timing
34-
35-
Additional subscribers are available but not enabled by default:
36-
37-
- **ActiveJob**: Background job execution (`perform`), enqueueing (`enqueue`), retry failures (`retry_stopped`), and job discarding (`discard`)
38-
- **ActionMailer**: Email delivery (`deliver`) and processing (`process`) events
39-
40-
See the [Options](#options) section for information on how to enable additional subscribers.
41-
42-
### Basic Rails Logger Integration
43-
44-
If you enable `:logger` patch, this will affect Rails' built-in logger. This means that anything that Rails logs, and any custom usage of the Rails logger, will result in sending log entries to Sentry:
45-
46-
```ruby
47-
Sentry.init do |config|
48-
config.dsn = "___PUBLIC_DSN___"
49-
config.enable_logs = true
50-
config.enabled_patches = [:logger]
51-
end
52-
```
53-
54-
Then all logs from Rails logger will be sent to Sentry, for example:
55-
56-
```ruby
57-
# All these calls will result in log entries in Sentry
58-
# if :logger patch is enabled
59-
Rails.logger.debug("Hello from Rails logger")
60-
Rails.logger.info("Hello from Rails logger")
61-
Rails.logger.error("Hello from Rails logger")
62-
```
63-
64-
<Alert level="warning" title="Note on logger patch">
65-
Enabling `:logger` patch will send all logs from Rails logger to Sentry. This includes logs from Rails framework itself, which might not be desired. In that case we recommend using [Sentry logger](#using-sentry-logger) or [structured logging with log subscribers](#structured-logging-with-log-subscribers).
66-
</Alert>
14+
See the [Usage](#usage) section for examples and [Options](#options) to customize which events are captured.
Lines changed: 11 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,56 +1,20 @@
1-
Once the feature is enabled on the SDK, you can send logs using the `Sentry.logger` API.
2-
3-
### Using Sentry Logger
4-
5-
The `logger` namespace exposes common logging methods that you can use to log messages at different log levels: `trace`, `debug`, `info`, `warning`, `error`, and `fatal`.
6-
7-
You can pass additional attributes directly to the logging functions. These properties will be sent to Sentry, and can be searched from within the Logs UI, and even added to the Logs views as a dedicated column.
1+
Use the `Sentry.logger` API to send logs to Sentry:
82

93
```ruby
10-
Sentry.logger.info("Updated global cache")
11-
12-
Sentry.logger.debug("Cache miss for user %{user_id}", user_id: 123)
13-
14-
Sentry.logger.trace(
15-
"Starting database connection %{database}",
16-
database: "users"
17-
)
18-
19-
Sentry.logger.warn(
20-
"Rate limit reached for endpoint %{endpoint}",
21-
endpoint: "/api/results/"
22-
)
23-
24-
Sentry.logger.error(
25-
"Failed to process payment. Order: %{order_id}. Amount: %{amount}",
26-
order_id: "or_2342", amount: 99.99
27-
)
28-
29-
Sentry.logger.fatal(
30-
"Database %{database} connection pool exhausted",
31-
database: "users"
32-
)
4+
Sentry.logger.info("User logged in successfully")
5+
Sentry.logger.error("Payment processing failed")
336
```
347

35-
### Message Templates
36-
37-
You can use message templates with positional or hash parameters:
8+
You can include additional context data as attributes:
389

3910
```ruby
40-
# Using named parameters
41-
Sentry.logger.info("User %{name} logged in", name: "Jane Doe")
42-
43-
# Using positional parameters
44-
Sentry.logger.info("User %s logged in", ["Jane Doe"])
11+
Sentry.logger.error(
12+
"Failed to process payment. Order: %{order_id}",
13+
order_id: "or_2342",
14+
amount: 99.99
15+
)
4516
```
4617

47-
Any other arbitrary attributes will be sent as part of the log event payload:
18+
Additional attributes like `amount` are sent as searchable metadata in Sentry's Logs UI.
4819

49-
```ruby
50-
# Here `user_id` and `action` will be sent as extra attributes that
51-
# Sentry Logs UI displays
52-
Sentry.logger.info(
53-
"User %{user} logged in",
54-
user: "Jane", user_id: 123, action: "create"
55-
)
56-
```
20+
See [Default Attributes](#default-attributes) for the complete list of metadata and [Options](#options) to customize which events are captured.

0 commit comments

Comments
 (0)