13
13
# limitations under the License.
14
14
15
15
import logging
16
+ from datetime import datetime
17
+ from typing import Optional
16
18
17
19
from opentelemetry .instrumentation .logging import LoggingInstrumentor
18
20
from pythonjsonlogger import jsonlogger
19
21
20
22
23
+ # We override JsonFormatter.formatTime() instead of using the datefmt strftime parameter
24
+ # because it does not support microsecond precision.
25
+
26
+
21
27
# [START opentelemetry_instrumentation_setup_logging]
28
+ class JsonFormatter (jsonlogger .JsonFormatter ):
29
+ def formatTime (self , record : logging .LogRecord , datefmt : Optional [str ] = None ):
30
+ # Format the timestamp as RFC 3339 with microsecond precision
31
+ isoformat = datetime .fromtimestamp (record .created ).isoformat ()
32
+ return f"{ isoformat } Z"
33
+
34
+
22
35
def setup_structured_logging () -> None :
23
36
LoggingInstrumentor ().instrument ()
24
37
25
38
log_handler = logging .StreamHandler ()
26
- formatter = jsonlogger . JsonFormatter (
39
+ formatter = JsonFormatter (
27
40
"%(asctime)s %(levelname)s %(message)s %(otelTraceID)s %(otelSpanID)s %(otelTraceSampled)s" ,
28
41
rename_fields = {
29
42
"levelname" : "severity" ,
@@ -32,7 +45,6 @@ def setup_structured_logging() -> None:
32
45
"otelSpanID" : "logging.googleapis.com/spanId" ,
33
46
"otelTraceSampled" : "logging.googleapis.com/trace_sampled" ,
34
47
},
35
- datefmt = "%Y-%m-%dT%H:%M:%SZ" ,
36
48
)
37
49
log_handler .setFormatter (formatter )
38
50
logging .basicConfig (
0 commit comments