Skip to content

Commit

Permalink
Enable adding custom LogStasher fields from apps
Browse files Browse the repository at this point in the history
I.e. allow apps to add their own custom fields in addition to those that
`GovukJsonLogging` already adds.

It looks like `LogStasher.add_custom_fields` can only be called one
time, otherwise subsequent calls overwrite previous ones.

We found this happening in the wild in the Content Store app, where
`govuk_request_id` et al were missing from the Rails framework logs but
present whenever the logger had been invoked directly from our own code.

I am curious about the possibility of being able to add custom fields to
both types of logs, together or separately, but the bug we're currently
experiencing is just a conflict between two calls to
`LogStasher.add_custom_fields`, so that's what I'm addressing.

---

I've tried to add specs for this and failed. LogStasher seems to only
load these settings inside of controllers, but adding a controller to
the dummy Rails app in the `GovukJsonLogging` specs didn't magically
solve the issue.

I don't think a more full-blown Rails app would be out-of-place in this
test suite, but without more confidence that introducing one would
actually get my specs working, I'm reluctant to spend an unspecified
amount of time bashing my head against that.

I've manually tested this change locally with Content Store, both with
and without its own custom field config.
  • Loading branch information
mike29736 committed Nov 15, 2023
1 parent d83f880 commit 4fa7abc
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 1 deletion.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
# Unreleased

* Enable adding custom LogStasher fields from apps ([#327](https://github.com/alphagov/govuk_app_config/pull/327))

# 9.5.0

* Allow gov.uk domains to embed pages in the global Content Security Policy ([#325](https://github.com/alphagov/govuk_app_config/pull/325))
Expand Down
14 changes: 14 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,20 @@ allow JSON format logs and `Govuk-Request-Id` to be visible.
For development logs, in order to see the production style logs, developers should
set `GOVUK_RAILS_JSON_LOGGING`in `govuk-docker` -> `docker-compose` files.

### Logger configuration

To include additional custom fields in your Rails logs, you can declare them
within a `GovukJsonLogging.configure` block in a `config/initializers/` file.

Example of adding a key/value to log entries based on a request header:

```ruby
GovukJsonLogging.configure do
add_custom_fields do |fields|
fields[:govuk_custom_field] = request.headers["GOVUK-Custom-Header"]
end
end
```

## Content Security Policy generation

Expand Down
20 changes: 19 additions & 1 deletion lib/govuk_app_config/govuk_json_logging.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,23 @@
require "action_controller"

module GovukJsonLogging
def self.configure
class Configuration
def initialize
@custom_fields_block = proc {}
end

attr_reader :custom_fields_block

def add_custom_fields(&block)
@custom_fields_block = block if block_given?
end
end

def self.configure(&block)
configuration = Configuration.new

configuration.instance_eval(&block) if block_given?

# We disable buffering, so that logs aren't lost on crash or delayed
# indefinitely while troubleshooting.
$stdout.sync = true
Expand Down Expand Up @@ -31,6 +47,8 @@ def self.configure
fields[:govuk_request_id] = request.headers["GOVUK-Request-Id"]
fields[:varnish_id] = request.headers["X-Varnish"]
fields[:govuk_app_config] = GovukAppConfig::VERSION

instance_exec(fields, &configuration.custom_fields_block) if block_given?
end

Rails.application.config.logstasher.enabled = true
Expand Down

0 comments on commit 4fa7abc

Please sign in to comment.