@@ -20,8 +20,6 @@ class LokiEmitter:
20
20
"""Base Loki emitter class."""
21
21
22
22
success_response_code = const .success_response_code
23
- level_tag = const .level_tag
24
- logger_tag = const .logger_tag
25
23
label_allowed_chars = const .label_allowed_chars
26
24
label_replace_with = const .label_replace_with
27
25
session_class = requests .Session
@@ -32,7 +30,9 @@ def __init__(self,
32
30
headers : Optional [dict ] = None ,
33
31
auth : BasicAuth = None ,
34
32
as_json : bool = False ,
35
- props_to_labels : Optional [list [str ]] = None
33
+ props_to_labels : Optional [list [str ]] = None ,
34
+ level_tag : Optional [str ] = const .level_tag ,
35
+ logger_tag : Optional [str ] = const .logger_tag
36
36
):
37
37
"""
38
38
Create new Loki emitter.
@@ -53,8 +53,12 @@ def __init__(self,
53
53
self .auth = auth
54
54
#: Optional bool, send record as json?
55
55
self .as_json = as_json
56
- #: Optional list, send record as json?
56
+ #: Optional list, convert properties to loki labels
57
57
self .props_to_labels = props_to_labels or []
58
+ #: Label name indicating logging level.
59
+ self .level_tag : str = level_tag
60
+ #: Label name indicating logger name.
61
+ self .logger_tag : str = logger_tag
58
62
59
63
self ._session : Optional [requests .Session ] = None
60
64
self ._lock = threading .Lock ()
@@ -102,14 +106,21 @@ def format_label(self, label: str) -> str:
102
106
label = label .replace (char_from , char_to )
103
107
return "" .join (char for char in label if char in self .label_allowed_chars )
104
108
105
- def build_tags (self , record : logging .LogRecord ) -> Dict [str , Any ]:
109
+ def build_tags (self , record : logging .LogRecord , line : str ) -> Dict [str , Any ]:
106
110
"""Return tags that must be send to Loki with a log record."""
107
111
tags = dict (self .tags ) if isinstance (self .tags , ConvertingDict ) else self .tags
108
112
tags = copy .deepcopy (tags )
109
- tags [self .level_tag ] = record .levelname .lower ()
110
- tags [self .logger_tag ] = record .name
111
-
112
- extra_tags = {k : getattr (record , k ) for k in self .props_to_labels if getattr (record , k , None )}
113
+ if self .level_tag :
114
+ tags [self .level_tag ] = record .levelname .lower ()
115
+ if self .logger_tag :
116
+ tags [self .logger_tag ] = record .name
117
+
118
+ extra_tags = {}
119
+ if self .props_to_labels :
120
+ jsonline = json .loads (line )
121
+ for k in self .props_to_labels :
122
+ if prop_value := getattr (record , k , None ) or jsonline .get (k , None ):
123
+ extra_tags .update ({k : prop_value })
113
124
if isinstance (passed_tags := getattr (record , "tags" , {}), dict ):
114
125
extra_tags = extra_tags | passed_tags
115
126
@@ -121,9 +132,9 @@ def build_tags(self, record: logging.LogRecord) -> Dict[str, Any]:
121
132
122
133
return tags
123
134
124
- def build_payload (self , record : logging .LogRecord , line ) -> dict :
135
+ def build_payload (self , record : logging .LogRecord , line : str ) -> dict :
125
136
"""Build JSON payload with a log entry."""
126
- labels = self .build_tags (record )
137
+ labels = self .build_tags (record , line )
127
138
ns = 1e9
128
139
ts = str (int (time .time () * ns ))
129
140
0 commit comments