From 71ad622fe1bbbbe16634650740ec643702716692 Mon Sep 17 00:00:00 2001 From: Ben Symonds Date: Tue, 28 Jan 2020 11:57:57 +0000 Subject: [PATCH] Ensure all strings with spaces are quoted in logs The current logic covers the case when the log data is already a `String` instance, but not when the data is some other object that, when interpolated into the log string, results in a string containing spaces. The example that led me here is where an exception is logged and the exception's message contains spaces. The exception gets interpolated into the string and has `to_s` called on it. [`Exception#to_s`](https://ruby-doc.org/core-2.6.5/Exception.html#method-i-to_s) returns the message, so the message (with its spaces) go into the log line, but it's bypassed the logic that adds quotes. I used `"#{v}"` instead of `v.to_s` because it seems there is a [subtle difference in their behaviour](https://github.com/ruby/spec/blob/master/language/string_spec.rb#L147-L158), to cover the rare case where `to_s` doesn't return a string. I think we want to keep the existing behaviour here. --- CHANGELOG.md | 1 + lib/pliny/log.rb | 9 ++++++--- spec/log_spec.rb | 14 ++++++++++++++ 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1406172e..73ad2e98 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p ## [Unreleased] ### Changed + - Ensure all strings with spaces are quoted in logs. ([#332](https://github.com/interagent/pliny/pull/332)) - Allow ActiveSupport 5 or 6. ([#331](https://github.com/interagent/pliny/pull/331)) ### Fixed diff --git a/lib/pliny/log.rb b/lib/pliny/log.rb index 6f98be86..42898460 100644 --- a/lib/pliny/log.rb +++ b/lib/pliny/log.rb @@ -146,12 +146,15 @@ def unparse_pair(k, v) k elsif v.is_a?(Float) "#{k}=#{format("%.3f", v)}" - elsif v.is_a?(String) && v =~ /\s/ - quote_string(k, v) elsif v.is_a?(Time) "#{k}=#{v.iso8601}" else - "#{k}=#{v}" + v = "#{v}" + if v =~ /\s/ + quote_string(k, v) + else + "#{k}=#{v}" + end end end end diff --git a/spec/log_spec.rb b/spec/log_spec.rb index 43839083..0ad43ef4 100644 --- a/spec/log_spec.rb +++ b/spec/log_spec.rb @@ -176,5 +176,19 @@ def to_s end Pliny.log(foo: klass.new) end + + it "quotes strings that are generated from object interpolation" do + expect(@io).to receive(:print).with("foo=\"message with space\"\n") + expect(@io).to receive(:print).with("foo=\"bar with space\"\n") + + Pliny.log(foo: StandardError.new("message with space")) + + klass = Class.new do + def to_s + "bar with space" + end + end + Pliny.log(foo: klass.new) + end end end