Skip to content

Commit fe1a8fb

Browse files
committed
support formatter styles '{' and '$' with Python 3.2 or above
1 parent 8e0f3a5 commit fe1a8fb

File tree

2 files changed

+71
-4
lines changed

2 files changed

+71
-4
lines changed

fluent/handler.py

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,19 +24,36 @@ class FluentRecordFormatter(logging.Formatter, object):
2424
2525
:param fmt: a dict with format string as values to map to provided keys.
2626
:param datefmt: strftime()-compatible date/time format string.
27-
:param style: (NOT USED)
27+
:param style: '%', '{' or '$' (used only with Python 3.2 or above)
2828
:param fill_missing_fmt_key: if True, do not raise a KeyError if the format
2929
key is not found. Put None if not found.s
3030
"""
3131
def __init__(self, fmt=None, datefmt=None, style='%', fill_missing_fmt_key=False):
3232
super(FluentRecordFormatter, self).__init__(None, datefmt)
3333

34-
if not fmt:
35-
self._fmt_dict = {
34+
if sys.version_info[0:2] >= (3, 2) and style != '%':
35+
self.__style, basic_fmt_dict = {
36+
'{': (logging.StrFormatStyle, {
37+
'sys_host': '{hostname}',
38+
'sys_name': '{name}',
39+
'sys_module': '{module}',
40+
}),
41+
'$': (logging.StringTemplateStyle, {
42+
'sys_host': '${hostname}',
43+
'sys_name': '${name}',
44+
'sys_module': '${module}',
45+
}),
46+
}[style]
47+
else:
48+
self.__style = None
49+
basic_fmt_dict = {
3650
'sys_host': '%(hostname)s',
3751
'sys_name': '%(name)s',
3852
'sys_module': '%(module)s',
3953
}
54+
55+
if not fmt:
56+
self._fmt_dict = basic_fmt_dict
4057
else:
4158
self._fmt_dict = fmt
4259

@@ -58,7 +75,10 @@ def format(self, record):
5875
data = {}
5976
for key, value in self._fmt_dict.items():
6077
try:
61-
value = value % record.__dict__
78+
if self.__style:
79+
value = self.__style(value).format(record)
80+
else:
81+
value = value % record.__dict__
6282
except KeyError as exc:
6383
value = None
6484
if not self.fill_missing_fmt_key:

tests/test_handler.py

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# -*- coding: utf-8 -*-
22

33
import logging
4+
import sys
45
import unittest
56

67
import fluent.handler
@@ -62,6 +63,52 @@ def test_custom_fmt(self):
6263
self.assertTrue('lineno' in data[0][2])
6364
self.assertTrue('emitted_at' in data[0][2])
6465

66+
@unittest.skipUnless(sys.version_info[0:2] >= (3, 2), 'supported with Python 3.2 or above')
67+
def test_custom_fmt_with_format_style(self):
68+
handler = fluent.handler.FluentHandler('app.follow', port=self._port)
69+
70+
logging.basicConfig(level=logging.INFO)
71+
log = logging.getLogger('fluent.test')
72+
handler.setFormatter(
73+
fluent.handler.FluentRecordFormatter(fmt={
74+
'name': '{name}',
75+
'lineno': '{lineno}',
76+
'emitted_at': '{asctime}',
77+
}, style='{')
78+
)
79+
log.addHandler(handler)
80+
log.info({'sample': 'value'})
81+
handler.close()
82+
83+
data = self.get_data()
84+
self.assertTrue('name' in data[0][2])
85+
self.assertEqual('fluent.test', data[0][2]['name'])
86+
self.assertTrue('lineno' in data[0][2])
87+
self.assertTrue('emitted_at' in data[0][2])
88+
89+
@unittest.skipUnless(sys.version_info[0:2] >= (3, 2), 'supported with Python 3.2 or above')
90+
def test_custom_fmt_with_template_style(self):
91+
handler = fluent.handler.FluentHandler('app.follow', port=self._port)
92+
93+
logging.basicConfig(level=logging.INFO)
94+
log = logging.getLogger('fluent.test')
95+
handler.setFormatter(
96+
fluent.handler.FluentRecordFormatter(fmt={
97+
'name': '${name}',
98+
'lineno': '${lineno}',
99+
'emitted_at': '${asctime}',
100+
}, style='$')
101+
)
102+
log.addHandler(handler)
103+
log.info({'sample': 'value'})
104+
handler.close()
105+
106+
data = self.get_data()
107+
self.assertTrue('name' in data[0][2])
108+
self.assertEqual('fluent.test', data[0][2]['name'])
109+
self.assertTrue('lineno' in data[0][2])
110+
self.assertTrue('emitted_at' in data[0][2])
111+
65112
def test_custom_field_raise_exception(self):
66113
handler = fluent.handler.FluentHandler('app.follow', port=self._port)
67114

0 commit comments

Comments
 (0)