@@ -45,6 +45,10 @@ class CloudLoggingFilter(logging.Filter):
45
45
overwritten using the `extras` argument when writing logs.
46
46
"""
47
47
48
+ # The subset of http_request fields have been tested to work consistently across GCP environments
49
+ # https://cloud.google.com/logging/docs/reference/v2/rest/v2/LogEntry#httprequest
50
+ _supported_http_fields = ("requestMethod" , "requestUrl" , "userAgent" , "protocol" )
51
+
48
52
def __init__ (self , project = None , default_labels = None ):
49
53
self .project = project
50
54
self .default_labels = default_labels if default_labels else {}
@@ -74,8 +78,17 @@ def filter(self, record):
74
78
Add new Cloud Logging data to each LogRecord as it comes in
75
79
"""
76
80
user_labels = getattr (record , "labels" , {})
81
+ # infer request data from the environment
77
82
inferred_http , inferred_trace , inferred_span = get_request_data ()
83
+ if inferred_http is not None :
84
+ # filter inferred_http to include only well-supported fields
85
+ inferred_http = {
86
+ k : v
87
+ for (k , v ) in inferred_http .items ()
88
+ if k in self ._supported_http_fields and v is not None
89
+ }
78
90
if inferred_trace is not None and self .project is not None :
91
+ # add full path for detected trace
79
92
inferred_trace = f"projects/{ self .project } /traces/{ inferred_trace } "
80
93
# set new record values
81
94
record ._resource = getattr (record , "resource" , None )
@@ -84,13 +97,14 @@ def filter(self, record):
84
97
record ._http_request = getattr (record , "http_request" , inferred_http )
85
98
record ._source_location = CloudLoggingFilter ._infer_source_location (record )
86
99
record ._labels = {** self .default_labels , ** user_labels } or None
87
- # create guaranteed string representations for structured logging
88
- record ._msg_str = record .msg or ""
100
+ # create string representations for structured logging
89
101
record ._trace_str = record ._trace or ""
90
102
record ._span_id_str = record ._span_id or ""
91
103
record ._http_request_str = json .dumps (record ._http_request or {})
92
104
record ._source_location_str = json .dumps (record ._source_location or {})
93
105
record ._labels_str = json .dumps (record ._labels or {})
106
+ # break quotes for parsing through structured logging
107
+ record ._msg_str = str (record .msg ).replace ('"' , '\\ "' ) if record .msg else ""
94
108
return True
95
109
96
110
0 commit comments