Add custom logfmt parser based off python-logfmt
This specifically doesn't add quotes where they're not necessary
This commit is contained in:
parent
9362be50b9
commit
af45867376
2 changed files with 89 additions and 0 deletions
31
catfish/utils/logfmt.py
Normal file
31
catfish/utils/logfmt.py
Normal file
|
@ -0,0 +1,31 @@
|
|||
# Adapted from https://github.com/jkakar/logfmt-python/blob/master/logfmt/formatter.py
|
||||
|
||||
from typing import Any, Dict
|
||||
|
||||
CHARS_TO_ESCAPE = [" ", "=", "\\", '"', "'"]
|
||||
|
||||
|
||||
def bool_to_str(i: bool) -> str:
|
||||
return str(i).lower()
|
||||
|
||||
|
||||
def escape_value(value: str):
|
||||
value = value.replace('"', '\\"')
|
||||
if any([char in value for char in CHARS_TO_ESCAPE]):
|
||||
value = '"{}"'.format(value)
|
||||
return value
|
||||
|
||||
|
||||
def logfmt(data: Dict[str, Any]):
|
||||
out = []
|
||||
for k, v in data.items():
|
||||
if not k.isidentifier():
|
||||
continue
|
||||
if v is None:
|
||||
v = ""
|
||||
elif isinstance(v, bool):
|
||||
v = bool_to_str(v)
|
||||
elif isinstance(v, str):
|
||||
v = escape_value(v)
|
||||
out.append("{}={}".format(k, v))
|
||||
return " ".join(out)
|
58
tests/test_utils/test_logfmt.py
Normal file
58
tests/test_utils/test_logfmt.py
Normal file
|
@ -0,0 +1,58 @@
|
|||
from catfish.utils.logfmt import logfmt
|
||||
from tests import BaseTestCase
|
||||
|
||||
|
||||
class LogFmtTestCase(BaseTestCase):
|
||||
def test_simple_logfmt(self):
|
||||
self.assertEqual(
|
||||
logfmt({"key1": "value1", "key2": "value2"}), "key1=value1 key2=value2"
|
||||
)
|
||||
|
||||
def test_quotes_space(self):
|
||||
self.assertEqual(
|
||||
logfmt({"key1": "value1 valuea", "key2": "value2 valueb"}),
|
||||
'key1="value1 valuea" key2="value2 valueb"',
|
||||
)
|
||||
|
||||
def test_quotes_equals(self):
|
||||
self.assertEqual(
|
||||
logfmt({"key1": "value1=valuea", "key2": "value2=valueb"}),
|
||||
'key1="value1=valuea" key2="value2=valueb"',
|
||||
)
|
||||
|
||||
def test_quotes_quotes(self):
|
||||
self.assertEqual(
|
||||
logfmt({"key1": '"value1"', "key2": '"value2"'}),
|
||||
'key1="\\"value1\\"" key2="\\"value2\\""',
|
||||
)
|
||||
self.assertEqual(
|
||||
logfmt({"key1": "'value1'", "key2": "'value2'"}),
|
||||
"key1=\"'value1'\" key2=\"'value2'\"",
|
||||
)
|
||||
|
||||
def test_empty(self):
|
||||
self.assertEqual(logfmt({}), "")
|
||||
|
||||
def test_boolean_values(self):
|
||||
self.assertEqual(logfmt({"key1": True, "key2": False}), "key1=true key2=false")
|
||||
|
||||
def test_none_values(self):
|
||||
self.assertEqual(logfmt({"key1": None, "key2": None}), "key1= key2=")
|
||||
|
||||
def test_numbers(self):
|
||||
self.assertEqual(
|
||||
logfmt({"key1": 12345, "key2": -12345}), "key1=12345 key2=-12345"
|
||||
)
|
||||
self.assertEqual(
|
||||
logfmt({"key1": "12345", "key2": "-12345"}), "key1=12345 key2=-12345"
|
||||
)
|
||||
|
||||
def test_float(self):
|
||||
self.assertEqual(
|
||||
logfmt({"key1": 12345.67, "key2": -12345.67}),
|
||||
"key1=12345.67 key2=-12345.67",
|
||||
)
|
||||
self.assertEqual(
|
||||
logfmt({"key1": "12345.67", "key2": "-12345.67"}),
|
||||
"key1=12345.67 key2=-12345.67",
|
||||
)
|
Reference in a new issue