1313
1414from logstash_async .constants import constants
1515
16+
1617try :
1718 import json
1819except ImportError :
@@ -82,29 +83,27 @@ def format(self, record):
8283 'process_id' : record .process ,
8384 'program' : self ._program_name ,
8485 'type' : self ._message_type ,
85- 'func_name' : record .funcName ,
86- 'line' : record .lineno ,
87- 'logger_name' : record .name ,
88- 'thread_name' : record .threadName ,
8986 }
9087 if self ._metadata :
9188 message ['@metadata' ] = self ._metadata
9289 if self ._tags :
9390 message ['tags' ] = self ._tags
9491
95- if record .exc_info :
96- message .update ({'stack_trace' , self ._format_exception (record .exc_info )})
97-
9892 # record fields
99- dynamic_extra_fields = self ._get_record_fields (record )
100- message .update (dynamic_extra_fields )
101- # prepare static extra fields
102- self ._format_extra_fields ()
103- message .update (self ._extra )
93+ record_fields = self ._get_record_fields (record )
94+ message .update (record_fields )
95+ # prepare dynamic extra fields
96+ extra_fields = self ._get_extra_fields (record )
10497 # remove all fields to be excluded
98+ self ._remove_excluded_fields (message , extra_fields )
99+ # wrap extra fields in configurable namespace
100+ if self ._extra_prefix :
101+ message [self ._extra_prefix ] = extra_fields
102+ else :
103+ message .update (extra_fields )
105104
106105 # move existing extra record fields into the configured prefix
107- # self._move_extra_record_fields_to_prefix(message)
106+ self ._move_extra_record_fields_to_prefix (message )
108107
109108 return self ._serialize (message )
110109
@@ -115,7 +114,6 @@ def _format_timestamp(self, time_):
115114
116115 # ----------------------------------------------------------------------
117116 def _get_record_fields (self , record ):
118-
119117 def value_repr (value ):
120118 easy_types = (type (None ), bool , str , int , float )
121119
@@ -135,21 +133,25 @@ def value_repr(value):
135133 fields = {}
136134
137135 for key , value in record .__dict__ .items ():
138- if key not in constants .FORMATTER_RECORD_FIELD_SKIP_LIST :
139- if self ._extra_prefix and key not in constants .FORMATTER_LOGSTASH_MESSAGE_FIELD_LIST :
140- key = self ._extra_prefix + "." + key
141- fields [key ] = value_repr (value )
136+ fields [key ] = value_repr (value )
142137 return fields
143138
144139 # ----------------------------------------------------------------------
145- def _format_extra_fields (self ):
140+ def _get_extra_fields (self , record ):
141+ extra_fields = {
142+ 'func_name' : record .funcName ,
143+ 'line' : record .lineno ,
144+ 'logger_name' : record .name ,
145+ 'process_name' : record .processName ,
146+ 'thread_name' : record .threadName ,
147+ }
146148 # static extra fields
147149 if self ._extra :
148- if self ._extra_prefix :
149- extra_fields_with_prefix = {}
150- for key in self . _extra :
151- extra_fields_with_prefix [ self . _extra_prefix + "." + key ] = self ._extra [ key ]
152- self . _extra = extra_fields_with_prefix
150+ extra_fields . update ( self ._extra )
151+ # exceptions
152+ if record . exc_info :
153+ extra_fields [ 'stack_trace' ] = self ._format_exception ( record . exc_info )
154+ return extra_fields
153155
154156 # ----------------------------------------------------------------------
155157 def _format_exception (self , exc_info ):
@@ -161,6 +163,29 @@ def _format_exception(self, exc_info):
161163 stack_trace = ''
162164 return stack_trace
163165
166+ # ----------------------------------------------------------------------
167+ def _remove_excluded_fields (self , message , extra_fields ):
168+ for fields in (message , extra_fields ):
169+ for field_name in list (fields ):
170+ if field_name in constants .FORMATTER_RECORD_FIELD_SKIP_LIST :
171+ del fields [field_name ]
172+
173+ # ----------------------------------------------------------------------
174+ def _move_extra_record_fields_to_prefix (self , message ):
175+ """
176+ Anythng added by the "extra" keyword in the logging call will be moved into the
177+ configured "extra" prefix. This way the event in Logstash will be clean and any extras
178+ will be paired together in the configured extra prefix.
179+ If not extra prefix is configured, the message will be kept as is.
180+ """
181+ if not self ._extra_prefix :
182+ return # early out if no prefix is configured
183+
184+ field_skip_list = constants .FORMATTER_LOGSTASH_MESSAGE_FIELD_LIST + [self ._extra_prefix ]
185+ for key in list (message ):
186+ if key not in field_skip_list :
187+ message [self ._extra_prefix ][key ] = message .pop (key )
188+
164189 # ----------------------------------------------------------------------
165190 def _serialize (self , message ):
166191 return json .dumps (message , ensure_ascii = self ._ensure_ascii )
0 commit comments