function.logging

Logging utilities for composition functions.

 1# Copyright 2023 The Crossplane Authors.
 2#
 3# Licensed under the Apache License, Version 2.0 (the "License");
 4# you may not use this file except in compliance with the License.
 5# You may obtain a copy of the License at
 6#
 7#     http://www.apache.org/licenses/LICENSE-2.0
 8#
 9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14
15"""Logging utilities for composition functions."""
16
17import enum
18import logging
19
20import structlog
21
22
23class Level(enum.Enum):
24    """Supported log levels."""
25
26    DISABLED = 0
27    DEBUG = 1
28    INFO = 2
29
30
31def configure(level: Level = Level.INFO) -> None:
32    """Configure logging.
33
34    Args:
35        level: What log level to enable.
36
37    Must be called before calling get_logger. When debug logging is enabled logs
38    will be printed in a human readable fashion. When not enabled, logs will be
39    printed as JSON lines.
40    """
41
42    def dropper(logger, method_name, event_dict):  # noqa: ARG001  # We need this signature.
43        raise structlog.DropEvent
44
45    if level == Level.DISABLED:
46        structlog.configure(processors=[dropper])
47        return
48
49    processors = [
50        structlog.stdlib.add_log_level,
51        structlog.processors.CallsiteParameterAdder(
52            {
53                structlog.processors.CallsiteParameter.FILENAME,
54                structlog.processors.CallsiteParameter.LINENO,
55            }
56        ),
57    ]
58
59    if level == Level.DEBUG:
60        structlog.configure(
61            processors=[
62                *processors,
63                structlog.processors.TimeStamper(fmt="iso"),
64                structlog.dev.ConsoleRenderer(),
65            ]
66        )
67        return
68
69    # Attempt to match function-sdk-go's production logger.
70    structlog.configure(
71        processors=[
72            *processors,
73            structlog.processors.dict_tracebacks,
74            structlog.processors.TimeStamper(key="ts"),
75            structlog.processors.EventRenamer(to="msg"),
76            structlog.processors.JSONRenderer(),
77        ],
78        wrapper_class=structlog.make_filtering_bound_logger(logging.INFO),
79    )
80
81
82def get_logger() -> structlog.stdlib.BoundLogger:
83    """Get a logger.
84
85    You must call configure before calling get_logger.
86    """
87    return structlog.stdlib.get_logger()
class Level(enum.Enum):
24class Level(enum.Enum):
25    """Supported log levels."""
26
27    DISABLED = 0
28    DEBUG = 1
29    INFO = 2

Supported log levels.

DISABLED = <Level.DISABLED: 0>
DEBUG = <Level.DEBUG: 1>
INFO = <Level.INFO: 2>
def configure(level: Level = <Level.INFO: 2>) -> None:
32def configure(level: Level = Level.INFO) -> None:
33    """Configure logging.
34
35    Args:
36        level: What log level to enable.
37
38    Must be called before calling get_logger. When debug logging is enabled logs
39    will be printed in a human readable fashion. When not enabled, logs will be
40    printed as JSON lines.
41    """
42
43    def dropper(logger, method_name, event_dict):  # noqa: ARG001  # We need this signature.
44        raise structlog.DropEvent
45
46    if level == Level.DISABLED:
47        structlog.configure(processors=[dropper])
48        return
49
50    processors = [
51        structlog.stdlib.add_log_level,
52        structlog.processors.CallsiteParameterAdder(
53            {
54                structlog.processors.CallsiteParameter.FILENAME,
55                structlog.processors.CallsiteParameter.LINENO,
56            }
57        ),
58    ]
59
60    if level == Level.DEBUG:
61        structlog.configure(
62            processors=[
63                *processors,
64                structlog.processors.TimeStamper(fmt="iso"),
65                structlog.dev.ConsoleRenderer(),
66            ]
67        )
68        return
69
70    # Attempt to match function-sdk-go's production logger.
71    structlog.configure(
72        processors=[
73            *processors,
74            structlog.processors.dict_tracebacks,
75            structlog.processors.TimeStamper(key="ts"),
76            structlog.processors.EventRenamer(to="msg"),
77            structlog.processors.JSONRenderer(),
78        ],
79        wrapper_class=structlog.make_filtering_bound_logger(logging.INFO),
80    )

Configure logging.

Arguments:
  • level: What log level to enable.

Must be called before calling get_logger. When debug logging is enabled logs will be printed in a human readable fashion. When not enabled, logs will be printed as JSON lines.

def get_logger() -> structlog.stdlib.BoundLogger:
83def get_logger() -> structlog.stdlib.BoundLogger:
84    """Get a logger.
85
86    You must call configure before calling get_logger.
87    """
88    return structlog.stdlib.get_logger()

Get a logger.

You must call configure before calling get_logger.