diff --git a/logfmt/formatter.py b/logfmt/formatter.py index e0937fa..74cbf43 100644 --- a/logfmt/formatter.py +++ b/logfmt/formatter.py @@ -16,7 +16,14 @@ def format_line(extra): else: if isinstance(v, (dict, object)): v = str(v) - v = '"%s"' % v.replace('"', '\\"') + needs_quoting = ' ' in v or '=' in v + needs_escaping = '"' in v + if needs_escaping: + v = '%s' % v.replace('"', '\\"') + if needs_quoting: + v = '"%s"' % v + if v == "": + v = '""' outarr.append("%s=%s" % (k, v)) return " ".join(outarr) diff --git a/tests/test_formatter.py b/tests/test_formatter.py index da0a8c0..df9d1c9 100644 --- a/tests/test_formatter.py +++ b/tests/test_formatter.py @@ -9,6 +9,10 @@ class FormatterTestCase(TestCase): def test_empty_log_line(self): data = format_line({}) self.assertEqual(data, "") + + def test_empty_string(self): + data = format_line({'key':''}) + self.assertEqual(data, 'key=""') def test_key_without_value(self): data = format_line( OrderedDict([("key1", None), ("key2", None)]) ) @@ -38,7 +42,7 @@ def test_custom_float_format(self): ("key2", "%.7f" % -234234234.2342342) ])) - self.assertEqual(data, "key1=342.23424 key2=\"-234234234.2342342\"") + self.assertEqual(data, "key1=342.23424 key2=-234234234.2342342") def test_string_value(self): data = format_line( OrderedDict([ @@ -48,6 +52,18 @@ def test_string_value(self): ])) self.assertEqual(data, '''key1="some random !@#$%^\\"&**_+-={}\\|;\':,./<>?)" key2="here\'s a line with\nmore stuff on the next"''') + + def test_kr_logfmt(self): + """ + Test using canonical example from https://github.com/kr/logfmt/blob/b84e30acd515aadc4b783ad4ff83aff3299bdfe0/example_test.go#L45 + """ + data = format_line(OrderedDict([ + ("measure.a", "1ms"), + ("measure.b", 10), + ("measure.c", "100MB"), + ("measure.d", "1s"), + ])) + self.assertEqual(data, "measure.a=1ms measure.b=10 measure.c=100MB measure.d=1s")