semantic_logger 5.0.0 → 5.2.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 (75) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +20 -10
  3. data/Rakefile +40 -0
  4. data/docs/api.md +506 -0
  5. data/docs/appenders.md +1074 -0
  6. data/docs/config.md +707 -0
  7. data/docs/index.md +223 -0
  8. data/docs/log.md +116 -0
  9. data/docs/metrics.md +171 -0
  10. data/docs/operations.md +446 -0
  11. data/docs/rails.md +890 -0
  12. data/docs/security.md +286 -0
  13. data/docs/testing.md +287 -0
  14. data/docs/upgrading.md +697 -0
  15. data/lib/semantic_logger/appender/async.rb +18 -5
  16. data/lib/semantic_logger/appender/bugsnag.rb +1 -1
  17. data/lib/semantic_logger/appender/cloudwatch_logs.rb +126 -29
  18. data/lib/semantic_logger/appender/elasticsearch.rb +2 -5
  19. data/lib/semantic_logger/appender/elasticsearch_base.rb +48 -23
  20. data/lib/semantic_logger/appender/elasticsearch_http.rb +15 -8
  21. data/lib/semantic_logger/appender/file.rb +141 -28
  22. data/lib/semantic_logger/appender/graylog.rb +22 -6
  23. data/lib/semantic_logger/appender/honeybadger.rb +1 -1
  24. data/lib/semantic_logger/appender/honeybadger_insights.rb +1 -1
  25. data/lib/semantic_logger/appender/http.rb +70 -11
  26. data/lib/semantic_logger/appender/io.rb +1 -1
  27. data/lib/semantic_logger/appender/kafka.rb +26 -12
  28. data/lib/semantic_logger/appender/loki.rb +13 -3
  29. data/lib/semantic_logger/appender/mongodb.rb +20 -1
  30. data/lib/semantic_logger/appender/new_relic.rb +7 -1
  31. data/lib/semantic_logger/appender/new_relic_logs.rb +11 -12
  32. data/lib/semantic_logger/appender/open_telemetry.rb +4 -3
  33. data/lib/semantic_logger/appender/opensearch.rb +2 -1
  34. data/lib/semantic_logger/appender/rabbitmq.rb +10 -4
  35. data/lib/semantic_logger/appender/sentry.rb +6 -1
  36. data/lib/semantic_logger/appender/sentry_ruby.rb +91 -17
  37. data/lib/semantic_logger/appender/splunk.rb +10 -1
  38. data/lib/semantic_logger/appender/syslog.rb +66 -25
  39. data/lib/semantic_logger/appender/tcp.rb +10 -4
  40. data/lib/semantic_logger/appender/udp.rb +11 -1
  41. data/lib/semantic_logger/appender/wrapper.rb +3 -2
  42. data/lib/semantic_logger/appender.rb +6 -3
  43. data/lib/semantic_logger/appenders.rb +11 -2
  44. data/lib/semantic_logger/base.rb +82 -32
  45. data/lib/semantic_logger/exception_details.rb +50 -0
  46. data/lib/semantic_logger/formatters/base.rb +52 -6
  47. data/lib/semantic_logger/formatters/color.rb +22 -3
  48. data/lib/semantic_logger/formatters/default.rb +28 -6
  49. data/lib/semantic_logger/formatters/logfmt.rb +155 -21
  50. data/lib/semantic_logger/formatters/loki.rb +26 -22
  51. data/lib/semantic_logger/formatters/one_line.rb +67 -3
  52. data/lib/semantic_logger/formatters/open_telemetry.rb +16 -17
  53. data/lib/semantic_logger/formatters/pattern.rb +11 -5
  54. data/lib/semantic_logger/formatters/raw.rb +4 -5
  55. data/lib/semantic_logger/formatters/syslog.rb +110 -17
  56. data/lib/semantic_logger/formatters/syslog_cee.rb +29 -15
  57. data/lib/semantic_logger/levels.rb +10 -1
  58. data/lib/semantic_logger/log.rb +183 -37
  59. data/lib/semantic_logger/loggable.rb +26 -3
  60. data/lib/semantic_logger/metric/new_relic.rb +1 -1
  61. data/lib/semantic_logger/metric/signalfx.rb +12 -8
  62. data/lib/semantic_logger/metric/statsd.rb +15 -7
  63. data/lib/semantic_logger/queue_processor/request.rb +55 -0
  64. data/lib/semantic_logger/queue_processor/throttled_counter.rb +46 -0
  65. data/lib/semantic_logger/queue_processor.rb +170 -68
  66. data/lib/semantic_logger/reporters/minitest.rb +4 -4
  67. data/lib/semantic_logger/semantic_logger.rb +15 -2
  68. data/lib/semantic_logger/subscriber.rb +96 -10
  69. data/lib/semantic_logger/sync_processor.rb +11 -0
  70. data/lib/semantic_logger/test/capture_log_events.rb +9 -6
  71. data/lib/semantic_logger/utils.rb +244 -16
  72. data/lib/semantic_logger/version.rb +1 -1
  73. data/lib/semantic_logger.rb +1 -1
  74. metadata +33 -6
  75. data/lib/semantic_logger/core_ext/thread.rb +0 -30
data/docs/rails.md ADDED
@@ -0,0 +1,890 @@
1
+ ---
2
+ layout: default
3
+ title: Rails
4
+ description: >-
5
+ Using Semantic Logger in Rails through the rails_semantic_logger gem:
6
+ configuring appenders, tuning what Rails logs, common recipes, and
7
+ upgrading.
8
+ ---
9
+
10
+
11
+ **Contents**
12
+
13
+ * TOC
14
+ {:toc}
15
+
16
+ [rails_semantic_logger](https://github.com/reidmorrison/rails_semantic_logger) is a companion gem
17
+ that wires Semantic Logger into Rails for you. Once installed it:
18
+
19
+ * Replaces the default Rails logger with Semantic Logger, so Rails, your application code, and many
20
+ common gems all log through it.
21
+ * Collapses the several lines Rails normally logs per request into a single, structured "Completed"
22
+ line, while keeping the individual fields (controller, action, status, durations, and so on)
23
+ searchable.
24
+ * Lets you send logs anywhere Semantic Logger supports: the standard Rails log file, standard out as
25
+ JSON for a container platform, a centralized log service, or several of these at once.
26
+
27
+ This page is a step-by-step guide that assumes no prior knowledge of either gem. Work through it
28
+ top to bottom: each section builds on the previous one. For the underlying logging API (logging
29
+ methods, tags, metrics, and so on) see the [Programmer's Guide](api.html), and for the full catalog
30
+ of log destinations see [Appenders](appenders.html).
31
+
32
+ > **Upgrading from v4?** The way appenders (log destinations) are configured changed in v5. Jump to
33
+ > [Migrating from v4 to v5](#migrating-from-v4-to-v5), then come back here.
34
+
35
+ ### Requirements
36
+
37
+ Rails Semantic Logger v5 requires **Ruby 3.2 or later** and **Rails 7.2 or later**. For the exact
38
+ list of tested Ruby and Rails versions, see the
39
+ [CI workflow](https://github.com/reidmorrison/rails_semantic_logger/blob/main/.github/workflows/ci.yml).
40
+
41
+ ### Installation
42
+
43
+ Add the following lines to your `Gemfile`:
44
+
45
+ ~~~ruby
46
+ gem "rails_semantic_logger"
47
+ gem "amazing_print" # optional
48
+ ~~~
49
+
50
+ `amazing_print` is optional but recommended: it produces colorized, readable output of the
51
+ structured data (the Hash payload) in development.
52
+
53
+ Install with bundler:
54
+
55
+ bundle install
56
+
57
+ That is all that is required. Rails Semantic Logger automatically replaces the standard Rails logger
58
+ with Semantic Logger and writes to the usual Rails log file.
59
+
60
+ #### Remove conflicting gems
61
+
62
+ Remove the following gems if present. They conflict with or duplicate what Rails Semantic Logger
63
+ already does:
64
+
65
+ * `lograge`
66
+ * `rails_stdout_logging`
67
+ * `rails_12factor`
68
+
69
+ ### Out of the box
70
+
71
+ With no configuration at all, Rails Semantic Logger:
72
+
73
+ * Writes to `log/<environment>.log` (for example `log/development.log`), the same file Rails uses.
74
+ * Colorizes that output when Rails colorized logging is enabled (the default in development).
75
+ * Logs to **standard out** when you run `rails server`, so you see requests in your terminal.
76
+ * Logs to **standard error** when you run `rails console`, so log lines do not get mixed up with
77
+ the return values of the commands you type.
78
+ * Replaces the multi-line Rails request log with a single structured "Completed" line.
79
+
80
+ Standard Rails log output for a single page request:
81
+
82
+ ![Rails Default](images/rails_default.png)
83
+
84
+ The same request after adding the `rails_semantic_logger` gem:
85
+
86
+ ![Rails Single Line](images/rails_single_line.png)
87
+
88
+ The rest of this page shows how to change **where** logs go and **how** they are formatted (the
89
+ appenders block), and then how to fine-tune **what** Rails logs.
90
+
91
+ Configuration goes in `config/application.rb` (for all environments) or in an environment file under
92
+ `config/environments/` (for one environment).
93
+
94
+ Use those two places, not `config/initializers/*`. Rails builds the logger **before** it loads
95
+ initializers, so the appenders block and the `semantic`, `replace_sidekiq_logger`, and
96
+ `replace_solid_queue_logger` options have no effect from an initializer; Rails Semantic Logger
97
+ prints a warning when it detects this. The output-tuning options consumed later in boot (`started`,
98
+ `processing`, `rendered`, `quiet_assets`, `action_message_format`) do still work from an
99
+ initializer, but not once the application has finished booting.
100
+
101
+ ---
102
+
103
+ ## Configuring where logs go: the appenders block
104
+
105
+ An **appender** is a destination for log output: a file, standard out, a centralized log service,
106
+ and so on. You declare the appenders you want inside a single block:
107
+
108
+ ~~~ruby
109
+ config.rails_semantic_logger.appenders do |appenders|
110
+ appenders.add(file_name: "log/#{Rails.env}.log", formatter: :color)
111
+ end
112
+ ~~~
113
+
114
+ There are three ways to declare an appender. **The method name says _when_ the appender is created;
115
+ the arguments say _where_ it writes and _how_ it is formatted.**
116
+
117
+ | Method | Created when… | Default destination |
118
+ |--------|---------------|---------------------|
119
+ | `add` | Always, during Rails initialization | (you must specify one) |
120
+ | `add_server` | Only when serving requests: `rails server` (see the note under [Step 3](#step-3-log-to-the-screen-only-while-serving)) and Sidekiq in server mode | `$stdout` |
121
+ | `add_console` | Only inside a `rails console` session | `$stderr` |
122
+
123
+ The arguments to all three are exactly the arguments to `SemanticLogger.add_appender` (covered in
124
+ detail in [the next section](#appender-options-and-destinations)), so anything Semantic Logger can
125
+ log to, any of these can declare. One default of note: since `add_server` and `add_console` are
126
+ screen appenders, their `formatter:` defaults to `:color` when not specified; `add` uses the
127
+ Semantic Logger default of plain text.
128
+
129
+ > **Important:** As soon as you declare **any** appender in this block, Rails Semantic Logger stops
130
+ > adding **all** of its automatic appenders: the default `log/<env>.log` file, the standard-out
131
+ > logger it normally adds under `rails server`, and the standard-error logger it normally adds in
132
+ > `rails console`. The block becomes the single source of truth for every destination. So declare
133
+ > what you want: `add` for an always-on destination (such as the file log), `add_server` for screen
134
+ > output while serving, and `add_console` for the Rails console.
135
+
136
+ ### Step 1: a single log file
137
+
138
+ ~~~ruby
139
+ config.rails_semantic_logger.appenders do |appenders|
140
+ appenders.add(file_name: "log/#{Rails.env}.log", formatter: :color)
141
+ end
142
+ ~~~
143
+
144
+ ### Step 2: add a JSON file for a log aggregator
145
+
146
+ Keep the human-readable color log and *also* write a JSON file for ingestion by Elasticsearch,
147
+ Splunk, Datadog, and the like:
148
+
149
+ ~~~ruby
150
+ config.rails_semantic_logger.appenders do |appenders|
151
+ appenders.add(file_name: "log/#{Rails.env}.log", formatter: :color)
152
+ appenders.add(file_name: "log/#{Rails.env}.json", formatter: :json)
153
+ end
154
+ ~~~
155
+
156
+ You can declare as many appenders as you like; every log entry is sent to all of them.
157
+
158
+ ### Step 3: log to the screen only while serving
159
+
160
+ `add_server` declares an appender that is created **only** when the application is actually serving
161
+ requests (under `rails server` or Sidekiq in server mode), and never during rake tasks, runners, or
162
+ generators. It defaults to `$stdout`:
163
+
164
+ ~~~ruby
165
+ config.rails_semantic_logger.appenders do |appenders|
166
+ appenders.add(file_name: "log/#{Rails.env}.log", formatter: :json)
167
+ appenders.add_server(formatter: :color) # → $stdout, only when serving
168
+ end
169
+ ~~~
170
+
171
+ > **Note:** Under `rails server`, the appender is created when Rails itself would log to standard
172
+ > out: in development, when not daemonized. To get it in another environment, pass
173
+ > `--log-to-stdout` to `rails server`. App servers started directly (bare `puma`, `rackup`, and so
174
+ > on) need a one-line boot hook; see
175
+ > [Other app servers](#other-app-servers-puma-rackup-passenger-unicorn).
176
+
177
+ ### Step 4: a dedicated console logger
178
+
179
+ `add_console` declares an appender created **only** inside a `rails console` session. It defaults to
180
+ `$stderr` so log output does not interleave with the results of the expressions you type:
181
+
182
+ ~~~ruby
183
+ config.rails_semantic_logger.appenders do |appenders|
184
+ appenders.add(file_name: "log/#{Rails.env}.log", formatter: :json)
185
+ appenders.add_server(formatter: :color) # $stdout while serving
186
+ appenders.add_console(formatter: :color) # $stderr inside `rails console`
187
+ end
188
+ ~~~
189
+
190
+ ### Several appenders in one context
191
+
192
+ Because each call simply appends to its context, a context can have more than one appender. For
193
+ example, write a color stream *and* a JSON file, but only while serving:
194
+
195
+ ~~~ruby
196
+ config.rails_semantic_logger.appenders do |appenders|
197
+ appenders.add_server(io: $stdout, formatter: :color)
198
+ appenders.add_server(file_name: "log/#{Rails.env}.log", formatter: :json)
199
+ end
200
+ ~~~
201
+
202
+ ---
203
+
204
+ ## Appender options and destinations
205
+
206
+ Every `add`, `add_server`, and `add_console` call accepts the same arguments as
207
+ `SemanticLogger.add_appender`. This section is the one-stop reference for those arguments, written as
208
+ Rails examples. For the complete list of destinations and their service-specific options, see
209
+ [Appenders](appenders.html).
210
+
211
+ ### Common options
212
+
213
+ In addition to a destination, most appenders accept these options:
214
+
215
+ | Option | Description |
216
+ |--------|-------------|
217
+ | `level` | Only write entries at this level or higher to this appender. Defaults to `SemanticLogger.default_level` (which Rails Semantic Logger sets from `config.log_level`). |
218
+ | `formatter` | How to format the output: `:default`, `:color`, `:json`, `:logfmt`, `:one_line`, or a custom formatter (see [Output formats](#output-formats)). |
219
+ | `filter` | A `Regexp` or `Proc` selecting which entries this appender accepts. See [Filtering](config.html#filtering). |
220
+ | `application`, `environment`, `host` | Override the global values for this appender only. |
221
+
222
+ For example, send only warnings and above to a separate JSON file:
223
+
224
+ ~~~ruby
225
+ config.rails_semantic_logger.appenders do |appenders|
226
+ appenders.add(file_name: "log/#{Rails.env}.log", formatter: :color)
227
+ appenders.add(file_name: "log/#{Rails.env}_errors.json", formatter: :json, level: :warn)
228
+ end
229
+ ~~~
230
+
231
+ ### Destinations
232
+
233
+ The destination is chosen by the argument you pass:
234
+
235
+ | Destination | Argument | Notes |
236
+ |-------------|----------|-------|
237
+ | Text or JSON file | `file_name:` | A path under `log/`. |
238
+ | IO stream | `io:` | `$stdout`, `$stderr`, or any `IO`. |
239
+ | Built-in appender | `appender: :name` | Selects a packaged appender by name (syslog, elasticsearch, http, bugsnag, and many more). |
240
+ | Existing Ruby/Rails logger | `logger:` | Wrap another logger instance. |
241
+ | Metrics destination | `metric:` | See [Metrics](metrics.html). |
242
+
243
+ A few common examples, all inside the appenders block:
244
+
245
+ ~~~ruby
246
+ config.rails_semantic_logger.appenders do |appenders|
247
+ # Local file
248
+ appenders.add(file_name: "log/#{Rails.env}.log", formatter: :color)
249
+
250
+ # Local Syslog
251
+ appenders.add(appender: :syslog)
252
+
253
+ # Remote syslog such as syslog-ng over TCP
254
+ appenders.add(appender: :syslog, url: "tcp://myloghost:514")
255
+
256
+ # Elasticsearch
257
+ appenders.add(appender: :elasticsearch, url: "http://localhost:9200")
258
+
259
+ # A generic HTTP(S) endpoint
260
+ appenders.add(appender: :http, url: "https://logs.example.com/ingest")
261
+
262
+ # Bugsnag (errors and above)
263
+ appenders.add(appender: :bugsnag, level: :error)
264
+ end
265
+ ~~~
266
+
267
+ Appenders for third-party services require their backing gem to be installed. See
268
+ [Appenders](appenders.html) for the full list of destinations, their gems, and their options.
269
+
270
+ ### Output formats
271
+
272
+ The `formatter:` option controls how each appender renders a log entry. Because it is per appender,
273
+ you can write color to the screen and JSON to a file at the same time.
274
+
275
+ | Formatter | Output |
276
+ |-----------|--------|
277
+ | `:default` | Plain text, no color. |
278
+ | `:color` | Plain text with color (uses Amazing Print for the payload when installed). |
279
+ | `:json` | One JSON object per entry. |
280
+ | `:logfmt` | `key=value` logfmt output. |
281
+ | `:one_line` | Each entry reduced to a single line: line breaks are removed from every field (or escaped with `escape_control_chars: true`) and an exception shows only its class and message, without the backtrace. |
282
+ | A class instance | Any instance of a class derived from `SemanticLogger::Formatters::Base`. |
283
+ | A `Proc` | Called with the `log` entry; returns the formatted output. |
284
+
285
+ JSON example:
286
+
287
+ ~~~ruby
288
+ config.rails_semantic_logger.appenders do |appenders|
289
+ appenders.add(file_name: "log/#{Rails.env}.json", formatter: :json)
290
+ end
291
+ ~~~
292
+
293
+ Custom formatter. Create `app/lib/my_formatter.rb`:
294
+
295
+ ~~~ruby
296
+ # A custom colorized formatter
297
+ class MyFormatter < SemanticLogger::Formatters::Color
298
+ # Return the complete log level name in uppercase
299
+ def level
300
+ "#{color}#{log.level.upcase}#{color_map.clear}"
301
+ end
302
+ end
303
+ ~~~
304
+
305
+ Then use it:
306
+
307
+ ~~~ruby
308
+ config.rails_semantic_logger.appenders do |appenders|
309
+ appenders.add(file_name: "log/#{Rails.env}.log", formatter: MyFormatter.new)
310
+ end
311
+ ~~~
312
+
313
+ See [SemanticLogger::Formatters::Color](https://github.com/reidmorrison/semantic_logger/blob/main/lib/semantic_logger/formatters/color.rb)
314
+ for the methods you can override, and [Custom formatters](config.html#custom-formatters) for more on formatters.
315
+
316
+ #### Amazing Print options for the color formatter
317
+
318
+ The color formatter renders the payload Hash with Amazing Print. To pass options to it, give the
319
+ `:color` formatter a Hash:
320
+
321
+ ~~~ruby
322
+ config.rails_semantic_logger.appenders do |appenders|
323
+ appenders.add(
324
+ file_name: "log/#{Rails.env}.log",
325
+ formatter: {color: {ap: {multiline: false}}}
326
+ )
327
+ end
328
+ ~~~
329
+
330
+ See the [Amazing Print documentation](https://github.com/amazing-print/amazing_print) for the
331
+ available options (or set defaults in a `~/.aprc` file). This has no effect if Amazing Print is not
332
+ installed.
333
+
334
+ ---
335
+
336
+ ## Common recipes
337
+
338
+ ### Development
339
+
340
+ Color to both the log file and the screen:
341
+
342
+ ~~~ruby
343
+ # config/environments/development.rb
344
+ config.rails_semantic_logger.appenders do |appenders|
345
+ appenders.add(file_name: "log/development.log", formatter: :color)
346
+ end
347
+ ~~~
348
+
349
+ (The default already does this, so in development you often need no configuration at all.)
350
+
351
+ ### Production on a container platform (Docker, Kubernetes, Heroku)
352
+
353
+ On a container platform the convention is to log JSON to standard out and let the platform collect
354
+ it. Use `add` (not `add_server`) so that rake tasks and one-off processes also log to stdout:
355
+
356
+ ~~~ruby
357
+ # config/environments/production.rb
358
+ config.rails_semantic_logger.appenders do |appenders|
359
+ appenders.add(io: $stdout, formatter: :json)
360
+ end
361
+ ~~~
362
+
363
+ Because the block disables the automatic appenders, this JSON-to-stdout appender is the *only*
364
+ destination: there is no default file log and no separate color logger under `rails server`, which
365
+ is exactly what a container platform wants.
366
+
367
+ To keep one configuration that works both locally and in-cluster, gate the JSON appender on an
368
+ environment variable that is only set in the container platform. For example, in
369
+ `config/application.rb` (so it applies to every environment), switch to JSON on standard out only
370
+ when running inside Kubernetes:
371
+
372
+ ~~~ruby
373
+ # config/application.rb
374
+ config.semantic_logger.application = "my_application"
375
+ config.semantic_logger.environment = ENV["STACK_NAME"] || Rails.env
376
+ config.log_level = ENV["LOG_LEVEL"] || :info
377
+
378
+ if ENV["LOG_TO_CONSOLE"] || ENV["KUBERNETES_SERVICE_HOST"]
379
+ config.rails_semantic_logger.appenders do |appenders|
380
+ appenders.add(io: $stdout, formatter: :json)
381
+ end
382
+ end
383
+ ~~~
384
+
385
+ Outside the cluster the block is skipped, so the default `log/<env>.log` file and the usual screen
386
+ loggers apply; inside the cluster JSON to stdout becomes the only destination.
387
+
388
+ On Heroku, also allow the log level to be set from the environment:
389
+
390
+ ~~~ruby
391
+ config.log_level = ENV["LOG_LEVEL"].presence&.downcase&.to_sym || :info
392
+ ~~~
393
+
394
+ `heroku config:set LOG_LEVEL=debug`
395
+
396
+ ### Production writing to files plus an error service
397
+
398
+ ~~~ruby
399
+ # config/environments/production.rb
400
+ config.rails_semantic_logger.appenders do |appenders|
401
+ appenders.add(file_name: "log/production.json", formatter: :json)
402
+ appenders.add(appender: :bugsnag, level: :error)
403
+ end
404
+ ~~~
405
+
406
+ ### Other app servers: puma, rackup, Passenger, Unicorn
407
+
408
+ `add_server` appenders are created automatically under `rails server` (following Rails' own
409
+ log-to-stdout rule: development and not daemonized, or the `--log-to-stdout` flag) and under Sidekiq
410
+ in server mode, because those have a definitive startup hook. App servers started **directly** (bare `puma`,
411
+ `rackup`, Passenger, Unicorn) have no such first-party hook, and Rails Semantic Logger deliberately
412
+ does **not** guess (a detection that only sometimes works is worse than none).
413
+
414
+ If you start your app with one of those servers and want your `add_server` appenders created, call
415
+ the helper from that server's own boot hook. For example, in `config/puma.rb`:
416
+
417
+ ~~~ruby
418
+ on_booted { RailsSemanticLogger.add_server_appenders }
419
+ ~~~
420
+
421
+ Alternatively, if you simply want a destination created in every context, declare it with `add`
422
+ instead of `add_server`.
423
+
424
+ ### Sidekiq
425
+
426
+ Sidekiq in server mode is treated as a serving context, so `add_server` appenders are created
427
+ automatically. No extra configuration is required.
428
+
429
+ This wiring is part of the Sidekiq logger integration, so setting
430
+ `config.rails_semantic_logger.replace_sidekiq_logger = false` also turns off the automatic creation.
431
+ In that case, call `RailsSemanticLogger.add_server_appenders` yourself from a Sidekiq startup hook:
432
+
433
+ ~~~ruby
434
+ # config/initializers/sidekiq.rb
435
+ Sidekiq.configure_server do |config|
436
+ config.on(:startup) { RailsSemanticLogger.add_server_appenders }
437
+ end
438
+ ~~~
439
+
440
+ ---
441
+
442
+ ## Tuning what Rails logs
443
+
444
+ The options below adjust Rails' own log output. They are independent of the appenders block and can
445
+ be combined with it.
446
+
447
+ ### Log level
448
+
449
+ ~~~ruby
450
+ # One of :trace, :debug, :info, :warn, :error, :fatal
451
+ config.log_level = :debug
452
+ ~~~
453
+
454
+ To change the level inside a running `rails console`:
455
+
456
+ ~~~ruby
457
+ SemanticLogger.default_level = :debug
458
+ ~~~
459
+
460
+ ### Re-enable Started, Processing, and Rendered messages
461
+
462
+ By default these messages are logged at `:debug` so they do not appear in production. To show them:
463
+
464
+ ~~~ruby
465
+ config.rails_semantic_logger.started = true # Rack "Started" line
466
+ config.rails_semantic_logger.processing = true # Controller "Processing" line
467
+ config.rails_semantic_logger.rendered = true # Action View render lines
468
+ ~~~
469
+
470
+ ![Semantic](images/rails_semantic.png)
471
+
472
+ ### Keep Rails' original wording
473
+
474
+ By default Action Controller and Active Record messages are converted to structured data:
475
+
476
+ ~~~
477
+ Rack -- Started -- { :ip => "127.0.0.1", :method => "GET", :path => "/users" }
478
+ UserController -- Completed #index -- { :action => "index", :db_runtime => 54.64, :format => "HTML", :method => "GET", :path => "/users", :status => 200, :status_message => "OK", :view_runtime => 709.88 }
479
+ ~~~
480
+
481
+ To keep Rails' original text messages (with Semantic Logger formatting) instead:
482
+
483
+ ~~~ruby
484
+ config.rails_semantic_logger.semantic = false
485
+ config.rails_semantic_logger.started = true
486
+ config.rails_semantic_logger.processing = true
487
+ config.rails_semantic_logger.rendered = true
488
+ ~~~
489
+
490
+ ![Semantic Disabled](images/rails_semantic_false.png)
491
+
492
+ ### Quiet asset logging
493
+
494
+ Rails logs asset requests at the debug level, which can clutter development logs:
495
+
496
+ ~~~
497
+ Rack -- Started -- {:ip => "127.0.0.1", :method => "GET", :path => "/assets/application.css"}
498
+ ~~~
499
+
500
+ To silence them:
501
+
502
+ ~~~ruby
503
+ config.rails_semantic_logger.quiet_assets = true
504
+ ~~~
505
+
506
+ ### Color output
507
+
508
+ Color is chosen per appender with the `formatter:` option: use `:color` for colorized output and
509
+ `:default` for plain text (see [Output formats](#output-formats)). For example, color on screen and
510
+ plain text in a file:
511
+
512
+ ~~~ruby
513
+ config.rails_semantic_logger.appenders do |appenders|
514
+ appenders.add(file_name: "log/#{Rails.env}.log", formatter: :default)
515
+ appenders.add_server(formatter: :color)
516
+ end
517
+ ~~~
518
+
519
+ The Rails `config.colorize_logging` setting does **not** affect appenders declared in the block; it
520
+ only influences the deprecated default file appender (see
521
+ [Deprecated configuration options](#deprecated-configuration-options)).
522
+
523
+ ### Named tags
524
+
525
+ Add tags to every log entry on a per-request basis by setting `config.log_tags` to a Hash:
526
+
527
+ ~~~ruby
528
+ config.log_tags = {
529
+ request_id: :request_id,
530
+ ip: :remote_ip,
531
+ user: ->(request) { request.cookie_jar["login"] }
532
+ }
533
+ ~~~
534
+
535
+ Notes:
536
+
537
+ * If a value returns `nil`, that key is omitted for that request.
538
+ * To turn named tags off in development, set `config.log_tags = nil` in
539
+ `config/environments/development.rb`.
540
+
541
+ ### Source file name and line number
542
+
543
+ To include the file and line number where each message originated:
544
+
545
+ ~~~ruby
546
+ config.semantic_logger.backtrace_level = :info
547
+ ~~~
548
+
549
+ ![with_source](images/rails_with_backtrace.png)
550
+
551
+ **Warning:** capturing a backtrace for every log entry allocates many objects. In production set this
552
+ to `nil` (disabled) or to a high level such as `:error`. By default backtraces are only captured for
553
+ `:error` and `:fatal`. This feature is best used in development.
554
+
555
+ ### Add custom data to the Completed message
556
+
557
+ Add an `append_info_to_payload` method to a controller to include extra fields in its Completed
558
+ message:
559
+
560
+ ~~~ruby
561
+ class ThingController < ApplicationController
562
+ private
563
+
564
+ def append_info_to_payload(payload)
565
+ super
566
+ payload[:user_id] = current_user&.id
567
+ end
568
+ end
569
+ ~~~
570
+
571
+ ### Customize the Completed message text
572
+
573
+ Provide a Proc to build the Action Controller message from the message and payload:
574
+
575
+ ~~~ruby
576
+ config.rails_semantic_logger.action_message_format = ->(message, payload) do
577
+ "#{message} - #{payload[:controller]}##{payload[:action]}"
578
+ end
579
+ ~~~
580
+
581
+ ### Background job loggers
582
+
583
+ By default Rails Semantic Logger replaces the Sidekiq and SolidQueue loggers. To leave them alone:
584
+
585
+ ~~~ruby
586
+ config.rails_semantic_logger.replace_sidekiq_logger = false
587
+ config.rails_semantic_logger.replace_solid_queue_logger = false
588
+ ~~~
589
+
590
+ Sidekiq v7 and v8 are supported. Earlier Sidekiq versions were supported up to
591
+ Rails Semantic Logger v5.0.
592
+
593
+ #### Sidekiq job lifecycle messages
594
+
595
+ For every Sidekiq job, Rails Semantic Logger emits a `Start #perform` and a `Completed #perform`
596
+ entry (with the `sidekiq.queue.latency` and `sidekiq.job.perform` metrics). On very high job volumes
597
+ these can add noise and cost in log aggregation tools. To turn them off (the job still runs and any
598
+ exceptions are still logged):
599
+
600
+ ~~~ruby
601
+ # config/initializers/sidekiq.rb
602
+ RailsSemanticLogger::Sidekiq::JobLogger.perform_messages = false
603
+ ~~~
604
+
605
+ This defaults to `true`, so the messages are emitted unless you opt out.
606
+
607
+ On Sidekiq 8, the standard Sidekiq setting has the same effect and is also honored:
608
+
609
+ ~~~ruby
610
+ Sidekiq.configure_server do |config|
611
+ config[:skip_default_job_logging] = true
612
+ end
613
+ ~~~
614
+
615
+ #### Sidekiq job logging context
616
+
617
+ Every log entry emitted while a job runs is tagged with the job's `jid`, class, and queue, plus its
618
+ `bid` (batch id) and `tags` when present. On Sidekiq 8, the standard `logged_job_attributes` setting
619
+ is honored, so additional job attributes can be added to the logging context:
620
+
621
+ ~~~ruby
622
+ Sidekiq.configure_server do |config|
623
+ config[:logged_job_attributes] = %w[bid tags priority]
624
+ end
625
+ ~~~
626
+
627
+ ### Custom controller base class
628
+
629
+ If your application uses a controller base class other than `ActionController::Base` or
630
+ `ActionController::API`, Rails Semantic Logger falls back to the `ActionController::Base` logger, so
631
+ those entries are named `ActionController::Base`. To give them the correct class name, include the
632
+ mixin in your base class:
633
+
634
+ ~~~ruby
635
+ include SemanticLogger::Loggable
636
+ ~~~
637
+
638
+ If the base class lives in a third-party gem, do it from an initializer:
639
+
640
+ ~~~ruby
641
+ CustomControllerBase.include(SemanticLogger::Loggable)
642
+ ~~~
643
+
644
+ ---
645
+
646
+ ## Metrics (prototype)
647
+
648
+ > **Prototype:** metrics support and the metric names below are an early prototype and **subject to
649
+ > change** in a future release. Do not hard-code these names into long-lived dashboards or alerts yet.
650
+
651
+ In addition to the structured log entry, Rails Semantic Logger attaches a Semantic Logger
652
+ [metric](metrics.html) to each entry that is logged at `:info`, `:warn`, or `:error`. When the entry
653
+ carries a duration (a request, query, render, job run, ...) the metric records that timing; otherwise
654
+ it acts as an event counter. Wire up a metrics appender (StatsD, Prometheus, ...) and these flow
655
+ through automatically alongside the logs.
656
+
657
+ Metric names follow `rails.<component>.<event>`, where `<component>` is the Rails component with its
658
+ `action_`/`active_` prefix dropped:
659
+
660
+ | Component | Metrics |
661
+ | --- | --- |
662
+ | Action Controller | `rails.controller.process_action`, `rails.controller.send_file`, `rails.controller.send_data`, `rails.controller.redirect_to`, `rails.controller.halted_callback`, `rails.controller.rescue_from_callback`, and the fragment-cache events (`rails.controller.write_fragment`, `read_fragment`, `exist_fragment`, `expire_fragment`, `expire_page`, `write_page`) |
663
+ | Action View | `rails.view.render.template`, `rails.view.render.partial`, `rails.view.render.layout`, `rails.view.render.collection` |
664
+ | Active Job | `rails.job.<event>` for every job event (`enqueue`, `enqueue_at`, `enqueue_all`, `perform_start`, `perform`, `enqueue_retry`, `retry_stopped`, `discard`, and the Rails 8.1 Continuation events `interrupt`, `resume`, `step_skipped`, `step_started`, `step`) |
665
+ | Action Mailer | `rails.mailer.deliver` |
666
+ | Solid Queue | `rails.solid_queue.<event>` for every Solid Queue event logged at info/warn/error (e.g. `rails.solid_queue.start_process`, `rails.solid_queue.thread_error`) |
667
+
668
+ Entries logged at `:debug` carry **no** metric. Because ActiveRecord logs SQL at `:debug`, there is
669
+ currently no `rails.db`/`rails.record` SQL metric, and Action View render metrics are only emitted
670
+ when rendered events are raised to `:info` (see
671
+ [Re-enable Started, Processing, and Rendered messages](#re-enable-started-processing-and-rendered-messages)).
672
+
673
+ ---
674
+
675
+ ## Operational notes
676
+
677
+ ### Process forking
678
+
679
+ If you use a forking server (Puma, Unicorn) or fork worker processes, see
680
+ [Process Forking](operations.html#process-forking). With Semantic Logger v5 appenders are reopened automatically after
681
+ a fork, so the manual `after_fork { SemanticLogger.reopen }` hook is usually no longer needed.
682
+
683
+ ### Drop messages instead of blocking
684
+
685
+ By default, if log messages arrive faster than the appenders can write them, calls to `logger.info`
686
+ wait once the in-memory queue is full, so requests, jobs, and shutdown hooks that log can stall behind
687
+ a slow destination. When staying responsive matters more than keeping every message, have them dropped
688
+ instead, in `config/application.rb` or `config/environments/production.rb`:
689
+
690
+ ~~~ruby
691
+ config.semantic_logger.non_blocking = true
692
+ ~~~
693
+
694
+ This needs Semantic Logger v5.2 or later. See
695
+ [Drop messages instead of blocking](operations.html#drop-messages-instead-of-blocking) for how it
696
+ relates to the per-appender `non_blocking:` option and how dropped messages are reported.
697
+
698
+ ### Log rotation
699
+
700
+ Because the log file is held open between writes, rotate it with a **copy-truncate** strategy rather
701
+ than deleting and recreating the file. Example `logrotate` configuration for Linux:
702
+
703
+ ~~~
704
+ /var/www/my_app/shared/log/*.log {
705
+ daily
706
+ missingok
707
+ copytruncate
708
+ rotate 14
709
+ compress
710
+ delaycompress
711
+ notifempty
712
+ }
713
+ ~~~
714
+
715
+ ### Loggers that are replaced automatically
716
+
717
+ After they initialize, Rails Semantic Logger replaces the loggers of these libraries when present:
718
+
719
+ - Action Cable
720
+ - Bugsnag
721
+ - Delayed Job
722
+ - IOStreams
723
+ - Mongo
724
+ - Mongoid
725
+ - Moped
726
+ - Resque
727
+ - Sidekiq (unless `replace_sidekiq_logger = false`)
728
+ - Sidetiq
729
+ - Solid Queue (unless `replace_solid_queue_logger = false`)
730
+
731
+ ---
732
+
733
+ ## Upgrading to v5.1
734
+
735
+ v5.1 requires Semantic Logger v5.1 and needs no configuration changes. Two behaviors differ.
736
+
737
+ ### A log file that cannot be opened now fails at boot
738
+
739
+ Semantic Logger v5.1 opens the file appender's log file when the appender is created, rather than on
740
+ the first write. A missing directory, a bad path, or insufficient permissions therefore raises
741
+ during boot, where Rails Semantic Logger catches it and falls back to logging to standard error at
742
+ the `:warn` level, with a message explaining the problem.
743
+
744
+ Previously that failure surfaced asynchronously on the appender thread after the application had
745
+ already booted, so the fallback never ran and the app kept running against an appender that silently
746
+ dropped every message. If you have been running with an unwritable log path without noticing, this
747
+ release is when you will find out.
748
+
749
+ As a side effect, the log file is created as soon as the appender is added, even if nothing has been
750
+ logged yet. This matches the standard Ruby and Rails loggers.
751
+
752
+ ### Sidekiq v4, v5, and v6 are no longer supported
753
+
754
+ Sidekiq v7 and v8 are supported and tested. The patches for older versions have been removed, along
755
+ with the pre-7.1.6 error handler branches. Sidekiq v7 and v8 both predate this gem's Rails 7.2 and
756
+ Ruby 3.2 minimums, so upgrading Sidekiq is the path forward.
757
+
758
+ On Sidekiq 8 two of its own settings are now honored: `logged_job_attributes` adds job attributes to
759
+ the logging context, and `skip_default_job_logging` suppresses the `Start #perform` /
760
+ `Completed #perform` messages (an alternative to
761
+ `RailsSemanticLogger::Sidekiq::JobLogger.perform_messages = false`). See
762
+ [Sidekiq](#sidekiq) for the logging configuration.
763
+
764
+ ---
765
+
766
+ ## Migrating from v4 to v5
767
+
768
+ ### Ruby and Rails minimums
769
+
770
+ v5 requires Ruby 3.2+ and Rails 7.2+. It also depends on Semantic Logger v5; review the
771
+ [Semantic Logger upgrade notes](upgrading.html) for changes there (the most relevant for Rails apps
772
+ is that appenders are now reopened automatically after fork, so you can remove manual reopen hooks).
773
+
774
+ ### Appender configuration is the main change
775
+
776
+ In v4 the log file, its format, and any extra destinations were configured through several separate
777
+ options (`format`, `add_file_appender`, `ap_options`, `filter`, `console_logger`) plus direct
778
+ `config.semantic_logger.add_appender(...)` calls. In v5 all of that lives in one place, the
779
+ [appenders block](#configuring-where-logs-go-the-appenders-block).
780
+
781
+ These v4 options still work in v5 but emit a deprecation warning and will be **removed in v6**.
782
+ Migrate them as follows:
783
+
784
+ | v4 | v5 |
785
+ |----|----|
786
+ | `config.rails_semantic_logger.format = :json` | `appenders.add(file_name: "log/#{Rails.env}.log", formatter: :json)` |
787
+ | `config.rails_semantic_logger.add_file_appender = false` then `config.semantic_logger.add_appender(...)` | Declare your destinations with `appenders.add(...)` (declaring any appender already replaces the default file appender) |
788
+ | `config.rails_semantic_logger.ap_options = {multiline: false}` | `appenders.add(..., formatter: {color: {ap: {multiline: false}}})` |
789
+ | `config.rails_semantic_logger.filter = /MyClass/` | `appenders.add(..., filter: /MyClass/)` |
790
+ | `config.rails_semantic_logger.console_logger = false` | Omit `add_console` (declare a console appender only if you want one) |
791
+
792
+ A v4 Heroku / standard-out configuration like:
793
+
794
+ ~~~ruby
795
+ # v4
796
+ if ENV["RAILS_LOG_TO_STDOUT"].present?
797
+ $stdout.sync = true
798
+ config.rails_semantic_logger.add_file_appender = false
799
+ config.semantic_logger.add_appender(io: $stdout, formatter: config.rails_semantic_logger.format)
800
+ end
801
+ ~~~
802
+
803
+ becomes, in v5:
804
+
805
+ ~~~ruby
806
+ # v5
807
+ config.rails_semantic_logger.appenders do |appenders|
808
+ appenders.add(io: $stdout, formatter: :json)
809
+ end
810
+ ~~~
811
+
812
+ ### Server standard-out behavior
813
+
814
+ In v4, running `rails server` always added a standard-out logger, which you suppressed with
815
+ `bin/rails s --daemon` or Puma's `--quiet`. In v5 this is the job of `add_server`: when you use the
816
+ appenders block, declare an `add_server` appender to log to the screen while serving, or omit it to
817
+ stay silent. If you do not use the appenders block at all, the v4 behavior is preserved.
818
+
819
+ ---
820
+
821
+ ## Migrating from earlier versions
822
+
823
+ These notes apply to upgrades between older releases and are retained for reference.
824
+
825
+ ### v4.16: Sidekiq metrics support
826
+
827
+ Rails Semantic Logger added support for Sidekiq metrics, available when the JSON logging format is
828
+ used:
829
+
830
+ * `sidekiq.job.perform` &mdash; the duration of each Sidekiq job; `duration` contains the time in
831
+ milliseconds that the job took to run.
832
+ * `sidekiq.queue.latency` &mdash; the time between when a Sidekiq job was enqueued and when it was
833
+ started; `metric_amount` contains the time in milliseconds that the job was waiting in the queue.
834
+
835
+ ### v4.15 and v4.16: Sidekiq support
836
+
837
+ Rails Semantic Logger introduced direct support for Sidekiq v4, v5, v6, and v7. Remove any previous
838
+ custom patches or configurations used to make Sidekiq work with Semantic Logger. To see the complete
839
+ list of patches and to contribute your own, see
840
+ [Sidekiq Patches](https://github.com/reidmorrison/rails_semantic_logger/blob/v5.0.0/lib/rails_semantic_logger/extensions/sidekiq/sidekiq.rb).
841
+ Support for Sidekiq v4, v5, and v6 ended after Rails Semantic Logger v5.0; Sidekiq v7 and v8 are
842
+ supported and tested.
843
+
844
+ ### v4.4
845
+
846
+ With some forking frameworks it was necessary to call `reopen` after the fork. As of v4.4 the
847
+ workaround for Ruby 2.5 crashes is no longer needed. Remove the following line if it is called
848
+ anywhere:
849
+
850
+ ~~~ruby
851
+ SemanticLogger::Processor.instance.instance_variable_set(:@queue, Queue.new)
852
+ ~~~
853
+
854
+ ---
855
+
856
+ ## Deprecated configuration options
857
+
858
+ The following options still function in v5 for backward compatibility but emit deprecation warnings
859
+ and will be **removed in v6**. Each is replaced by the [appenders block](#configuring-where-logs-go-the-appenders-block).
860
+
861
+ | Deprecated option | Replacement |
862
+ |-------------------|-------------|
863
+ | `config.rails_semantic_logger.format` | `formatter:` on each appender, e.g. `appenders.add(file_name: ..., formatter: :json)` |
864
+ | `config.rails_semantic_logger.ap_options` | `formatter: {color: {ap: {...}}}` on the appender |
865
+ | `config.rails_semantic_logger.filter` | `filter:` on the appender |
866
+ | `config.rails_semantic_logger.console_logger` | Declare (or omit) an `add_console` appender |
867
+ | `config.rails_semantic_logger.add_file_appender` | Declare appenders in the block (doing so already replaces the default file appender) |
868
+
869
+ ### Silencing the warnings until you migrate
870
+
871
+ The gem registers its deprecator with the application as
872
+ `Rails.application.deprecators[:rails_semantic_logger]`, so the standard Rails deprecation settings
873
+ govern these warnings:
874
+
875
+ ~~~ruby
876
+ # Hide them until you have migrated
877
+ config.active_support.report_deprecations = false
878
+
879
+ # Or silence only this gem's warnings, leaving the rest of the application's in place
880
+ Rails.application.deprecators[:rails_semantic_logger].silenced = true
881
+
882
+ # Or make them fatal, e.g. in config/environments/test.rb, so CI catches them
883
+ config.active_support.deprecation = :raise
884
+ ~~~
885
+
886
+ The warnings are recorded when the option is set and emitted once Rails has applied the settings
887
+ above. Rails reads `config/environments/*.rb` well before it applies deprecation configuration, so
888
+ warning from the option setter itself would land where none of these settings could reach it. Each
889
+ option is reported once per boot, attributed to the place it was set. Options set later, from
890
+ `config/initializers/*` or at runtime, warn immediately instead.