From 3cdb63336ca769883c9589320edf8fe3f21e1b26 Mon Sep 17 00:00:00 2001 From: Mike Patrick Date: Wed, 15 Nov 2023 14:35:14 +0000 Subject: [PATCH] Enable adding custom LogStasher fields from apps 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 manually tested this change locally with Content Store, both with and without its own custom field config. --- CHANGELOG.md | 4 ++++ README.md | 14 ++++++++++++++ lib/govuk_app_config/govuk_json_logging.rb | 20 +++++++++++++++++++- 3 files changed, 37 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 874a820..0b28940 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +# Unreleased + +* Enable adding custom LogStasher fields from apps ([#327](https://github.com/alphagov/govuk_app_config/pull/327)) + # 9.6.0 * Allow YouTube thumbnails from https://i.ytimg.com in the global Content Security Policy ([#328](https://github.com/alphagov/govuk_app_config/pull/328)) diff --git a/README.md b/README.md index 6aaccab..6c4618d 100644 --- a/README.md +++ b/README.md @@ -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 diff --git a/lib/govuk_app_config/govuk_json_logging.rb b/lib/govuk_app_config/govuk_json_logging.rb index c52ecbd..79c35ce 100644 --- a/lib/govuk_app_config/govuk_json_logging.rb +++ b/lib/govuk_app_config/govuk_json_logging.rb @@ -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 @@ -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